Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/honojs/hono/llms.txt

Use this file to discover all available pages before exploring further.

Parts of the SSG Helper are experimental. The API may change in future versions.
The SSG (Static Site Generation) Helper enables pre-rendering of Hono applications to static files, allowing you to generate static HTML, CSS, JSON, and other assets at build time.

Import

import { toSSG, fetchRoutesContent, saveContentToFile } from 'hono/ssg'
import { ssgParams, isSSGContext, disableSSG, onlySSG } from 'hono/ssg'
import type { ToSSGOptions, ToSSGResult } from 'hono/ssg'

Functions

toSSG()

Generates static files from a Hono application.
function toSSG(
  app: Hono<any, any, any>,
  fsModule: FileSystemModule,
  options?: ToSSGOptions
): Promise<ToSSGResult>
app
Hono
required
The Hono application instance to generate static files from
fsModule
FileSystemModule
required
File system module with writeFile and mkdir methods (e.g., Node.js fs/promises)
options
ToSSGOptions
Configuration options for static generation
return
Promise<ToSSGResult>
Result object containing:
  • success: boolean indicating if generation succeeded
  • files: array of generated file paths
  • error: Error object if generation failed
Example
import { Hono } from 'hono'
import { toSSG } from 'hono/ssg'
import fs from 'fs/promises'

const app = new Hono()

app.get('/', (c) => c.html('<h1>Home</h1>'))
app.get('/about', (c) => c.html('<h1>About</h1>'))
app.get('/api/data', (c) => c.json({ message: 'Hello' }))

// Generate static files
const result = await toSSG(app, fs, {
  dir: './dist'
})

if (result.success) {
  console.log(`Generated ${result.files.length} files`)
  result.files.forEach(file => console.log(file))
} else {
  console.error('Generation failed:', result.error)
}

ssgParams()

Middleware to define parameters for dynamic routes during SSG.
function ssgParams<E extends Env = Env>(
  params: SSGParams
): MiddlewareHandler<E>

function ssgParams<E extends Env = Env>(
  generateParams: (c: Context<E>) => SSGParams | Promise<SSGParams>
): MiddlewareHandler<E>
params
SSGParams | Function
required
Either an array of parameter objects or a function that returns them
return
MiddlewareHandler
Middleware that provides parameters for static generation
Example
import { ssgParams } from 'hono/ssg'

app.get(
  '/posts/:id',
  ssgParams(async (c) => {
    // Generate pages for these post IDs
    return [
      { id: '1' },
      { id: '2' },
      { id: '3' }
    ]
  }),
  (c) => {
    const id = c.req.param('id')
    return c.html(`<h1>Post ${id}</h1>`)
  }
)

// Static array
app.get(
  '/users/:userId',
  ssgParams([
    { userId: 'alice' },
    { userId: 'bob' }
  ]),
  (c) => {
    const userId = c.req.param('userId')
    return c.html(`<h1>User: ${userId}</h1>`)
  }
)

isSSGContext()

Checks if the current request is running in SSG context.
function isSSGContext(c: Context): boolean
c
Context
required
The Hono context object
return
boolean
true if running in SSG context, false otherwise
Example
import { isSSGContext } from 'hono/ssg'

app.get('/page', (c) => {
  if (isSSGContext(c)) {
    // Render static version
    return c.html('<h1>Static Page</h1>')
  } else {
    // Render dynamic version with live data
    return c.html(`<h1>Dynamic Page - ${new Date()}</h1>`)
  }
})

disableSSG()

Middleware to prevent a route from being statically generated.
function disableSSG(): MiddlewareHandler
return
MiddlewareHandler
Middleware that disables SSG for the route
Example
import { disableSSG } from 'hono/ssg'

// This route will not be statically generated
app.get('/admin', disableSSG(), (c) => {
  return c.html('<h1>Admin Panel</h1>')
})

// Dynamic API route
app.get('/api/current-time', disableSSG(), (c) => {
  return c.json({ time: new Date().toISOString() })
})

onlySSG()

Middleware to make a route only available during SSG (returns 404 at runtime).
function onlySSG(): MiddlewareHandler
return
MiddlewareHandler
Middleware that makes the route SSG-only
Example
import { onlySSG } from 'hono/ssg'

// This route only exists in static builds
app.get('/sitemap.xml', onlySSG(), (c) => {
  const sitemap = generateSitemap()
  return c.text(sitemap, 200, {
    'Content-Type': 'application/xml'
  })
})

fetchRoutesContent()

Generator function that fetches content for all routes.
function* fetchRoutesContent<E extends Env = Env, S extends Schema = {}, BasePath extends string = '/'>(
  app: Hono<E, S, BasePath>,
  beforeRequestHook?: BeforeRequestHook,
  afterResponseHook?: AfterResponseHook,
  concurrency?: number
): Generator<Promise<...>>
app
Hono
required
The Hono application instance
beforeRequestHook
BeforeRequestHook
Hook called before each request
afterResponseHook
AfterResponseHook
Hook called after each response
concurrency
number
Number of concurrent requests (default: 2)
return
Generator
Generator yielding Promises that resolve to route content

saveContentToFile()

Saves content to a file.
function saveContentToFile(
  data: Promise<{ routePath: string; content: string | ArrayBuffer; mimeType: string } | undefined>,
  fsModule: FileSystemModule,
  outDir: string,
  extensionMap?: Record<string, string>
): Promise<string | undefined>
data
Promise<object>
required
Promise resolving to content data
fsModule
FileSystemModule
required
File system module
outDir
string
required
Output directory path
extensionMap
Record<string, string>
Custom MIME type to file extension mapping
return
Promise<string | undefined>
Path to the saved file, or undefined if save was skipped

Types

ToSSGOptions

interface ToSSGOptions {
  dir?: string // Output directory (default: './static')
  concurrency?: number // Concurrent requests (default: 2)
  extensionMap?: Record<string, string> // MIME type to extension mapping
  plugins?: SSGPlugin[] // SSG plugins
}

ToSSGResult

interface ToSSGResult {
  success: boolean
  files: string[]
  error?: Error
}

SSGParams

type SSGParams = Array<Record<string, string>>

// Example:
const params: SSGParams = [
  { id: '1', slug: 'first' },
  { id: '2', slug: 'second' }
]

FileSystemModule

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

Advanced Usage

Custom Extension Mapping

import { toSSG } from 'hono/ssg'
import fs from 'fs/promises'

const result = await toSSG(app, fs, {
  dir: './dist',
  extensionMap: {
    'text/html': 'html',
    'application/json': 'json',
    'text/xml': 'xml',
    'application/rss+xml': 'rss'
  }
})

Build Script Example

// build.ts
import { Hono } from 'hono'
import { toSSG } from 'hono/ssg'
import fs from 'fs/promises'

const app = new Hono()

// Define your routes
app.get('/', (c) => c.html('<h1>Home</h1>'))
app.get('/about', (c) => c.html('<h1>About</h1>'))

// Generate static site
async function build() {
  console.log('Generating static site...')
  
  const result = await toSSG(app, fs, {
    dir: './dist',
    concurrency: 4
  })
  
  if (result.success) {
    console.log(`✓ Generated ${result.files.length} files`)
  } else {
    console.error('✗ Build failed:', result.error)
    process.exit(1)
  }
}

build()

Dynamic Routes with Database

import { ssgParams } from 'hono/ssg'

app.get(
  '/blog/:slug',
  ssgParams(async () => {
    // Fetch all blog post slugs from database
    const posts = await db.posts.findAll()
    return posts.map(post => ({ slug: post.slug }))
  }),
  async (c) => {
    const slug = c.req.param('slug')
    const post = await db.posts.findBySlug(slug)
    
    return c.html(`
      <article>
        <h1>${post.title}</h1>
        <div>${post.content}</div>
      </article>
    `)
  }
)

File Output

Generated files follow these patterns:
  • //index.html
  • /about/about.html
  • /about//about/index.html
  • /api/data/api/data.json (for JSON responses)
  • /feed.xml/feed.xml

Build docs developers (and LLMs) love