No description
  • TypeScript 89.9%
  • JavaScript 7.4%
  • HTML 2.7%
Find a file
2026-05-20 10:17:12 +02:00
scripts 1. Updated from @temir.ra/create-template@0.1.3. 2026-04-13 17:21:24 +02:00
src 1. Updated from @temir.ra/create-template@0.1.3. 2026-04-13 17:21:24 +02:00
template version 0.3.3 2026-05-20 10:16:00 +02:00
tests 1. Updated from template@0.1.7 template. 2026-05-19 22:20:08 +02:00
.gitignore 1. Updated from template@0.1.7 template. 2026-05-19 22:20:08 +02:00
CHANGELOG.md version 0.3.3 2026-05-20 10:16:00 +02:00
LICENSE version 0.3.1 2026-04-13 18:49:31 +02:00
package.json version 0.3.3 2026-05-20 10:16:00 +02:00
README.md 1. Updated from template@0.1.7 template. 2026-05-19 22:20:08 +02:00
tsconfig.json 1. Updated from template@0.1.7 template. 2026-05-19 22:20:08 +02:00

Introduction

A template for single-page applications distributed as Hono sub-app libraries. The generated package bundles a frontend shell (HTML, JS, CSS, PWA manifest, favicon) as static assets and exposes a createSpa() function that returns a Hono instance serving them. Intended to be consumed by a @temir.ra/create-hono-server backend, where it is mounted as a route group.

Table of Contents

  1. Quick Start
  2. Documentation
    1. template/
    2. Architecture
    3. src/spa.ts
    4. src/constants.ts
    5. assets/
  3. DevOps
    1. Change Management
    2. Publish

Quick Start

# placeholder:
    # <TEMPLATE_PACKAGE: @temir.ra/create-hono-spa
    # <TEMPLATE_NAME: @temir.ra/hono-spa
    # <NEW_PACKAGE: <NEW_PACKAGE>
      # is used as:
      #   - the path where the package is created
      #   - the "name" field in the generated package.json
    # <@_VERSION: <@_VERSION>

# pinned version
bun info "@temir.ra/create-hono-spa" version
bun create --no-install --no-git "@temir.ra/hono-spa<@_VERSION>" <NEW_PACKAGE>

# latest
# clear the cache to pick up the latest version
bun pm cache rm
bun create --no-install --no-git "@temir.ra/hono-spa" <NEW_PACKAGE>

# templates only copy files, run install and any setup scripts manually
cd <NEW_PACKAGE>
bun install

Documentation

The following sections explain the configurations and conventions baked into the generated package. Useful when adapting it to fit specific needs.

template/

Official documentation provided by the Hono team is a great resource.

Architecture

The generated SPA package is a library - not a runnable server. It abstracts three things from the consuming server:

Asset serving - All frontend assets (HTML shell, JS bundle, CSS, PWA manifest, favicon) are resolved from the package directory via import.meta.url and served by the sub-app itself. The consuming server does not configure static file serving or copy any files.

Client-side routing - The /app/* wildcard returns index.html for every navigation path. The <base href> tag is patched at request time from basePath and path, so relative asset URLs resolve correctly wherever the sub-app is mounted.

PWA scaffold - The assets/ directory ships with the structure expected by browsers for PWA installation: manifest, favicon, and screenshots.

The consuming server treats the package as an opaque route group passed to endpointGroups. See @temir.ra/create-hono-server for the mount pattern.

src/spa.ts

Built-in routes:

Path Description
/health Returns ok with status 200
/buildinfo Returns the contents of buildinfo.txt
/app/* Serves index.html with runtime substitutions applied
/<faviconPath> Serves favicon.svg as image/svg+xml
/<webmanifestPath> Serves manifest.webmanifest as application/manifest+json
/<indexJsPath> Serves dist/index.bundle.js
/<indexCssPath> Serves dist/index.css
/<siteCssPath> Serves dist/site.css

Options:

type CreateSpaOptions = {
    basePath?: string;               // outer base path matching the server host's basePath
    path?: string;                   // sub-path for this SPA within the server
    metaDescriptionContent?: string; // replaces content="" in the description meta tag
    faviconPath?: string;            // serve path for the favicon (default: 'favicon.svg')
    webmanifestPath?: string;        // default: 'manifest.webmanifest'
    vAppContainerId?: string;        // id attribute of the root app container div
    indexJsPath?: string;            // default: 'index.js'
    indexCssPath?: string;           // default: 'index.css'
    siteCssPath?: string;            // default: 'site.css'
}

src/constants.ts

export const packageUrl    = new URL('../',                         import.meta.url);
export const buildinfoUrl  = new URL('buildinfo.txt',               packageUrl);
export const distUrl       = new URL('dist/',                       packageUrl);
export const indexJsUrl    = new URL('index.bundle.js',             distUrl);
export const assetsUrl     = new URL('assets/@scope/package-name/', packageUrl);
export const indexHtmlUrl  = new URL('index.html',                  assetsUrl);
// ...

Replace @scope/package-name with your actual package name when adapting the template. Update constants.ts and rename the assets/@scope/package-name/ directory to match.

assets/

The template provides a PWA shell scaffold:

assets/
└── @scope/
    └── package-name/
        ├── index.html                  ← SPA entry point; base href patched at request time
        ├── favicon.svg
        ├── manifest.webmanifest
        └── images/
            ├── mobile-screenshot.png   ← used in manifest for PWA install UI
            └── wide-screenshot.png

assets/ is included in the files field of package.json and published with the package. The naming convention (assets/@scope/package-name/) follows the asset resolution contract from @temir.ra/create-ts-lib - scoped directories prevent naming collisions when multiple SPA packages coexist in the same server.

DevOps

bun update
bun install

bun run clean
bun run build
bun run tests

# see publish section for publish instructions

Change Management

  1. Create a new branch for the change.
  2. Make the changes and commit.
  3. Bump the version in package.json.
  4. Add an entry for the new version in CHANGELOG.md.
  5. Pull request the branch.
  6. Ensure package artifacts are current.
  7. Publish.

Publish

Publish to the public npm registry.

# authenticate
npm login
# publish
bun publish --registry https://registry.npmjs.org/ --access public