Loading...
Loading...
Use when structuring or refactoring Convex codebases with Domain-Driven Design boundaries, repository abstractions, adapters for external APIs, and transaction-safe workflows.
npx skill4agent add sebas5384/agentic-stuff convex-ddd-architectureschemaqueriesmutationsdomainadaptersctx.db./convex/
_generated/ # Auto-generated by Convex (do not edit)
_shared/ # Cross-domain utilities
_libs/
aggregate.ts # Base aggregate interface
repository.ts # Base repository interface
_triggers.ts # Central trigger registry
customFunctions.ts # Wrapped mutation/query exports
schema.ts # Composed schema from all sub-domains
[subDomainName]/ # Each sub-domain folder (camelCase)
_libs/
stripeClient.ts # Libs or helpers
_tables.ts # Database schema tables
_triggers.ts # Sub-domain trigger handlers
_seeds.ts # Seeds for models
_workflows.ts # Convex workflows
queries/
[queryName].ts # One query per file, export default
mutations/
[mutationName].ts # One mutation per file, export default
domain/
[modelName].model.ts # Model schema, types, Aggregate
[modelName].repository.ts # Repository interface
adapters/
[actionName].action.ts # External API actions
[modelName].repository.ts # Repository implementationcontactRepository.tssendInvoice.action.ts_tables.ts_triggers.ts_workflows.ts| Concern | Rule |
|---|---|
| Convex imports | Import |
| Function exports | One function per file with |
| Domain model shape | Include |
| Persistence boundary | Access DB through repositories in |
| External integrations | Keep translation in actions; business decisions stay in mutations/aggregates |
| Schema | Compose root schema from each sub-domain |
mutationqueryinternalMutationcustomFunctions.ts_generated/server// ✅ Correct
import { mutation } from "../../customFunctions";
// ❌ Wrong - bypasses trigger integration
import { mutation } from "../../_generated/server";// convex/combat/mutations/createBattle.ts
import { mutation } from "../../customFunctions";
import { v } from "convex/values";
const createBattle = mutation({
args: { heroId: v.id("heroProfiles") },
handler: async (ctx, args) => {
// ...
},
});
export default createBattle;.defaultimport { api } from "@/convex/_generated/api";
useMutation(api.combat.mutations.createBattle.default);
useQuery(api.economy.queries.getHeroProfile.default);export const createBattleapi.combat.mutations.createBattle.createBattle// convex/schema.ts
import { defineSchema } from "convex/server";
import { combatTables } from "./combat/_tables";
import { economyTables } from "./economy/_tables";
export default defineSchema({
...combatTables,
...economyTables,
});_generated/server