Skip to content

x402-tollbooth/web

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🌾 Oat Stack

A minimal, fast, dependency-light web stack.

Zero React on the client. Server-rendered TSX. Under 25KB shipped to the browser.

Stack

Layer Tool What it does
Runtime Bun Server, SQLite, TSX transpilation
Server better-call Typed endpoints, router, Zod validation
Auth better-auth Email/password, sessions, cookie-based
Templates @kitajs/html JSX → HTML strings (server-only, zero runtime)
Interactivity HTMX HTML fragment swapping (~14KB)
Styling Oat.ink Semantic CSS components (~8KB)

Getting Started

# Install dependencies
bun install

# Run dev server with hot reload
bun dev

# Run production
bun start

Then open http://localhost:3000

Project Structure

oat-stack/
├── src/
│   ├── index.tsx          # Entry point — Bun.serve()
│   ├── router.ts          # Imports all endpoints into createRouter()
│   ├── auth.ts            # better-auth config
│   ├── db.ts              # SQLite schema + queries
│   ├── routes/
│   │   ├── pages.tsx      # Full page endpoints (HTML)
│   │   └── api.tsx        # API endpoints (HTML fragments for HTMX)
│   ├── components/
│   │   ├── Layout.tsx     # Base HTML shell
│   │   └── ui.tsx         # Reusable UI components
│   └── middleware/
│       └── auth.ts        # Auth middleware for endpoints
├── public/
│   └── styles.css         # Minimal custom styles
├── package.json
└── tsconfig.json

How It Works

  1. Pages return full HTML (Layout + content) for initial page loads
  2. HTMX makes requests to API endpoints that return HTML fragments
  3. HTMX swaps the fragments into the DOM — no client-side rendering
  4. better-auth handles sessions via cookies — works naturally with server-rendered HTML
  5. @kitajs/html lets you write TSX that compiles to HTML strings — full TypeScript DX, zero client JS

Adding a New Route

  1. Create your endpoint in src/routes/:
import Html from "@kitajs/html";
import { createEndpoint } from "better-call";

export const myPage = createEndpoint("/my-page", {
  method: "GET",
}, async (ctx) => {
  return new Response(
    (<Layout title="My Page"><h1>Hello!</h1></Layout>) as string,
    { headers: { "Content-Type": "text/html; charset=utf-8" } }
  );
});
  1. Import it in src/router.ts:
import { myPage } from "./routes/pages";
// add to createRouter({ ..., myPage })

That's it. No file-based routing magic, no build step, no config.

Notes

  • Auth forms: The login/signup forms POST directly to better-auth endpoints. better-auth handles validation, password hashing, session creation.
  • HTMX + Auth: The authMiddleware checks cookies on every request. HTMX requests automatically include cookies, so auth "just works".
  • Database: SQLite via bun:sqlite. The DB file is oat-stack.db in the project root. better-auth creates its own tables alongside yours.
  • No bundler: Bun transpiles TSX natively. No webpack, no vite, no esbuild config.

Releases

Packages

Contributors

Languages