---
title: "Static Generation"
description: "Static Generation (SSG) in Hono enables pre-rendering routes into static files during the build process, significantly improving performance by serving assets directly from the file system rather t..."
last_updated: "2026-07-02T09:13:47.263532+00:00"
canonical_url: "https://www.doc0.app/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/developer-helpers/static-generation"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [package.json](https://github.com/blade47/hono/blob/main/package.json)
- [src/helper/ssg/ssg.ts](https://github.com/blade47/hono/blob/main/src/helper/ssg/ssg.ts)
- [src/hono-base.ts](https://github.com/blade47/hono/blob/main/src/hono-base.ts)
- [src/adapter/cloudflare-pages/handler.ts](https://github.com/blade47/hono/blob/main/src/adapter/cloudflare-pages/handler.ts)
- [src/preset/quick.ts](https://github.com/blade47/hono/blob/main/src/preset/quick.ts)
- [src/helper/ssg/utils.ts](https://github.com/blade47/hono/blob/main/src/helper/ssg/utils.ts)
- [src/hono.ts](https://github.com/blade47/hono/blob/main/src/hono.ts)
- [src/router/reg-exp-router/prepared-router.ts](https://github.com/blade47/hono/blob/main/src/router/reg-exp-router/prepared-router.ts)
- [src/helper/route/index.ts](https://github.com/blade47/hono/blob/main/src/helper/route/index.ts)
- [src/utils/url.ts](https://github.com/blade47/hono/blob/main/src/utils/url.ts)
- [src/router/reg-exp-router/router.ts](https://github.com/blade47/hono/blob/main/src/router/reg-exp-router/router.ts)
- [jsr.json](https://github.com/blade47/hono/blob/main/jsr.json)
- [src/helper/ssg/plugins.ts](https://github.com/blade47/hono/blob/main/src/helper/ssg/plugins.ts)
- [src/helper/dev/index.ts](https://github.com/blade47/hono/blob/main/src/helper/dev/index.ts)
- [src/helper/ssg/middleware.ts](https://github.com/blade47/hono/blob/main/src/helper/ssg/middleware.ts)
- [src/helper/ssg/index.ts](https://github.com/blade47/hono/blob/main/src/helper/ssg/index.ts)
- [src/router/linear-router/router.ts](https://github.com/blade47/hono/blob/main/src/router/linear-router/router.ts)
- [src/preset/tiny.ts](https://github.com/blade47/hono/blob/main/src/preset/tiny.ts)
- [src/adapter/deno/ssg.ts](https://github.com/blade47/hono/blob/main/src/adapter/deno/ssg.ts)
- [src/adapter/bun/ssg.ts](https://github.com/blade47/hono/blob/main/src/adapter/bun/ssg.ts)
- [src/middleware/serve-static/index.ts](https://github.com/blade47/hono/blob/main/src/middleware/serve-static/index.ts)
- [src/router/reg-exp-router/index.ts](https://github.com/blade47/hono/blob/main/src/router/reg-exp-router/index.ts)
- [perf-measures/type-check/scripts/generate-app.ts](https://github.com/blade47/hono/blob/main/perf-measures/type-check/scripts/generate-app.ts)
- [src/router/smart-router/index.ts](https://github.com/blade47/hono/blob/main/src/router/smart-router/index.ts)
- [src/router/reg-exp-router/trie.ts](https://github.com/blade47/hono/blob/main/src/router/reg-exp-router/trie.ts)
- [src/adapter/deno/index.ts](https://github.com/blade47/hono/blob/main/src/adapter/deno/index.ts)
- [src/router/pattern-router/index.ts](https://github.com/blade47/hono/blob/main/src/router/pattern-router/index.ts)
- [src/router/trie-router/index.ts](https://github.com/blade47/hono/blob/main/src/router/trie-router/index.ts)
- [src/router/linear-router/index.ts](https://github.com/blade47/hono/blob/main/src/router/linear-router/index.ts)
- [src/adapter/bun/index.ts](https://github.com/blade47/hono/blob/main/src/adapter/bun/index.ts)
</details>

Static Generation (SSG) in Hono enables pre-rendering routes into static files during the build process, significantly improving performance by serving assets directly from the file system rather than invoking the application logic at runtime. This subsystem is designed to crawl the application's defined routes, execute them, and persist their outputs to a specified directory.

By abstracting the file system interface through `FileSystemModule`, Hono's SSG mechanism remains environment-agnostic, allowing seamless integration with different runtimes like Node.js, Deno, or Bun. This flexibility ensures that the SSG workflow is consistent across various platforms while leveraging environment-specific optimized file writing routines.

The architecture emphasizes composability and extensibility via plugin support. This allows developers to intercept the request lifecycle, handle dynamic routing parameters, or modify generated responses to suit specific requirements, such as handling redirects or content transformations.

## The Generation Lifecycle

The SSG process coordinates route discovery, execution, and persistence. It starts by filtering routes to identify eligible static content, then proceeds through the SSG plugins to collect content and save it to the disk.

```mermaid
flowchart TD
    A["Hono App"] --> B["toSSG"]
    B --> C{SSG Plugins}
    C -->|Hook Execution| D["app.request (Internal)"]
    D --> E["parseResponseContent"]
    E --> F["saveContentToFile"]
    F --> G["fsModule"]
```

Sources: [src/helper/ssg/ssg.ts:368-470](https://github.com/blade47/hono/blob/main/src/helper/ssg/ssg.ts#L368-L470), [src/helper/ssg/ssg.ts:310-334](https://github.com/blade47/hono/blob/main/src/helper/ssg/ssg.ts#L310-L334)

## File System Abstraction

The system requires an implementation of `FileSystemModule` to perform I/O operations. This decoupling allows the core logic to avoid runtime-specific dependencies, ensuring the same `toSSG` function works across diverse environments.

```typescript
export interface FileSystemModule {
  writeFile(path: string, data: string | Uint8Array): Promise<void>
  mkdir(path: string, options: { recursive: boolean }): Promise<void | string>
}
```

Implementations are provided for specific adapters:
- **Bun**: Configured via the export module in `src/adapter/bun/ssg.ts`.
- **Deno**: Configured via the export module in `src/adapter/deno/ssg.ts`.

Sources: [src/helper/ssg/ssg.ts:34-37](https://github.com/blade47/hono/blob/main/src/helper/ssg/ssg.ts#L34-L37), [src/adapter/bun/ssg.ts:13-18](https://github.com/blade47/hono/blob/main/src/adapter/bun/ssg.ts#L13-L18), [src/adapter/deno/ssg.ts:9-18](https://github.com/blade47/hono/blob/main/src/adapter/deno/ssg.ts#L9-L18)

## Dynamic Routing and Parameter Injection

For routes containing dynamic parameters, Hono uses the `ssgParams` middleware to inform the generator which specific paths to pre-render. When the generator encounters a route identified by `isDynamicRoute`, it expects the application to provide context via `ssgParams`.

> [!IMPORTANT]
> The `ssgParams` middleware effectively "short-circuits" the request processing for those routes in the generator's context, preventing unnecessary handler execution while collecting the required parameters for static rendering.

```typescript
export const ssgParams: SSGParamsMiddleware = (params) => async (c, next) => {
  if (isDynamicRoute(c.req.path)) {
    (c.req.raw as AddedSSGDataRequest).ssgParams = Array.isArray(params) ? params : await params(c)
    return c.notFound() 
  }
  await next()
}
```

Sources: [src/helper/ssg/middleware.ts:43-49](https://github.com/blade47/hono/blob/main/src/helper/ssg/middleware.ts#L43-L49), [src/helper/ssg/utils.ts:73-75](https://github.com/blade47/hono/blob/main/src/helper/ssg/utils.ts#L73-L75)

## Plugin System

Plugins allow customization of the SSG process. By bundling hooks, plugins can easily inject logic before a request is sent, after a response is received, or after the generation process completes.

| Hook Type | Trigger Point | Purpose |
| :--- | :--- | :--- |
| `beforeRequestHook` | Before sending the request | Request modification or filtering |
| `afterResponseHook` | After the response is received | Response processing, status check, or redirect generation |
| `afterGenerateHook` | After file writing | Cleanup or reporting |

Sources: [src/helper/ssg/ssg.ts:175-179](https://github.com/blade47/hono/blob/main/src/helper/ssg/ssg.ts#L175-L179), [src/helper/ssg/plugins.ts:11-20](https://github.com/blade47/hono/blob/main/src/helper/ssg/plugins.ts#L11-L20)

## Path Resolution and Sanitization

The `generateFilePath` function transforms route paths into valid file system paths, applying directory and extension logic. It guarantees that generated files are contained within the `outDir` to prevent potential path traversal vulnerabilities.

> [!CAUTION]
> The `ensureWithinOutDir` check is a security invariant that throws an error if a computed `filePath` escapes the `outDir`. This is critical for preventing arbitrary file system writes during the generation phase.

Sources: [src/helper/ssg/ssg.ts:50-71](https://github.com/blade47/hono/blob/main/src/helper/ssg/ssg.ts#L50-L71), [src/helper/ssg/utils.ts:77-87](https://github.com/blade47/hono/blob/main/src/helper/ssg/utils.ts#L77-L87)

## Execution Walkthrough: `toSSG`

The `toSSG` orchestrator follows this sequence:

1. **Initialization**: Normalizes hooks from the provided `plugins` array.
2. **Setup**: Configures internal utilities for routing and hook execution.
3. **Execution**: Iterates through route paths, resolving parameters via `ssgParams`.
4. **Processing**: Triggers internal app requests for each parameter set.
5. **Persistence**: `saveContentToFile` creates the necessary directories recursively and writes the data to the `outputDir` using the injected `fsModule`.
6. **Finalization**: Executes `afterGenerateHook` callbacks after the main operations conclude.

Sources: [src/helper/ssg/ssg.ts:368-470](https://github.com/blade47/hono/blob/main/src/helper/ssg/ssg.ts#L368-L470)

## Related

- [JSX Renderer](https://www.doc0.app/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/rendering-jsx/jsx-renderer)


## Sitemap

See the full [sitemap](https://www.doc0.app/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/llms.txt) for all pages in this wiki.
