bosia 0.2.3 → 0.3.1
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.
- package/README.md +39 -39
- package/package.json +56 -54
- package/src/ambient.d.ts +31 -0
- package/src/cli/add.ts +120 -114
- package/src/cli/build.ts +10 -10
- package/src/cli/create.ts +142 -137
- package/src/cli/dev.ts +7 -9
- package/src/cli/feat.ts +266 -258
- package/src/cli/index.ts +51 -42
- package/src/cli/registry.ts +136 -115
- package/src/cli/start.ts +17 -17
- package/src/cli/test.ts +25 -0
- package/src/core/build.ts +72 -56
- package/src/core/client/App.svelte +177 -156
- package/src/core/client/appState.svelte.ts +33 -31
- package/src/core/client/enhance.ts +83 -78
- package/src/core/client/hydrate.ts +95 -81
- package/src/core/client/prefetch.ts +101 -94
- package/src/core/client/router.svelte.ts +64 -51
- package/src/core/cookies.ts +70 -66
- package/src/core/cors.ts +44 -35
- package/src/core/csrf.ts +38 -38
- package/src/core/dedup.ts +17 -17
- package/src/core/dev.ts +196 -168
- package/src/core/env.ts +160 -148
- package/src/core/envCodegen.ts +73 -73
- package/src/core/errors.ts +48 -49
- package/src/core/hooks.ts +50 -50
- package/src/core/html.ts +184 -145
- package/src/core/matcher.ts +130 -121
- package/src/core/paths.ts +8 -10
- package/src/core/plugin.ts +113 -107
- package/src/core/prerender.ts +191 -122
- package/src/core/renderer.ts +359 -286
- package/src/core/routeFile.ts +140 -127
- package/src/core/routeTypes.ts +144 -83
- package/src/core/scanner.ts +125 -95
- package/src/core/server.ts +538 -424
- package/src/core/types.ts +25 -20
- package/src/lib/index.ts +8 -8
- package/src/lib/utils.ts +44 -30
- package/templates/default/.prettierignore +5 -0
- package/templates/default/.prettierrc.json +9 -0
- package/templates/default/README.md +5 -5
- package/templates/default/package.json +22 -18
- package/templates/default/src/app.css +80 -80
- package/templates/default/src/app.d.ts +3 -3
- package/templates/default/src/routes/+error.svelte +7 -10
- package/templates/default/src/routes/+layout.svelte +2 -2
- package/templates/default/src/routes/+page.svelte +30 -32
- package/templates/default/src/routes/about/+page.svelte +3 -3
- package/templates/default/tsconfig.json +20 -20
- package/templates/demo/.prettierignore +5 -0
- package/templates/demo/.prettierrc.json +9 -0
- package/templates/demo/README.md +9 -9
- package/templates/demo/package.json +22 -17
- package/templates/demo/src/app.css +80 -80
- package/templates/demo/src/app.d.ts +3 -3
- package/templates/demo/src/hooks.server.ts +9 -9
- package/templates/demo/src/routes/(public)/+layout.svelte +45 -23
- package/templates/demo/src/routes/(public)/+page.svelte +96 -67
- package/templates/demo/src/routes/(public)/about/+page.svelte +13 -25
- package/templates/demo/src/routes/(public)/all/[...catchall]/+page.svelte +24 -28
- package/templates/demo/src/routes/(public)/blog/+page.svelte +55 -46
- package/templates/demo/src/routes/(public)/blog/[slug]/+page.server.ts +36 -38
- package/templates/demo/src/routes/(public)/blog/[slug]/+page.svelte +60 -42
- package/templates/demo/src/routes/+error.svelte +10 -7
- package/templates/demo/src/routes/+layout.server.ts +4 -4
- package/templates/demo/src/routes/+layout.svelte +2 -2
- package/templates/demo/src/routes/actions-test/+page.server.ts +16 -16
- package/templates/demo/src/routes/actions-test/+page.svelte +49 -49
- package/templates/demo/src/routes/api/hello/+server.ts +25 -25
- package/templates/demo/tsconfig.json +20 -20
- package/templates/todo/.prettierignore +5 -0
- package/templates/todo/.prettierrc.json +9 -0
- package/templates/todo/README.md +9 -9
- package/templates/todo/package.json +22 -17
- package/templates/todo/src/app.css +80 -80
- package/templates/todo/src/app.d.ts +7 -7
- package/templates/todo/src/hooks.server.ts +9 -9
- package/templates/todo/src/routes/+error.svelte +10 -7
- package/templates/todo/src/routes/+layout.server.ts +4 -4
- package/templates/todo/src/routes/+layout.svelte +2 -2
- package/templates/todo/src/routes/+page.svelte +44 -44
- package/templates/todo/template.json +1 -1
- package/templates/todo/tsconfig.json +20 -20
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"allowJs": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"allowImportingTsExtensions": true,
|
|
10
|
+
"noEmit": true,
|
|
11
|
+
"verbatimModuleSyntax": true,
|
|
12
|
+
"types": ["bun-types"],
|
|
13
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
14
|
+
"rootDirs": [".", ".bosia/types"],
|
|
15
|
+
"paths": {
|
|
16
|
+
"$lib": ["./src/lib"],
|
|
17
|
+
"$lib/*": ["./src/lib/*"]
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"include": ["src/**/*"],
|
|
21
|
+
"exclude": ["node_modules", "dist"]
|
|
22
22
|
}
|
package/templates/demo/README.md
CHANGED
|
@@ -12,15 +12,15 @@ bun x bosia start # run production server
|
|
|
12
12
|
|
|
13
13
|
## Routes
|
|
14
14
|
|
|
15
|
-
| URL
|
|
16
|
-
|
|
17
|
-
| `/`
|
|
18
|
-
| `/about`
|
|
19
|
-
| `/blog`
|
|
20
|
-
| `/blog/:slug`
|
|
21
|
-
| `/api/hello`
|
|
22
|
-
| `/actions-test` | `actions-test/+page.svelte`
|
|
23
|
-
| `/*`
|
|
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 |
|
|
24
24
|
|
|
25
25
|
## Learn More
|
|
26
26
|
|
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
2
|
+
"name": "{{PROJECT_NAME}}",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "bosia dev",
|
|
7
|
+
"build": "bosia build",
|
|
8
|
+
"start": "bosia start",
|
|
9
|
+
"check": "tsc --noEmit && prettier --check .",
|
|
10
|
+
"format": "prettier --write .",
|
|
11
|
+
"format:check": "prettier --check ."
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"bosia": "^{{BOSIA_VERSION}}",
|
|
15
|
+
"svelte": "^5.20.0",
|
|
16
|
+
"tailwind-merge": "^3.5.0"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/bun": "latest",
|
|
20
|
+
"prettier": "^3.3.0",
|
|
21
|
+
"prettier-plugin-svelte": "^3.2.0",
|
|
22
|
+
"typescript": "^5"
|
|
23
|
+
}
|
|
19
24
|
}
|
|
@@ -8,125 +8,125 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
@theme {
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
--color-background: hsl(var(--background));
|
|
12
|
+
--color-foreground: hsl(var(--foreground));
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
--color-card: hsl(var(--card));
|
|
15
|
+
--color-card-foreground: hsl(var(--card-foreground));
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
--color-popover: hsl(var(--popover));
|
|
18
|
+
--color-popover-foreground: hsl(var(--popover-foreground));
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
--color-primary: hsl(var(--primary));
|
|
21
|
+
--color-primary-foreground: hsl(var(--primary-foreground));
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
--color-secondary: hsl(var(--secondary));
|
|
24
|
+
--color-secondary-foreground: hsl(var(--secondary-foreground));
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
--color-muted: hsl(var(--muted));
|
|
27
|
+
--color-muted-foreground: hsl(var(--muted-foreground));
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
--color-accent: hsl(var(--accent));
|
|
30
|
+
--color-accent-foreground: hsl(var(--accent-foreground));
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
--color-destructive: hsl(var(--destructive));
|
|
33
|
+
--color-destructive-foreground: hsl(var(--destructive-foreground));
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
--color-border: hsl(var(--border));
|
|
36
|
+
--color-input: hsl(var(--input));
|
|
37
|
+
--color-ring: hsl(var(--ring));
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
43
|
}
|
|
44
44
|
|
|
45
45
|
/* ─── Light Theme (Default) ─────────────────────────────── */
|
|
46
46
|
|
|
47
47
|
:root {
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
--background: 0 0% 100%;
|
|
49
|
+
--foreground: 222.2 84% 4.9%;
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
--card: 0 0% 100%;
|
|
52
|
+
--card-foreground: 222.2 84% 4.9%;
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
--popover: 0 0% 100%;
|
|
55
|
+
--popover-foreground: 222.2 84% 4.9%;
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
--primary: 222.2 47.4% 11.2%;
|
|
58
|
+
--primary-foreground: 210 40% 98%;
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
--secondary: 210 40% 96.1%;
|
|
61
|
+
--secondary-foreground: 222.2 47.4% 11.2%;
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
--muted: 210 40% 96.1%;
|
|
64
|
+
--muted-foreground: 215.4 16.3% 46.9%;
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
--accent: 210 40% 96.1%;
|
|
67
|
+
--accent-foreground: 222.2 47.4% 11.2%;
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
--destructive: 0 84.2% 60.2%;
|
|
70
|
+
--destructive-foreground: 210 40% 98%;
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
--border: 214.3 31.8% 91.4%;
|
|
73
|
+
--input: 214.3 31.8% 91.4%;
|
|
74
|
+
--ring: 222.2 84% 4.9%;
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
--radius: 0.5rem;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
/* ─── Dark Theme ─────────────────────────────────────────── */
|
|
80
80
|
|
|
81
81
|
.dark {
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
--background: 222.2 84% 4.9%;
|
|
83
|
+
--foreground: 210 40% 98%;
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
--card: 222.2 84% 4.9%;
|
|
86
|
+
--card-foreground: 210 40% 98%;
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
--popover: 222.2 84% 4.9%;
|
|
89
|
+
--popover-foreground: 210 40% 98%;
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
--primary: 210 40% 98%;
|
|
92
|
+
--primary-foreground: 222.2 47.4% 11.2%;
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
--secondary: 217.2 32.6% 17.5%;
|
|
95
|
+
--secondary-foreground: 210 40% 98%;
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
--muted: 217.2 32.6% 17.5%;
|
|
98
|
+
--muted-foreground: 215 20.2% 65.1%;
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
--accent: 217.2 32.6% 17.5%;
|
|
101
|
+
--accent-foreground: 210 40% 98%;
|
|
102
102
|
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
--destructive: 0 62.8% 30.6%;
|
|
104
|
+
--destructive-foreground: 210 40% 98%;
|
|
105
105
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
109
|
}
|
|
110
110
|
|
|
111
111
|
/* ─── Base Styles ────────────────────────────────────────── */
|
|
112
112
|
|
|
113
113
|
@layer base {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
132
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="svelte" />
|
|
2
2
|
|
|
3
3
|
declare module "*.svelte" {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
import type { Component } from "svelte";
|
|
5
|
+
const component: Component<Record<string, any>, Record<string, any>, any>;
|
|
6
|
+
export default component;
|
|
7
7
|
}
|
|
@@ -3,19 +3,19 @@ import type { Handle } from "bosia";
|
|
|
3
3
|
|
|
4
4
|
// Sets locals that every loader and API handler can read
|
|
5
5
|
const authHandle: Handle = async ({ event, resolve }) => {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
event.locals.requestTime = Date.now();
|
|
7
|
+
event.locals.user = null; // replace with real session logic
|
|
8
|
+
return resolve(event);
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
// Logs each request with method, path, status, and duration
|
|
12
12
|
const loggingHandle: Handle = async ({ event, resolve }) => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
19
|
};
|
|
20
20
|
|
|
21
21
|
export const handle = sequence(authHandle, loggingHandle);
|
|
@@ -1,31 +1,53 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
2
|
+
import type { LayoutData } from "../$types";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
let { children, data }: { children: any; data: LayoutData } = $props();
|
|
5
5
|
</script>
|
|
6
6
|
|
|
7
7
|
<div class="flex min-h-screen flex-col bg-background text-foreground">
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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"
|
|
11
|
+
><img src="/favicon.svg" alt="" class="size-5" /> {data.appName}</a
|
|
12
|
+
>
|
|
13
|
+
<a
|
|
14
|
+
href="/"
|
|
15
|
+
class="text-sm text-muted-foreground hover:text-foreground transition-colors"
|
|
16
|
+
>Home</a
|
|
17
|
+
>
|
|
18
|
+
<a
|
|
19
|
+
href="/about"
|
|
20
|
+
class="text-sm text-muted-foreground hover:text-foreground transition-colors"
|
|
21
|
+
>About</a
|
|
22
|
+
>
|
|
23
|
+
<a
|
|
24
|
+
href="/blog"
|
|
25
|
+
class="text-sm text-muted-foreground hover:text-foreground transition-colors"
|
|
26
|
+
>Blog</a
|
|
27
|
+
>
|
|
28
|
+
<a
|
|
29
|
+
href="/all/foo/bar"
|
|
30
|
+
class="text-sm text-muted-foreground hover:text-foreground transition-colors"
|
|
31
|
+
>Catch-all</a
|
|
32
|
+
>
|
|
33
|
+
<a
|
|
34
|
+
href="/api/hello"
|
|
35
|
+
target="_blank"
|
|
36
|
+
class="text-sm text-muted-foreground hover:text-foreground transition-colors">API</a
|
|
37
|
+
>
|
|
38
|
+
</nav>
|
|
39
|
+
</header>
|
|
18
40
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
41
|
+
<main class="mx-auto w-full max-w-4xl flex-1 px-4 py-8">
|
|
42
|
+
{@render children()}
|
|
43
|
+
</main>
|
|
22
44
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
45
|
+
<footer class="border-t py-4 text-center text-sm text-muted-foreground">
|
|
46
|
+
Powered by Bosia
|
|
47
|
+
{#if data.requestTime}
|
|
48
|
+
<span class="ml-2 opacity-40 font-mono text-xs">
|
|
49
|
+
req at {new Date(data.requestTime).toISOString()}
|
|
50
|
+
</span>
|
|
51
|
+
{/if}
|
|
52
|
+
</footer>
|
|
31
53
|
</div>
|
|
@@ -1,79 +1,108 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
2
|
+
let count = $state(0);
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
4
|
+
const features = [
|
|
5
|
+
{
|
|
6
|
+
icon: "📂",
|
|
7
|
+
label: "File-based routing",
|
|
8
|
+
desc: "+page.svelte, +layout.svelte, route groups, dynamic [params]",
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
icon: "⚡",
|
|
12
|
+
label: "SSR + Hydration",
|
|
13
|
+
desc: "Server renders HTML, Svelte hydrates on the client",
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
icon: "🔁",
|
|
17
|
+
label: "Server loaders",
|
|
18
|
+
desc: "+page.server.ts and +layout.server.ts with parent() threading",
|
|
19
|
+
},
|
|
20
|
+
{ icon: "🪝", label: "Hooks", desc: "sequence() middleware — auth, logging, locals" },
|
|
21
|
+
{
|
|
22
|
+
icon: "📡",
|
|
23
|
+
label: "API routes",
|
|
24
|
+
desc: "+server.ts exports GET, POST, PUT, PATCH, DELETE",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
icon: "🧩",
|
|
28
|
+
label: "Component registry",
|
|
29
|
+
desc: "bosia add button — shadcn-style, code you own",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
icon: "✨",
|
|
33
|
+
label: "feat system",
|
|
34
|
+
desc: "bosia feat login — scaffold entire features, not just components",
|
|
35
|
+
},
|
|
36
|
+
];
|
|
13
37
|
</script>
|
|
14
38
|
|
|
15
39
|
<svelte:head>
|
|
16
|
-
|
|
17
|
-
|
|
40
|
+
<title>Bosia Demo</title>
|
|
41
|
+
<meta name="description" content="Bosia Demo — SSR + Svelte 5 + Bun + ElysiaJS" />
|
|
18
42
|
</svelte:head>
|
|
19
43
|
|
|
20
44
|
<div class="space-y-12">
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
45
|
+
<!-- Hero -->
|
|
46
|
+
<div class="space-y-3 pt-4">
|
|
47
|
+
<h1 class="text-5xl font-bold tracking-tight flex items-center gap-3">
|
|
48
|
+
<img src="/favicon.svg" alt="" class="size-10" />
|
|
49
|
+
Bosia Demo
|
|
50
|
+
</h1>
|
|
51
|
+
<p class="text-xl text-muted-foreground max-w-xl">
|
|
52
|
+
A minimalist fullstack framework — SSR, Svelte 5 Runes, Bun, and ElysiaJS.
|
|
53
|
+
</p>
|
|
54
|
+
</div>
|
|
28
55
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
<!-- Svelte 5 reactivity demo -->
|
|
57
|
+
<div class="rounded-lg border bg-card p-6 space-y-3 max-w-sm">
|
|
58
|
+
<p class="text-sm font-medium text-muted-foreground">Svelte 5 $state demo</p>
|
|
59
|
+
<p class="text-5xl font-bold tabular-nums">{count}</p>
|
|
60
|
+
<div class="flex gap-2">
|
|
61
|
+
<button
|
|
62
|
+
onclick={() => count++}
|
|
63
|
+
class="rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors"
|
|
64
|
+
>
|
|
65
|
+
+1
|
|
66
|
+
</button>
|
|
67
|
+
<button
|
|
68
|
+
onclick={() => (count = 0)}
|
|
69
|
+
class="rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted transition-colors"
|
|
70
|
+
>
|
|
71
|
+
Reset
|
|
72
|
+
</button>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
48
75
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
76
|
+
<!-- Features grid -->
|
|
77
|
+
<div class="space-y-4">
|
|
78
|
+
<h2 class="text-2xl font-semibold tracking-tight">Features</h2>
|
|
79
|
+
<div class="grid gap-4 sm:grid-cols-2">
|
|
80
|
+
{#each features as f}
|
|
81
|
+
<div class="rounded-lg border bg-card p-4 space-y-1">
|
|
82
|
+
<p class="font-medium">{f.icon} {f.label}</p>
|
|
83
|
+
<p class="text-sm text-muted-foreground">{f.desc}</p>
|
|
84
|
+
</div>
|
|
85
|
+
{/each}
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
61
88
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
89
|
+
<!-- Navigation demo -->
|
|
90
|
+
<div class="space-y-4">
|
|
91
|
+
<h2 class="text-2xl font-semibold tracking-tight">Routes in this demo</h2>
|
|
92
|
+
<div class="flex flex-wrap gap-2">
|
|
93
|
+
{#each ["/", "/about", "/blog", "/blog/hello-world", "/blog/route-groups", "/all/foo/bar", "/missing-page"] as href}
|
|
94
|
+
<a
|
|
95
|
+
{href}
|
|
96
|
+
class="rounded-md border px-3 py-1.5 text-sm font-mono hover:bg-muted transition-colors"
|
|
97
|
+
>{href}</a
|
|
98
|
+
>
|
|
99
|
+
{/each}
|
|
100
|
+
<a
|
|
101
|
+
href="/api/hello"
|
|
102
|
+
target="_blank"
|
|
103
|
+
class="rounded-md border px-3 py-1.5 text-sm font-mono hover:bg-muted transition-colors"
|
|
104
|
+
>/api/hello ↗</a
|
|
105
|
+
>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
79
108
|
</div>
|