{"id":13809767,"url":"https://github.com/seamapi/nextlove","last_synced_at":"2025-07-25T05:06:32.414Z","repository":{"id":64792405,"uuid":"507769510","full_name":"seamapi/nextlove","owner":"seamapi","description":"An NPM module that has best practices and essential modules for building APIs with NextJS","archived":false,"fork":false,"pushed_at":"2025-06-18T23:16:25.000Z","size":1714,"stargazers_count":21,"open_issues_count":39,"forks_count":2,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-07-18T11:59:49.669Z","etag":null,"topics":["maintained"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/seamapi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-06-27T05:05:40.000Z","updated_at":"2025-06-18T23:16:27.000Z","dependencies_parsed_at":"2023-10-11T12:22:08.849Z","dependency_job_id":"185e66b1-9798-4aba-b34f-8c57fb3e655b","html_url":"https://github.com/seamapi/nextlove","commit_stats":{"total_commits":97,"total_committers":10,"mean_commits":9.7,"dds":0.5979381443298969,"last_synced_commit":"031a454a227166f7226d2508420c4123f0a0e08b"},"previous_names":[],"tags_count":68,"template":false,"template_full_name":null,"purl":"pkg:github/seamapi/nextlove","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seamapi%2Fnextlove","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seamapi%2Fnextlove/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seamapi%2Fnextlove/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seamapi%2Fnextlove/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/seamapi","download_url":"https://codeload.github.com/seamapi/nextlove/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seamapi%2Fnextlove/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266959682,"owners_count":24012545,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-25T02:00:09.625Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["maintained"],"created_at":"2024-08-04T02:00:35.748Z","updated_at":"2025-07-25T05:06:32.318Z","avatar_url":"https://github.com/seamapi.png","language":"TypeScript","readme":"# nextlove - Enhanced NextJS API Types, OpenAPI and Utilities\n\nMake type-safe routes that automatically generate OpenAPI in NextJS easy!\n\n- Define endpoints with middleware and have your request objects and responses automatically be typed\n- The same [zod](https://github.com/colinhacks/zod) schemas used for your types will be in the generated\n  `openapi.json` file!\n- Throw [http exceptions and they'll magically be handled](https://github.com/seamapi/nextjs-exception-middleware#exception-types)\n- Have well-typed middleware\n\n## Installation\n\n`yarn add nextlove`\n\n## Create well-typed routes + middleware with nextlove!\n\n`nextlove` allows you to create well-typed middleware and routes using utility types and functions. The\ntwo main functions to know are `createWithRouteSpec`, which allows you to create a `withRouteSpec` function\nthat can be used with all your endpoints, and the `Middleware` utility function which makes middleware type-safe.\n\nLet's take a look at an example project with three files:\n\n- **lib/with-route-spec.ts** - This file is used to create the `withRouteSpec` middleware. This middleware should\n  be used for all your routes.\n- **lib/middlewares/with-auth-token.ts** - This is an authentication middleware we'll be using to make sure requests are authenticating\n- **lib/middlewares/with-db.ts** - A common global middleware that attaches a database client to the request object\n- **pages/api/health.ts** - Just a health endpoint to see if the server is running! It won't have any auth\n- **pages/api/todos/add.ts** - An endpoint to add a TODO, this will help show how we can use auth!\n\n```ts\n// pages/api/health.ts\nimport { withRouteSpec } from \"lib/with-route-spec\"\nimport { z } from \"zod\"\n\nconst routeSpec = {\n  methods: [\"GET\"],\n  auth: \"none\",\n  jsonResponse: z.object({\n    healthy: z.boolean(),\n  }),\n} as const\n\nexport default withRouteSpec(routeSpec)(async (req, res) =\u003e {\n  /* ... */\n  return res.status(200).json({ healthy: true })\n})\n```\n\n```ts\n// lib/with-route-spec.ts\nexport const withRouteSpec = createWithRouteSpec({\n  authMiddlewareMap: { auth_token: withAuthToken },\n  globalMiddlewares: [globalMiddleware],\n\n  // For OpenAPI Generation\n  apiName: \"My API\",\n  productionServerUrl: \"https://example.com\",\n  globalSchemas: {\n    user: z.object({\n      user_id: z.string().uuid(),\n    }),\n  },\n} as const)\n```\n\n```ts\n// lib/middlewares/with-auth-token.ts\nimport { UnauthorizedException, Middleware } from \"nextlove\"\n\nexport const withAuthToken: Middleware\u003c{\n  auth: {\n    authorized_by: \"auth_token\"\n  }\n}\u003e = (next) =\u003e async (req, res) =\u003e {\n  req.auth = {\n    authorized_by: \"auth_token\",\n  }\n\n  return next(req, res)\n}\n\nexport default withAuthToken\n```\n\n```ts\n// pages/api/todos/add.ts\nimport { withRouteSpec, UnauthorizedException } from \"lib/with-route-spec\"\nimport { z } from \"zod\"\n\nconst routeSpec = {\n  methods: [\"POST\"],\n  auth: \"auth_token\",\n  jsonBody: z.object({\n    content: z.string(),\n  }),\n  jsonResponse: z.object({\n    ok: z.boolean(),\n  }),\n} as const\n\nexport default withRouteSpec(routeSpec)(async (req, res) =\u003e {\n  // req.auth is correctly typed here!\n  if (req.auth.authorized_by !== \"auth_token\") {\n    throw new UnauthorizedException({\n      type: \"unauthorized\",\n      message: \"Authenticate yourself to get the requested response\",\n    })\n  }\n  // TODO add todo\n  return res.status(200).json({ ok: true })\n})\n```\n\n## createWithRouteSpec Parameters\n\n| Parameter             | Description                                                  |\n| --------------------- | ------------------------------------------------------------ |\n| `authMiddlewareMap`   | Object that maps different types of auth to their middleware |\n| `globalMiddlewares`   | Middlewares that should be applied on every route            |\n| `apiName`             | Used as the name of the api in openapi.json                  |\n| `productionServerUrl` | Used as the default server url in openapi.json               |\n\n## withRouteSpec Parameters\n\n| Parameter      | Description                                                                                                                            |\n| -------------- | -------------------------------------------------------------------------------------------------------------------------------------- |\n| `methods`      | HTTP Methods accepted by this route                                                                                                    |\n| `auth`         | `none` or a key from your `authMiddlewareMap`, this authentication middleware will be applied                                          |\n| `queryParams`  | Any GET query parameters on the request as a zod object                                                                                |\n| `jsonBody`     | The JSON body this endpoint accepts as a zod object                                                                                    |\n| `formData`     | The `multipart/form-data` [(todo)](https://github.com/seamapi/nextlove/issues/127) or `application/x-www-form-urlencoded` encoded body |\n| `commonParams` | Parameters common to both the query and json body as a zod object, this is sometimes used if a GET route also accepts POST             |\n| `jsonResponse` | A zod object representing the json resposne                                                                                            |\n\n### Generating OpenAPI Types (Command Line)\n\nJust run `nextlove generate-openapi` in your project root!\n\nExamples:\n\n```bash\n# Print OpenAPI JSON directly to the command line for the package in the current directory\nnextlove generate-openapi --packageDir .\n\n# Write OpenAPI JSON to \"openapi.json\" file\nnextlove generate-openapi . --outputFile openapi.json\n\n# Only generate OpenAPI JSON for public api routes\nnextlove generate-openapi . --pathGlob '/pages/api/public/**/*.ts'\n```\n\n| Parameter    | Description                                                                                |\n| ------------ | ------------------------------------------------------------------------------------------ |\n| `packageDir` | Path to directory containing package.json and NextJS project                               |\n| `outputFile` | Path to output openapi.json file                                                           |\n| `pathGlob`   | Paths to consider as valid routes for OpenAPI generation, defaults to `/pages/api/**/*.ts` |\n\n### Generating OpenAPI Types (Script)\n\n```ts\nimport { generateOpenAPI } from \"nextlove\"\n\ngenerateOpenAPI({\n  packageDir: \".\",\n  outputFile: \"openapi.json\",\n  pathGlob: \"/src/pages/api/**/*.ts\",\n\n  // Tags improve the organization of an OpenAPI spec by making \"expandable\"\n  // sections including routes\n  tags: [\"users\", \"teams\", \"workspaces\"].map((t) =\u003e ({\n    name: `/${t}`,\n    description: t,\n    doesRouteHaveTag: (route) =\u003e route.includes(`/${t}`),\n  })),\n  mapFilePathToHTTPRoute(fp) {\n    return fp\n      .replace(\"src/pages/api/public\", \"\")\n      .replace(/\\.ts$/, \"\")\n      .replace(/\\/index$/, \"\")\n  },\n})\n```\n\n### Extracting route specs (Command Line)\n\nJust run `nextlove extract-route-specs` in your project root! It will output a ESM file bundled by esbuild.\n\nCaveats:\n\n- All dependencies and dev dependencies in your `package.json` are automatically marked as external when bundling. This means that you may want to re-bundle the output file if you plan on publishing it as part of a library.\n- By default, API route files aren't allowed to import anything besides dependencies declared in `package.json`. This is to avoid accidentally polluting the bundle. To allow specific imports, use the `--allowed-import-patterns` flag: `--allowed-import-patterns '**/lib/**' --allowed-import-patterns '**/models/**'`\n\n### Wrap middlewares together using `wrappers`!\n\n```ts\nimport { wrappers } from \"nextlove\"\n\nwrappers(withDatabase, logger.withContext(\"somecontext\"), async (req, res) =\u003e {\n  res.status(200).end(\"...\")\n})\n```\n\n### nextjs-exception-middleware\n\n```ts\nimport { BadRequestException } from \"nextlove\"\n\n// Inside a route handler\nif (bad_soups.includes(soup_param)) {\n  throw new BadRequestException({\n    type: \"cant_make_soup\",\n    message: \"Soup was too difficult, please specify a different soup\",\n    data: { soup_param },\n  })\n}\n```\n\n### All Modules\n\nThis repo bundles NextJS utility modules including...\n\n- [nextjs-exception-middleware](https://github.com/seamapi/nextjs-exception-middleware)\n- [nextjs-server-modules](https://github.com/seamapi/nextjs-server-modules)\n- [nextjs-middleware-wrappers](https://github.com/seamapi/wrappers)\n- openAPI generation utilities\n","funding_links":[],"categories":["Official Projects"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseamapi%2Fnextlove","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseamapi%2Fnextlove","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseamapi%2Fnextlove/lists"}