4.4 KiB
Codebase Improvements Design
Date: 2026-04--03 Scope: General code quality, error handling, resilience, and maintainability improvements
1. Server Hardening
1a. Explicit DB Context Middleware
File: src/server/index.ts
Add middleware that explicitly sets c.set("db", prodDb) for all API routes. Currently routes call c.get("db") but nothing sets it in production — services silently fall back to prodDb via default parameters. This makes production behavior match the test pattern.
import { db as prodDb } from "../db/index.ts";
app.use("/api/*", async (c, next) => {
c.set("db", prodDb);
return next();
});
Place this before the auth middleware so db is available when auth checks run.
1b. Route Parameter Validation
New file: src/server/lib/params.ts
Create a helper that validates numeric route params:
export function parseId(raw: string): number | null {
const id = Number(raw);
if (!Number.isInteger(id) || id <= 0) return null;
return id;
}
Update all route files (items.ts, threads.ts, categories.ts, setups.ts) to replace Number(c.req.param("id")) with parseId(), returning 400 for invalid IDs.
1c. Centralized Error Handling
File: src/server/index.ts
Add Hono's onError handler:
app.onError((err, c) => {
console.error(`[${c.req.method}] ${c.req.path}:`, err);
const status = err instanceof HTTPException ? err.status : 500;
const message = process.env.NODE_ENV === "production"
? "Internal server error"
: err.message;
return c.json({ error: message }, status);
});
1d. Auth Comment Fix
File: src/server/index.ts
Change comment from:
// Auth middleware for write operations (POST/PUT/DELETE) on non-auth routes
To:
// Auth middleware for write operations (POST/PUT/PATCH/DELETE) on non-auth routes
1e. Rate Limiting on Auth Endpoints
New file: src/server/middleware/rateLimit.ts
In-memory rate limiter using a Map<string, { count: number; resetAt: number }>:
- Tracks by IP (
c.req.header("x-forwarded-for") || "unknown") - 5 attempts per 15-minute window
- Returns 429 with
{ error: "Too many attempts. Try again later." }andRetry-Afterheader - Stale entries cleaned on each check
- Applied to
POST /api/auth/loginandPOST /api/auth/setup
2. Client Resilience
Error Boundary
File: src/client/routes/__root.tsx
Add errorComponent to the root route definition:
export const Route = createRootRoute({
component: RootLayout,
errorComponent: RootErrorBoundary,
});
RootErrorBoundary renders a centered error message with:
- "Something went wrong" heading
- Error message in dev mode
- "Try again" button that calls
router.invalidate()+reset()
Uses TanStack Router's ErrorComponentProps which provides error and reset.
3. Client Refactor
Split collection/index.tsx
Extract the three tab-level functions into separate component files:
| Source function | New file | Approx lines |
|---|---|---|
CollectionView() |
src/client/components/CollectionView.tsx |
~260 |
PlanningView() |
src/client/components/PlanningView.tsx |
~190 |
SetupsView() |
src/client/components/SetupsView.tsx |
~110 |
collection/index.tsx keeps:
- Route definition with
searchSchemaandvalidateSearch CollectionPagefunction (tab switcher + AnimatePresence)TAB_ORDERandslideVariantsconstants- Imports from the three new component files
Each extracted component is a named export, self-contained with its own hooks and local state.
4. Docs Cleanup
PROJECT.md
File: .planning/PROJECT.md
Update Constraints section line:
- **Scope**: No auth, single user for v1
To:
- **Scope**: Single user with cookie/API key auth
Commit Strategy
Group into 3-4 commits by area:
- Server hardening: DB middleware, param validation, error handler, rate limiter, comment fix
- Client resilience + refactor: Error boundary, split collection route
- Docs cleanup: PROJECT.md update
Testing
- All 183 existing tests must continue to pass
- Rate limiter: manual verification (no automated test needed for in-memory rate limiting in a single-user app)
- Error boundary: manual verification by triggering a render error
- Param validation: existing route tests cover happy paths; invalid IDs are a new edge case but won't break existing tests