Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Release

# Release pipeline:
# 1) smoke: pack, install the tarball, scaffold Node and Express apps, boot their
# 1) smoke: pack, install the tarball, scaffold Node, Express, and Hono apps, boot their
# servers and verify a live HTTP response. Kept out of the per-PR ci.yml job.
# 2) publish: on a version tag, publish the CLI and npm-create wrapper to npm
# using OIDC trusted publishing (no long-lived token; provenance is attached
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,5 @@ dist

# Prettier File

AGENTS.md
package-lock.json
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## Unreleased

## 2.4.0 - 2026-06-24

- Add Hono framework support with TypeScript-first generated apps, Docker files, generated tests, and JSON routes for `/`, `/about`, `/contact`, and `/health`.
- Add OpenAPI output for Hono apps while keeping `--view` and `--db` Express-only.
- Update interactive mode, docs, examples, tarball packaging tests, and release smoke coverage for Hono.

## 2.3.0 - 2026-06-24

- Add TypeScript support for generated Express apps with `src/index.ts`, `tsconfig.json`, `tsx` development, `tsc` builds to `dist`, generated TypeScript tests, and Docker support.
Expand Down
23 changes: 13 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
[![Node >=20](https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg)](package.json)
[![GitHub release](https://img.shields.io/github/v/release/theinfosecguy/ServerGen?display_name=tag)](https://github.com/theinfosecguy/ServerGen/releases/latest)

ServerGen is an npm CLI for scaffolding Node.js and Express API projects with
practical defaults: MVC-style folders, health checks, Docker files, ready-to-run
npm scripts, optional Express views, and optional Mongoose/MongoDB config.
ServerGen is an npm CLI for scaffolding Node.js, Express, and Hono API projects
with practical defaults: MVC-style folders, health checks, Docker files,
ready-to-run npm scripts, optional Express views, and optional
Mongoose/MongoDB config.

## 30-Second Quick Start

Expand Down Expand Up @@ -48,14 +49,15 @@ npx servergen@latest my-api
| Choice | Output |
| --- | --- |
| Default Express app | `index.js`, `routes/index.js`, `controllers/`, `model/`, `views/`, `.env.example`, `Dockerfile`, `.dockerignore`, `.gitignore`, generated `README.md`, `package.json`, and `test/app.test.js`. |
| `--typescript` | Express app with `src/index.ts`, `src/routes/index.ts`, `tsconfig.json`, `test/app.test.ts`, `tsx` for development, and `dist/` output for production start. |
| `--typescript` | TypeScript Express app with `src/index.ts`, `src/routes/index.ts`, `tsconfig.json`, `test/app.test.ts`, `tsx` for development, and `dist/` output for production start. Hono apps are TypeScript by default. |
| `--framework node` | Plain Node.js HTTP server with `/`, `/about`, `/contact`, and `/health`, plus MVC folders, Docker files, `.gitignore`, generated `README.md`, and `package.json`. |
| `--framework hono` | TypeScript Hono API app with `src/index.ts`, `tsconfig.json`, `test/app.test.ts`, Docker files, `.gitignore`, generated `README.md`, and `package.json`. |
| `--view ejs`, `pug`, or `hbs` | Adds the selected Express view template and renders it from `/`. |
| `--db` | Adds Mongoose, `config/mongoose.js`, and `MONGODB_URI` in `.env.example` for Express apps. |
| `--openapi` | Adds `docs/openapi.yaml`, a static OpenAPI 3.0 spec for the generated Express routes. |
| `--openapi` | Adds `docs/openapi.yaml`, a static OpenAPI 3.0 spec for generated Express and Hono routes. |

Generated apps include `npm start` and `npm run dev`. Express apps also include
`npm test`. TypeScript Express apps also include `npm run build`.
`npm test`. TypeScript Express and Hono apps also include `npm run build`.

## CLI Usage

Expand All @@ -70,11 +72,11 @@ servergen [options] [name]
```text
-V, --version output the version number
-n, --name <name> name of the app to create
-f, --framework <type> framework: express | node (default: "express")
-f, --framework <type> framework: express | node | hono (default: "express")
-v, --view <type> view engine (express only): ejs | pug | hbs
--db add Mongoose and a MongoDB config (express only)
--openapi generate an OpenAPI spec file (express only)
--typescript generate an Express TypeScript app
--openapi generate an OpenAPI spec file (express and hono)
--typescript generate a TypeScript app where supported
-p, --port <number> port for the generated app (1-65535) (default: "3000")
--skip-install skip the npm install step
--debug enable debug logging
Expand All @@ -87,6 +89,7 @@ servergen [options] [name]
npm create servergen@latest
npx servergen@latest my-api
npx servergen@latest my-api --framework node
npx servergen@latest my-api --framework hono
npx servergen@latest my-api --view ejs
npx servergen@latest my-api --db
npx servergen@latest my-api --openapi
Expand Down Expand Up @@ -137,7 +140,7 @@ servergen my-api
Tagged releases are published from GitHub Actions with npm trusted publishing
and provenance, using OIDC instead of a long-lived npm token. Before publishing,
the release workflow packs the package, installs that tarball in a throwaway
project, scaffolds Express and Node apps, starts them, and verifies live HTTP
project, scaffolds Express, Hono, and Node apps, starts them, and verifies live HTTP
responses.

The same workflow creates or updates the matching GitHub Release as `latest`
Expand Down
15 changes: 8 additions & 7 deletions bin/servergen.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env node

/**
* ServerGen CLI - Generates Node.js/Express application scaffolding.
* ServerGen CLI - Generates Node.js, Express, and Hono application scaffolding.
* @module bin/servergen
*/

Expand All @@ -28,15 +28,15 @@ const config = getConfig(__dirname, process.cwd());

program
.name('servergen')
.description('Scaffold a Node.js or Express application.')
.description('Scaffold a Node.js, Express, or Hono application.')
.version(pkg.version)
.argument('[name]', 'name of the app to create (alternative to --name)')
.option('-n, --name <name>', 'name of the app to create')
.option('-f, --framework <type>', 'framework: express | node', 'express')
.option('-f, --framework <type>', 'framework: express | node | hono', 'express')
.option('-v, --view <type>', 'view engine (express only): ejs | pug | hbs')
.option('--db', 'add Mongoose and a MongoDB config (express only)')
.option('--openapi', 'generate an OpenAPI spec file (express only)')
.option('--typescript', 'generate an Express TypeScript app')
.option('--openapi', 'generate an OpenAPI spec file (express and hono)')
.option('--typescript', 'generate a TypeScript app where supported')
.option('-p, --port <number>', 'port for the generated app (1-65535)', '3000')
.option('--skip-install', 'skip the npm install step')
.option('--debug', 'enable debug logging')
Expand All @@ -46,10 +46,11 @@ program
Examples:
$ servergen my-api create an Express app (default)
$ servergen my-api -f node create a Node app
$ servergen my-api -f hono create a Hono app
$ servergen my-api -v ejs Express app with the EJS view engine
$ servergen my-api --db Express app with Mongoose/MongoDB
$ servergen my-api --openapi Express app with docs/openapi.yaml
$ servergen my-api --typescript Express app with TypeScript
$ servergen my-api --openapi API app with docs/openapi.yaml
$ servergen my-api --typescript TypeScript where supported
$ servergen my-api -p 8080 use a custom port
$ servergen my-api --skip-install scaffold without running npm install
$ servergen --name my-api name via flag (equivalent to positional)
Expand Down
4 changes: 3 additions & 1 deletion docs/examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ The command-by-command examples use `npx --yes servergen@latest` to follow the c
- [Default Express app](./express.md)
- [TypeScript Express app](./typescript.md)
- [Plain Node app](./node.md)
- [Hono app](./hono.md)
- [Express views with EJS, Pug, or HBS](./views.md)
- [Express app with MongoDB/Mongoose config](./mongodb.md)
- [Custom port and Docker notes](./custom-port-docker.md)
Expand All @@ -27,5 +28,6 @@ The command-by-command examples use `npx --yes servergen@latest` to follow the c
- Generated apps require Node.js 20 or newer.
- Generation runs `npm install` unless you pass `--skip-install`.
- When install is not skipped, npm also creates `node_modules/` and `package-lock.json` inside the generated app.
- Express-only options: `--view ejs|pug|hbs`, `--db`, `--openapi`, and `--typescript`.
- Express-only options: `--view ejs|pug|hbs` and `--db`.
- Hono accepts `--typescript` and `--openapi`; the Hono preset does not support `--view` or `--db`.
- Generated apps include Docker support files. Express apps also include `.env.example`; Node apps do not.
48 changes: 48 additions & 0 deletions docs/examples/hono.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Hono App

Use this when you want a Hono API preset.

## Command

```bash
npx --yes servergen@latest hello-hono --framework hono
```

Hono apps are TypeScript apps. Passing `--typescript` is accepted but not
required:

```bash
npx --yes servergen@latest hello-hono --framework hono --typescript
```

## Option Compatibility

Hono supports OpenAPI output:

```bash
npx --yes servergen@latest hello-hono --framework hono --openapi
```

Hono does not support the Express-only view and database options:

```bash
npx --yes servergen@latest hello-hono --framework hono --view ejs
npx --yes servergen@latest hello-hono --framework hono --db
```

Each command fails before creating the app directory.

## Run

```bash
cd hello-hono
npm run dev
```

## Verify

```bash
npm test
npm run build
curl http://localhost:3000/health
```
32 changes: 21 additions & 11 deletions lib/app_generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class AppGenerator {
* Creates an AppGenerator instance.
* @param {Object} options - Generation options.
* @param {string} options.appName - The application name.
* @param {string} options.framework - The framework type ('node' or 'express').
* @param {string} options.framework - The framework type ('node', 'express', or 'hono').
* @param {string|null} options.view - The view engine name.
* @param {boolean} options.db - Whether to include database configuration.
* @param {boolean} options.openapi - Whether to generate an OpenAPI spec.
Expand Down Expand Up @@ -46,9 +46,8 @@ class AppGenerator {
this.logger = dependencies.logger;

this.folderDir = path.join(this.config.paths.cwd, this.appName);
this.templatesDir = this.framework === 'node'
? this.config.paths.templates.node
: this.config.paths.templates.express;
this.templatesDir = this.config.paths.templates[this.framework]
|| this.config.paths.templates.express;
}

/**
Expand Down Expand Up @@ -100,6 +99,16 @@ class AppGenerator {
this.view,
this.db
);
} else if (this.framework === 'hono') {
if (typeof this.fileCreator.createHonoApp !== 'function') {
throw new Error('The hono framework is recognized, but Hono generation is not available in this build.');
}
this.fileCreator.createHonoApp(
this.templatesDir,
this.folderDir,
this.appName,
{ typescript: this.typescript }
);
} else {
this.fileCreator.createExpressApp(
this.templatesDir,
Expand All @@ -118,7 +127,7 @@ class AppGenerator {
configurePort() {
if (this.port !== 3000) {
this.logger?.debug('Configuring custom port', { port: this.port });
const indexPath = this.typescript
const indexPath = this.typescript || this.framework === 'hono'
? path.join(this.folderDir, 'src', 'index.ts')
: path.join(this.folderDir, 'index.js');
try {
Expand All @@ -136,11 +145,10 @@ class AppGenerator {
}

/**
* Sets up view engine if specified. View engines are express-only, so this
* is a no-op for the node framework.
* Sets up view engine if specified. View engines are express-only.
*/
setupViews() {
if (this.framework === 'node') {
if (this.framework !== 'express') {
return;
}
this.fileCreator.handleViews(
Expand All @@ -155,7 +163,7 @@ class AppGenerator {
* Sets up database configuration if enabled.
*/
setupDatabase() {
if (this.db) {
if (this.framework === 'express' && this.db) {
this.fileCreator.handleConfig(
this.folderDir,
this.config.paths.templates.express,
Expand All @@ -168,11 +176,12 @@ class AppGenerator {
* Adds gitignore and Docker support files.
*/
addSupportFiles() {
const typescript = this.typescript || this.framework === 'hono';
const supportOptions = {
db: Boolean(this.db),
openapi: Boolean(this.openapi),
port: this.port,
typescript: this.typescript,
typescript,
};

this.fileCreator.addGitIgnore(this.folderDir, this.templatesDir);
Expand All @@ -182,9 +191,10 @@ class AppGenerator {
appName: this.appName,
});
this.fileCreator.addEnvExample(this.folderDir, this.templatesDir, supportOptions);
if (this.framework === 'express' && this.openapi) {
if ((this.framework === 'express' || this.framework === 'hono') && this.openapi) {
this.fileCreator.addOpenApiSpec(this.folderDir, {
appName: this.appName,
framework: this.framework,
port: this.port,
view: this.view,
});
Expand Down
3 changes: 2 additions & 1 deletion lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ export const getConfig = (baseDir, cwd) => {
paths: {
templates: {
express: path.join(baseDir, '..', 'templates', 'express'),
hono: path.join(baseDir, '..', 'templates', 'hono'),
node: path.join(baseDir, '..', 'templates', 'node'),
views: path.join(baseDir, '..', 'templates', 'express', 'views'),
},
cwd,
},
validation: {
frameworks: ['node', 'express'],
frameworks: ['node', 'express', 'hono'],
views: ['ejs', 'pug', 'hbs'],
},
defaults: {
Expand Down
2 changes: 2 additions & 0 deletions lib/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export const DEPENDENCY_VERSIONS = {
nodemon: '^3.1.14',
cors: '^2.8.6',
express: '^5.2.1',
hono: '^4.12.27',
'@hono/node-server': '^2.0.6',
mongoose: '^9.7.0',
dotenv: '^17.4.2',
supertest: '^7.2.2',
Expand Down
Loading
Loading