{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "hono-api",
  "type": "registry:base",
  "title": "tneemo/hono-api",
  "description": "TypeScript REST API starter for Node with Hono: validated env, JSON errors, security headers, health check and vitest.",
  "author": "tneemo",
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": ".env.example",
      "type": "registry:file",
      "target": "~/.env.example",
      "content": "# Port the HTTP server listens on\nPORT=3000\n"
    },
    {
      "path": ".gitignore",
      "type": "registry:file",
      "target": "~/.gitignore",
      "content": "node_modules/\ndata/\ndist/\n.env\n"
    },
    {
      "path": "AGENTS.md",
      "type": "registry:file",
      "target": "~/AGENTS.md",
      "content": "# Conventions\n\n- The Hono app is assembled in `src/app.ts` (`createApp`). Mount feature routers there: `app.route(\"/todos\", todoRoutes)`.\n- Put each feature in its own folder under `src/` (for example `src/todos/routes.ts`) exporting a `new Hono()` router.\n- Validate request bodies with zod: `schema.parse(await c.req.json())`. Validation errors become 400 responses automatically.\n- Throw `HTTPException` from `hono/http-exception` for expected errors (404, 409, ...). Responses are JSON: `{ \"error\": \"...\" }`.\n- Declare environment variables in `src/env.ts`; document them in `.env.example`.\n- Tests live in `test/` and use `app.request(path, init)`, no running server needed. Run `npm test`.\n- Builds installed with pkg are listed in `pkg.lock.json`. Look for existing ones before writing a common feature: `npx -y @tneemo/pkg search \"<need>\"`.\n"
    },
    {
      "path": "package.json",
      "type": "registry:file",
      "target": "~/package.json",
      "content": "{\n  \"name\": \"hono-api\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"engines\": {\n    \"node\": \">=22.12\"\n  },\n  \"scripts\": {\n    \"dev\": \"tsx watch src/index.ts\",\n    \"start\": \"tsx src/index.ts\",\n    \"test\": \"vitest run\",\n    \"typecheck\": \"tsc --noEmit\"\n  },\n  \"dependencies\": {\n    \"@hono/node-server\": \"^2.1.0\",\n    \"hono\": \"^4.13.0\",\n    \"zod\": \"^4.0.0\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^24.0.0\",\n    \"tsx\": \"^4.20.0\",\n    \"typescript\": \"^5.9.0\",\n    \"vitest\": \"^5.0.0\"\n  }\n}\n"
    },
    {
      "path": "src/app.ts",
      "type": "registry:file",
      "target": "~/src/app.ts",
      "content": "import { Hono } from \"hono\";\nimport { HTTPException } from \"hono/http-exception\";\nimport { logger } from \"hono/logger\";\nimport { secureHeaders } from \"hono/secure-headers\";\nimport { ZodError } from \"zod\";\nimport { env } from \"./env\";\n\nexport function createApp() {\n  const app = new Hono();\n\n  if (env.NODE_ENV !== \"test\") app.use(logger());\n  app.use(secureHeaders());\n\n  app.get(\"/health\", (c) => c.json({ status: \"ok\" }));\n\n  // Mount feature routers here, e.g. app.route(\"/todos\", todoRoutes);\n\n  app.notFound((c) => c.json({ error: \"Not found\" }, 404));\n  app.onError((err, c) => {\n    if (err instanceof HTTPException) return err.res ?? c.json({ error: err.message }, err.status);\n    if (err instanceof ZodError) return c.json({ error: \"Invalid request\", issues: err.issues }, 400);\n    if (err instanceof SyntaxError) return c.json({ error: \"Invalid JSON body\" }, 400);\n    console.error(err);\n    return c.json({ error: \"Internal server error\" }, 500);\n  });\n\n  return app;\n}\n\nexport const app = createApp();\n"
    },
    {
      "path": "src/env.ts",
      "type": "registry:file",
      "target": "~/src/env.ts",
      "content": "import { z } from \"zod\";\n\n// Load .env when present (Node >= 20.12). Real environment variables win.\ntry {\n  process.loadEnvFile();\n} catch {\n  // No .env file: fine.\n}\n\nconst schema = z.object({\n  NODE_ENV: z.enum([\"development\", \"test\", \"production\"]).default(\"development\"),\n  PORT: z.coerce.number().int().positive().default(3000),\n});\n\n/** Validated environment. Add new variables to the schema above. */\nexport const env = schema.parse(process.env);\n"
    },
    {
      "path": "src/index.ts",
      "type": "registry:file",
      "target": "~/src/index.ts",
      "content": "import { serve } from \"@hono/node-server\";\nimport { app } from \"./app\";\nimport { env } from \"./env\";\n\nserve({ fetch: app.fetch, port: env.PORT }, (info) => {\n  console.log(`Listening on http://localhost:${info.port}`);\n});\n"
    },
    {
      "path": "test/app.test.ts",
      "type": "registry:file",
      "target": "~/test/app.test.ts",
      "content": "import { describe, expect, it } from \"vitest\";\nimport { app } from \"../src/app\";\n\ndescribe(\"app\", () => {\n  it(\"reports health\", async () => {\n    const res = await app.request(\"/health\");\n    expect(res.status).toBe(200);\n    expect(await res.json()).toEqual({ status: \"ok\" });\n  });\n\n  it(\"returns JSON for unknown routes\", async () => {\n    const res = await app.request(\"/nope\");\n    expect(res.status).toBe(404);\n    expect(await res.json()).toEqual({ error: \"Not found\" });\n  });\n\n  it(\"sets security headers\", async () => {\n    const res = await app.request(\"/health\");\n    expect(res.headers.get(\"x-content-type-options\")).toBe(\"nosniff\");\n  });\n});\n"
    },
    {
      "path": "tsconfig.json",
      "type": "registry:file",
      "target": "~/tsconfig.json",
      "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2023\",\n    \"lib\": [\"ES2023\"],\n    \"module\": \"Preserve\",\n    \"moduleResolution\": \"Bundler\",\n    \"strict\": true,\n    \"noEmit\": true,\n    \"skipLibCheck\": true,\n    \"types\": [\"node\"]\n  },\n  \"include\": [\"src\", \"test\"]\n}\n"
    }
  ],
  "envVars": {},
  "docs": "This is a foundation: it creates the project. After installing:\n\n1. `npm test` should pass and `npm run dev` serves on http://localhost:3000 (`GET /health`).\n2. Add features as routers in `src/<feature>/routes.ts` and mount them in `createApp()` in `src/app.ts` with `app.route(\"/<feature>\", routes)`.\n3. Follow `AGENTS.md` for validation, errors, env vars and tests.\n",
  "categories": [
    "api",
    "rest",
    "http",
    "server",
    "backend",
    "starter",
    "node",
    "typescript"
  ],
  "meta": {
    "pkg": "https://pkg.tneemo.com/tneemo/hono-api",
    "version": "1.0.0",
    "license": "MIT"
  }
}