Backend Migration Audit: Next.js → Workers
Status (2026): Migration complete —
apps/webis a Vite React SPA;apps/workeris the Hono API. This document is retained as a historical audit trail.
Original goal: Migrate from Next.js to Workers backend (Hono API) + Pages frontend (React SPA).
Source: apps/web/src/app/api/ — 78 route files
Target: apps/worker/src/routes/ + services in apps/worker/src/lib/services/
1. What’s Already in Place (“The Rails”)
These are stable and reused for every new route:
- Centralized cache: Durable Objects +
lib/services/cache/(auth, session, user, maintenance, analytics, id). Micro caches (e.g.cache.user,cache.session) follow the same pattern; new domains add a new cache module and export. - DB: Drizzle + Neon in
lib/db/; schema and types inlib/db/schema.ts,types/database/. - Services model: Factory in
lib/services/init/,getService()/getServices()inlib/services/init/get.ts. New feature = new service class + optional Zod schemas inlib/services/zod/. - Auth: JWT + cookies,
auth/verifyfor protected routes, RBAC helpers (requireRole,requireDepartmentAccess). - Response:
ApiResponseand consistentcode/success/data|errorshape. - OpenAPI: Routes defined with
createRoutefrom@hono/zod-openapi; spec at/docs/openapi.json.
Implication: New routes do not re‑invent cache/DB/auth. They add a route file, call existing (or new) services, and follow the same patterns. Effort per route is lower than the first wave (auth + maintenance).
2. Completion by Domain
2.1 Auth (/auth) — ~35% of Next.js auth surface migrated
| Next.js route file(s) | Workers status | Notes |
|---|---|---|
auth/login | ✅ Done | routes/auth/login.ts |
auth/logout | ✅ Done | routes/auth/logout.ts |
auth/register/{employee,hod,technician} | ✅ Done | Unified routes/auth/register.ts |
auth/password/change | ✅ Done | routes/auth/change-password.ts |
auth/account/verify | ❌ Not migrated | No /auth/verify or /auth/refresh route (logic exists in auth/verify for internal use) |
auth/2fa/* (backup, verify, generate) | ❌ Not migrated | 3 route files |
auth/secureaction/* (route, verify, backup, session) | ❌ Not migrated | 4 route files |
auth/password/forget, auth/password/reset | ❌ Not migrated | 2 route files |
auth/analytics | ❌ Not migrated | 1 route file |
Count: ~4 route groups done, ~10 route files not migrated. Must-have for MVP: login, logout, register, change-password ✅. Nice-to-have: verify/refresh, 2FA, secureaction, forget/reset, auth analytics.
2.2 Me (/me) — ~55% migrated
| Next.js route file(s) | Workers status | Notes |
|---|---|---|
me/route (GET current user) | ✅ Done | routes/me/index.ts |
me/settings | ✅ Done | routes/me/settings.ts (get + update) |
me/security | ✅ Done | routes/me/security.ts (get + update) |
me/profile (update) | ✅ Done | routes/me/profile.ts |
me/avatar, me/avatar/[filename] | ✅ Done | routes/me/avatar.ts (upload, get, delete) |
me/session | ✅ Done | routes/me/session.ts (get session info) |
me/session/revoke/[id], me/session/revoke/all | ❌ Not migrated | 2 route files |
me/session/[id] | ❌ Not migrated | 1 |
me/change/email, me/change/email/verify | ❌ Not migrated | 2 |
me/stats | ❌ Not migrated | 1 |
me/notifications, me/notifications/[id], read/[id], read/all | ❌ Not migrated | 4 |
me/security/login-logs, login-logs/[id], regenerate-backup-codes | ❌ Not migrated | 3 |
Count: Core me (identity, settings, security, profile, avatar, session info) done. Missing: session revoke, change email, stats, notifications, security login-logs/backup-codes.
2.3 Maintenance (/maintenance) — ~85% migrated
| Next.js route file(s) | Workers status | Notes |
|---|---|---|
maintenance/route (list, create) | ✅ Done | list.ts, create.ts |
maintenance/[id]/route (get, update) | ✅ Done | get.ts, update.ts |
maintenance/[id]/approve, assign, status, complete | ✅ Done | Respective route files |
maintenance/attachment/[filename] | ❌ Not migrated | Serve attachment (Phase 6: R2) |
upload/attachment | ❌ Not migrated | Upload attachment (Phase 6) |
Count: Core CRUD + workflow done. Missing: attachment upload + serve (R2; already in Phase 6).
2.4 Users (/users) — 100% migrated ✅
| Next.js route file(s) | Workers status | Notes |
|---|---|---|
users/route (list) | ❌ | Phase 5 |
users/[id]/route (get, update, delete) | ❌ | Phase 5 |
users/hod, users/employee, users/technician (list by role) | ❌ | Phase 5 |
users/hod/[id], employee/[id], technician/[id] | ❌ | Phase 5 |
users/[id]/status, suspend, manage, sessions, maintenance, reset-verification | ❌ | Phase 5 |
Count: 14 route files. No Workers routes mounted; Phase 5: User Management Service. Uses same DB, cache (user cache exists), auth (requireRole admin). Effort: same pattern as maintenance (queries, mutations, permissions, Zod), no new infra.
2.5 System (/system) — 0% migrated (service exists)
| Next.js route file(s) | Workers status | Notes |
|---|---|---|
system/settings/route, type/[type], id/[id] | ❌ | SystemService exists, no routes |
system/settings/departments | ❌ | |
system/seed | ❌ | Dev-only; optional |
Count: 5–6 route files. Phase 5: System Endpoints. Service already has getHealth(); add Hono routes that call existing (or extended) SystemService. Low effort.
2.6 Dashboard & Analytics — 0% migrated
| Next.js route file(s) | Workers status | Notes |
|---|---|---|
dashboard/employee, dashboard/hod, dashboard/technician | ❌ | Aggregation; Phase 5 or 6 |
analytics/hod | ❌ | Cache analytics exists (cache/analytics.ts); need route |
Count: 4 route files. Can share cache/analytics and DB queries; medium effort.
2.7 Other
| Next.js | Workers status | Notes |
|---|---|---|
status/route, status/system, status/api, status/auth | ⚠️ Partial | /health exists; no /status/system, /status/api, /status/auth |
ipLogger/* | ❌ | 3 files; optional for MVP |
departments/route | ❌ | 1 file; list departments |
upload/avatar | ✅ | Covered by me/avatar |
test/route, admin/fix-department-relationships | ❌ | Dev/admin; skip or optional |
3. Overall Backend Migration Completion
| Domain | Next.js route files | Migrated (approx.) | % (by route files) |
|---|---|---|---|
| Auth | 17 | ~4 groups (5 files) | ~29% |
| Me | 20 | ~11 files equivalent | ~55% |
| Maintenance | 8 | ~7 (no attachments yet) | ~85% |
| Users | 14 | ~14 | ~100% |
| System | 6 | 0 | 0% |
| Dashboard + Analytics | 4 | 0 | 0% |
| Other (status, ipLogger, departments, etc.) | 9 | 1–2 | ~15% |
| Total | 78 | ~40–42 | ~52% |
By “must-have” for MVP (auth + me + maintenance + users + system settings):
- Done: auth core, me core, maintenance core, users (all).
- Not done: system routes, me gaps (session revoke, notifications, change email), attachments.
Rough MVP backend completion: ~65%. Full backend (all 78): ~52%.
4. Effort Assessment: Same or Easier?
- Rails are stable: Cache, DB, services, auth, response shape, OpenAPI pattern are in place. New routes reuse them.
- User management (Phase 5): Same pattern as maintenance: service (e.g.
UserServiceor extend existing), queries/mutations, permissions, Zod, route file. Roughly same effort per endpoint as maintenance, but no new infra. - System routes: Service exists; add thin route layer. Lower effort than maintenance.
- Me gaps (session revoke, notifications, change email, stats): Small additions to existing me routes or new small route files; cache/DB already there. Lower effort.
- Auth gaps (verify/refresh, 2FA, secureaction, forget/reset): More logic (email, tokens, 2FA). Same or slightly higher effort per route than simple CRUD.
- Attachments (Phase 6): R2 + signed URLs; new storage service. Medium effort, defined in Phase 6.
- Dashboard/Analytics: Reuse cache/analytics and DB. Medium effort.
Conclusion: A large share of the remaining work is repeating established patterns (users, system, me gaps). The hard part (cache, DB, auth, service model, maintenance workflow) is done. Remaining is not the same total effort as Phases 1–3; it’s pattern application plus a few new areas (attachments, optional 2FA/secureaction).
5. Recommended Focus for Completion
- Phase 4 (current): Finish validation, deployment, and service-injection cleanup. No new migration scope.
- Phase 5 — Backend migration (priority):
- Users: Full user CRUD + list by role + status/suspend/manage/sessions/maintenance/reset-verification (mirror Next.js).
- System: Mount system routes (settings CRUD, departments); optionally status/system, status/api, status/auth.
- Me gaps: Session revoke (by id, all), change email ( + verify), notifications (list, read, read all), optional stats and security login-logs/backup-codes.
- Auth gaps (optional for MVP):
/auth/verifyor/auth/refresh(if frontend needs it), then password forget/reset, then 2FA/secureaction if required.
- Phase 6: Attachments (R2), notifications (email), dashboard/analytics routes.
- Frontend: Once backend is complete enough for the current app, switch frontend to React SPA and point to Workers API; slug handling on Pages is a frontend/routing concern.
This audit should be updated as routes are migrated (e.g. mark “Users” and “System” rows when done).
6. Backend Test Status (Unit Tests)
| Area | Status | Notes |
|---|---|---|
| Non-maintenance | Done | Auth (login, logout, register, profile), cache (DO ops, instances, session, usage), storage, avatar, attachment (unavailable + key helpers), JWT, cookies, mailer, internal logger, system. Setup uses real init (createServicesForEnv), Env-shaped mock, full InitializedServices, CF-typed mock DO. |
| Maintenance | Deferred | Full maintenance tests will be added when maintenance microservices (queries, mutations, permissions, validation) are stabilized and corrected. Maintenance test files exist but have type/API mismatches; not blocking current phase. |
Implication: All existing system parts except maintenance are covered by unit tests. Maintenance is the only remaining area for full test coverage once its services are ready.
7. OpenAPI Schema Quality (Strict Rule from Phase 5)
Requirement: Every API endpoint must have a rich OpenAPI schema.
- What “rich” means: Full request and response body schemas (not placeholders), clear operation and parameter descriptions, examples where they help, and accurate status codes (200, 400, 401, 403, 404, 500, etc.). The spec at
/docs/openapi.jsonshould be the single source of truth for API contracts and for tooling (client generation, docs, Postman). - Current state: Many routes (especially early auth and maintenance) already have strong schemas. Some newer or added routes do not yet match that level and should be brought up to the same standard.
- Phase 5 and beyond: (1) Audit — Identify any existing route with weak or minimal schema and fix it. (2) Strict rule for new routes — As new routes are added (users, system, me gaps, etc.), each must be implemented with a rich OpenAPI schema from the start. No shipping new endpoints with thin or placeholder schemas.
- Reminder: When adding or touching routes in any phase, always ensure the OpenAPI schema for that endpoint is rich and consistent with the rest of the API. This keeps the spec reliable for consumers and tooling over time.