{"_id":"@elizabeth-js/elizabeth","_rev":"2-dc701bd5fcc4b54fe2e8abb62ce1c8ad","name":"@elizabeth-js/elizabeth","dist-tags":{"latest":"0.0.7"},"versions":{"0.0.6":{"name":"@elizabeth-js/elizabeth","version":"0.0.6","_id":"@elizabeth-js/elizabeth@0.0.6","maintainers":[{"name":"shinapri","email":"shinapri.2003.1@gmail.com"}],"bin":{"elizabeth":"bin/elizabeth"},"dist":{"shasum":"0b25827a79c0bc1b14972ef7744b729bcba7ea55","tarball":"https://registry.npmjs.org/@elizabeth-js/elizabeth/-/elizabeth-0.0.6.tgz","fileCount":32,"integrity":"sha512-/L1FLuiI++U4NMXtYEIKtNBtzwXOkn3Wib2i3xTlnE2YvwdBDJ4baWNaSg+Lz3354SlBzU49dC25vD3CGUim5Q==","signatures":[{"sig":"MEUCIQC1CeLS+Ba/tDwYZCGvW7q5Dl5m+rFE8gE8e3Yvfry94gIgBJ44nFgkBXeBrXubMQrgzRe0GTrE7zy6jkGWCIVbMfU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2839694},"type":"module","exports":{".":"./src/elizabeth.ts","./route":"./src/route.ts","./client":"./src/client.ts"},"gitHead":"0dca12c75ef0326e1c61bb0ed2824c96f05f6361","scripts":{"dev":"bun run src/dev/server.ts","test":"bun test ./tests","build":"bun run src/cli.ts build","check":"tsc --noEmit","smoke":"bun run src/dev/smoke.ts"},"_npmUser":{"name":"shinapri","email":"shinapri.2003.1@gmail.com"},"workspaces":["packages/*"],"_npmVersion":"10.8.2","description":"<kbd>   <img src=\"./assets/banner.png\"> </kbd>","directories":{},"_nodeVersion":"20.20.2","dependencies":{"chokidar":"^5.0.0","oxc-parser":"^0.128.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.10","@types/bun":"^1.3.13","typescript":"^6.0.3","tailwindcss":"^4.2.4","@types/react":"^19.2.14","@tailwindcss/vite":"^4.2.4"},"_npmOperationalInternal":{"tmp":"tmp/elizabeth_0.0.6_1778783736812_0.1607999618799485","host":"s3://npm-registry-packages-npm-production"}},"0.0.7":{"name":"@elizabeth-js/elizabeth","version":"0.0.7","type":"module","publishConfig":{"access":"public"},"workspaces":["packages/*"],"bin":{"elizabeth":"bin/elizabeth"},"exports":{".":"./src/elizabeth.ts","./client":"./src/client.ts","./route":"./src/route.ts","./server":"./src/runtime/server.ts"},"scripts":{"check":"tsc --noEmit","test":"bun test ./tests ./packages/*/tests","test:packages":"bun test ./packages/*/tests","smoke":"bun run src/dev/smoke.ts","dev":"bun run src/dev/server.ts","build":"bun run src/cli.ts build","format":"biome format --write .","format:check":"biome format .","lint":"biome lint .","lint:fix":"biome lint --write .","biome":"biome check --write .","biome:ci":"biome check ."},"devDependencies":{"@biomejs/biome":"^2.4.15","@changesets/cli":"^2.31.0","@tailwindcss/vite":"^4.2.4","@types/bun":"^1.3.13","@types/react":"^19.2.14","tailwindcss":"^4.2.4","typescript":"^6.0.3","vite":"^8.0.10"},"dependencies":{"chokidar":"^5.0.0","oxc-parser":"^0.128.0"},"_id":"@elizabeth-js/elizabeth@0.0.7","gitHead":"0a4d88e4fec4f359b59d48504e90438d27d79551","description":"<kbd>   <img src=\"./assets/banner.png\"> </kbd>","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-NiTSttdRxOTxwVEoLhmAJkaHwk3rncM9232gJVXIKzhg+9gi8FkFihIzgYrF1qWZN51CX7WM02rSFWfEgAzPcQ==","shasum":"ef800fc6f46afbc971a715c1010bef6c5a62ebf8","tarball":"https://registry.npmjs.org/@elizabeth-js/elizabeth/-/elizabeth-0.0.7.tgz","fileCount":37,"unpackedSize":2912345,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDmoI8cBxHmG0fmZrHzfuKCIn79V1zNcR+uyhMupAfVlgIhAIf6lvh5OxV2+j562iesGQnu8tuHgHJr/tnTPfobp4KL"}]},"_npmUser":{"name":"shinapri","email":"shinapri.2003.1@gmail.com"},"directories":{},"maintainers":[{"name":"shinapri","email":"shinapri.2003.1@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/elizabeth_0.0.7_1779122951918_0.5330815503422046"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-14T18:35:36.714Z","modified":"2026-05-18T16:49:12.354Z","0.0.6":"2026-05-14T18:35:37.064Z","0.0.7":"2026-05-18T16:49:12.232Z"},"description":"<kbd>   <img src=\"./assets/banner.png\"> </kbd>","maintainers":[{"name":"shinapri","email":"shinapri.2003.1@gmail.com"}],"readme":"<kbd>\n  <img src=\"./assets/banner.png\">\n</kbd>\n\n# Elizabeth\n\nElizabeth is a Bun full-stack web framework with `.liz` components, server rendering, file routes, API routes, scoped styles, CSS modules, client islands, and automatic layout transition.\n\nThis is an early `0.0.x` release. Expect rough edges while the syntax and runtime settle.\n\n## Create An App\n\n```bash\nbun create elizabeth-app my-app\ncd my-app\nbun run dev\n```\n\nThe dev server starts on port `3712` by default.\n\n## Component Syntax\n\n```tsx\n@default\n<HomePage>\n  const items = [\n    { text: \"Fast\" },\n    { text: \"Server first\" },\n    { text: \"Scoped styles\" },\n  ];\n\n  <style>\n    .hero {\n      padding: 32px;\n      border: 1px solid rgba(0, 0, 0, .12);\n      border-radius: 8px;\n    }\n  </style>\n\n  <main className=\"hero\">\n    <h1>Elizabeth</h1>\n    <ul>\n      {\n        for (const item of items) {\n          <li>{item.text}</li>\n        }\n      }\n    </ul>\n  </main>\n</HomePage>\n```\n\n`{...}` inside markup is JavaScript. To render text that looks like template syntax, use a string expression.\n\n## Routes\n\nPages live in `src/pages` by default:\n\n```text\nsrc/pages/index.liz       -> /\nsrc/pages/about.liz       -> /about\nsrc/pages/users/[id].liz  -> /users/:id\nsrc/pages/404.liz         -> custom 404\n```\n\nAPI routes live in `src/api` by default:\n\n```ts\nexport function GET() {\n  return Response.json({ message: \"Hello from Elizabeth\" });\n}\n```\n\n`.liz` endpoint files can return rendered HTML fragments:\n\n```liz\n<POST>\n  const form = await ctx.request.formData();\n\n  <p>{form.get(\"title\")}</p>\n</POST>\n```\n\nRoute roots can be configured:\n\n```ts\nexport default {\n  pageRoutes: {\n    \"src/pages\": \"/\",\n  },\n  apiRoutes: {\n    \"src/api\": \"/api\",\n  },\n};\n```\n\n## Layouts\n\n`layout.liz` wraps child routes:\n\n```tsx\n@default\n<RootLayout>\n  <html>\n    <body>\n      <nav>\n        <a href=\"/\">Home</a>\n        <a href=\"/about\">About</a>\n      </nav>\n      {children}\n    </body>\n  </html>\n</RootLayout>\n```\n\nWhen a shared layout exists, Elizabeth enhances same-origin link clicks by fetching the next page and swapping only the layout child boundary.\n\n### `<head>`\n\nElizabeth does **not** inject an HTML document for you. The root layout owns the entire `<html>` shell — including `<head>`. Anything you write inside `<head>` in your root layout is what the browser sees:\n\n```liz\n@default\n<RootLayout>\n  <html lang=\"en\">\n    <head>\n      <title>My Site</title>\n      <meta charset=\"utf-8\" />\n      <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n      <meta name=\"description\" content=\"A small Elizabeth app\" />\n      <link rel=\"icon\" href=\"/favicon.svg\" />\n    </head>\n    <body>{children}</body>\n  </html>\n</RootLayout>\n```\n\nNotes:\n\n- `<!doctype html>` is prepended automatically — don't write it yourself.\n- The dev server injects its HMR/island bootstrap `<script>` and CSS links into your `</head>`. If `</head>` is missing, they get prepended to the document instead, so always provide a `<head>` to keep things tidy.\n- **Nested layouts are body partials.** They render inside the root layout's `<body>` via `{children}`, so don't put `<html>` / `<head>` / `<body>` inside them — keep that in the root layout only.\n- **Per-route titles.** Client-side link navigation already syncs `document.title` from the new page, so each route's root layout `<title>` is honored after navigation. For section-specific titles within the same root layout, the simplest pattern today is a small `@client` component that runs `document.title = ...`.\n\nScoped component `<style>` blocks emit inline in the body next to the markup they target — you don't need to put them in `<head>`.\n\n## Client Islands\n\nUse `@client` for browser-interactive components:\n\n```liz\nimport { clientState } from \"elizabeth/client\";\n\n@client\n@public\n<Counter>\n  const [count, setCount] = clientState(0);\n\n  <button onClick={() => setCount(count + 1)}>{count}</button>\n</Counter>\n```\n\nClient helpers from `elizabeth/client` are compiler-aware and only run in the generated island runtime where needed.\n\n### Client State\n\n`clientState` returns the current value and a setter. Setting state rerenders reactive text, attributes, HTML blocks, and event bindings inside the island:\n\n```liz\nimport { clientState } from \"elizabeth/client\";\n\n@client\n@public\n<TodoCounter>\n  const [count, setCount] = clientState(0);\n\n  <button onClick={() => setCount((current) => current + 1)}>\n    Added {count}\n  </button>\n</TodoCounter>\n```\n\n### Client Memo\n\nUse `clientMemo` for derived values that should only recompute when dependencies change:\n\n```liz\nimport { clientMemo, clientState } from \"elizabeth/client\";\n\n@client\n@public\n<CartSummary>\n  const [price, setPrice] = clientState(20);\n  const [quantity, setQuantity] = clientState(2);\n  const total = clientMemo(() => price * quantity, [price, quantity]);\n\n  <p>Total: {total}</p>\n</CartSummary>\n```\n\n### Client Ready\n\nUse `clientReady` for browser-side setup after the island mounts. Return a cleanup function when needed. `onReady` remains available as a compatibility alias.\n\n```liz\nimport { clientReady, clientRef } from \"elizabeth/client\";\n\n@client\n@public\n<SearchBox>\n  const input = clientRef<HTMLInputElement>();\n\n  clientReady(() => {\n    input.current?.focus();\n  });\n\n  <input ref={input} />\n</SearchBox>\n```\n\n### Client Context\n\n`clientContext` shares values across local child components in the same client island without passing props through every layer. Use `.provide(value) { ... }` with Elizabeth render-wrapper syntax, then read with `.use()`.\n\n```liz\nimport { clientContext, clientState } from \"elizabeth/client\";\n\nconst ThemeContext = clientContext(\"light\");\n\n@private\n<ThemeLabel>\n  const theme = ThemeContext.use();\n\n  <p>Theme: {theme}</p>\n</ThemeLabel>\n\n@client\n@public\n<ThemePanel>\n  const [theme, setTheme] = clientState(\"dark\");\n\n  ThemeContext.provide(theme) {\n    <ThemeLabel />\n    <button onClick={() => setTheme(theme === \"dark\" ? \"light\" : \"dark\")}>\n      Toggle\n    </button>\n  }\n</ThemePanel>\n```\n\nContext is scoped by the render wrapper. A provided value is available while that wrapped subtree renders, including async render blocks.\n\n## Render Wrappers\n\nAny function call in render position can wrap Elizabeth markup by accepting the rendered block as its final argument:\n\n```liz\nfunction Card(title, render) {\n  return `<section><h2>${title}</h2>${render()}</section>`;\n}\n\n@default\n<ProfilePage>\n  Card(\"Profile\") {\n    <p>Ada Lovelace</p>\n    <p>Mathematician</p>\n  }\n</ProfilePage>\n```\n\nThis is useful for scoped behavior such as auth gates, feature flags, cache boundaries, error/loading boundaries, forms, and client context:\n\n```liz\nAuth.required() {\n  <AdminPanel />\n}\n\nFeature.enabled(\"new-dashboard\") {\n  <Dashboard />\n}\n\nThemeContext.provide(theme) {\n  <Toolbar />\n}\n```\n\nWrapper blocks can contain multiple tags, control flow, components, and nested wrappers. In client islands, Elizabeth rerenders the smallest wrapper boundary whose call header depends on state:\n\n```liz\nLayout(\"Dashboard\") {\n  Card(\"Counter \" + count) {\n    <button onClick={() => setCount(count + 1)}>{count}</button>\n  }\n}\n```\n\nHere only the `Card(...)` block rerenders when `count` changes; the stable `Layout(...)` wrapper stays mounted.\n\n## Build\n\n```bash\nbun run build\nbun run start\n```\n\n`bun run build` creates both static HTML for static routes and a production `dist/server.js`.\n","readmeFilename":"README.md"}