Appearance
Implementing a Full Feature End-to-End
Follow this process to implement a feature across the service, gateway, and frontend layers.
Layer order
Always work bottom-up:
- Database + Service — Schema, migration, business logic
- Gateway — HTTP route + OpenAPI spec
- Frontend — Queries + UI components
Step 1: Service action (if the feature needs new backend logic)
See the /service-action-development skill for the complete guide on:
- Directory structure, IO types, database schemas
- Query/command utilities, action implementation
- Error handling with structured error codes
- Test fixtures and integration tests
Quick summary of the action pattern:
typescript
@action('my-action')
async myAction(input: MyActionInput): Promise<IRPCResponse<MyActionOutput>> {
return this.handleAction(
{ data: input, schema: myActionInputSchema },
{ successMessage: 'Action completed.' },
async (validated) => {
// Drizzle queries + business logic
return result
},
)
}Step 2: Gateway route
In apps/gateway/src/api/v1/:
- Create route file(s) following
[verb]-[resource].tsnaming - Define Zod request/response schemas (gateway owns its own schemas — independent of service types)
- Export inferred types (propagate to SDK automatically)
- Add
authJwt()+access()middleware (see/gateway-route-creationfor scope patterns) - Implement handler delegating to service binding
- Register in
apps/gateway/src/index.ts
See the /gateway-route-creation skill for detailed patterns.
Step 3: Frontend
In apps/frontend/app/:
- Create query definitions in
queries/ - Create page in
pages/ - Create components in
components/ - Create form schemas in
schemas/(if forms are needed) - Add route middleware in
middleware/(if access control needed)
See the /frontend-feature-development skill for detailed patterns.
Step 4: Verify
- Run
bun typecheckto verify types across the monorepo - Run
bun lintto check formatting/linting - Run
bun test:<service>to verify service tests pass (e.g.bun test:order,bun test:auth) - Run
bun test:gwfor all gateway tests (unit + integration, excludes E2E) - Run
bun test:fefor frontend unit tests - Run
bun test:e2efor Playwright E2E tests (optional, runs in a browser)
Checklist
Before considering the feature complete:
- [ ] Service action exists and returns
IRPCResponse<T>(custom services only) - [ ] Input Zod schema defined and validated via
handleAction - [ ] Output types use
InferSelectModelfrom drizzle-orm (not Zod) - [ ] DB schema uses
basemixin from@develit-io/backend-sdk - [ ] Gateway route has full OpenAPI spec with its own Zod schemas
- [ ] Gateway route exports inferred types
- [ ] Gateway route has
authJwt()+access()middleware - [ ] Route registered in
apps/gateway/src/index.ts - [ ] Frontend query uses typed SDK client (
useTxsApi()) - [ ] Frontend types derived from
@devizovaburza/txs-sdk/v1— never defined manually - [ ] Tests cover happy path + error cases
- [ ] No
anyorunknowntypes anywhere - [ ] All imports use
import typewhere applicable - [ ] Files use
kebab-casenaming - [ ] Code passes
bun lintandbun typecheck