hono-fsr
v1.2.1
Published
File system router for the Hono web framework.
Maintainers
Readme
hono-fsr
File system router for the Hono web framework.
Features
- Zero-overhead: All file system operations happen once at initialization.
- Convention-based: Intuitive file and folder naming conventions.
- Bundlers: Support for Vite, Esbuild, and more.
Installation
# npm
npm install hono-fsr
# pnpm
pnpm add hono-fsr
# yarn
yarn add hono-fsr
# bun
bun add hono-fsrhono-fsr is an ESM-only package.
Usage
Create Your Routes
Create a routes directory and start adding your endpoint files. The file and folder names will map directly to your URL structure.
Core Principles
- HTTP Methods: To handle a specific HTTP method, export a constant with the method's name in all uppercase (e.g.,
export const GET,export const POST). - Default Export: For convenience, a default export will automatically be treated as a GET request.
createRoute(): All handlers must be wrapped in the createRoute function. This function can accept multiple arguments, including any Hono middleware (likezValidator) followed by your final handler function.
Example
import { createRoute } from "hono-fsr";
import { zValidator } from "@hono/zod-validator";
import { z } from "zod";
// Default exports are treated as GET methods
export default createRoute((c) => {
return c.json([
{ id: 1, title: "First Post" },
{ id: 2, title: "Second Post" },
]);
});
const postSchema = z.object({
title: z.string().min(1),
body: z.string().min(1),
});
// POST method
export const POST = createRoute(zValidator("json", postSchema), (c) => {
// c.req.valid("json") is now typed
const newPost = c.req.valid("json");
return c.json({ success: true, post: newPost }, 201);
});Initialize the Router
In your main server file, import createRouter and connect it to your Hono app.
/index.ts
import { Hono } from "hono";
import { serve } from "@hono/node-server";
// The function required to initialize the router
import { createRouter } from "hono-fsr";
import path from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const app = new Hono();
// Initializes the router at ./routes
await createRouter(app, {
root: path.join(__dirname, "routes"),
});
serve(
{
fetch: app.fetch,
port: 3000,
},
(info) => {
console.log(
`Server is running on port ${info.port}. (http://localhost:${info.port})`
);
}
);Routing Conventions
hono-fsr uses a simple and powerful file-naming convention.
| File Name | URL Path | Example |
| ------------------ | ------------ | ----------------------------------------------------------- |
| index.ts | / | routes/index.ts → / |
| users.ts | /users | routes/users.ts → /users |
| users/index.ts | /users | routes/users/index.ts → /users |
| [id].ts | /:id | routes/users/[id].ts → /users/:id |
| [[id]].ts | /:id? | routes/optional/[[id]].ts → /optional/:id? |
| [...path].ts | /* | routes/files/[...path].ts → /files/* |
| (group)/about.ts | /about | routes/(marketing)/about.ts → /about |
| +middleware.ts | (Middleware) | Applies to all routes in its directory and sub-directories. |
| _filename.ts | (Ignored) | Files that start with an underscore are ignored. |
Configuration
The createRouter function accepts an options object to customize its behavior.
| Option | Description | Type | Default |
| --------------- | --------------------------------------------------------------------------- | ----------------------------------- | ------------ |
| root | The root directory of the routes. | string | Required |
| manifest | The path to the generated manifest file. | Manifest | undefined |
| debug | Enable verbose logging for debugging. | boolean | false |
| rpc | Allows sharing of the API specifications between the server and the client. | boolean | false |
| basePath | A path prefix for all routes. | string | / |
| trailingSlash | Defines the trailing slash behavior for all routes. | "always" \| "never" \| "preserve" | "preserve" |
Read more about how to use the manifest option in the Bundlers section of the Wiki.
Example Configuration
createRouter(app, {
root: path.join(__dirname, "routes"),
debug: process.env.NODE_ENV !== "production",
rpc: true,
basePath: "/api/v1",
trailingSlash: "never",
});Alternatives
For projects that require tight integration between a frontend (React) and backend, or a full-stack experience, consider using honox. It is a full meta-framework that also supports file system routing and server-side rendering with React.
hono-fsr is a powerful and lean server-side routing layer. Its sole focus is to provide a robust, convention-driven foundation for organizing your application's endpoints. It remains completely unopinionated about what your handlers return, be it JSON for an API, or HTML from Hono's built-in JSX renderer for a server-rendered site.
Documentation
This README provides a quickstart and reference for the main features. For detailed guides on all conventions, configuration options, and advanced topics, please visit the Wiki.
License
hono-fsr is under the MIT license.
