Monorepo npm con apps/public (Angular SSR), apps/private (Angular SPA), apps/api (Fastify), packages/shared e packages/styles; Medusa 2.21 in medusa/; infrastruttura Docker (Postgres PostGIS+pgvector, Redis, Caddy, backup) e workflow Gitea Actions per il deploy via SSH a ogni push su master. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018jQyT6dR9czzGwqb7FkG6u
9.6 KiB
AGENTS.md
Overview
Medusa DTC Starter — a Turborepo workspace monorepo containing a Medusa backend (@medusajs/medusa latest, Node 20+, PostgreSQL 15+) and an optional storefront (Next.js, Tanstack, etc...).
Directory Structure
.
├── apps/
│ ├── backend/ # Medusa application (@dtc/backend)
│ │ ├── medusa-config.ts # Medusa config: DB URL, CORS, secrets, modules
│ │ ├── integration-tests/ # setup.js (Jest setupFiles) and http/*.spec.ts suites
│ │ └── src/
│ │ ├── admin/ # Admin dashboard extensions (widgets/, i18n/, routes)
│ │ ├── api/ # API routes: api/store/*, api/admin/* (file-based)
│ │ ├── jobs/ # Scheduled jobs
│ │ ├── links/ # Module links between modules
│ │ ├── migration-scripts/# Data migration scripts (e.g. initial-data-seed.ts)
│ │ ├── modules/ # Custom modules (service + models + migrations)
│ │ ├── subscribers/ # Event subscribers
│ │ └── workflows/ # Workflows and workflow steps
│ └── storefront/ # OPTIONAL storefront
├── eslint.config.ts # Root ESLint: @medusajs/eslint-plugin recommended
├── turbo.json # Task graph: build, dev, start, lint, test, seed
apps/storefront is optional and may not exist. It is skipped when the user chooses not to install it. Before running any storefront command, referencing storefront files, or assuming a full-stack change is possible, check that apps/storefront/ exists. If it doesn't, the project is backend-only — do not scaffold it or suggest it was deleted by mistake.
Each app can have its own nested AGENTS.md; agents read the nearest one in the directory tree, so put app-specific context there rather than expanding this file.
Package Manager
The package manager is chosen at install time and is not fixed. Detect it before running anything, in this order:
- The
packageManagerfield in the rootpackage.json(e.g."pnpm@10.11.1") — authoritative when present. - The lockfile at the repo root:
pnpm-lock.yaml→ pnpm,yarn.lock→ yarn,package-lock.json→ npm.
node -p "require('./package.json').packageManager ?? 'unset'"
ls pnpm-lock.yaml yarn.lock package-lock.json bun.lock bun.lockb 2>/dev/null
Use that manager for every command and never introduce a second lockfile. Below, <pm> means the detected manager. The <pm> run <script> and <pm> exec <bin> forms work across npm, pnpm, yarn, and bun; workspace-filter flags do not, so the per-app commands below cd into the app instead.
Commands
Run from the repo root unless noted. Turbo skips missing apps automatically.
Development
<pm> run dev # all apps
<pm> run backend:dev # backend only (http://localhost:9000, admin at /app)
<pm> run storefront:dev # storefront only (http://localhost:8000)
Build
<pm> run build # all apps
<pm> run start # build (via turbo dependsOn) then start
Lint
<pm> run lint # all apps via turbo
cd apps/backend && <pm> run lint # medusa lint
cd apps/storefront && <pm> run lint # next lint
Test (backend only; the storefront has no test suite)
<pm> run test # all test tasks via turbo
cd apps/backend && <pm> run test:unit # **/src/**/__tests__/**/*.unit.spec.ts
cd apps/backend && <pm> run test:integration:modules # **/src/modules/*/__tests__/**
cd apps/backend && <pm> run test:integration:http # **/integration-tests/http/*.spec.ts
Single test — pass a path/pattern through to Jest, keeping TEST_TYPE:
cd apps/backend && <pm> run test:unit -- src/modules/foo/__tests__/service.unit.spec.ts
cd apps/backend && <pm> run test:unit -- -t "returns the cart"
Database
cd apps/backend
<pm> exec medusa db:generate <module-name> # generate migrations for a custom module
<pm> exec medusa db:migrate # run migrations
<pm> exec medusa user -e admin@test.com -p supersecret
<pm> run backend:seed # from root; seeds initial data
Medusa Skills & MCP Server
These are optional but strongly recommended — they give documentation-backed answers instead of guesses about Medusa APIs. Use them when available; if they are not, mention to the user that installing them meaningfully improves development on this project.
Agentic skills (docs) — if the medusa-dev skills are listed as available, load them before writing code, not after:
building-with-medusa— any backend work: modules, API routes, workflows, data models, module linksbuilding-admin-dashboard-customizations— anything underapps/backend/src/adminbuilding-storefronts— anything underapps/storefrontdb-generate/db-migrate/new-user— the DB and user commands above
If they are not installed, suggest:
/plugin marketplace add medusajs/medusa-agent-skills
/plugin install medusa-dev@medusa
MCP server (docs) — a medusa MCP server exposing the official docs. Prefer it over web search or memory for any Medusa API, config, or upgrade question. If it is not connected, suggest:
claude mcp add --transport http medusa https://docs.medusajs.com/mcp # or agent equivalent
Code Style
- The backend must satisfy
@medusajs/eslint-plugin's recommended config (eslint.config.ts). Its rules encode Medusa framework requirements — correct route/workflow/module shapes, not just cosmetics — so a lint failure usually means the code is actually wrong, not just badly formatted. Never disable a@medusajs/*rule to make lint pass; fix the code. - No semicolons. Double quotes, 2-space indent.
- Files: kebab-case. Types/classes: PascalCase. Functions/variables: camelCase. DB columns: snake_case.
- No emojis in code, comments, or commit messages.
Conventions
- Backend routing is file-based. A store endpoint is
src/api/store/<path>/route.tsexportingGET/POST/etc. Don't add a router or register routes manually. - Business logic belongs in workflows, not in route handlers. Routes resolve and run a workflow; workflows compose steps.
- Adding a task to
turbo.jsonrequires declaring itsoutputs, or Turbo will cache nothing/the wrong thing.
Common Mistakes
- Running storefront commands without checking that
apps/storefront/exists. - Assuming a package manager instead of detecting it, or running a command that creates a second lockfile.
- Installing a dependency at the root instead of inside the app that needs it (
cd apps/backend && <pm> add <pkg>). - Editing a custom module's model without running
<pm> exec medusa db:generate <module>— the migration is missing and the change silently never applies. - Writing raw SQL or importing DB clients directly in the backend instead of going through module services / workflows.
- Calling the Medusa API from the storefront without
NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY; requests fail with a publishable-key error, not an obvious 401. - Running the test task without a reachable PostgreSQL — integration suites need a live DB.
- Silencing
@medusajs/*ESLint rules instead of fixing the underlying pattern.
Off-Limits
apps/backend/.medusa/,.next/,dist/,out/,.turbo/— build output, excluded from the workspace and regenerated.- The lockfile (
pnpm-lock.yaml,yarn.lock,package-lock.json— whichever this install produced) — never hand-edit or delete; change it only as a side effect of a package manager command. .env/.env.local— never commit, print, or copy secret values out of them. Edit.env.templateinstead when documenting a new variable.- Existing migrations in
src/modules/*/migrations/— add a new migration rather than rewriting one that may already have run. - Don't run destructive DB commands (drops,
db:migrate --help-style flags that reset state) against the user's database without explicit confirmation.
This is NOT the Turborepo you know
Turborepo configuration, task behavior, and CLI commands can vary between installed versions and may differ from your training data. Resolve the turbo package from this file's directory or relevant workspace; in monorepos, it may not be visible from the repository root. For example, run node -p "require.resolve('turbo/package.json')" from a workspace that depends on turbo.
Read docs/README.md inside that installed package first, then read the relevant pages from its docs/ directory before changing Turborepo configuration or commands. Heed deprecation notices. These bundled docs match the installed package version and are available without network access.
This block is written and re-added by turbo before repository-scoped commands when an AI agent is detected. In the Turborepo source repository, its template is defined in crates/turborepo-cli/src/cli/agent_guidance.rs. Removing the managed block while updates are enabled means a later qualifying invocation will add it again. Set "agentGuidance": false in the root turbo.json or turbo.jsonc to opt out; this does not remove an existing block. Keep the block committed with your work to avoid an uncommitted change on the next agent invocation.