# Buntal JS: complete reference for AI agents
> Buntal JS is an ultra-lightweight, type-safe full-stack framework for Bun and React with Next.js-like file-system routing. This file is the whole API in one place. All packages share one version (see npm). Requires Bun >= 1.2.
## Ground rules
- Buntal is NOT Next.js. Never import from `next/*`. There is no App Router, no server components, no `"use client"`, no `getServerSideProps`, no `generateMetadata`. Use the APIs below only.
- Runtime is Bun. Prefer Bun built-ins: `Bun.SQL` (database), `Bun.markdown`, `Bun.password`, `Bun.file`, `Bun.write`, `bun test`.
- TypeScript everywhere. `.tsx` for pages and layouts, `.ts` for API routes.
## Packages
| Package | Purpose |
| --- | --- |
| `buntal` | React framework: pages, layouts, `Link`, `Meta`, `Script`, `Svg`, `useRouter`, `BuntalConfig` |
| `@buntal/http` | HTTP server: `Http`, `h`, `Req`, `Res`, `Cookie` |
| `@buntal/http/middlewares` | `auth`, `jwt`, `cors`, `logger`, `secureHeaders` |
| `@buntal/cli` | `buntal dev`, `buntal build`, `buntal start` |
| `create-buntal` | `bun create buntal@latest my-app` |
## Full-stack project
```sh
bun create buntal@latest my-app # interactive template picker
bun create buntal@latest my-app --template landing # landing page / portfolio
bun create buntal@latest my-app --template blog # Markdown blog with a SQL database
# use --template, not -t: `bun create` consumes short flags itself
cd my-app
bun dev # http://localhost:3000 (PORT env overrides)
bun run build && bun start # production
```
Structure:
```
app/
layout.tsx root layout: renders ,
,
index.tsx page for /
globals.css Tailwind CSS v4 entry (compiled to /globals.css)
favicon.svg
about/index.tsx page for /about
posts/[id]/index.tsx dynamic segment -> params.id
docs/[[...slug]]/index.tsx optional catch-all -> params.slug ("a/b")
api/hello/index.ts API route for /api/hello
404.tsx optional custom not-found page
public/ static files served as-is (dotfiles are not served, except .well-known/)
buntal.config.ts optional config
```
Rules:
- A page is `app//index.tsx` with a default export. Folders starting with `_` are ignored.
- `layout.tsx` wraps every page in its folder and below. A folder's layout only renders when that folder has a page.
- The `@/` import alias maps to the project root (see tsconfig).
- Import text files with `import Logo from '@/app/logo.svg' with { type: 'text' }`.
### Root layout
```tsx
import { Meta, type MetaProps } from 'buntal'
export default function RootLayout({
children,
data
}: Readonly<{ children: React.ReactNode; data?: { _meta?: MetaProps } }>) {
return (
{children}
)
}
```
### Pages and props
```tsx
export default function Page({
params,
query,
data
}: {
params: Record
query: Record
data?: unknown
}) {
return
Hello {query.name ?? 'there'}
}
```
### `$`: server data loader
Export `$` from a page or layout. It runs on the server for the initial render and is re-fetched as JSON on client navigation. The page receives the return value as `data`. `data._meta` sets SEO tags (merged with layout `_meta`, page wins).
```tsx
import type { Req } from '@buntal/http'
import type { MetaProps } from 'buntal'
export const $ = async (req: Req) => {
const post = await getPost(req.params.id)
if (!post) return { notFound: true }
return { post, _meta: { title: post.title, description: post.excerpt } satisfies MetaProps }
}
export default function PostPage({ data }: { data?: Awaited> }) {
if (!data || 'notFound' in data) return