Plugin Structure
This guide explains the standard file and folder organization for nopCommerce plugins.
Standard Directory Layout
Based on the official NopStation plugin template, here is the recommended folder structure:
NopStation.Plugin.Misc.Plugin/
│
├── 📄 NopStation.Plugin.Misc.Plugin.csproj # Project file (.NET 9)
├── 📄 plugin.json # Plugin manifest (required)
├── 📄 Plugin.cs # Main plugin class
├── 📄 PluginDefaults.cs # Constants and file paths
├── 📄 PluginPermissions.cs # Custom permissions
│
├── 📁 Areas/ # MVC Areas (recommended)
│ └── 📁 Admin/ # Admin area
│ ├── 📁 Controllers/ # Admin controllers
│ ├── 📁 Factories/ # Model factories
│ ├── 📁 Infrastructure/ # Admin-specific DI & Mapper
│ ├── 📁 Models/ # Admin view models
│ │ └── ConfigurationModel.cs
│ ├── 📁 Validators/ # FluentValidation
│ └── 📁 Views/ # Admin Razor views
│ ├── _ViewImports.cshtml
│ └── _ViewStart.cshtml
│
├── 📁 Components/ # ViewComponents
│ └── CustomViewComponent.cs # Widget view components
│
├── 📁 Controllers/ # Public controllers
│
├── 📁 Data/ # Data access layer
│ ├── 📁 Builders/ # Entity mapping builders
│ ├── 📁 Migrations/ # Update migrations
│ ├── BaseNameCompatibility.cs # Table name compatibility
│ └── SchemaMigration.cs # Initial schema migration
│
├── 📁 Domains/ # Domain entities
│ └── 📁 Enums/ # Enumerations
│
├── 📁 Events/ # Custom events
│
├── 📁 Extensions/ # Extension methods
│
├── 📁 Factories/ # Public model factories
│
├── 📁 Helpers/ # Utility classes
│
├── 📁 Infrastructure/ # DI and startup
│ ├── 📁 Mapper/ # AutoMapper profiles
│ ├── NopStartup.cs # Service registration
│ └── ViewLocationExpander.cs # Custom view paths
│
├── 📁 Localization/ # Language resources
│ └── pluginResources.en-us.xml # English translations
│
├── 📁 Models/ # Public view models
│
├── 📁 Services/ # Business logic
│ ├── 📁 Cache/ # Cache key definitions
│ └── EventConsumer.cs # Event handlers
│
├── 📁 Settings/ # Plugin settings classes
│
└── 📁 Views/ # Public views
├── 📁 Shared/ # Shared views
│ └── 📁 Components/ # ViewComponent views
│ └── 📁 Custom/ # Named after component
│ └── Default.cshtml # Default view
├── _ViewImports.cshtml
└── _ViewStart.cshtmlAreas Pattern
The Areas/Admin pattern is recommended for separating admin and public concerns. It provides better organization and follows ASP.NET Core MVC conventions.
Essential Files
plugin.json
The plugin manifest is required. It defines metadata nopCommerce uses to discover and manage your plugin.
json
{
"Group": "Misc",
"FriendlyName": "My Plugin Name",
"SystemName": "NopStation.Plugin.Misc.Plugin",
"Version": "4.90.0",
"SupportedVersions": ["4.90"],
"Author": "nopStation team",
"DisplayOrder": 1,
"FileName": "NopStation.Plugin.Misc.Plugin.dll",
"Description": "Add your plugin description"
}| Property | Required | Description |
|---|---|---|
Group | Yes | Category in admin panel |
FriendlyName | Yes | Display name |
SystemName | Yes | Unique identifier |
Version | Yes | Plugin version |
SupportedVersions | Yes | Compatible nopCommerce versions |
Author | Yes | Developer/company name |
FileName | Yes | Main assembly name |
DisplayOrder | No | Sort order in lists |
Description | No | Plugin description |
DependsOn | No | If the plugin depends on other plugins, list them here |
Main Plugin Class
csharp
// MyAwesomePlugin.cs
public class MyAwesomePlugin : BasePlugin, IWidgetPlugin
{
// Required for widgets: define render zones
public Task<IList<string>> GetWidgetZonesAsync() { }
// Required for widgets: return view component type
public Type GetWidgetViewComponent(string widgetZone) { }
// Optional: configuration page URL
public override string GetConfigurationPageUrl() { }
// Optional: custom install logic
public override async Task InstallAsync() { }
// Optional: update logic
public override async Task UpdateAsync(string currentVersion, string targetVersion){ }
// Optional: custom uninstall logic
public override async Task UninstallAsync() { }
}Settings Class
csharp
// MyAwesomeSettings.cs
using Nop.Core.Configuration;
public class MyAwesomeSettings : ISettings
{
public bool Enabled { get; set; }
public string ApiKey { get; set; }
public int MaxItems { get; set; } = 10;
}Naming Conventions
Project & Namespace
| Convention | Example |
|---|---|
| Project Name | Nop.Plugin.{Type}.{Name} |
| Namespace | Same as project name |
| Assembly | Same as project name |
Common Types
| Type | Pattern | Example |
|---|---|---|
| Widget | Nop.Plugin.Widgets.{Name} | Nop.Plugin.Widgets.Slider |
| Payment | Nop.Plugin.Payments.{Name} | Nop.Plugin.Payments.Stripe |
| Shipping | Nop.Plugin.Shipping.{Name} | Nop.Plugin.Shipping.UPS |
| Tax | Nop.Plugin.Tax.{Name} | Nop.Plugin.Tax.Avalara |
| Misc | Nop.Plugin.Misc.{Name} | Nop.Plugin.Misc.Export |
| ExternalAuth | Nop.Plugin.ExternalAuth.{Name} | Nop.Plugin.ExternalAuth.Google |
Files and Classes
csharp
// ✅ Good naming
MyAwesomePlugin.cs // Main plugin class
MyAwesomeSettings.cs // Settings
MyAwesomeDefaults.cs // Constants
MyAwesomeController.cs // Admin controller
ConfigurationModel.cs // Admin config model
Configure.cshtml // Admin config view
// ❌ Avoid
Plugin.cs // Too generic
Settings.cs // Not specific enough
Controller.cs // Conflicts with baseViews & ViewComponents
For detailed documentation on view organization, ViewLocationExpander, and ViewComponents, see Views & ViewComponents.
Output Directory
After build, your plugin files are copied to:
src/Presentation/Nop.Web/Plugins/{SystemName}/
├── Nop.Plugin.Widgets.MyAwesome.dll
├── Nop.Plugin.Widgets.MyAwesome.pdb
├── plugin.json
├── logo.png
└── Views/
└── ...Build Target
Add a post-build target in your .csproj to automatically copy files to the Nop.Web/Plugins folder. See Creating a Plugin.
Next Steps
- Services & DI - Add business logic
- Database - Create custom tables
- Admin UI - Build configuration interfaces