Contributing to Equibles
May 26, 2026 · View on GitHub
Thanks for your interest in contributing! This guide covers how to get started, submit changes, and extend the platform.
Getting Started
Prerequisites
- .NET 10 SDK
- Docker (for the database)
Development Setup
-
Fork and clone the repository.
-
Start the database:
docker compose up dbThis starts ParadeDB (PostgreSQL + pgvector + pg_search) on port 5432 with default credentials (
postgres/postgres). -
Configure local settings. Create
appsettings.Development.jsonin the host project you're running (e.g.,src/Equibles.Web/):{ "ConnectionStrings": { "DefaultConnection": "Host=localhost;Database=equibles;Username=postgres;Password=postgres" } }This file is gitignored. See README.md for optional settings (FINRA, FRED API keys, ticker filtering).
-
Build and run:
dotnet build Equibles.sln dotnet run --project src/Equibles.Web # Web portal (port 5000) dotnet run --project src/Equibles.Mcp.Server # MCP server dotnet run --project src/Equibles.Worker.Host # Background scrapersEF Core migrations run automatically on startup.
-
Install the pre-commit hooks (recommended). They run CSharpier, markdownlint, codespell, and a few hygiene checks before every commit:
# Restore CSharpier (and other .NET tools) dotnet tool restore # Install hooks — pick whichever tool you prefer prek install -f # https://prek.j178.dev — Rust port, faster # or: pre-commit install --install-hooks # Run once across the repo prek run --all-files
Submitting Changes
-
Create a feature branch from
main:git checkout -b feat/your-feature -
Make your changes, following the code style guidelines below.
-
Ensure the solution builds cleanly:
dotnet build Equibles.sln -
Commit with a descriptive message using Conventional Commits:
feat(holdings): add quarterly comparison endpoint fix(sec): handle missing CIK in EDGAR response docs: update MCP connection instructions -
Push your branch and open a pull request against
main. -
Keep PRs focused — one logical change per PR.
Code Style
- Follow existing patterns — consistency over personal preference.
- One class per file.
- Repositories return
IQueryable<T>, not materialized lists. - No business logic in repositories — that goes in managers.
- Controllers are thin — HTTP concerns only.
- Write operations go through managers for validation and business logic; read operations can call repositories directly.
Architecture Overview
Equibles is a modular monolith. Each financial domain (Holdings, Insider Trading, SEC, etc.) is a self-contained module distributed as NuGet packages. Three thin host applications compose modules at startup:
| Host | Purpose |
|---|---|
Equibles.Web | ASP.NET Core MVC web portal (DaisyUI + Tailwind) |
Equibles.Mcp.Server | MCP server exposing tools for AI assistants |
Equibles.Worker.Host | Background scrapers and processors |
Module Structure
Every domain module follows a layered pattern. Not all layers are required — create only what the module needs:
Equibles.{Module}.Data → Entity models, EF configuration, IModuleConfiguration
Equibles.{Module}.Repositories → Data access via BaseRepository<T>
Equibles.{Module}.BusinessLogic → Managers with business logic (when needed)
Equibles.{Module}.Mcp → MCP tool definitions (when applicable)
Equibles.{Module}.HostedService → Background scrapers/processors (when applicable)
DbContext Module System
One shared EquiblesDbContext composed from modules at startup. Each module implements IModuleConfiguration to register its entity configurations:
builder.Services.AddEquiblesDbContext(connectionString, modules => {
modules.AddCommonStocks();
modules.AddHoldings();
modules.AddInsiderTrading();
// ...
});
Modules declare their dependencies automatically — calling modules.AddSec() auto-registers AddCommonStocks() and AddMedia() if not already added.
Data Flow
Data (models) → Repositories (data access) → Managers (business logic) → Controllers / MCP Tools / HostedServices
Adding a New Module
1. Create the Data Project
dotnet new classlib -n Equibles.YourModule.Data -o src/Equibles.YourModule.Data
Add entity models and implement IModuleConfiguration:
public class YourModuleConfiguration : IModuleConfiguration
{
public void Configure(ModelBuilder builder)
{
builder.ApplyConfiguration(new YourEntityConfiguration());
}
}
Create the registration extension method:
public static class ModuleBuilderExtensions
{
public static ModuleBuilder AddYourModule(this ModuleBuilder builder)
{
builder.AddCommonStocks(); // if your module depends on stocks
builder.Add<YourModuleConfiguration>();
return builder;
}
}
2. Create the Repositories Project
dotnet new classlib -n Equibles.YourModule.Repositories -o src/Equibles.YourModule.Repositories
Repositories inherit from BaseRepository<T> — data access only, no business logic.
3. Register in a Host
Add modules.AddYourModule() in the host's Program.cs and create a migration:
dotnet ef migrations add AddYourModule --project src/Equibles.Migrations
4. Optional Layers
Create additional projects only when needed:
.BusinessLogic— Managers with validation or complex write operations.Mcp— MCP tools for AI assistant access.HostedService— Background scrapers or processors
Smart Enums
Domain-specific enums like DocumentType and ErrorSource use a smart enum pattern. They can be extended by calling their Register() method — no need to modify the core packages.
Contributor License Agreement
In order for Us to accept patches and other contributions from you, you need to sign our Contributor License Agreement (the "CLA"). The CLA grants Us the rights needed to maintain Equibles as an open-source project under AGPL-3.0 while also distributing it under separate terms in our commercial offering. You retain ownership of your contributions.
Equibles uses CLA Assistant to track contributor CLA status. When you open a pull request, CLA Assistant will post a comment indicating whether you have signed the CLA. If you have not, you must sign before we can merge your contribution. Signing is a one-time process, valid for all future contributions, and takes under a minute via your GitHub account.
License
Equibles is released under the AGPL-3.0 license. By signing the CLA, you grant Us the rights described in the agreement; you continue to own the copyright in your contributions.