Skip to content
STACK IT FAST

Hono JSX + Bun + SQLite (Server-Rendered Internal Tools)

Curated rule Internal Admin Tool · Workflow & Automation Updated Oct 2026 Which file does my tool read?
hono-jsx-internal-tools.md

Rules for internal tools rendered on the server with Hono JSX on Bun: forms over fetch, htmx where needed, an OAuth allow-list, Drizzle over SQLite or a read replica, and cron in the same process.

Formats
4 files
AGENTS.md
43 lines
CLAUDE.md
13 lines
Languages
TypeScript
Updated
Oct 2026
Used by
4 projects
Install

Writes .claude/skills/hono-jsx-internal-tools/SKILL.md

$ curl -s --create-dirs -o .claude/skills/hono-jsx-internal-tools/SKILL.md https://stackitfast.com/rules/hono-jsx-internal-tools/SKILL.md

Rule files

AGENTS.md· 43 lines · 3.0 KB
1# Project Architecture & Guidelines (Hono JSX Internal Tool)
2
3## 1. System Architecture
4- **Runtime**: Bun, one process serving HTML and running scheduled jobs.
5- **Framework**: Hono v4 with its built-in JSX renderer (`hono/jsx`). Pages are rendered on the server; there is no client build.
6- **Interactivity**: Plain HTML forms that POST and redirect. htmx for the few places that need partial updates (inline edit, live filters).
7- **Data**: Drizzle ORM over SQLite (`bun:sqlite`) for the tool's own tables. Product data is read from a read replica, and writes to the product go through the product's API.
8- **Auth**: Google Workspace or GitHub OAuth with an allow-list of emails or a team; no passwords stored.
9- **Hosting**: A small VPS or container behind the company VPN or an identity-aware proxy.
10
11## 2. File Layout
12- `src/index.ts`: The Hono app, middleware order (logger → auth → routes), and `export default { port, fetch }`.
13- `src/auth.ts`: OAuth callback and the allow-list middleware, in one file.
14- `src/pages/<screen>.tsx`: One file per screen: the GET handler renders, the POST handler validates, writes and redirects.
15- `src/components/Layout.tsx`: The one page shell (nav, flash messages, CSS link).
16- `src/db/schema.ts`, `src/db/client.ts`, `drizzle/`: Schema, connection and generated migrations.
17- `src/jobs/<name>.ts`: Scheduled work, registered in `src/index.ts` with an in-process scheduler (e.g. `croner`) or exposed as a cron route the host calls.
18
19## 3. Request Rules
20- Validate every form with `@hono/zod-validator` (`zValidator('form', schema)`). On failure, re-render the same page with errors and the submitted values.
21- Successful POSTs redirect (303) to a GET; never render a page from a POST.
22- htmx endpoints return HTML fragments from the same components the full page uses, so markup is never duplicated.
23- Escape by default: render user data through JSX, never by string concatenation.
24
25## 4. Auth & Safety
26- Every route except `/login` and the OAuth callback sits behind the allow-list middleware.
27- Record who did what: an `audit_log` table written by the same transaction as the change.
28- Destructive actions require a POST with a CSRF token (`hono/csrf`) and a confirmation step.
29
30## 5. Coding Standards
31- Strict TypeScript, zero `any`. Row types come from `typeof table.$inferSelect`.
32- No React, no bundler, no client state. If a screen seems to need them, it is probably two screens.
33- Jobs are plain async functions that can be run from a test or a one-off script.
34
35## 6. Testing Conventions
36- `bun test` with `app.request()` against an in-memory SQLite database: assert status codes, redirects and key text in the HTML.
37- Test the allow-list explicitly: a non-listed email gets 403 on every route.
38- Call job functions directly in tests; do not wait on the scheduler.
39
40## 7. Git Workflow & PR Conventions
41- Conventional Commits scoped to the screen or job: `feat(refunds): bulk approve screen`.
42- A schema change ships with its Drizzle migration.
43- Changes to the allow-list or auth are reviewed by a second person, even on a small team.

Works with Cursor · Claude Code · Windsurf · AGY

Architecture notes

Architecture Overview

Guidelines for internal tools built as server-rendered HTML with Hono JSX on Bun: forms instead of fetch calls, htmx where a reload hurts, Drizzle over SQLite for the tool’s own data, and scheduled jobs in the same process.

Key Advantages

  • One file per screen: the GET renders, the POST validates and redirects, so an agent can add a screen and a table in one change.
  • Nothing on the client: no bundler, no state library, no API layer between the form and the database.
  • Safe by default: an OAuth allow-list, CSRF on mutations and an audit log are part of the template, not an afterthought.

Frequently asked questions

Why server-rendered HTML instead of React for an internal tool?

Internal tools are mostly tables and forms. Rendering them on the server removes the client build, the API layer between screen and database, and all client state, which is most of what an agent gets wrong in a CRUD app. htmx covers the few interactions that need partial updates.

How is this different from the Bun + Hono + SQLite API rules?

Those rules are for a JSON API consumed by other apps. This one is for a tool people use in a browser: Hono renders the HTML itself, forms replace fetch calls, and authentication is an allow-list rather than tokens for clients.

Does this AGENTS.md work with Cursor, Claude Code and Windsurf?

Yes. AGENTS.md is the cross-tool standard read by Cursor, Claude Code, Windsurf, Codex and others. A .mdc file is included for Cursor's native rules format.

Used in production

Explore all stacks
Where this stack fits

Stack It First recommends it at:

Walk the backend roadmap