Skip to Content
Front door: index.ts

Front door: index.ts

Path: hono-backend/src/index.ts

This is the first file that runs when the Node process starts (after TypeScript compiles).

What it does in order

  1. import 'dotenv/config' — load .env into process.env.
  2. Create app = new Hono<HonoEnv>() — empty web application with typed context.
  3. CORS middleware — which browser origins may call us (vite dev ports + ALLOWED_ORIGIN + chrome-extension://*). credentials: true and X-Request-Id / RateLimit-* / Retry-After are added to exposeHeaders.
  4. requestIdMiddleware — assign or honor X-Request-Id for correlated logs.
  5. rateLimitMiddleware — dynamic quota check; fails open if the limiter itself errors.
  6. GET /health — liveness probe ({ status: 'ok' }).
  7. GET /ready — readiness probe; returns 503 until mongoose.connection.readyState === 1, then { status: 'ready', db: 'connected', requestId }.
  8. app.route(...) — attach each router at a URL prefix (see Route map).
  9. app.onError — last-resort error handler:
    • ZodError400 { error, code: 'VALIDATION_ERROR', requestId, details[] } (paths formatted with lib/format-zod-issue-path.ts).
    • any other error → 500 { error, code: 'INTERNAL_ERROR', requestId } and a structured logServerError(...) call.
  10. connectDB() then serve({ port: env.PORT }) — Mongo first, HTTP second.

Code idea (simplified)

const app = new Hono<HonoEnv>() app.use('*', cors({ /* origins + expose headers */ })) app.use('*', requestIdMiddleware) app.use('*', rateLimitMiddleware) app.get('/health', (c) => c.json({ status: 'ok' })) app.get('/ready', (c) => readyOr503(c)) app.route('/api/v1/auth', authRouter) // ... more routes ... app.onError((err, c) => zodOr500(err, c)) connectDB().then(() => serve({ fetch: app.fetch, port: env.PORT }))

Who imports what

Import groupFiles
Configconfig/env.js, config/db.js
Middlewaremiddleware/request-id.middleware.js, middleware/rate-limit.middleware.js
Liblib/format-zod-issue-path.js, lib/logger.js
Typestypes/index.js (HonoEnv)
Routesroutes/auth.route.js, routes/user.route.js, routes/admin.route.js, routes/admin-rate-limits.routes.js, routes/timestamps.route.js, routes/practice-pyq-public.routes.js, routes/current-affairs-public.routes.js, routes/notification.route.js (× 3 routers)

Nothing in index.ts should contain business logic — only wiring.

If you add a new feature area

  1. Create routes/my-feature.route.ts exporting a Hono<HonoEnv> router.
  2. Import it in index.ts.
  3. app.route('/api/v1/my-feature', myFeatureRouter).
  4. Document the prefix in Route map.
  5. If the surface is admin-only, also call requirePermission(...) per-route so the right role can see it.

Read the real file in the repo — it has a long comment block at the top explaining the same story.

Last updated on