Plugin System & Catalog
The Clarity platform uses a modular plugin architecture where every feature—from payment processing to ERP connectors—is an isolated, composable plugin. Plugins register their own database entities, API endpoints, pipelines, and frontend code through a unified interface.
Plugin System
Every plugin implements the IPlugin interface, which defines the contract between the plugin and the Phoenix.Core host. This interface provides lifecycle hooks for service registration, database model configuration, and application startup.
public interface IPlugin { string Name { get; } string Schema { get; } void RegisterServices(WebApplicationBuilder builder); void OnStartup(WebApplication app); void OnModelCreating(ModelBuilder builder); Type[] GetAdditionalDatabaseTypes(); }
A PluginBase abstract class provides sensible defaults for optional members, so most plugins only need to override the methods they actually use.
.csproj Project File
Defines the C# project, NuGet dependencies, and references to Phoenix.Core. Each plugin is a standalone .NET class library.
Plugin Class (C#)
The backend implementation: IPlugin interface, database entities, pipelines, hooks, API endpoints, and service registrations.
plugin.json (Frontend)
Declares frontend routes, components, extension points, and assets that the Remix UI should load for this plugin.
Each plugin specifies its own database entities, API endpoints, pipelines, and frontend code. This isolation means plugins can be developed, tested, and deployed independently without modifying core platform code.
Plugin Lifecycle
Plugins are registered in a specific order within Startup.cs using the fluent .AddPhoenixPlugin<>() chain. Registration order determines initialization sequence and can affect dependency resolution.
builder
.AddPhoenixPlugin<SitePlugin>()
.AddPhoenixPlugin<ConnectCorePlugin>()
.AddPhoenixPlugin<PaymentsPlugin>()
.AddPhoenixPlugin<InvoicingPlugin>()
.AddPhoenixPlugin<SalesPlugin>()
.AddPhoenixPlugin<ProductsPlugin>()
.AddPhoenixPlugin<NetSuitePlugin>()
.AddPhoenixPlugin<NuveiPlugin>();
Initialization Sequence
RegisterServices
Called during application build. Each plugin registers its DI services, repositories, pipeline handlers, and configuration options into the shared service collection.
OnModelCreating
Called when Entity Framework builds the database model. Each plugin configures its own entity mappings, indexes, relationships, and schema isolation.
OnStartup
Called after the application is built. Plugins can map endpoints, register middleware, seed data, or perform any startup initialization.
Workflow Taxonomy
Connector plugins use WorkflowVendor and WorkflowProduct properties to categorize their pipelines within the workflow engine. This taxonomy enables the platform to route workflows to the correct connector implementation.
Submodules & Git
Plugins are managed as Git submodules within the host project. Understanding Git fundamentals is essential to working with this architecture, so let us walk through the key concepts.
Git Basics: Commits
A Git repository is fundamentally a sequence of commits. Each commit is a snapshot of your project at a point in time, identified by a unique hash (SHA). Commits form a chain, where each commit points back to its parent.
Branch References
A branch is simply a pointer (reference) to a specific commit. The HEAD pointer indicates which branch you currently have checked out.
Creating Commits
When you create a new commit, Git creates a new snapshot and moves the current branch pointer forward. The branch always points to the latest commit on that line of development.
Creating Branches
Creating a branch simply adds a new pointer to the current commit. You can then switch to it and start making independent changes without affecting the original branch.
Branch Divergence
When commits are made on different branches, the branches diverge. Each branch has its own line of history, and they can later be merged back together.
What Are Submodules?
A Git submodule is a reference to another Git repository embedded within your project. Rather than copying code, the parent repository stores a pointer to a specific commit in the submodule's repository. This means the submodule's code lives in its own repository with its own history, branches, and pull requests—but it appears as a folder in your project.
- check_circle Shared bug fixes: Fix a bug in the plugin once, and every project using that plugin gets the fix when they update their submodule reference.
- check_circle No manual cherry-picking: Without submodules, you would need to manually copy changes between projects or maintain complex cherry-pick workflows.
- check_circle Shared code stays live: The plugin code in your project is not a snapshot—it is a live link to the plugin repository, making collaboration seamless.
Submodule Status
When a submodule has changes or is pointing to a different commit than what the parent expects, git status will show the submodule as modified. The status shows the submodule folder with a special notation indicating the commit reference has changed.
Working with Submodules
git submodule update --init
git submodule foreach git pull origin develop
When you enter a submodule directory, you are typically in a detached HEAD state. This means HEAD points directly to a commit rather than a branch. Before making changes inside a submodule, always check out a branch first (e.g., git checkout develop) to avoid losing commits.
Adding a Plugin to a Project
Follow these steps to add a new plugin as a Git submodule and integrate it into both the backend and frontend.
Get the Clone URL from Azure Repos
Navigate to the plugin repository in Azure DevOps and click the Clone button to get the HTTPS URL.
Click the Clone button
Copy the HTTPS URL
Add the Submodule
Run the submodule add command from the project root, targeting the /Plugins folder.
git submodule add <CLONE_URL> Plugins/Phoenix.YourPlugin
Fix .gitmodules
Verify the .gitmodules file has the correct path and URL for the new submodule entry. Ensure the path matches your intended directory structure.
Add to Visual Studio Solution
In Visual Studio, right-click the solution and select "Add Existing Project" to include the plugin's .csproj file.
Add Project Reference
Add a project reference from the client/host project to the plugin project so it compiles and links correctly.
Register in Startup.cs
Add the plugin to the registration chain in Startup.cs.
builder.AddPhoenixPlugin<YourPlugin>();
Configure Frontend
Add the plugin to the plugins array in the project's package.json so the Remix build system includes the plugin's frontend code.
{
"plugins": [
"phoenix-site",
"phoenix-payments",
"phoenix-your-plugin"
]
}
Updating Submodule References
When a plugin has been updated in its own repository, you need to update the submodule reference in the parent project. Navigate into the submodule directory, pull the latest changes, then go back to the parent and commit the updated reference.
When your changes span both the plugin and the host project, create separate pull requests for each repository. In the host project's PR description, include a link to the plugin's PR so reviewers understand the full scope of changes. Merge the plugin PR first, then update the submodule reference and merge the host PR.
Plugin Catalog
Hundreds of plugins are available for the Clarity platform across five categories: Core, Feature, Connector, Provider, and Build. Below is a handful of the most common plugins; many more are available to review and discuss upon request.
| Plugin | Category | Schema | Description |
|---|---|---|---|
| Phoenix.ConnectCore | Core | Connect | Connector infrastructure, EkDB, entity reference system |
| Phoenix.Payments | Core | Payments | Payment processing hub, tokenization, provider abstraction |
| Phoenix.Invoicing | Core | Invoicing | Invoice management, quick-pay tokens, surcharges, aging |
| Phoenix.Sales | Core | Sales | Sales collections, fulfillment tracking |
| Phoenix.Site | Core | Site | Tenant/site configuration, registration |
| Phoenix.Products | Feature | Products | Product catalog, import, associations |
| Phoenix.CMS | Feature | CMS | Content management, block editor |
| Phoenix.Reporting | Feature | Reporting | Analytics, templates, aggregation |
| Phoenix.Currencies | Feature | Currencies | Multi-currency support |
| Phoenix.Shipping | Feature | Shipping | Fulfillment, shipping providers |
| Phoenix.Taxes.Base | Feature | Taxes | Tax calculation framework |
| Phoenix.Functionality | Feature | — | Additional functionality base |
| Phoenix.ProductUpdate | Feature | — | Product data synchronization |
| Phoenix.Maestro | Feature | Maestro | AI integration |
| Phoenix.Connector.Netsuite | Connector | NetSuite | NetSuite ERP integration (OAuth 2.0, 15+ pipelines) |
| Phoenix.Payments.Providers.Mock | Provider | — | Reference/test payment provider |
| Phoenix.Payments.Providers.Nuvei | Provider | — | Production payment gateway (CC + ACH) |
| Phoenix.RootOverlay | Build | — | Build configuration overlay |
Plugin Dependency Graph
The dependency structure radiates outward from Phoenix.Core. Core plugins have direct dependencies, while feature plugins, connectors, and providers depend on both Core and the relevant core plugins.