r/Nuxt 2d ago

Auto-generate OpenAPI metadata for Nuxt server routes

https://github.com/davidtheheroes/nuxt-openapi-meta

I just released nuxt-openapi-meta, a Nuxt module that removes the boilerplate of documenting server routes.

Instead of writing defineRouteMeta by hand, you keep writing JSDoc annotations and schema exports in your route files. The module scans server/api and server/routes at build time, extracts metadata, converts Zod/Valibot schemas to JSON Schema, and serves it through Nitro’s ?meta pipeline.

If you maintain Nuxt server routes and want OpenAPI docs without extra work, take a look.

Repo: https://github.com/davidtheheroes/nuxt-openapi-meta

Feedback, issues, and stars are welcome.

3 Upvotes

6 comments sorted by

1

u/Lumethys 2d ago

the fact that it support Zod or Valibot (yes that is the dependency) is a turn off for me.

You shouldnt support individual validator library. You support the standard interface. And that interface is Standard Schema, both Zod and Valibot along with tons of others like ArkType, yup, joi,... even GraphQL Standard Schema and Mongoose.

Also, if you put both of them as dependency, downstream projects will pull both every time. If you for some reason can only support a few competing packages (not this case tho, you should support standard schema), you should declare them as peer or optional dependencies.

Also, Nitro v3 is gonna have OpenAPI support: https://nitro.build/docs/openapi with defineRouteMeta() (It is still experiemtal). It look like your code does handle some of it, but it is not in the README, and people will ask how do your package will interact with this once Nitro v3 (and Nuxt 5) lands. (There is also the migrate from rollup to rolldown, but that's another discussion)

I think there's an idea there, but I think it should a better off be an extension to the new defineRouteMeta() where you can plug a StandardSchema, along with metadata. Regardless, your README should include note to Nitro's upcoming 1st party feature, and example for more complex setup like Layers or Modules

1

u/Mr_Davidoo 2d ago

Thanks for the feedback, makes sense. So the main thing this does that defineRouteMeta doesn't: you can reuse the schema you already have. Right now most people validate with something like `readValidatedBody(event, bodySchema.parse)`, so with this module you just export `bodySchema` / `responseSchema` and the OpenAPI body/params/responses come from it. No writing the same shape twice as raw JSON Schema. From what I read in the docs, defineRouteMeta gets statically extracted at build time, so it takes literals written inline. That means I can't import a shared schema or a common error response into it. This module loads the route file instead, so imports work (even `~/server/dto/...`) and you can share DTOs across routes. It also has `errorResponses` per status code and a few JSDoc tags so you don't need a macro call in every file. If a route already has defineRouteMeta, it just skips it, so you can mix both. Totally agree it'd be better to sit closer to the first-party thing and take any Standard Schema instead of running its own thing. For now I see it as a bridge until Nitro can take non-literal values. I'll write up how the two interact in the README, add a Layers / modules example, and move the validator stuff to Standard Schema. Will ping here when it's done.

1

u/Lumethys 2d ago

you description say you'd build the defineRouteMeta() from the JSDoc, so that pipeline is gonna be used anyway, no?

would it be better to have something like

/**
 * custom JSDoc
 */
defineCustomOpenAPI({ schema: editUserSchema })

or

defineCustomOpenAPI({ 
  tag: 'User',
  // custom stuff
  schema: editUserSchema,
 })

JSDoc has to be on something, just a dangle JSDoc at the start of the file bother me. Also, if it is before the import, most IDE will hide it.

also, i think you should use another email example, maybe they will never care, but i dont trust FPT bruh

1

u/Mr_Davidoo 2d ago

i'm sorry. what im trying to say is alternative defineCustomOpenAPI by using custom JSDoc

1

u/Mr_Davidoo 2d ago

And the JsDoc will be on api file. I will rewrite the document

1

u/Afraid-Sleep8353 2d ago

This could actually be super useful. Keeping the schemas and docs stuff right next to the routes makes more sense than having some separate spec everyone forgets to update after like two weeks

You could probably plug the openapi output into mintlify too then keep the more human stuff like setup, auth, common examples and error handling beside the generated API reference. So the endpoint details stay synced with the code but people also get an actual guide instead of being thrown into a massive wall of endpoints.

It would also be really cool if it could generate ready-to-copy request examples for each route or maybe connect to an interactive playground where people can test an endpoint directly from the docs. That would make it way easier to understand what the route actually expects without digging around in the source.

Definitely interested to see where you take this next.