bosbun 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +12 -12
  2. package/package.json +5 -5
  3. package/src/cli/add.ts +5 -5
  4. package/src/cli/create.ts +67 -7
  5. package/src/cli/feat.ts +5 -5
  6. package/src/cli/index.ts +18 -17
  7. package/src/cli/start.ts +2 -4
  8. package/src/core/build.ts +17 -17
  9. package/src/core/client/App.svelte +12 -12
  10. package/src/core/client/hydrate.ts +7 -7
  11. package/src/core/client/prefetch.ts +8 -8
  12. package/src/core/client/router.svelte.ts +1 -1
  13. package/src/core/dev.ts +8 -7
  14. package/src/core/env.ts +1 -1
  15. package/src/core/envCodegen.ts +20 -20
  16. package/src/core/hooks.ts +2 -2
  17. package/src/core/html.ts +20 -20
  18. package/src/core/paths.ts +41 -0
  19. package/src/core/plugin.ts +48 -14
  20. package/src/core/prerender.ts +3 -2
  21. package/src/core/renderer.ts +3 -3
  22. package/src/core/routeFile.ts +6 -6
  23. package/src/core/routeTypes.ts +10 -10
  24. package/src/core/server.ts +4 -4
  25. package/src/core/types.ts +1 -1
  26. package/src/lib/index.ts +3 -3
  27. package/templates/default/.env.example +6 -6
  28. package/templates/default/README.md +3 -3
  29. package/templates/default/package.json +4 -4
  30. package/templates/default/public/favicon.svg +14 -0
  31. package/templates/default/src/routes/+page.svelte +4 -4
  32. package/templates/default/tsconfig.json +1 -1
  33. package/templates/demo/.env.example +52 -0
  34. package/templates/demo/README.md +23 -0
  35. package/templates/demo/package.json +20 -0
  36. package/templates/demo/public/.gitkeep +0 -0
  37. package/templates/demo/public/favicon.svg +14 -0
  38. package/templates/demo/src/app.css +132 -0
  39. package/templates/demo/src/app.d.ts +7 -0
  40. package/templates/demo/src/hooks.server.ts +21 -0
  41. package/templates/demo/src/lib/utils.ts +1 -0
  42. package/templates/demo/src/routes/(public)/+layout.svelte +31 -0
  43. package/templates/demo/src/routes/(public)/+page.svelte +79 -0
  44. package/templates/demo/src/routes/(public)/about/+page.server.ts +1 -0
  45. package/templates/demo/src/routes/(public)/about/+page.svelte +31 -0
  46. package/templates/demo/src/routes/(public)/all/[...catchall]/+page.svelte +38 -0
  47. package/templates/demo/src/routes/(public)/blog/+page.svelte +55 -0
  48. package/templates/demo/src/routes/(public)/blog/[slug]/+page.server.ts +62 -0
  49. package/templates/demo/src/routes/(public)/blog/[slug]/+page.svelte +53 -0
  50. package/templates/demo/src/routes/+error.svelte +15 -0
  51. package/templates/demo/src/routes/+layout.server.ts +10 -0
  52. package/templates/demo/src/routes/+layout.svelte +6 -0
  53. package/templates/demo/src/routes/actions-test/+page.server.ts +28 -0
  54. package/templates/demo/src/routes/actions-test/+page.svelte +60 -0
  55. package/templates/demo/src/routes/api/hello/+server.ts +44 -0
  56. package/templates/demo/tsconfig.json +22 -0
@@ -1,6 +1,6 @@
1
1
  # {{PROJECT_NAME}}
2
2
 
3
- A [Bunia](https://github.com/bosapi/bunia) project — SSR · Svelte 5 · Bun · ElysiaJS.
3
+ A [Bosbun](https://github.com/bosapi/bosbun) project — SSR · Svelte 5 · Bun · ElysiaJS.
4
4
 
5
5
  ## Getting Started
6
6
 
@@ -45,7 +45,7 @@ Fetch data on the server before rendering:
45
45
 
46
46
  ```typescript
47
47
  // src/routes/blog/[slug]/+page.server.ts
48
- import type { LoadEvent } from "bunia";
48
+ import type { LoadEvent } from "bosbun";
49
49
 
50
50
  export async function load({ params }: LoadEvent) {
51
51
  return { post: await getPost(params.slug) };
@@ -97,6 +97,6 @@ cn("px-4 py-2", isActive && "bg-primary")
97
97
 
98
98
  ## Learn More
99
99
 
100
- - [Bunia documentation](https://github.com/bosapi/bunia)
100
+ - [Bosbun documentation](https://github.com/bosapi/bosbun)
101
101
  - [Svelte 5 docs](https://svelte.dev)
102
102
  - [Tailwind CSS v4](https://tailwindcss.com)
@@ -3,13 +3,13 @@
3
3
  "private": true,
4
4
  "type": "module",
5
5
  "scripts": {
6
- "dev": "bunia dev",
7
- "build": "bunia build",
8
- "start": "bunia start",
6
+ "dev": "bosbun dev",
7
+ "build": "bosbun build",
8
+ "start": "bosbun start",
9
9
  "check": "tsc --noEmit"
10
10
  },
11
11
  "dependencies": {
12
- "bunia": "*",
12
+ "bosbun": "*",
13
13
  "svelte": "^5.20.0",
14
14
  "clsx": "^2.1.1",
15
15
  "tailwind-merge": "^3.5.0"
@@ -0,0 +1,14 @@
1
+ <svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
2
+ <!-- Top block -->
3
+ <rect fill="currentColor" x="50" y="50" width="28" height="28" rx="6"/>
4
+ <rect fill="currentColor" x="86" y="50" width="60" height="28" rx="6"/>
5
+
6
+ <!-- Middle block -->
7
+ <rect fill="currentColor" x="86" y="86" width="72" height="28" rx="6"/>
8
+
9
+ <!-- Bottom block -->
10
+ <rect fill="currentColor" x="86" y="122" width="60" height="28" rx="6"/>
11
+
12
+ <!-- Connector bar on left -->
13
+ <rect fill="currentColor" x="50" y="50" width="28" height="100" rx="6"/>
14
+ </svg>
@@ -4,16 +4,16 @@
4
4
 
5
5
  <main class="flex min-h-screen flex-col items-center justify-center gap-6 p-8">
6
6
  <div class="flex flex-col items-center gap-3 text-center">
7
- <p class="text-6xl">🐰</p>
7
+ <img src="/favicon.svg" alt="" class="size-16" />
8
8
  <h1 class="text-4xl font-bold tracking-tight">{name}</h1>
9
9
  <p class="text-muted-foreground text-lg">
10
- A Bunia project — SSR + Svelte 5 + Bun + ElysiaJS
10
+ A Bosbun project — SSR + Svelte 5 + Bun + ElysiaJS
11
11
  </p>
12
12
  </div>
13
13
 
14
14
  <div class="mt-4 flex gap-3">
15
15
  <a
16
- href="https://github.com/bosapi/bunia"
16
+ href="https://github.com/bosapi/bosbun"
17
17
  target="_blank"
18
18
  rel="noopener noreferrer"
19
19
  class="bg-primary text-primary-foreground hover:bg-primary/90 rounded-md px-4 py-2 text-sm font-medium transition-colors"
@@ -21,7 +21,7 @@
21
21
  Docs
22
22
  </a>
23
23
  <a
24
- href="https://github.com/bosapi/bunia/tree/main/registry"
24
+ href="https://github.com/bosapi/bosbun/tree/main/registry"
25
25
  target="_blank"
26
26
  rel="noopener noreferrer"
27
27
  class="border-border bg-secondary text-secondary-foreground hover:bg-secondary/80 rounded-md border px-4 py-2 text-sm font-medium transition-colors"
@@ -11,7 +11,7 @@
11
11
  "verbatimModuleSyntax": true,
12
12
  "types": ["bun-types"],
13
13
  "lib": ["dom", "dom.iterable", "esnext"],
14
- "rootDirs": [".", ".bunia/types"],
14
+ "rootDirs": [".", ".bosbun/types"],
15
15
  "paths": {
16
16
  "$lib": ["./src/lib"],
17
17
  "$lib/*": ["./src/lib/*"]
@@ -0,0 +1,52 @@
1
+ # Server port. Defaults to 9000 in production, 9001 in dev (proxied via :9000).
2
+ PORT=9000
3
+
4
+ # Maximum request body size. Supports K/M/G suffixes or "Infinity". Defaults to 512K.
5
+ BODY_SIZE_LIMIT=512K
6
+
7
+ # Comma-separated list of allowed CORS origins for CSRF validation.
8
+ # Leave unset to allow same-origin requests only.
9
+ # Example: https://app.example.com, https://admin.example.com
10
+ CSRF_ALLOWED_ORIGINS=
11
+
12
+ # Comma-separated list of origins allowed to make cross-origin requests.
13
+ # Leave unset to disable CORS (browsers block cross-origin requests by default).
14
+ # Example: https://app.example.com, http://localhost:5173
15
+ CORS_ALLOWED_ORIGINS=
16
+
17
+ # Comma-separated HTTP methods to allow in CORS requests.
18
+ # Default: GET, HEAD, PUT, PATCH, POST, DELETE
19
+ # CORS_ALLOWED_METHODS=GET, POST
20
+
21
+ # Comma-separated request headers to allow in CORS requests.
22
+ # Default: Content-Type, Authorization
23
+ # CORS_ALLOWED_HEADERS=Content-Type, Authorization, X-Custom-Header
24
+
25
+ # Comma-separated response headers to expose to the browser.
26
+ # Default: none
27
+ # CORS_EXPOSED_HEADERS=X-Total-Count, X-Request-Id
28
+
29
+ # Whether to allow cookies and auth credentials in cross-origin requests.
30
+ # Must be "true" to enable; requires CORS_ALLOWED_ORIGINS to be set (not wildcard).
31
+ # Default: false
32
+ # CORS_CREDENTIALS=true
33
+
34
+ # Preflight response cache duration in seconds.
35
+ # Default: 86400 (24 hours)
36
+ # CORS_MAX_AGE=86400
37
+
38
+ # Timeout for load() functions (layout + page) in milliseconds. Defaults to 5000 (5s).
39
+ # Set to 0 or Infinity to disable.
40
+ # LOAD_TIMEOUT=5000
41
+
42
+ # Timeout for metadata() functions in milliseconds. Defaults to 3000 (3s).
43
+ # Set to 0 or Infinity to disable.
44
+ # METADATA_TIMEOUT=3000
45
+
46
+ # Timeout for prerender fetches during build in milliseconds. Defaults to 5000 (5s).
47
+ # Set to 0 or Infinity to disable.
48
+ # PRERENDER_TIMEOUT=5000
49
+
50
+ # Set automatically by the framework (bosbun dev / bosbun build / bosbun start).
51
+ # Do not set manually.
52
+ # NODE_ENV=production
@@ -0,0 +1,23 @@
1
+ # {{PROJECT_NAME}}
2
+
3
+ A [Bosbun](https://github.com/nicholascostadev/bosbun) project with demo routes, hooks, API endpoints, and form actions.
4
+
5
+ ## Running
6
+
7
+ ```bash
8
+ bun x bosbun dev # http://localhost:9000
9
+ bun x bosbun build # production build
10
+ bun x bosbun start # run production server
11
+ ```
12
+
13
+ ## Routes
14
+
15
+ | URL | File | Description |
16
+ |-----|------|-------------|
17
+ | `/` | `(public)/+page.svelte` | Home page |
18
+ | `/about` | `(public)/about/+page.svelte` | About page |
19
+ | `/blog` | `(public)/blog/+page.svelte` | Blog listing |
20
+ | `/blog/:slug` | `(public)/blog/[slug]/+page.svelte` | Blog post — fetched via server loader |
21
+ | `/api/hello` | `api/hello/+server.ts` | Multi-method JSON API |
22
+ | `/actions-test` | `actions-test/+page.svelte` | Form actions demo |
23
+ | `/*` | `(public)/[...catchall]/+page.svelte` | 404 catch-all |
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "{{PROJECT_NAME}}",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "bosbun dev",
7
+ "build": "bosbun build",
8
+ "start": "bosbun start"
9
+ },
10
+ "dependencies": {
11
+ "bosbun": "*",
12
+ "svelte": "^5.20.0",
13
+ "clsx": "^2.1.1",
14
+ "tailwind-merge": "^3.5.0"
15
+ },
16
+ "devDependencies": {
17
+ "@types/bun": "latest",
18
+ "typescript": "^5"
19
+ }
20
+ }
File without changes
@@ -0,0 +1,14 @@
1
+ <svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
2
+ <!-- Top block -->
3
+ <rect fill="currentColor" x="50" y="50" width="28" height="28" rx="6"/>
4
+ <rect fill="currentColor" x="86" y="50" width="60" height="28" rx="6"/>
5
+
6
+ <!-- Middle block -->
7
+ <rect fill="currentColor" x="86" y="86" width="72" height="28" rx="6"/>
8
+
9
+ <!-- Bottom block -->
10
+ <rect fill="currentColor" x="86" y="122" width="60" height="28" rx="6"/>
11
+
12
+ <!-- Connector bar on left -->
13
+ <rect fill="currentColor" x="50" y="50" width="28" height="100" rx="6"/>
14
+ </svg>
@@ -0,0 +1,132 @@
1
+ @import "tailwindcss";
2
+ @source "../src";
3
+
4
+ /*
5
+ * ─── shadcn-inspired Design Tokens ──────────────────────
6
+ * CSS custom properties for light & dark themes.
7
+ * Uses HSL values so Tailwind can apply opacity modifiers.
8
+ */
9
+
10
+ @theme {
11
+ --color-background: hsl(var(--background));
12
+ --color-foreground: hsl(var(--foreground));
13
+
14
+ --color-card: hsl(var(--card));
15
+ --color-card-foreground: hsl(var(--card-foreground));
16
+
17
+ --color-popover: hsl(var(--popover));
18
+ --color-popover-foreground: hsl(var(--popover-foreground));
19
+
20
+ --color-primary: hsl(var(--primary));
21
+ --color-primary-foreground: hsl(var(--primary-foreground));
22
+
23
+ --color-secondary: hsl(var(--secondary));
24
+ --color-secondary-foreground: hsl(var(--secondary-foreground));
25
+
26
+ --color-muted: hsl(var(--muted));
27
+ --color-muted-foreground: hsl(var(--muted-foreground));
28
+
29
+ --color-accent: hsl(var(--accent));
30
+ --color-accent-foreground: hsl(var(--accent-foreground));
31
+
32
+ --color-destructive: hsl(var(--destructive));
33
+ --color-destructive-foreground: hsl(var(--destructive-foreground));
34
+
35
+ --color-border: hsl(var(--border));
36
+ --color-input: hsl(var(--input));
37
+ --color-ring: hsl(var(--ring));
38
+
39
+ --radius-sm: calc(var(--radius) - 4px);
40
+ --radius-md: calc(var(--radius) - 2px);
41
+ --radius-lg: var(--radius);
42
+ --radius-xl: calc(var(--radius) + 4px);
43
+ }
44
+
45
+ /* ─── Light Theme (Default) ─────────────────────────────── */
46
+
47
+ :root {
48
+ --background: 0 0% 100%;
49
+ --foreground: 222.2 84% 4.9%;
50
+
51
+ --card: 0 0% 100%;
52
+ --card-foreground: 222.2 84% 4.9%;
53
+
54
+ --popover: 0 0% 100%;
55
+ --popover-foreground: 222.2 84% 4.9%;
56
+
57
+ --primary: 222.2 47.4% 11.2%;
58
+ --primary-foreground: 210 40% 98%;
59
+
60
+ --secondary: 210 40% 96.1%;
61
+ --secondary-foreground: 222.2 47.4% 11.2%;
62
+
63
+ --muted: 210 40% 96.1%;
64
+ --muted-foreground: 215.4 16.3% 46.9%;
65
+
66
+ --accent: 210 40% 96.1%;
67
+ --accent-foreground: 222.2 47.4% 11.2%;
68
+
69
+ --destructive: 0 84.2% 60.2%;
70
+ --destructive-foreground: 210 40% 98%;
71
+
72
+ --border: 214.3 31.8% 91.4%;
73
+ --input: 214.3 31.8% 91.4%;
74
+ --ring: 222.2 84% 4.9%;
75
+
76
+ --radius: 0.5rem;
77
+ }
78
+
79
+ /* ─── Dark Theme ─────────────────────────────────────────── */
80
+
81
+ .dark {
82
+ --background: 222.2 84% 4.9%;
83
+ --foreground: 210 40% 98%;
84
+
85
+ --card: 222.2 84% 4.9%;
86
+ --card-foreground: 210 40% 98%;
87
+
88
+ --popover: 222.2 84% 4.9%;
89
+ --popover-foreground: 210 40% 98%;
90
+
91
+ --primary: 210 40% 98%;
92
+ --primary-foreground: 222.2 47.4% 11.2%;
93
+
94
+ --secondary: 217.2 32.6% 17.5%;
95
+ --secondary-foreground: 210 40% 98%;
96
+
97
+ --muted: 217.2 32.6% 17.5%;
98
+ --muted-foreground: 215 20.2% 65.1%;
99
+
100
+ --accent: 217.2 32.6% 17.5%;
101
+ --accent-foreground: 210 40% 98%;
102
+
103
+ --destructive: 0 62.8% 30.6%;
104
+ --destructive-foreground: 210 40% 98%;
105
+
106
+ --border: 217.2 32.6% 17.5%;
107
+ --input: 217.2 32.6% 17.5%;
108
+ --ring: 212.7 26.8% 83.9%;
109
+ }
110
+
111
+ /* ─── Base Styles ────────────────────────────────────────── */
112
+
113
+ @layer base {
114
+ * {
115
+ border-color: theme(--color-border);
116
+ }
117
+
118
+ body {
119
+ background-color: theme(--color-background);
120
+ color: theme(--color-foreground);
121
+ font-family:
122
+ "Inter",
123
+ system-ui,
124
+ -apple-system,
125
+ BlinkMacSystemFont,
126
+ "Segoe UI",
127
+ Roboto,
128
+ "Helvetica Neue",
129
+ Arial,
130
+ sans-serif;
131
+ }
132
+ }
@@ -0,0 +1,7 @@
1
+ /// <reference types="svelte" />
2
+
3
+ declare module "*.svelte" {
4
+ import type { Component } from "svelte";
5
+ const component: Component<Record<string, any>, Record<string, any>, any>;
6
+ export default component;
7
+ }
@@ -0,0 +1,21 @@
1
+ import { sequence } from "bosbun";
2
+ import type { Handle } from "bosbun";
3
+
4
+ // Sets locals that every loader and API handler can read
5
+ const authHandle: Handle = async ({ event, resolve }) => {
6
+ event.locals.requestTime = Date.now();
7
+ event.locals.user = null; // replace with real session logic
8
+ return resolve(event);
9
+ };
10
+
11
+ // Logs each request with method, path, status, and duration
12
+ const loggingHandle: Handle = async ({ event, resolve }) => {
13
+ const start = Date.now();
14
+ const res = await resolve(event);
15
+ const ms = Date.now() - start;
16
+ console.log(`[${event.request.method}] ${event.url.pathname} ${res.status} (${ms}ms)`);
17
+ res.headers.set("X-Response-Time", `${ms}ms`);
18
+ return res;
19
+ };
20
+
21
+ export const handle = sequence(authHandle, loggingHandle);
@@ -0,0 +1 @@
1
+ export { cn } from "bosbun";
@@ -0,0 +1,31 @@
1
+ <script lang="ts">
2
+ import type { LayoutData } from '../$types';
3
+
4
+ let { children, data }: { children: any; data: LayoutData } = $props();
5
+ </script>
6
+
7
+ <div class="flex min-h-screen flex-col bg-background text-foreground">
8
+ <header class="sticky top-0 z-10 border-b bg-background/80 backdrop-blur">
9
+ <nav class="mx-auto flex max-w-4xl items-center gap-6 px-4 py-3">
10
+ <a href="/" class="font-bold tracking-tight flex items-center gap-2"><img src="/favicon.svg" alt="" class="size-5" /> {{PROJECT_NAME}}</a>
11
+ <a href="/" class="text-sm text-muted-foreground hover:text-foreground transition-colors">Home</a>
12
+ <a href="/about" class="text-sm text-muted-foreground hover:text-foreground transition-colors">About</a>
13
+ <a href="/blog" class="text-sm text-muted-foreground hover:text-foreground transition-colors">Blog</a>
14
+ <a href="/all/foo/bar" class="text-sm text-muted-foreground hover:text-foreground transition-colors">Catch-all</a>
15
+ <a href="/api/hello" target="_blank" class="text-sm text-muted-foreground hover:text-foreground transition-colors">API</a>
16
+ </nav>
17
+ </header>
18
+
19
+ <main class="mx-auto w-full max-w-4xl flex-1 px-4 py-8">
20
+ {@render children()}
21
+ </main>
22
+
23
+ <footer class="border-t py-4 text-center text-sm text-muted-foreground">
24
+ Powered by Bosbun
25
+ {#if data.requestTime}
26
+ <span class="ml-2 opacity-40 font-mono text-xs">
27
+ req at {new Date(data.requestTime).toISOString()}
28
+ </span>
29
+ {/if}
30
+ </footer>
31
+ </div>
@@ -0,0 +1,79 @@
1
+ <script lang="ts">
2
+ let count = $state(0);
3
+
4
+ const features = [
5
+ { icon: "📂", label: "File-based routing", desc: "+page.svelte, +layout.svelte, route groups, dynamic [params]" },
6
+ { icon: "⚡", label: "SSR + Hydration", desc: "Server renders HTML, Svelte hydrates on the client" },
7
+ { icon: "🔁", label: "Server loaders", desc: "+page.server.ts and +layout.server.ts with parent() threading" },
8
+ { icon: "🪝", label: "Hooks", desc: "sequence() middleware — auth, logging, locals" },
9
+ { icon: "📡", label: "API routes", desc: "+server.ts exports GET, POST, PUT, PATCH, DELETE" },
10
+ { icon: "🧩", label: "Component registry", desc: "bosbun add button — shadcn-style, code you own" },
11
+ { icon: "✨", label: "feat system", desc: "bosbun feat login — scaffold entire features, not just components" },
12
+ ];
13
+ </script>
14
+
15
+ <svelte:head>
16
+ <title>{{PROJECT_NAME}}</title>
17
+ <meta name="description" content="{{PROJECT_NAME}} — SSR + Svelte 5 + Bun + ElysiaJS" />
18
+ </svelte:head>
19
+
20
+ <div class="space-y-12">
21
+ <!-- Hero -->
22
+ <div class="space-y-3 pt-4">
23
+ <h1 class="text-5xl font-bold tracking-tight flex items-center gap-3"><img src="/favicon.svg" alt="" class="size-10" /> {{PROJECT_NAME}}</h1>
24
+ <p class="text-xl text-muted-foreground max-w-xl">
25
+ A minimalist fullstack framework — SSR, Svelte 5 Runes, Bun, and ElysiaJS.
26
+ </p>
27
+ </div>
28
+
29
+ <!-- Svelte 5 reactivity demo -->
30
+ <div class="rounded-lg border bg-card p-6 space-y-3 max-w-sm">
31
+ <p class="text-sm font-medium text-muted-foreground">Svelte 5 $state demo</p>
32
+ <p class="text-5xl font-bold tabular-nums">{count}</p>
33
+ <div class="flex gap-2">
34
+ <button
35
+ onclick={() => count++}
36
+ class="rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors"
37
+ >
38
+ +1
39
+ </button>
40
+ <button
41
+ onclick={() => count = 0}
42
+ class="rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted transition-colors"
43
+ >
44
+ Reset
45
+ </button>
46
+ </div>
47
+ </div>
48
+
49
+ <!-- Features grid -->
50
+ <div class="space-y-4">
51
+ <h2 class="text-2xl font-semibold tracking-tight">Features</h2>
52
+ <div class="grid gap-4 sm:grid-cols-2">
53
+ {#each features as f}
54
+ <div class="rounded-lg border bg-card p-4 space-y-1">
55
+ <p class="font-medium">{f.icon} {f.label}</p>
56
+ <p class="text-sm text-muted-foreground">{f.desc}</p>
57
+ </div>
58
+ {/each}
59
+ </div>
60
+ </div>
61
+
62
+ <!-- Navigation demo -->
63
+ <div class="space-y-4">
64
+ <h2 class="text-2xl font-semibold tracking-tight">Routes in this demo</h2>
65
+ <div class="flex flex-wrap gap-2">
66
+ {#each ["/", "/about", "/blog", "/blog/hello-world", "/blog/route-groups", "/all/foo/bar", "/missing-page"] as href}
67
+ <a
68
+ {href}
69
+ class="rounded-md border px-3 py-1.5 text-sm font-mono hover:bg-muted transition-colors"
70
+ >{href}</a>
71
+ {/each}
72
+ <a
73
+ href="/api/hello"
74
+ target="_blank"
75
+ class="rounded-md border px-3 py-1.5 text-sm font-mono hover:bg-muted transition-colors"
76
+ >/api/hello ↗</a>
77
+ </div>
78
+ </div>
79
+ </div>
@@ -0,0 +1 @@
1
+ export const prerender = true;
@@ -0,0 +1,31 @@
1
+ <svelte:head>
2
+ <title>About | {{PROJECT_NAME}}</title>
3
+ </svelte:head>
4
+
5
+ <div class="space-y-6 max-w-2xl">
6
+ <h1 class="text-4xl font-bold tracking-tight">About {{PROJECT_NAME}}</h1>
7
+ <p class="text-muted-foreground text-lg">
8
+ A minimalist fullstack framework built on Bun, ElysiaJS, and Svelte 5.
9
+ </p>
10
+
11
+ <ul class="space-y-2 text-foreground">
12
+ {#each [
13
+ "Bun runtime — fast builds, native TypeScript",
14
+ "ElysiaJS — HTTP server with type-safe routing",
15
+ "Svelte 5 Runes — fine-grained reactivity",
16
+ "Isomorphic SSR with client hydration",
17
+ "File-based routing (SvelteKit-compatible conventions)",
18
+ "Nested layouts and route groups (public), (auth), (admin)",
19
+ "Dynamic params [slug] and catch-all [...rest]",
20
+ "Server loaders with parent() data threading",
21
+ "Hooks — sequence() middleware for auth, logging, etc.",
22
+ "Component registry — bosbun add button",
23
+ "Feature registry — bosbun feat login",
24
+ ] as item}
25
+ <li class="flex items-start gap-2">
26
+ <span class="text-primary mt-0.5">✓</span>
27
+ <span>{item}</span>
28
+ </li>
29
+ {/each}
30
+ </ul>
31
+ </div>
@@ -0,0 +1,38 @@
1
+ <script lang="ts">
2
+ let { data = {} }: { data?: Record<string, any> } = $props();
3
+ const segments = $derived(
4
+ ((data as any)?.params?.catchall ?? "")
5
+ .split("/")
6
+ .filter(Boolean)
7
+ );
8
+ </script>
9
+
10
+ <svelte:head>
11
+ <title>Catch-all Demo | {{PROJECT_NAME}}</title>
12
+ </svelte:head>
13
+
14
+ <div class="flex flex-col items-center justify-center py-24 text-center space-y-6">
15
+ <h1 class="text-3xl font-bold">Catch-all Route Demo</h1>
16
+ <p class="text-muted-foreground text-sm">
17
+ This page matches <code class="bg-muted rounded px-1 font-mono">/all/[...catchall]</code>
18
+ </p>
19
+
20
+ {#if segments.length > 0}
21
+ <div class="mt-2 space-y-1">
22
+ <p class="text-sm text-muted-foreground">Captured segments:</p>
23
+ <div class="flex gap-2 flex-wrap justify-center">
24
+ {#each segments as segment, i}
25
+ <span class="bg-muted rounded px-2 py-1 font-mono text-sm">
26
+ [{i}] {segment}
27
+ </span>
28
+ {/each}
29
+ </div>
30
+ </div>
31
+ {:else}
32
+ <p class="text-muted-foreground text-sm italic">No segments captured</p>
33
+ {/if}
34
+
35
+ <a href="/" class="mt-4 rounded-md border px-4 py-2 text-sm hover:bg-muted transition-colors">
36
+ Go Home
37
+ </a>
38
+ </div>
@@ -0,0 +1,55 @@
1
+ <script lang="ts">
2
+ const posts = [
3
+ {
4
+ slug: "hello-world",
5
+ title: "Hello, World!",
6
+ date: "2026-03-05",
7
+ excerpt: "The first post in the demo — a quick intro to the framework.",
8
+ tags: ["intro", "bosbun"],
9
+ },
10
+ {
11
+ slug: "route-groups",
12
+ title: "Route Groups Explained",
13
+ date: "2026-03-04",
14
+ excerpt: "How (public), (auth), (admin) groups work — invisible in URLs, share layouts.",
15
+ tags: ["routing", "layouts"],
16
+ },
17
+ {
18
+ slug: "dynamic-params",
19
+ title: "Dynamic Params with [slug]",
20
+ date: "2026-03-03",
21
+ excerpt: "Using [slug] segments to match any value and pass it to server loaders.",
22
+ tags: ["routing", "dynamic"],
23
+ },
24
+ ];
25
+ </script>
26
+
27
+ <svelte:head>
28
+ <title>Blog | {{PROJECT_NAME}}</title>
29
+ </svelte:head>
30
+
31
+ <div class="space-y-8">
32
+ <div class="space-y-2">
33
+ <h1 class="text-4xl font-bold tracking-tight">Blog</h1>
34
+ <p class="text-muted-foreground">Routing patterns and framework internals.</p>
35
+ </div>
36
+
37
+ <div class="grid gap-4" data-bosbun-preload="hover">
38
+ {#each posts as post}
39
+ <a href="/blog/{post.slug}" class="group block rounded-lg border bg-card p-5 hover:border-primary transition-colors">
40
+ <div class="flex items-start justify-between gap-4">
41
+ <div class="space-y-1">
42
+ <p class="font-semibold group-hover:text-primary transition-colors">{post.title}</p>
43
+ <p class="text-xs text-muted-foreground font-mono">{post.date}</p>
44
+ </div>
45
+ <div class="flex gap-1 shrink-0">
46
+ {#each post.tags as tag}
47
+ <span class="rounded-full bg-secondary px-2 py-0.5 text-xs text-secondary-foreground">{tag}</span>
48
+ {/each}
49
+ </div>
50
+ </div>
51
+ <p class="mt-2 text-sm text-muted-foreground">{post.excerpt}</p>
52
+ </a>
53
+ {/each}
54
+ </div>
55
+ </div>