blob: 5f3f3f5b6ea5a16bd2bc289be4bd3ea91e285e74 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
# Kioku
Spaced repetition learning app (Anki clone). Full-stack TypeScript with Hono backend, React frontend, PostgreSQL database, and offline-first PWA support.
## Quick Reference
```bash
pnpm install # Install dependencies
pnpm dev # Start backend server (hot reload)
pnpm dev:client # Start frontend dev server (port 5173)
pnpm build # Build both server and client
pnpm test # Run tests (Vitest)
pnpm typecheck # TypeScript type checking
pnpm lint # Lint with Biome
pnpm lint:fix # Auto-fix lint issues
pnpm format # Format with Biome
pnpm db:generate # Generate database migrations
pnpm db:migrate # Run database migrations
pnpm db:push # Push schema changes to DB
```
## Architecture
- **Backend**: Hono on Node.js 22 (built with esbuild) — `src/server/`
- **Frontend**: React 19 + Vite — `src/client/`
- **Shared**: Common utilities — `src/shared/`
- **Database**: PostgreSQL with Drizzle ORM — schema in `src/server/db/`
- **Migrations**: SQL files in `drizzle/`
### Backend Structure (`src/server/`)
Repository pattern with dependency injection. Routes → Services → Repositories → Drizzle ORM.
- `routes/` — API endpoint handlers
- `repositories/` — Data access layer
- `middleware/` — Auth, CORS, error handling, rate limiting
- `schemas/` — Zod validation schemas
- `services/` — Business logic
- `types/` — TypeScript interfaces (includes repository interfaces)
- `db/schema.ts` — Drizzle database schema
### Frontend Structure (`src/client/`)
- `pages/` — Route-level page components
- `components/` — Reusable React components
- `atoms/` — Jotai state management atoms
- `api/` — API client
- `db/` — Dexie.js IndexedDB schema (offline storage)
- `sync/` — Sync engine (client ↔ server)
- `utils/` — Utilities (CSV parser, template renderer)
### Key Libraries
- **State**: Jotai (atoms suffixed with `Atom`)
- **Routing**: Wouter
- **Styling**: Tailwind CSS v4
- **Sync**: Automerge CRDT for conflict-free offline sync
- **Scheduling**: ts-fsrs (spaced repetition algorithm)
- **Validation**: Zod
## Code Style
- **Formatter/Linter**: Biome (run `pnpm lint` to check, `pnpm lint:fix` to auto-fix)
- **Indentation**: Tabs
- **Quotes**: Double quotes for JS/TS
- **Imports**: Organized by Biome (auto-sorted)
- **Naming**: PascalCase for components/types, camelCase for functions/variables, atoms suffixed with `Atom`
- **Tests**: Co-located with source files (`*.test.ts`, `*.test.tsx`)
## Database Conventions
- Soft deletes via `deletedAt` timestamp
- Sync versioning via `syncVersion` field
- All tables have `createdAt` and `updatedAt` timestamps with timezone
## Testing
Vitest with `@testing-library/react` for component tests. Tests run with:
```bash
pnpm test # Single run
pnpm test:watch # Watch mode
```
Test environment uses `JWT_SECRET=test-secret-key` and mock factories for test data. IndexedDB is mocked with `fake-indexeddb`.
## CI Pipeline
Lint → Typecheck → Test → Build (see `.github/workflows/ci.yaml`)
|