# Full-Stack Feature Development

Complete guide for adding new features to Sketchy from database to UI. Use this when implementing new domain entities or CRUD functionality.

## When to Use This Skill

- Adding a new domain entity (e.g., "appointments", "invoices")
- Creating CRUD functionality for a new resource
- Understanding how all layers connect end-to-end
- Building a new feature that touches database, API, and UI

## The Stack

```
1. Database Layer (lib/db/schema.ts)
   └── Drizzle table + inline RLS policies via pgPolicy()
        │
        v
2. Schema Layer (lib/api/schemas/)
   └── Zod schemas via drizzle-zod (select, insert, update)
        │
        v
3. tRPC Layer (lib/trpc/routers/)
   └── Type-safe API with auth middleware + Sentry tracing
        │
        v
4. Component Layer (components/)
   └── Forms (native FormData), tables, selects (shadcn/ui)
        │
        v
5. Testing Layer (*.stories.tsx)
   └── Stories + .test() + msw-trpc handlers
```

## Quick Checklist

See [adding-entity.md](resources/adding-entity.md) for detailed steps.

### Minimal Feature (Read-Only)

- [ ] Add table to `lib/db/schema.ts` with inline RLS policies
- [ ] Create base schemas in `lib/api/schemas/_base/`
- [ ] Create enhanced schemas in `lib/api/schemas/`
- [ ] Create tRPC router in `lib/trpc/routers/`
- [ ] Register router in `_app.ts`
- [ ] Create component with tRPC hook
- [ ] Add story with msw-trpc handler (object format)

### Full CRUD Feature

All of the above, plus:
- [ ] Create form component (native FormData pattern)
- [ ] Create form drawer component
- [ ] Create table component
- [ ] Add create/update/delete to router
- [ ] Add success/error story scenarios
- [ ] Add integration tests for RLS

## Resource Files

- [adding-entity.md](resources/adding-entity.md) - Step-by-step checklist
- [example-horse.md](resources/example-horse.md) - Complete worked example
- [common-patterns.md](resources/common-patterns.md) - Reusable patterns

## Key Principles

1. **organizationId comes from context** - Never accept it from client input
2. **RLS defined inline** - Use Drizzle's `pgPolicy()` in table definition
3. **Validate at boundaries** - Use Zod schemas in tRPC
4. **Test with msw-trpc** - Type-safe mocking with object handler format
5. **RLS as backup** - Database enforces multi-tenancy even if app code fails
6. **Use shadcn/ui components** - Import from `@/components/ui/`
7. **Forms use native FormData** - Not react-hook-form
