@pauldvlp/vp-react-ts-hono
v0.3.1
Published
Vite+ monorepo template: a React web app + a Hono api (conformed to the Vite+ toolchain) sharing Zod contracts.
Maintainers
Readme
@pauldvlp/vp-react-ts-hono
A Vite+ monorepo generator that scaffolds a full-stack workspace where the front-end and the back-end share one toolchain:
apps/web— a minimal React + Vite+ app that calls the api through Hono's typed RPC client (hc<AppType>) over a/apidev proxy (no CORS, no hand-written URLs)apps/api— a Hono api conformed to Vite+ (plain TypeScript, no transform plugin) that validates withsValidatorand exports itsAppTypefor the clientpackages/contracts— shared Zod schemas + inferred types, the single source of truth for the data shapes
Hono is plain TypeScript — no decorators, no metadata — so the api is a plain Vite+ package with zero
wiring. The web and api are typed end to end: the api's route chain is exported as AppType and the
web consumes it via hc<AppType>, so paths, params, request bodies and responses are all checked at
compile time. Dev runs on vite-node --watch, the production build is a Vite SSR bundle (dist/main.js),
and a single vp check / vp test / vp run -r build covers the whole workspace. It's the lightweight,
edge-friendly counterpart to vp-react-ts-nestjs.
Options can be passed on the vp create command line (anything after --) or answered interactively.
Usage
Published under the @pauldvlp/create manifest:
# Interactive (prompts for anything you don't pass)
vp create @pauldvlp:vp-react-ts-hono
# Non-interactive, fully specified
vp create @pauldvlp:vp-react-ts-hono -- \
--name my-app --scope @acme --apiPort 3000 --webPort 5173Boolean options (
--openapi,--serveWeb,--docker,--install) accept both forms: pass--openapito enable or--no-openapito disable. Omit any option to answer it at the interactive prompt.
Options
| Option | Type / values | Default | Notes |
| ------------ | ------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| --name | string | my-app | Root project / package name. |
| --scope | string | @<name> | npm scope for workspace packages → @scope/web, @scope/api, @scope/contracts. Defaults to the project name prefixed with @ (e.g. --name acme → @acme); falls back to @app. |
| --apiPort | string | 3000 | Port the Hono api listens on (substituted into the env default + the web proxy). |
| --webPort | string | 5173 | Port the web dev server listens on. |
| --openapi | boolean | false | Expose Swagger UI at /docs and the OpenAPI JSON at /docs.json, generated from the Zod contracts (adds @hono/swagger-ui). |
| --serveWeb | boolean | false | Have the api serve the built web app for a single deployable (uses @hono/node-server's serveStatic). |
| --docker | boolean | false | Emit a multi-stage apps/api/Dockerfile (+ root .dockerignore). |
| --install | boolean | true | Run pnpm install after scaffolding. false = files only. |
What it scaffolds
produce() reads the static monorepo skeleton under template/, rewriting the @app scope, project
name and ports, then conditionally wires the optional features via marker comments:
--openapiswaps the// __OPENAPI_*__markers inapps/api/src/app.tsfor theswaggerUI+/docs.jsonroutes and keepsapps/api/src/openapi.ts(the doc built from the contracts withz.toJSONSchema); otherwise the markers are stripped andopenapi.tsis dropped.--serveWebswaps the// __SERVEWEB_*__markers inapps/api/src/app.tsfor aserveStaticmount ofapps/web/dist(registered after the/apiroutes); otherwise they're stripped.--dockerkeepsapps/api/Dockerfile+ the root.dockerignore; otherwise both are dropped.
The optional Swagger UI dep (@hono/swagger-ui) is added to apps/api/package.json only when
--openapi is on, and the README's <!-- OPENAPI/SERVEWEB/DOCKER --> doc blocks are kept or dropped to
match. With --install, pnpm install runs as a post-scaffold step.
Develop the generator
pnpm install
node bin/index.ts --help # list options
node bin/index.ts --directory /tmp/demo --name demo --scope @demo --apiPort 3000 --webPort 5173