Skip to content

Backend Migration Audit: Next.js → Workers

Status (2026): Migration completeapps/web is a Vite React SPA; apps/worker is 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 in lib/db/schema.ts, types/database/.
  • Services model: Factory in lib/services/init/, getService() / getServices() in lib/services/init/get.ts. New feature = new service class + optional Zod schemas in lib/services/zod/.
  • Auth: JWT + cookies, auth/verify for protected routes, RBAC helpers (requireRole, requireDepartmentAccess).
  • Response: ApiResponse and consistent code / success / data|error shape.
  • OpenAPI: Routes defined with createRoute from @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 statusNotes
auth/login✅ Doneroutes/auth/login.ts
auth/logout✅ Doneroutes/auth/logout.ts
auth/register/{employee,hod,technician}✅ DoneUnified routes/auth/register.ts
auth/password/change✅ Doneroutes/auth/change-password.ts
auth/account/verify❌ Not migratedNo /auth/verify or /auth/refresh route (logic exists in auth/verify for internal use)
auth/2fa/* (backup, verify, generate)❌ Not migrated3 route files
auth/secureaction/* (route, verify, backup, session)❌ Not migrated4 route files
auth/password/forget, auth/password/reset❌ Not migrated2 route files
auth/analytics❌ Not migrated1 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 statusNotes
me/route (GET current user)✅ Doneroutes/me/index.ts
me/settings✅ Doneroutes/me/settings.ts (get + update)
me/security✅ Doneroutes/me/security.ts (get + update)
me/profile (update)✅ Doneroutes/me/profile.ts
me/avatar, me/avatar/[filename]✅ Doneroutes/me/avatar.ts (upload, get, delete)
me/session✅ Doneroutes/me/session.ts (get session info)
me/session/revoke/[id], me/session/revoke/all❌ Not migrated2 route files
me/session/[id]❌ Not migrated1
me/change/email, me/change/email/verify❌ Not migrated2
me/stats❌ Not migrated1
me/notifications, me/notifications/[id], read/[id], read/all❌ Not migrated4
me/security/login-logs, login-logs/[id], regenerate-backup-codes❌ Not migrated3

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 statusNotes
maintenance/route (list, create)✅ Donelist.ts, create.ts
maintenance/[id]/route (get, update)✅ Doneget.ts, update.ts
maintenance/[id]/approve, assign, status, complete✅ DoneRespective route files
maintenance/attachment/[filename]❌ Not migratedServe attachment (Phase 6: R2)
upload/attachment❌ Not migratedUpload 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 statusNotes
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-verificationPhase 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 statusNotes
system/settings/route, type/[type], id/[id]SystemService exists, no routes
system/settings/departments
system/seedDev-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 statusNotes
dashboard/employee, dashboard/hod, dashboard/technicianAggregation; Phase 5 or 6
analytics/hodCache analytics exists (cache/analytics.ts); need route

Count: 4 route files. Can share cache/analytics and DB queries; medium effort.


2.7 Other

Next.jsWorkers statusNotes
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/route1 file; list departments
upload/avatarCovered by me/avatar
test/route, admin/fix-department-relationshipsDev/admin; skip or optional

3. Overall Backend Migration Completion

DomainNext.js route filesMigrated (approx.)% (by route files)
Auth17~4 groups (5 files)~29%
Me20~11 files equivalent~55%
Maintenance8~7 (no attachments yet)~85%
Users14~14~100%
System600%
Dashboard + Analytics400%
Other (status, ipLogger, departments, etc.)91–2~15%
Total78~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. UserService or 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).


  1. Phase 4 (current): Finish validation, deployment, and service-injection cleanup. No new migration scope.
  2. 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/verify or /auth/refresh (if frontend needs it), then password forget/reset, then 2FA/secureaction if required.
  3. Phase 6: Attachments (R2), notifications (email), dashboard/analytics routes.
  4. 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)

AreaStatusNotes
Non-maintenanceDoneAuth (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.
MaintenanceDeferredFull 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.json should 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.