@pyreon/create-zero 0.1.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.
@@ -0,0 +1,133 @@
1
+ import { useHead } from '@pyreon/head'
2
+ import type { LoaderContext } from '@pyreon/zero'
3
+
4
+ export const meta = {
5
+ title: 'Dashboard — Pyreon Zero',
6
+ }
7
+
8
+ /**
9
+ * Navigation guard — runs before the route renders.
10
+ * Demonstrates how to protect routes with authentication checks.
11
+ *
12
+ * In a real app, you'd check a session cookie, JWT token, or auth state.
13
+ * Returning a string redirects to that path.
14
+ */
15
+ export function guard() {
16
+ // Simulate auth check — in a real app, check session/token
17
+ const isAuthenticated =
18
+ typeof window !== 'undefined' &&
19
+ localStorage.getItem('zero-demo-auth') === 'true'
20
+
21
+ if (!isAuthenticated) {
22
+ return '/about' // Redirect unauthenticated users
23
+ }
24
+ return true // Allow navigation
25
+ }
26
+
27
+ /**
28
+ * Per-route middleware — runs on the server before the loader.
29
+ * Great for logging, auth checks, rate limiting per-route.
30
+ */
31
+ export const middleware = async (
32
+ request: Request,
33
+ next: (req: Request) => Promise<Response>,
34
+ ) => {
35
+ const start = Date.now()
36
+ const response = await next(request)
37
+ const duration = Date.now() - start
38
+
39
+ // Add server timing header
40
+ const headers = new Headers(response.headers)
41
+ headers.set('Server-Timing', `route;dur=${duration}`)
42
+
43
+ return new Response(response.body, {
44
+ status: response.status,
45
+ statusText: response.statusText,
46
+ headers,
47
+ })
48
+ }
49
+
50
+ export async function loader(_ctx: LoaderContext) {
51
+ return {
52
+ user: 'Demo User',
53
+ stats: {
54
+ views: 12_847,
55
+ routes: 6,
56
+ buildTime: '1.2s',
57
+ },
58
+ }
59
+ }
60
+
61
+ export default function Dashboard() {
62
+ useHead({ title: meta.title })
63
+
64
+ return (
65
+ <>
66
+ <div class="page-header">
67
+ <span class="badge">Protected Route</span>
68
+ <h1 style="margin-top: var(--space-md);">Dashboard</h1>
69
+ <p>
70
+ This route is protected by a <code>guard</code> function and uses
71
+ per-route <code>middleware</code> for server-side logging.
72
+ </p>
73
+ </div>
74
+
75
+ <div class="about-grid">
76
+ <div class="card about-stat">
77
+ <div class="stat-value">12.8k</div>
78
+ <div class="stat-label">Page views</div>
79
+ </div>
80
+ <div class="card about-stat">
81
+ <div class="stat-value">6</div>
82
+ <div class="stat-label">Routes</div>
83
+ </div>
84
+ <div class="card about-stat">
85
+ <div class="stat-value">1.2s</div>
86
+ <div class="stat-label">Build time</div>
87
+ </div>
88
+ </div>
89
+
90
+ <div
91
+ class="code-block"
92
+ style="max-width: 520px; margin: var(--space-2xl) auto 0;"
93
+ >
94
+ <div class="code-block-header">
95
+ <span>dashboard.tsx</span>
96
+ </div>
97
+ <pre>
98
+ <code>
99
+ <span class="cm">{'// Navigation guard — protect routes'}</span>
100
+ <span class="kw">export function</span>{' '}
101
+ <span class="fn">guard</span>() {'{'}
102
+ <span class="kw">if</span> (!isAuthenticated) {'{'}
103
+ <span class="kw">return</span> <span class="str">"/login"</span>{' '}
104
+ <span class="cm">{'// redirect'}</span>
105
+ {'}'}
106
+ <span class="kw">return</span> <span class="str">true</span>{' '}
107
+ <span class="cm">{'// allow'}</span>
108
+ {'}'}
109
+ <span class="cm">{'// Per-route server middleware'}</span>
110
+ <span class="kw">export const</span>{' '}
111
+ <span class="fn">middleware</span> = (req, next) =&gt; {'{'}
112
+ <span class="cm">{'// logging, auth, rate limiting...'}</span>
113
+ <span class="kw">return</span> <span class="fn">next</span>(req)
114
+ {'}'}
115
+ </code>
116
+ </pre>
117
+ </div>
118
+
119
+ <div style="text-align: center; margin-top: var(--space-2xl);">
120
+ <button
121
+ type="button"
122
+ class="btn btn-secondary"
123
+ onclick={() => {
124
+ localStorage.removeItem('zero-demo-auth')
125
+ window.location.href = '/about'
126
+ }}
127
+ >
128
+ Log out (clear demo auth)
129
+ </button>
130
+ </div>
131
+ </>
132
+ )
133
+ }
@@ -0,0 +1,24 @@
1
+ import { useHead } from '@pyreon/head'
2
+ import { Link } from '@pyreon/zero/link'
3
+
4
+ export default function ErrorPage() {
5
+ useHead({ title: 'Something went wrong — Zero' })
6
+
7
+ return (
8
+ <div class="error-page">
9
+ <div class="error-code">500</div>
10
+ <h1>Something went wrong</h1>
11
+ <p style="color: var(--c-text-secondary); max-width: 400px;">
12
+ An unexpected error occurred. Try refreshing the page or navigating back
13
+ home.
14
+ </p>
15
+ <Link
16
+ href="/"
17
+ class="btn btn-primary"
18
+ style="margin-top: var(--space-md);"
19
+ >
20
+ Back to Home
21
+ </Link>
22
+ </div>
23
+ )
24
+ }
@@ -0,0 +1,49 @@
1
+ import { Link } from '@pyreon/zero/link'
2
+ import { ThemeToggle } from '@pyreon/zero/theme'
3
+
4
+ export function layout(props: { children: any }) {
5
+ return (
6
+ <>
7
+ <header class="app-header">
8
+ <div class="app-header-inner">
9
+ <Link href="/" class="app-logo">
10
+ <span class="logo-mark">Z</span>
11
+ <span>Zero</span>
12
+ </Link>
13
+ <nav class="app-nav">
14
+ <Link href="/" prefetch="viewport" exactActiveClass="nav-active">
15
+ Home
16
+ </Link>
17
+ <Link
18
+ href="/counter"
19
+ prefetch="hover"
20
+ exactActiveClass="nav-active"
21
+ >
22
+ Counter
23
+ </Link>
24
+ <Link href="/posts" prefetch="hover" activeClass="nav-active">
25
+ Posts
26
+ </Link>
27
+ <Link href="/about" prefetch="hover" exactActiveClass="nav-active">
28
+ About
29
+ </Link>
30
+ <Link
31
+ href="/dashboard"
32
+ prefetch="hover"
33
+ exactActiveClass="nav-active"
34
+ >
35
+ Dashboard
36
+ </Link>
37
+ <ThemeToggle class="theme-toggle" />
38
+ </nav>
39
+ </div>
40
+ </header>
41
+
42
+ <main class="app-main">{props.children}</main>
43
+
44
+ <footer class="app-footer">
45
+ Built with Pyreon Zero — signal-based, blazing fast.
46
+ </footer>
47
+ </>
48
+ )
49
+ }
@@ -0,0 +1,8 @@
1
+ export default function Loading() {
2
+ return (
3
+ <div class="loading-page">
4
+ <div class="loading-spinner" />
5
+ <p style="color: var(--c-text-muted); font-size: 0.9rem;">Loading...</p>
6
+ </div>
7
+ )
8
+ }
@@ -0,0 +1,125 @@
1
+ import { useHead } from '@pyreon/head'
2
+ import { Link } from '@pyreon/zero/link'
3
+
4
+ export const meta = {
5
+ title: 'About — Pyreon Zero',
6
+ description: 'Learn about the Pyreon Zero meta-framework.',
7
+ }
8
+
9
+ export default function About() {
10
+ useHead({
11
+ title: meta.title,
12
+ meta: [{ name: 'description', content: meta.description }],
13
+ })
14
+
15
+ return (
16
+ <>
17
+ <div class="page-header">
18
+ <h1>About Zero</h1>
19
+ <p>
20
+ A signal-based meta-framework built on Vite — designed for developers
21
+ who care about performance and simplicity.
22
+ </p>
23
+ </div>
24
+
25
+ <div class="about-grid">
26
+ <div class="card about-stat">
27
+ <div class="stat-value">0</div>
28
+ <div class="stat-label">Virtual DOM overhead</div>
29
+ </div>
30
+ <div class="card about-stat">
31
+ <div class="stat-value">4</div>
32
+ <div class="stat-label">Rendering strategies</div>
33
+ </div>
34
+ <div class="card about-stat">
35
+ <div class="stat-value">5+</div>
36
+ <div class="stat-label">Deploy adapters</div>
37
+ </div>
38
+ </div>
39
+
40
+ <section style="margin-top: var(--space-3xl); max-width: 680px;">
41
+ <h2 style="font-size: 1.3rem; font-weight: 700; margin-bottom: var(--space-md);">
42
+ Why Zero?
43
+ </h2>
44
+ <div style="color: var(--c-text-secondary); line-height: 1.8; display: flex; flex-direction: column; gap: var(--space-lg);">
45
+ <p>
46
+ Most frameworks make you choose between developer experience and
47
+ runtime performance. Zero doesn't. Pyreon's signal-based reactivity
48
+ means your components compile to surgical DOM updates — no diffing,
49
+ no reconciliation, no wasted work.
50
+ </p>
51
+ <p>
52
+ On top of that, Zero gives you file-based routing, server-side
53
+ rendering, static generation, incremental regeneration, font
54
+ optimization, image optimization, smart caching, link prefetching,
55
+ and SEO utilities — all built in, all zero-config.
56
+ </p>
57
+ <p>
58
+ Deploy to Node, Bun, Vercel, Cloudflare, Netlify, or export as a
59
+ static site. One codebase, any target.
60
+ </p>
61
+ </div>
62
+ </section>
63
+
64
+ <section style="margin-top: var(--space-3xl); max-width: 680px;">
65
+ <h2 style="font-size: 1.3rem; font-weight: 700; margin-bottom: var(--space-md);">
66
+ The Stack
67
+ </h2>
68
+ <div style="display: grid; gap: var(--space-sm);">
69
+ {[
70
+ ['Pyreon', 'Signal-based UI framework with JSX'],
71
+ ['Vite', 'Lightning-fast dev server and optimized builds'],
72
+ [
73
+ 'File Router',
74
+ 'Drop a file, get a route — layouts, guards, loaders',
75
+ ],
76
+ [
77
+ 'SSR / SSG / ISR',
78
+ 'Every rendering strategy, per-route overrides',
79
+ ],
80
+ [
81
+ '<Image>',
82
+ 'Lazy loading, responsive srcset, blur-up placeholders',
83
+ ],
84
+ ['<Link>', 'Prefetch on hover or viewport entry for instant nav'],
85
+ [
86
+ 'Font Plugin',
87
+ 'Google Fonts optimization, preconnect, font-display:swap',
88
+ ],
89
+ [
90
+ 'Cache MW',
91
+ 'Immutable hashed assets, stale-while-revalidate pages',
92
+ ],
93
+ ['SEO Tools', 'Sitemap, robots.txt, JSON-LD structured data'],
94
+ ].map(([name, desc]) => (
95
+ <div
96
+ class="card"
97
+ style="display: flex; align-items: center; gap: var(--space-md); padding: var(--space-md) var(--space-lg);"
98
+ >
99
+ <code style="min-width: 130px; font-weight: 600; color: var(--c-accent);">
100
+ {name}
101
+ </code>
102
+ <span style="color: var(--c-text-secondary); font-size: 0.9rem;">
103
+ {desc}
104
+ </span>
105
+ </div>
106
+ ))}
107
+ </div>
108
+ </section>
109
+
110
+ <section style="text-align: center; margin-top: var(--space-3xl); padding-bottom: var(--space-xl);">
111
+ <h2 style="font-size: 1.3rem; font-weight: 700; margin-bottom: var(--space-md);">
112
+ Ready to build something?
113
+ </h2>
114
+ <div style="display: flex; gap: var(--space-md); justify-content: center;">
115
+ <Link href="/" class="btn btn-primary">
116
+ Get Started
117
+ </Link>
118
+ <Link href="/counter" class="btn btn-secondary">
119
+ Try the Demo
120
+ </Link>
121
+ </div>
122
+ </section>
123
+ </>
124
+ )
125
+ }
@@ -0,0 +1,94 @@
1
+ import { useHead } from '@pyreon/head'
2
+ import { computed, signal } from '@pyreon/reactivity'
3
+
4
+ export const meta = {
5
+ title: 'Counter — Pyreon Zero',
6
+ description: "See Pyreon's signal-based reactivity in action.",
7
+ }
8
+
9
+ export default function Counter() {
10
+ useHead({ title: meta.title })
11
+
12
+ const count = signal(0)
13
+ const doubled = computed(() => count() * 2)
14
+ const isEven = computed(() => count() % 2 === 0)
15
+
16
+ return (
17
+ <>
18
+ <div class="page-header" style="text-align: center;">
19
+ <span class="badge">Interactive Demo</span>
20
+ <h1 style="margin-top: var(--space-md);">Signal Reactivity</h1>
21
+ <p>
22
+ Fine-grained reactivity with zero virtual DOM. Only the exact text
23
+ nodes that display these values are updated — nothing else re-renders.
24
+ </p>
25
+ </div>
26
+
27
+ <div class="counter-demo">
28
+ <div class="counter-display">{count}</div>
29
+
30
+ <div class="counter-controls">
31
+ <button
32
+ type="button"
33
+ class="btn btn-secondary"
34
+ onclick={() => count(count() - 1)}
35
+ >
36
+ -
37
+ </button>
38
+ <button
39
+ type="button"
40
+ class="btn btn-primary"
41
+ onclick={() => count(0)}
42
+ >
43
+ Reset
44
+ </button>
45
+ <button
46
+ type="button"
47
+ class="btn btn-secondary"
48
+ onclick={() => count(count() + 1)}
49
+ >
50
+ +
51
+ </button>
52
+ </div>
53
+
54
+ <div class="counter-meta">
55
+ <div>
56
+ count() → <strong>{count}</strong>
57
+ </div>
58
+ <div>
59
+ doubled() → <strong>{doubled}</strong>
60
+ </div>
61
+ <div>
62
+ isEven() → <strong>{() => (isEven() ? 'true' : 'false')}</strong>
63
+ </div>
64
+ </div>
65
+ </div>
66
+
67
+ <div
68
+ class="code-block"
69
+ style="max-width: 520px; margin: var(--space-2xl) auto 0;"
70
+ >
71
+ <div class="code-block-header">
72
+ <span>counter.tsx</span>
73
+ </div>
74
+ <pre>
75
+ <code>
76
+ <span class="kw">import</span> {'{'} signal, computed {'}'}{' '}
77
+ <span class="kw">from</span>{' '}
78
+ <span class="str">"@pyreon/reactivity"</span>
79
+ <span class="kw">const</span> <span class="fn">count</span> ={' '}
80
+ <span class="fn">signal</span>(<span class="str">0</span>)
81
+ <span class="kw">const</span> <span class="fn">doubled</span> ={' '}
82
+ <span class="fn">computed</span>(() =&gt;{' '}
83
+ <span class="fn">count</span>() * <span class="str">2</span>)
84
+ <span class="cm">{'// Just reference the signal in JSX —'}</span>
85
+ <span class="cm">{'// only this text node updates'}</span>
86
+ <span class="tag">&lt;span&gt;</span>
87
+ {'{'}count{'}'}
88
+ <span class="tag">&lt;/span&gt;</span>
89
+ </code>
90
+ </pre>
91
+ </div>
92
+ </>
93
+ )
94
+ }
@@ -0,0 +1,225 @@
1
+ import { useHead } from '@pyreon/head'
2
+ import { Link } from '@pyreon/zero/link'
3
+
4
+ export const meta = {
5
+ title: 'Pyreon Zero',
6
+ description: 'The signal-based meta-framework. Build fast, stay fast.',
7
+ }
8
+
9
+ export default function Home() {
10
+ useHead({
11
+ title: 'Pyreon Zero — The Signal-Based Meta-Framework',
12
+ meta: [{ name: 'description', content: meta.description }],
13
+ })
14
+
15
+ return (
16
+ <>
17
+ <section class="hero">
18
+ <span class="badge">Open Source</span>
19
+ <h1>
20
+ Build fast.
21
+ <br />
22
+ <span class="gradient">Stay fast.</span>
23
+ </h1>
24
+ <p>
25
+ Pyreon Zero is a signal-based full-stack framework powered by Vite.
26
+ File-based routing, SSR, SSG, ISR — everything you need, nothing you
27
+ don't.
28
+ </p>
29
+ <div class="hero-actions">
30
+ <Link href="/counter" class="btn btn-primary">
31
+ See it in action
32
+ </Link>
33
+ <a
34
+ href="https://github.com/pyreon/zero"
35
+ class="btn btn-secondary"
36
+ target="_blank"
37
+ rel="noopener noreferrer"
38
+ >
39
+ GitHub
40
+ </a>
41
+ </div>
42
+
43
+ <div class="code-block">
44
+ <div class="code-block-header">
45
+ <span>terminal</span>
46
+ </div>
47
+ <pre>
48
+ <code>
49
+ <span class="cm"># Create a new project in seconds</span>
50
+ <span class="fn">bun</span> create zero my-app
51
+ <span class="fn">cd</span> my-app
52
+ <span class="fn">bun</span> install
53
+ <span class="fn">bun</span> run dev
54
+ </code>
55
+ </pre>
56
+ </div>
57
+ </section>
58
+
59
+ <section class="features">
60
+ <div class="card feature">
61
+ <div class="feature-icon">
62
+ <svg
63
+ width="24"
64
+ height="24"
65
+ viewBox="0 0 24 24"
66
+ fill="none"
67
+ stroke="currentColor"
68
+ stroke-width="2"
69
+ stroke-linecap="round"
70
+ stroke-linejoin="round"
71
+ aria-hidden="true"
72
+ >
73
+ <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />
74
+ </svg>
75
+ </div>
76
+ <h3>Signal-Based Reactivity</h3>
77
+ <p>
78
+ Fine-grained reactivity with zero virtual DOM overhead. Only the
79
+ exact DOM nodes that need updating are touched.
80
+ </p>
81
+ </div>
82
+
83
+ <div class="card feature">
84
+ <div class="feature-icon">
85
+ <svg
86
+ width="24"
87
+ height="24"
88
+ viewBox="0 0 24 24"
89
+ fill="none"
90
+ stroke="currentColor"
91
+ stroke-width="2"
92
+ stroke-linecap="round"
93
+ stroke-linejoin="round"
94
+ aria-hidden="true"
95
+ >
96
+ <path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z" />
97
+ </svg>
98
+ </div>
99
+ <h3>File-Based Routing</h3>
100
+ <p>
101
+ Drop a file in <code>src/routes/</code> and it's a route. Layouts,
102
+ dynamic params, catch-alls, and route groups built in.
103
+ </p>
104
+ </div>
105
+
106
+ <div class="card feature">
107
+ <div class="feature-icon">
108
+ <svg
109
+ width="24"
110
+ height="24"
111
+ viewBox="0 0 24 24"
112
+ fill="none"
113
+ stroke="currentColor"
114
+ stroke-width="2"
115
+ stroke-linecap="round"
116
+ stroke-linejoin="round"
117
+ aria-hidden="true"
118
+ >
119
+ <rect x="2" y="3" width="20" height="14" rx="2" ry="2" />
120
+ <line x1="8" y1="21" x2="16" y2="21" />
121
+ <line x1="12" y1="17" x2="12" y2="21" />
122
+ </svg>
123
+ </div>
124
+ <h3>SSR / SSG / ISR / SPA</h3>
125
+ <p>
126
+ Every rendering strategy out of the box. Per-route overrides let you
127
+ mix SSR pages with static marketing pages.
128
+ </p>
129
+ </div>
130
+
131
+ <div class="card feature">
132
+ <div class="feature-icon">
133
+ <svg
134
+ width="24"
135
+ height="24"
136
+ viewBox="0 0 24 24"
137
+ fill="none"
138
+ stroke="currentColor"
139
+ stroke-width="2"
140
+ stroke-linecap="round"
141
+ stroke-linejoin="round"
142
+ aria-hidden="true"
143
+ >
144
+ <path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z" />
145
+ </svg>
146
+ </div>
147
+ <h3>Font & Image Optimization</h3>
148
+ <p>
149
+ Automatic Google Fonts inlining, font-display swap, and an{' '}
150
+ <code>{'<Image>'}</code> component with lazy loading and blur-up
151
+ placeholders.
152
+ </p>
153
+ </div>
154
+
155
+ <div class="card feature">
156
+ <div class="feature-icon">
157
+ <svg
158
+ width="24"
159
+ height="24"
160
+ viewBox="0 0 24 24"
161
+ fill="none"
162
+ stroke="currentColor"
163
+ stroke-width="2"
164
+ stroke-linecap="round"
165
+ stroke-linejoin="round"
166
+ aria-hidden="true"
167
+ >
168
+ <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
169
+ </svg>
170
+ </div>
171
+ <h3>Smart Caching & Security</h3>
172
+ <p>
173
+ Built-in middleware for immutable asset caching,
174
+ stale-while-revalidate, security headers, and compression hints.
175
+ </p>
176
+ </div>
177
+
178
+ <div class="card feature">
179
+ <div class="feature-icon">
180
+ <svg
181
+ width="24"
182
+ height="24"
183
+ viewBox="0 0 24 24"
184
+ fill="none"
185
+ stroke="currentColor"
186
+ stroke-width="2"
187
+ stroke-linecap="round"
188
+ stroke-linejoin="round"
189
+ aria-hidden="true"
190
+ >
191
+ <circle cx="12" cy="12" r="10" />
192
+ <line x1="2" y1="12" x2="22" y2="12" />
193
+ <path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" />
194
+ </svg>
195
+ </div>
196
+ <h3>Deploy Anywhere</h3>
197
+ <p>
198
+ Adapters for Node, Bun, Vercel, Cloudflare, and Netlify. Or export
199
+ as a fully static site.
200
+ </p>
201
+ </div>
202
+ </section>
203
+
204
+ <section style="text-align: center; margin-top: var(--space-3xl); padding-bottom: var(--space-xl);">
205
+ <h2 style="font-size: 1.5rem; font-weight: 700; letter-spacing: -0.02em; margin-bottom: var(--space-sm);">
206
+ Ready to build?
207
+ </h2>
208
+ <p style="color: var(--c-text-secondary); margin-bottom: var(--space-xl);">
209
+ Explore the demo pages to see Zero's features in action.
210
+ </p>
211
+ <div style="display: flex; gap: var(--space-md); justify-content: center; flex-wrap: wrap;">
212
+ <Link href="/counter" class="btn btn-secondary">
213
+ Signal Reactivity
214
+ </Link>
215
+ <Link href="/posts" class="btn btn-secondary">
216
+ Data Loading
217
+ </Link>
218
+ <Link href="/about" class="btn btn-secondary">
219
+ About Zero
220
+ </Link>
221
+ </div>
222
+ </section>
223
+ </>
224
+ )
225
+ }