convex-ddd-architecture

Use when structuring or refactoring Convex codebases with Domain-Driven Design boundaries, repository abstractions, adapters for external APIs, and transaction-safe workflows.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "convex-ddd-architecture" with this command: npx skills add sebas5384/agentic-stuff/sebas5384-agentic-stuff-convex-ddd-architecture

Convex DDD Architecture

Reference skill for organizing Convex projects with DDD and Hexagonal architecture. It keeps domain logic isolated from database and external API concerns so changes remain local and safer to evolve.

When to Use

Use this skill when work includes one or more of these signals:

  • New Convex sub-domain design (schema, queries, mutations, domain, adapters)
  • Legacy Convex code migration toward DDD/Hexagonal boundaries
  • Business rules drifting into handlers instead of aggregates
  • Direct ctx.db access spreading outside repositories
  • External API calls requiring retries, orchestration, or translation layers
  • Team-level need for consistent file layout and naming in Convex projects

Do not use this as a strict template for tiny prototypes where speed matters more than architectural boundaries.

Project Shape

./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 implementation

Naming Rules

  • Files: Use camelCase (contactRepository.ts, sendInvoice.action.ts)
  • Underscore prefix: For non-domain files (_tables.ts, _triggers.ts)
  • Directory vs file: Start with a file (for example _workflows.ts), split into a directory after growth

Quick Reference

ConcernRule
Convex importsImport mutation, query, internalMutation from customFunctions.ts
Function exportsOne function per file with export default
Domain model shapeInclude _id, _creationTime, plus New<Model> without system fields
Persistence boundaryAccess DB through repositories in adapters/
External integrationsKeep translation in actions; business decisions stay in mutations/aggregates
SchemaCompose root schema from each sub-domain _tables export

Core Patterns

1) Custom Functions Boundary

Always import mutation, query, internalMutation from customFunctions.ts, not from _generated/server. See custom-functions.md.

// ✅ Correct
import { mutation } from "../../customFunctions";

// ❌ Wrong - bypasses trigger integration
import { mutation } from "../../_generated/server";

2) API Path Convention

One function per file with named definition and default export:

// 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;

Frontend usage with .default suffix:

import { api } from "@/convex/_generated/api";
useMutation(api.combat.mutations.createBattle.default);
useQuery(api.economy.queries.getHeroProfile.default);

Avoid named exports like export const createBattle - this creates redundant paths like api.combat.mutations.createBattle.createBattle.

3) Schema Composition

Compose schema from sub-domain tables:

// convex/schema.ts
import { defineSchema } from "convex/server";
import { combatTables } from "./combat/_tables";
import { economyTables } from "./economy/_tables";

export default defineSchema({
  ...combatTables,
  ...economyTables,
});

4) Domain + Repository + Adapter Roles

  • Domain models and aggregates define invariants (domain-models.md)
  • Repositories isolate persistence logic (repositories.md)
  • Actions adapt external DTOs and call mutations for business transitions (adapters.md)
  • Triggers and workflows orchestrate reliable side effects (triggers.md)

5) Workflow and Trigger Safety

  • Prefer one-way flow: UI mutation -> scheduled action/workflow -> mutation -> reactive query
  • Keep trigger handlers lightweight; schedule async work when possible
  • Treat trigger code as transaction-sensitive

Common Mistakes

  • Importing handlers directly from _generated/server and bypassing shared wrappers
  • Writing business rules in actions or handlers instead of aggregates
  • Updating records with ad-hoc field mutations rather than aggregate transitions
  • Returning raw records where aggregate behavior is expected
  • Introducing required schema fields without staged migration strategy (migrations.md)

Supporting References

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

openclaw-version-monitor

监控 OpenClaw GitHub 版本更新,获取最新版本发布说明,翻译成中文, 并推送到 Telegram 和 Feishu。用于:(1) 定时检查版本更新 (2) 推送版本更新通知 (3) 生成中文版发布说明

Archived SourceRecently Updated
Coding

ask-claude

Delegate a task to Claude Code CLI and immediately report the result back in chat. Supports persistent sessions with full context memory. Safe execution: no data exfiltration, no external calls, file operations confined to workspace. Use when the user asks to run Claude, delegate a coding task, continue a previous Claude session, or any task benefiting from Claude Code's tools (file editing, code analysis, bash, etc.).

Archived SourceRecently Updated
Coding

ai-dating

This skill enables dating and matchmaking workflows. Use it when a user asks to make friends, find a partner, run matchmaking, or provide dating preferences/profile updates. The skill should execute `dating-cli` commands to complete profile setup, task creation/update, match checking, contact reveal, and review.

Archived SourceRecently Updated
Coding

clawhub-rate-limited-publisher

Queue and publish local skills to ClawHub with a strict 5-per-hour cap using the local clawhub CLI and host scheduler.

Archived SourceRecently Updated