scaffold-standards
GitHub定义后端或全栈领域、路由及CRUD功能的标准化骨架结构。涵盖Node/TS与Python/FastAPI的文件布局、命名规范及错误处理机制,确保代码一致性,适用于新建模块前的初始化阶段。
Trigger Scenarios
Install
npx skills add AjayIrkal23/agentic-mercy-10x --skill scaffold-standards -g -y
SKILL.md
Frontmatter
{
"name": "scaffold-standards",
"schema": 1,
"category": "backend",
"surfaces": [
"backend"
],
"triggers": {
"paths": [
"\/router\/",
"\/routes\/",
"route.ts",
"route.tsx",
"routes.ts"
],
"intents": [
"backend"
],
"keywords": [
"backend",
"crud",
"domain",
"entry",
"feature",
"file",
"frontend",
"full-stack",
"implementation",
"list",
"minimum",
"plan",
"planning",
"points",
"route\/controller\/service\/schema",
"scaffold",
"scaffolding",
"skeleton",
"skeletons",
"standard",
"standards",
"structure",
"tree"
]
},
"platforms": [
"linux",
"darwin",
"windows"
],
"token-cost": 1908,
"description": "ALWAYS invoke when scaffolding a new backend or full-stack domain, a route\/controller\/service\/schema skeleton, or a standard list and CRUD feature structure.",
"disable-model-invocation": false
}
Scaffold Standards
Overview
This skill defines the standard skeleton for new domains and features.
Use it when consistency of file layout, naming, and build order matters more than one-off speed.
Use When
- Creating a new backend domain.
- Adding a new route/controller/service/schema flow.
- Scaffolding a new full-stack CRUD or list feature.
- Defining the minimum skeleton before implementation starts.
Backend Skeleton
Pick the block matching the repo's actual stack — confirmed against 3 reference codebases (site-sync-vista = Fastify/TS, MARKETING REPORT AUTOMATION = FastAPI/Python, GO_UDP/UDP_PLATFORM = Go/chi). Don't force one stack's file-naming onto another.
Node/TypeScript (Fastify/Express style)
/routes/{domain}.routes.ts
/controller/{domain}/{verb}-{domain}.controller.ts
/schemas/{domain}/{verb}-{domain}.schema.ts
/schemas/{domain}/{domain}-response.schema.ts
/models/{domain}.model.ts
/models/schema/{shared-subschema}.schema.ts
/services/{domain}/{verb}{Domain}.ts
/utils/{domain}/{helper}.ts
/types/{domain}/{name}.ts
- Controller folder is singular
controller/in some repos, pluralcontrollers/in others — check the existing repo before scaffolding, don't assume. - Controller and schema files are kebab-case, verb-first:
create-camera-type.controller.ts,list-expenses.schema.ts. - Service files are either bare verb+noun (
createCameraType.ts) or explicitly suffixed (createProjectMapFeature.service.ts) — match the existing repo's convention within that domain, don't mix both inside one domain folder. - Model files are kebab-case, one per collection (
{resource}.model.ts); shared embedded sub-schemas live inmodels/schema/. - Centralize errors in one
utils/errors.ts(AppErrorclass +isAppError()guard) consumed by a single app-levelsetErrorHandler— not per-route try/catch. - If no real queue library is wired (check for actual consumers, not just an installed dependency), background jobs are polling loops under
/jobs/{job-name}.job.tsguarded by a DB-backed distributed lock (acquireLock/releaseLock), not BullMQ workers.
Python (FastAPI)
/app/routes/{domain}.py # APIRouter, registered into routes/__init__.py's api_router
/app/controllers/{domain}.py # thin handlers: {verb}_{domain}_controller
/app/controllers/{domain}_{variant}.py # config/admin variants get a suffixed sibling file, not a subfolder
/app/schemas/{domain}.py # pydantic request/query DTOs + Literal[...] sort/filter whitelists
/app/schemas/{domain}_record.py # response ("Public") DTO, kept separate from the request DTO
/app/models/{domain}.py # Beanie/ORM Document
/app/services/{domain}/{verb}.py # one file per verb: list.py, create.py, update.py, delete.py, export.py
/app/services/cron/{domain}.py # thin scheduled-job entrypoint only; real logic stays in services/{domain}/
/app/utils/{domain}/{helper}.py
/app/core/{errors,responses,exception_handlers,scheduler}.py # cross-cutting infra, not per-domain
- One file per domain per layer (not one-file-per-action) — the folder name (
routes/,controllers/,schemas/) already disambiguates the layer, so files are just{domain}.py, snake_case. - Compound/config domains get a suffixed sibling file (
credit_report_config.py), not a nested subfolder. - Response DTOs suffixed
Public; query/sort DTOs suffixedQuery/SortBy. - Centralized error taxonomy:
core/errors.py(AppErrorbase withstatus_code/code, subclassed per error kind) +core/exception_handlers.pymapping to the shared envelope incore/responses.py. - Scheduling (APScheduler) lives in
core/scheduler.pyas a start/shutdown-managed singleton with string job-id constants — no top-leveljobs//workers/folder;services/cron/{domain}.pyis a thin entrypoint that delegates to the domain's ownservices/{domain}/poller.py/ingest.py.
Go (chi or similar router)
/internal/routes/{domain}/register.go # func Register(router chi.Router, service ...)
/internal/controllers/{domain}/{verb}.controller.go
/internal/controllers/{domain}/service_interfaces.go # controller-owned, narrow interface onto the service
/internal/services/{domain}/{verb}.service.go
/internal/services/{domain}/store.go # persistence — distinguished from business logic by filename, not folder
/internal/schemas/{domain}/{verb}.schema.go # wire-level request/response structs
/internal/types/{domain}/{verb}_params.go # internal params passed controller -> service
/internal/models/{resource}.go # DB-facing struct (GORM/etc.)
- Package name = folder name, all-lowercase-no-separator (
locoeventpacket,superadmin) — applied consistently across every layer folder for the same domain. - Three-tier data-shape split:
schemas(wire-level request/response) ->types(internal params) ->models(persistence) — don't collapse these into one struct. - One
routes/{domain}/register.goper domain exposing a singleRegister(router chi.Router, ...); a top-levelroutes/routes.goaggregates every domain'sRegistercall under auth-scopedrouter.Groupblocks. - Centralized error/envelope contracts live in
internal/contracts/(errors.go->DomainError+NormalizeError;envelope.go->SuccessResponse/ErrorResponse+WriteSuccess/WriteJSON) — not redefined per domain. - Tests are standard
_test.go, colocated in the same package as the code under test — never a paralleltests/tree. - A protocol-specific ingestion/listener layer (UDP/TCP/etc.), if the service has one, stays fully separate from the
controllers/services/routesHTTP layers, organized by pipeline stage (decode -> process -> sink), and is wired frominternal/app/, not from any domain'sroutes/.
Keep reusable backend types in the stack's types layer (/types/{domain}/{name}.ts, app/schemas/{domain}.py, or internal/types/{domain}/*.go) instead of declaring them inline inside config, routes, controllers, services, or queue modules.
If the repo already uses controller-mirror feature folders, scaffold into that feature-folder pattern instead of forcing flat per-action service files.
Use the query helper and mapper files when the domain needs list/query logic or DTO conversion.
Standard Action Set
Where applicable:
listgetByIdcreateupdatedelete
Contract Expectations
- Success responses follow the standard envelope.
- List features use paginated backend-driven query behavior.
- Errors follow the shared error envelope.
Suggested Build Order
- Lock the contract.
- Add schema.
- Add service.
- Add controller and route.
- Add helpers or mappers if needed.
- Add frontend integration if the feature is full-stack.
Naming Rules
- TypeScript/Node: folders kebab-case, identifiers camelCase/PascalCase, controller/schema files verb-first kebab-case.
- Python: folders and files snake_case, one file per domain per layer.
- Go: package/folder names lowercase-no-separator (no underscore or hyphen); files snake_case with a
.controller.go/.service.go/.schema.gosuffix. - Whichever stack: keep route/controller/service naming aligned across the stack (same domain name in every layer).
Combine With
api-contract-standardsfor envelope and compatibility rules.service-layer-standardsfor boundary discipline.backend-api-standardsfor list/query semantics.
References
- Use
references/full-guide.mdfor the longer strict version with full-stack scaffolding details and extended examples.
Version History
- 581d130 Current 2026-07-19 09:14


