create-vorzelajs 0.0.1 → 0.0.3

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/dist/index.js CHANGED
@@ -5,16 +5,9 @@ import url from 'node:url';
5
5
  import prompts from 'prompts';
6
6
  const __filename = url.fileURLToPath(import.meta.url);
7
7
  const __dirname = path.dirname(__filename);
8
- // Templates ship inside the vorzelajs package
8
+ // Templates are bundled inside create-vorzelajs at package root
9
9
  function resolveTemplatesDir() {
10
- try {
11
- const vorzelaRoot = path.dirname(require.resolve('vorzelajs/package.json'));
12
- return path.join(vorzelaRoot, 'templates');
13
- }
14
- catch {
15
- // Fallback: assume templates are sibling to create-vorzelajs
16
- return path.resolve(__dirname, '..', '..', 'templates');
17
- }
10
+ return path.resolve(__dirname, '..', 'templates');
18
11
  }
19
12
  async function copyDir(src, dest) {
20
13
  await fs.mkdir(dest, { recursive: true });
@@ -50,7 +43,7 @@ function generatePackageJson(config) {
50
43
  check: 'tsc --noEmit',
51
44
  },
52
45
  dependencies: {
53
- vorzelajs: '^0.0.1',
46
+ vorzelajs: '^0.0.2',
54
47
  'solid-js': '^1.9',
55
48
  },
56
49
  devDependencies: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-vorzelajs",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "type": "module",
5
5
  "description": "Create a new VorzelaJs project",
6
6
  "license": "MIT",
@@ -10,13 +10,15 @@
10
10
  "directory": "create-vorzelajs"
11
11
  },
12
12
  "bin": {
13
- "create-vorzelajs": "./dist/index.js"
13
+ "create-vorzelajs": "dist/index.js"
14
14
  },
15
15
  "files": [
16
- "dist"
16
+ "dist",
17
+ "templates"
17
18
  ],
18
19
  "scripts": {
19
- "build": "tsc -p tsconfig.json"
20
+ "build": "tsc -p tsconfig.json",
21
+ "prepack": "node --input-type=module -e \"import fs from 'node:fs'; fs.cpSync('../templates', 'templates', { recursive: true })\""
20
22
  },
21
23
  "dependencies": {
22
24
  "prompts": "^2.4.2"
@@ -0,0 +1,22 @@
1
+ # My App
2
+
3
+ Built with [VorzelaJs](https://github.com/vorzela/VorzelaJS).
4
+
5
+ ## Getting Started
6
+
7
+ ```bash
8
+ npm run dev # Start dev server
9
+ npm run build # Build for production
10
+ npm run serve # Serve production build
11
+ ```
12
+
13
+ ## Project Structure
14
+
15
+ ```
16
+ src/
17
+ ├── routes/ # File-based routes
18
+ │ ├── __root.tsx # Root layout
19
+ │ └── index.tsx # Home page (/)
20
+ ├── components/ # Reusable components
21
+ └── styles.css # Global styles
22
+ ```
@@ -0,0 +1,19 @@
1
+ import { createSignal } from 'solid-js'
2
+
3
+ export function CounterCard() {
4
+ const [count, setCount] = createSignal(0)
5
+
6
+ return (
7
+ <div class="counter-card">
8
+ <p class="counter-value">{count()}</p>
9
+ <div class="counter-actions">
10
+ <button onClick={() => setCount((c) => c - 1)} class="counter-btn">
11
+
12
+ </button>
13
+ <button onClick={() => setCount((c) => c + 1)} class="counter-btn">
14
+ +
15
+ </button>
16
+ </div>
17
+ </div>
18
+ )
19
+ }
@@ -0,0 +1,24 @@
1
+ import { createRootRoute, Outlet } from 'vorzelajs'
2
+
3
+ export const Route = createRootRoute()({
4
+ component: RootLayout,
5
+ head: () => ({
6
+ meta: [
7
+ { name: 'description', content: 'Built with VorzelaJs' },
8
+ ],
9
+ }),
10
+ notFoundComponent: () => (
11
+ <div class="not-found">
12
+ <h1>404</h1>
13
+ <p>Page not found</p>
14
+ </div>
15
+ ),
16
+ })
17
+
18
+ function RootLayout() {
19
+ return (
20
+ <div class="app">
21
+ <Outlet />
22
+ </div>
23
+ )
24
+ }
@@ -0,0 +1,36 @@
1
+ import { createFileRoute } from 'vorzelajs'
2
+ import { CounterCard } from '../components/counter-card'
3
+
4
+ export const Route = createFileRoute('/')({
5
+ component: HomePage,
6
+ head: () => ({
7
+ title: 'VorzelaJs',
8
+ }),
9
+ })
10
+
11
+ function HomePage() {
12
+ return (
13
+ <main class="hero">
14
+ <div class="hero-content">
15
+ <h1 class="hero-title">VorzelaJs</h1>
16
+ <p class="hero-description">
17
+ A batteries-included SolidJS framework with file-based routing, streamed SSR, and server-only boundaries.
18
+ </p>
19
+
20
+ <CounterCard />
21
+
22
+ <nav class="hero-links">
23
+ <a href="https://github.com/vorzela/VorzelaJS" target="_blank" rel="noopener noreferrer" class="link">
24
+ GitHub
25
+ </a>
26
+ <a href="https://github.com/vorzela/VorzelaJS#readme" target="_blank" rel="noopener noreferrer" class="link">
27
+ Documentation
28
+ </a>
29
+ <a href="https://www.npmjs.com/package/vorzelajs" target="_blank" rel="noopener noreferrer" class="link">
30
+ npm
31
+ </a>
32
+ </nav>
33
+ </div>
34
+ </main>
35
+ )
36
+ }
@@ -0,0 +1,4 @@
1
+ node_modules/
2
+ dist/
3
+ src/routeTree.gen.ts
4
+ src/routeHydration.gen.ts
@@ -0,0 +1,5 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none">
2
+ <rect width="32" height="32" rx="6" fill="#1a1a2e"/>
3
+ <path d="M8 10l8-4 8 4v12l-8 4-8-4V10z" stroke="#7c3aed" stroke-width="1.5" fill="none"/>
4
+ <path d="M16 6v20M8 10l8 6 8-6" stroke="#7c3aed" stroke-width="1.5" fill="none" opacity="0.5"/>
5
+ </svg>
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "jsx": "preserve",
7
+ "jsxImportSource": "solid-js",
8
+ "strict": true,
9
+ "noEmit": true,
10
+ "isolatedModules": true,
11
+ "esModuleInterop": true,
12
+ "skipLibCheck": true,
13
+ "paths": {
14
+ "~/*": ["./src/*"]
15
+ }
16
+ },
17
+ "include": ["src"]
18
+ }
@@ -0,0 +1,28 @@
1
+ # My App
2
+
3
+ Built with [VorzelaJs](https://github.com/vorzela/VorzelaJS).
4
+
5
+ ## Getting Started
6
+
7
+ ```bash
8
+ npm run dev # Start dev server
9
+ npm run build # Build for production
10
+ npm run serve # Serve production build
11
+ ```
12
+
13
+ ## Project Structure
14
+
15
+ ```
16
+ src/
17
+ ├── routes/ # File-based routes
18
+ │ ├── __root.tsx # Root layout
19
+ │ ├── index.tsx # Home page (/)
20
+ │ └── about.tsx # About page (/about)
21
+ ├── components/ # Reusable components
22
+ └── styles.css # Global styles
23
+ ```
24
+
25
+ ## Learn More
26
+
27
+ - [VorzelaJs Documentation](https://github.com/vorzela/VorzelaJS#readme)
28
+ - [SolidJS](https://www.solidjs.com/)
@@ -0,0 +1,19 @@
1
+ import { createSignal } from 'solid-js'
2
+
3
+ export function CounterCard() {
4
+ const [count, setCount] = createSignal(0)
5
+
6
+ return (
7
+ <div class="counter-card">
8
+ <p class="counter-value">{count()}</p>
9
+ <div class="counter-actions">
10
+ <button onClick={() => setCount((c) => c - 1)} class="counter-btn">
11
+
12
+ </button>
13
+ <button onClick={() => setCount((c) => c + 1)} class="counter-btn">
14
+ +
15
+ </button>
16
+ </div>
17
+ </div>
18
+ )
19
+ }
@@ -0,0 +1,42 @@
1
+ import { createRootRoute, Link, Outlet } from 'vorzelajs'
2
+
3
+ export const Route = createRootRoute()({
4
+ component: RootLayout,
5
+ head: () => ({
6
+ meta: [
7
+ { name: 'description', content: 'Built with VorzelaJs' },
8
+ ],
9
+ }),
10
+ notFoundComponent: () => (
11
+ <div class="not-found">
12
+ <h1>404</h1>
13
+ <p>Page not found</p>
14
+ <Link to="/" class="link">
15
+ Go home
16
+ </Link>
17
+ </div>
18
+ ),
19
+ })
20
+
21
+ function RootLayout() {
22
+ return (
23
+ <div class="app">
24
+ <header class="header">
25
+ <nav class="nav">
26
+ <Link to="/" class="nav-brand">
27
+ VorzelaJs
28
+ </Link>
29
+ <div class="nav-links">
30
+ <Link to="/" class="nav-link">
31
+ Home
32
+ </Link>
33
+ <Link to="/about" class="nav-link">
34
+ About
35
+ </Link>
36
+ </div>
37
+ </nav>
38
+ </header>
39
+ <Outlet />
40
+ </div>
41
+ )
42
+ }
@@ -0,0 +1,55 @@
1
+ import { createFileRoute } from 'vorzelajs'
2
+
3
+ export const Route = createFileRoute('/about')({
4
+ component: AboutPage,
5
+ head: () => ({
6
+ title: 'About — VorzelaJs',
7
+ }),
8
+ })
9
+
10
+ function AboutPage() {
11
+ return (
12
+ <main class="page">
13
+ <div class="page-content">
14
+ <h1>About VorzelaJs</h1>
15
+ <p>
16
+ VorzelaJs is a batteries-included SolidJS framework. Here's how your project is structured:
17
+ </p>
18
+
19
+ <section class="guide-section">
20
+ <h2>Project Structure</h2>
21
+ <pre class="code-block">{`src/
22
+ ├── routes/ # File-based routes
23
+ │ ├── __root.tsx # Root layout (wraps all pages)
24
+ │ ├── index.tsx # Home page (/)
25
+ │ └── about.tsx # This page (/about)
26
+ ├── components/ # Reusable components
27
+ └── styles.css # Global styles`}</pre>
28
+ </section>
29
+
30
+ <section class="guide-section">
31
+ <h2>Routes</h2>
32
+ <p>
33
+ Each file in <code>src/routes/</code> becomes a route. Use <code>createFileRoute</code> to define
34
+ loaders, head tags, and components. Files prefixed with <code>_</code> are pathless layout routes.
35
+ </p>
36
+ </section>
37
+
38
+ <section class="guide-section">
39
+ <h2>Server Boundaries</h2>
40
+ <p>
41
+ Name files with <code>.server.ts</code> to keep code server-only. Route <code>loader</code> and{' '}
42
+ <code>beforeLoad</code> functions run exclusively on the server and are stripped from the client bundle.
43
+ </p>
44
+ </section>
45
+
46
+ <section class="guide-section">
47
+ <h2>Commands</h2>
48
+ <pre class="code-block">{`npm run dev # Start dev server
49
+ npm run build # Build for production
50
+ npm run serve # Serve production build`}</pre>
51
+ </section>
52
+ </div>
53
+ </main>
54
+ )
55
+ }
@@ -0,0 +1,51 @@
1
+ import { createFileRoute } from 'vorzelajs'
2
+ import { CounterCard } from '../components/counter-card'
3
+
4
+ export const Route = createFileRoute('/')({
5
+ component: HomePage,
6
+ head: () => ({
7
+ title: 'VorzelaJs',
8
+ }),
9
+ })
10
+
11
+ function HomePage() {
12
+ return (
13
+ <main class="hero">
14
+ <div class="hero-content">
15
+ <h1 class="hero-title">VorzelaJs</h1>
16
+ <p class="hero-description">
17
+ A batteries-included SolidJS framework with file-based routing, streamed SSR, and server-only boundaries.
18
+ </p>
19
+
20
+ <CounterCard />
21
+
22
+ <div class="features">
23
+ <div class="feature-card">
24
+ <h3>File-Based Routing</h3>
25
+ <p>Drop a file in <code>src/routes/</code> and it becomes a route. Automatic code splitting included.</p>
26
+ </div>
27
+ <div class="feature-card">
28
+ <h3>Streamed SSR</h3>
29
+ <p>Server-rendered HTML streams to the browser with selective hydration per route.</p>
30
+ </div>
31
+ <div class="feature-card">
32
+ <h3>Server Boundaries</h3>
33
+ <p>Use <code>.server</code> files and route loaders to keep secrets on the server.</p>
34
+ </div>
35
+ </div>
36
+
37
+ <nav class="hero-links">
38
+ <a href="https://github.com/vorzela/VorzelaJS" target="_blank" rel="noopener noreferrer" class="link">
39
+ GitHub
40
+ </a>
41
+ <a href="https://github.com/vorzela/VorzelaJS#readme" target="_blank" rel="noopener noreferrer" class="link">
42
+ Documentation
43
+ </a>
44
+ <a href="https://www.npmjs.com/package/vorzelajs" target="_blank" rel="noopener noreferrer" class="link">
45
+ npm
46
+ </a>
47
+ </nav>
48
+ </div>
49
+ </main>
50
+ )
51
+ }
@@ -0,0 +1,269 @@
1
+ :root {
2
+ --color-bg: #0a0a0f;
3
+ --color-surface: #15151e;
4
+ --color-border: #2a2a3e;
5
+ --color-text: #e4e4ef;
6
+ --color-text-muted: #8888a0;
7
+ --color-accent: #7c3aed;
8
+ --color-accent-hover: #6d28d9;
9
+ --font-sans: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
10
+ --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;
11
+ }
12
+
13
+ *,
14
+ *::before,
15
+ *::after {
16
+ margin: 0;
17
+ padding: 0;
18
+ box-sizing: border-box;
19
+ }
20
+
21
+ html {
22
+ font-family: var(--font-sans);
23
+ background: var(--color-bg);
24
+ color: var(--color-text);
25
+ -webkit-font-smoothing: antialiased;
26
+ -moz-osx-font-smoothing: grayscale;
27
+ }
28
+
29
+ body {
30
+ min-height: 100dvh;
31
+ }
32
+
33
+ a {
34
+ color: var(--color-accent);
35
+ text-decoration: none;
36
+ }
37
+
38
+ a:hover {
39
+ color: var(--color-accent-hover);
40
+ }
41
+
42
+ code {
43
+ font-family: var(--font-mono);
44
+ font-size: 0.9em;
45
+ background: var(--color-surface);
46
+ padding: 0.15em 0.4em;
47
+ border-radius: 4px;
48
+ }
49
+
50
+ .app {
51
+ min-height: 100dvh;
52
+ display: flex;
53
+ flex-direction: column;
54
+ }
55
+
56
+ .header {
57
+ border-bottom: 1px solid var(--color-border);
58
+ padding: 0.75rem 1.5rem;
59
+ }
60
+
61
+ .nav {
62
+ max-width: 64rem;
63
+ margin: 0 auto;
64
+ display: flex;
65
+ align-items: center;
66
+ justify-content: space-between;
67
+ }
68
+
69
+ .nav-brand {
70
+ font-weight: 700;
71
+ font-size: 1.125rem;
72
+ color: var(--color-text);
73
+ }
74
+
75
+ .nav-links {
76
+ display: flex;
77
+ gap: 1.5rem;
78
+ }
79
+
80
+ .nav-link {
81
+ color: var(--color-text-muted);
82
+ font-size: 0.875rem;
83
+ transition: color 0.15s;
84
+ }
85
+
86
+ .nav-link:hover {
87
+ color: var(--color-text);
88
+ }
89
+
90
+ .hero {
91
+ flex: 1;
92
+ display: flex;
93
+ align-items: center;
94
+ justify-content: center;
95
+ padding: 3rem 1.5rem;
96
+ }
97
+
98
+ .hero-content {
99
+ max-width: 40rem;
100
+ text-align: center;
101
+ }
102
+
103
+ .hero-title {
104
+ font-size: 3rem;
105
+ font-weight: 800;
106
+ letter-spacing: -0.02em;
107
+ background: linear-gradient(135deg, var(--color-accent) 0%, #a78bfa 100%);
108
+ -webkit-background-clip: text;
109
+ -webkit-text-fill-color: transparent;
110
+ background-clip: text;
111
+ }
112
+
113
+ .hero-description {
114
+ margin-top: 1rem;
115
+ font-size: 1.125rem;
116
+ color: var(--color-text-muted);
117
+ line-height: 1.6;
118
+ }
119
+
120
+ .hero-links {
121
+ margin-top: 2rem;
122
+ display: flex;
123
+ gap: 1.5rem;
124
+ justify-content: center;
125
+ }
126
+
127
+ .link {
128
+ color: var(--color-accent);
129
+ font-weight: 500;
130
+ transition: color 0.15s;
131
+ }
132
+
133
+ .link:hover {
134
+ color: var(--color-accent-hover);
135
+ }
136
+
137
+ .counter-card {
138
+ margin-top: 2rem;
139
+ background: var(--color-surface);
140
+ border: 1px solid var(--color-border);
141
+ border-radius: 12px;
142
+ padding: 1.5rem;
143
+ display: inline-flex;
144
+ flex-direction: column;
145
+ align-items: center;
146
+ gap: 1rem;
147
+ }
148
+
149
+ .counter-value {
150
+ font-size: 2.5rem;
151
+ font-weight: 700;
152
+ font-variant-numeric: tabular-nums;
153
+ }
154
+
155
+ .counter-actions {
156
+ display: flex;
157
+ gap: 0.75rem;
158
+ }
159
+
160
+ .counter-btn {
161
+ width: 2.5rem;
162
+ height: 2.5rem;
163
+ border-radius: 8px;
164
+ border: 1px solid var(--color-border);
165
+ background: var(--color-bg);
166
+ color: var(--color-text);
167
+ font-size: 1.25rem;
168
+ cursor: pointer;
169
+ display: flex;
170
+ align-items: center;
171
+ justify-content: center;
172
+ transition: background 0.15s, border-color 0.15s;
173
+ }
174
+
175
+ .counter-btn:hover {
176
+ background: var(--color-surface);
177
+ border-color: var(--color-accent);
178
+ }
179
+
180
+ .features {
181
+ margin-top: 3rem;
182
+ display: grid;
183
+ grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
184
+ gap: 1rem;
185
+ text-align: left;
186
+ }
187
+
188
+ .feature-card {
189
+ background: var(--color-surface);
190
+ border: 1px solid var(--color-border);
191
+ border-radius: 12px;
192
+ padding: 1.25rem;
193
+ }
194
+
195
+ .feature-card h3 {
196
+ font-size: 1rem;
197
+ font-weight: 600;
198
+ margin-bottom: 0.5rem;
199
+ }
200
+
201
+ .feature-card p {
202
+ font-size: 0.875rem;
203
+ color: var(--color-text-muted);
204
+ line-height: 1.5;
205
+ }
206
+
207
+ .page {
208
+ flex: 1;
209
+ padding: 3rem 1.5rem;
210
+ }
211
+
212
+ .page-content {
213
+ max-width: 48rem;
214
+ margin: 0 auto;
215
+ }
216
+
217
+ .page-content h1 {
218
+ font-size: 2rem;
219
+ font-weight: 700;
220
+ margin-bottom: 1rem;
221
+ }
222
+
223
+ .page-content p {
224
+ color: var(--color-text-muted);
225
+ line-height: 1.6;
226
+ margin-bottom: 1.5rem;
227
+ }
228
+
229
+ .guide-section {
230
+ margin-top: 2rem;
231
+ }
232
+
233
+ .guide-section h2 {
234
+ font-size: 1.25rem;
235
+ font-weight: 600;
236
+ margin-bottom: 0.75rem;
237
+ }
238
+
239
+ .code-block {
240
+ background: var(--color-surface);
241
+ border: 1px solid var(--color-border);
242
+ border-radius: 8px;
243
+ padding: 1rem;
244
+ font-family: var(--font-mono);
245
+ font-size: 0.8125rem;
246
+ line-height: 1.6;
247
+ overflow-x: auto;
248
+ white-space: pre;
249
+ }
250
+
251
+ .not-found {
252
+ flex: 1;
253
+ display: flex;
254
+ flex-direction: column;
255
+ align-items: center;
256
+ justify-content: center;
257
+ text-align: center;
258
+ gap: 0.5rem;
259
+ }
260
+
261
+ .not-found h1 {
262
+ font-size: 4rem;
263
+ font-weight: 800;
264
+ color: var(--color-text-muted);
265
+ }
266
+
267
+ .not-found p {
268
+ color: var(--color-text-muted);
269
+ }
@@ -0,0 +1,269 @@
1
+ :root {
2
+ --color-bg: #0a0a0f;
3
+ --color-surface: #15151e;
4
+ --color-border: #2a2a3e;
5
+ --color-text: #e4e4ef;
6
+ --color-text-muted: #8888a0;
7
+ --color-accent: #7c3aed;
8
+ --color-accent-hover: #6d28d9;
9
+ --font-sans: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
10
+ --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;
11
+ }
12
+
13
+ *,
14
+ *::before,
15
+ *::after {
16
+ margin: 0;
17
+ padding: 0;
18
+ box-sizing: border-box;
19
+ }
20
+
21
+ html {
22
+ font-family: var(--font-sans);
23
+ background: var(--color-bg);
24
+ color: var(--color-text);
25
+ -webkit-font-smoothing: antialiased;
26
+ -moz-osx-font-smoothing: grayscale;
27
+ }
28
+
29
+ body {
30
+ min-height: 100dvh;
31
+ }
32
+
33
+ a {
34
+ color: var(--color-accent);
35
+ text-decoration: none;
36
+ }
37
+
38
+ a:hover {
39
+ color: var(--color-accent-hover);
40
+ }
41
+
42
+ code {
43
+ font-family: var(--font-mono);
44
+ font-size: 0.9em;
45
+ background: var(--color-surface);
46
+ padding: 0.15em 0.4em;
47
+ border-radius: 4px;
48
+ }
49
+
50
+ .app {
51
+ min-height: 100dvh;
52
+ display: flex;
53
+ flex-direction: column;
54
+ }
55
+
56
+ .header {
57
+ border-bottom: 1px solid var(--color-border);
58
+ padding: 0.75rem 1.5rem;
59
+ }
60
+
61
+ .nav {
62
+ max-width: 64rem;
63
+ margin: 0 auto;
64
+ display: flex;
65
+ align-items: center;
66
+ justify-content: space-between;
67
+ }
68
+
69
+ .nav-brand {
70
+ font-weight: 700;
71
+ font-size: 1.125rem;
72
+ color: var(--color-text);
73
+ }
74
+
75
+ .nav-links {
76
+ display: flex;
77
+ gap: 1.5rem;
78
+ }
79
+
80
+ .nav-link {
81
+ color: var(--color-text-muted);
82
+ font-size: 0.875rem;
83
+ transition: color 0.15s;
84
+ }
85
+
86
+ .nav-link:hover {
87
+ color: var(--color-text);
88
+ }
89
+
90
+ .hero {
91
+ flex: 1;
92
+ display: flex;
93
+ align-items: center;
94
+ justify-content: center;
95
+ padding: 3rem 1.5rem;
96
+ }
97
+
98
+ .hero-content {
99
+ max-width: 40rem;
100
+ text-align: center;
101
+ }
102
+
103
+ .hero-title {
104
+ font-size: 3rem;
105
+ font-weight: 800;
106
+ letter-spacing: -0.02em;
107
+ background: linear-gradient(135deg, var(--color-accent) 0%, #a78bfa 100%);
108
+ -webkit-background-clip: text;
109
+ -webkit-text-fill-color: transparent;
110
+ background-clip: text;
111
+ }
112
+
113
+ .hero-description {
114
+ margin-top: 1rem;
115
+ font-size: 1.125rem;
116
+ color: var(--color-text-muted);
117
+ line-height: 1.6;
118
+ }
119
+
120
+ .hero-links {
121
+ margin-top: 2rem;
122
+ display: flex;
123
+ gap: 1.5rem;
124
+ justify-content: center;
125
+ }
126
+
127
+ .link {
128
+ color: var(--color-accent);
129
+ font-weight: 500;
130
+ transition: color 0.15s;
131
+ }
132
+
133
+ .link:hover {
134
+ color: var(--color-accent-hover);
135
+ }
136
+
137
+ .counter-card {
138
+ margin-top: 2rem;
139
+ background: var(--color-surface);
140
+ border: 1px solid var(--color-border);
141
+ border-radius: 12px;
142
+ padding: 1.5rem;
143
+ display: inline-flex;
144
+ flex-direction: column;
145
+ align-items: center;
146
+ gap: 1rem;
147
+ }
148
+
149
+ .counter-value {
150
+ font-size: 2.5rem;
151
+ font-weight: 700;
152
+ font-variant-numeric: tabular-nums;
153
+ }
154
+
155
+ .counter-actions {
156
+ display: flex;
157
+ gap: 0.75rem;
158
+ }
159
+
160
+ .counter-btn {
161
+ width: 2.5rem;
162
+ height: 2.5rem;
163
+ border-radius: 8px;
164
+ border: 1px solid var(--color-border);
165
+ background: var(--color-bg);
166
+ color: var(--color-text);
167
+ font-size: 1.25rem;
168
+ cursor: pointer;
169
+ display: flex;
170
+ align-items: center;
171
+ justify-content: center;
172
+ transition: background 0.15s, border-color 0.15s;
173
+ }
174
+
175
+ .counter-btn:hover {
176
+ background: var(--color-surface);
177
+ border-color: var(--color-accent);
178
+ }
179
+
180
+ .features {
181
+ margin-top: 3rem;
182
+ display: grid;
183
+ grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
184
+ gap: 1rem;
185
+ text-align: left;
186
+ }
187
+
188
+ .feature-card {
189
+ background: var(--color-surface);
190
+ border: 1px solid var(--color-border);
191
+ border-radius: 12px;
192
+ padding: 1.25rem;
193
+ }
194
+
195
+ .feature-card h3 {
196
+ font-size: 1rem;
197
+ font-weight: 600;
198
+ margin-bottom: 0.5rem;
199
+ }
200
+
201
+ .feature-card p {
202
+ font-size: 0.875rem;
203
+ color: var(--color-text-muted);
204
+ line-height: 1.5;
205
+ }
206
+
207
+ .page {
208
+ flex: 1;
209
+ padding: 3rem 1.5rem;
210
+ }
211
+
212
+ .page-content {
213
+ max-width: 48rem;
214
+ margin: 0 auto;
215
+ }
216
+
217
+ .page-content h1 {
218
+ font-size: 2rem;
219
+ font-weight: 700;
220
+ margin-bottom: 1rem;
221
+ }
222
+
223
+ .page-content p {
224
+ color: var(--color-text-muted);
225
+ line-height: 1.6;
226
+ margin-bottom: 1.5rem;
227
+ }
228
+
229
+ .guide-section {
230
+ margin-top: 2rem;
231
+ }
232
+
233
+ .guide-section h2 {
234
+ font-size: 1.25rem;
235
+ font-weight: 600;
236
+ margin-bottom: 0.75rem;
237
+ }
238
+
239
+ .code-block {
240
+ background: var(--color-surface);
241
+ border: 1px solid var(--color-border);
242
+ border-radius: 8px;
243
+ padding: 1rem;
244
+ font-family: var(--font-mono);
245
+ font-size: 0.8125rem;
246
+ line-height: 1.6;
247
+ overflow-x: auto;
248
+ white-space: pre;
249
+ }
250
+
251
+ .not-found {
252
+ flex: 1;
253
+ display: flex;
254
+ flex-direction: column;
255
+ align-items: center;
256
+ justify-content: center;
257
+ text-align: center;
258
+ gap: 0.5rem;
259
+ }
260
+
261
+ .not-found h1 {
262
+ font-size: 4rem;
263
+ font-weight: 800;
264
+ color: var(--color-text-muted);
265
+ }
266
+
267
+ .not-found p {
268
+ color: var(--color-text-muted);
269
+ }
@@ -0,0 +1,271 @@
1
+ @import "tailwindcss";
2
+
3
+ :root {
4
+ --color-bg: #0a0a0f;
5
+ --color-surface: #15151e;
6
+ --color-border: #2a2a3e;
7
+ --color-text: #e4e4ef;
8
+ --color-text-muted: #8888a0;
9
+ --color-accent: #7c3aed;
10
+ --color-accent-hover: #6d28d9;
11
+ --font-sans: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
12
+ --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;
13
+ }
14
+
15
+ *,
16
+ *::before,
17
+ *::after {
18
+ margin: 0;
19
+ padding: 0;
20
+ box-sizing: border-box;
21
+ }
22
+
23
+ html {
24
+ font-family: var(--font-sans);
25
+ background: var(--color-bg);
26
+ color: var(--color-text);
27
+ -webkit-font-smoothing: antialiased;
28
+ -moz-osx-font-smoothing: grayscale;
29
+ }
30
+
31
+ body {
32
+ min-height: 100dvh;
33
+ }
34
+
35
+ a {
36
+ color: var(--color-accent);
37
+ text-decoration: none;
38
+ }
39
+
40
+ a:hover {
41
+ color: var(--color-accent-hover);
42
+ }
43
+
44
+ code {
45
+ font-family: var(--font-mono);
46
+ font-size: 0.9em;
47
+ background: var(--color-surface);
48
+ padding: 0.15em 0.4em;
49
+ border-radius: 4px;
50
+ }
51
+
52
+ .app {
53
+ min-height: 100dvh;
54
+ display: flex;
55
+ flex-direction: column;
56
+ }
57
+
58
+ .header {
59
+ border-bottom: 1px solid var(--color-border);
60
+ padding: 0.75rem 1.5rem;
61
+ }
62
+
63
+ .nav {
64
+ max-width: 64rem;
65
+ margin: 0 auto;
66
+ display: flex;
67
+ align-items: center;
68
+ justify-content: space-between;
69
+ }
70
+
71
+ .nav-brand {
72
+ font-weight: 700;
73
+ font-size: 1.125rem;
74
+ color: var(--color-text);
75
+ }
76
+
77
+ .nav-links {
78
+ display: flex;
79
+ gap: 1.5rem;
80
+ }
81
+
82
+ .nav-link {
83
+ color: var(--color-text-muted);
84
+ font-size: 0.875rem;
85
+ transition: color 0.15s;
86
+ }
87
+
88
+ .nav-link:hover {
89
+ color: var(--color-text);
90
+ }
91
+
92
+ .hero {
93
+ flex: 1;
94
+ display: flex;
95
+ align-items: center;
96
+ justify-content: center;
97
+ padding: 3rem 1.5rem;
98
+ }
99
+
100
+ .hero-content {
101
+ max-width: 40rem;
102
+ text-align: center;
103
+ }
104
+
105
+ .hero-title {
106
+ font-size: 3rem;
107
+ font-weight: 800;
108
+ letter-spacing: -0.02em;
109
+ background: linear-gradient(135deg, var(--color-accent) 0%, #a78bfa 100%);
110
+ -webkit-background-clip: text;
111
+ -webkit-text-fill-color: transparent;
112
+ background-clip: text;
113
+ }
114
+
115
+ .hero-description {
116
+ margin-top: 1rem;
117
+ font-size: 1.125rem;
118
+ color: var(--color-text-muted);
119
+ line-height: 1.6;
120
+ }
121
+
122
+ .hero-links {
123
+ margin-top: 2rem;
124
+ display: flex;
125
+ gap: 1.5rem;
126
+ justify-content: center;
127
+ }
128
+
129
+ .link {
130
+ color: var(--color-accent);
131
+ font-weight: 500;
132
+ transition: color 0.15s;
133
+ }
134
+
135
+ .link:hover {
136
+ color: var(--color-accent-hover);
137
+ }
138
+
139
+ .counter-card {
140
+ margin-top: 2rem;
141
+ background: var(--color-surface);
142
+ border: 1px solid var(--color-border);
143
+ border-radius: 12px;
144
+ padding: 1.5rem;
145
+ display: inline-flex;
146
+ flex-direction: column;
147
+ align-items: center;
148
+ gap: 1rem;
149
+ }
150
+
151
+ .counter-value {
152
+ font-size: 2.5rem;
153
+ font-weight: 700;
154
+ font-variant-numeric: tabular-nums;
155
+ }
156
+
157
+ .counter-actions {
158
+ display: flex;
159
+ gap: 0.75rem;
160
+ }
161
+
162
+ .counter-btn {
163
+ width: 2.5rem;
164
+ height: 2.5rem;
165
+ border-radius: 8px;
166
+ border: 1px solid var(--color-border);
167
+ background: var(--color-bg);
168
+ color: var(--color-text);
169
+ font-size: 1.25rem;
170
+ cursor: pointer;
171
+ display: flex;
172
+ align-items: center;
173
+ justify-content: center;
174
+ transition: background 0.15s, border-color 0.15s;
175
+ }
176
+
177
+ .counter-btn:hover {
178
+ background: var(--color-surface);
179
+ border-color: var(--color-accent);
180
+ }
181
+
182
+ .features {
183
+ margin-top: 3rem;
184
+ display: grid;
185
+ grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
186
+ gap: 1rem;
187
+ text-align: left;
188
+ }
189
+
190
+ .feature-card {
191
+ background: var(--color-surface);
192
+ border: 1px solid var(--color-border);
193
+ border-radius: 12px;
194
+ padding: 1.25rem;
195
+ }
196
+
197
+ .feature-card h3 {
198
+ font-size: 1rem;
199
+ font-weight: 600;
200
+ margin-bottom: 0.5rem;
201
+ }
202
+
203
+ .feature-card p {
204
+ font-size: 0.875rem;
205
+ color: var(--color-text-muted);
206
+ line-height: 1.5;
207
+ }
208
+
209
+ .page {
210
+ flex: 1;
211
+ padding: 3rem 1.5rem;
212
+ }
213
+
214
+ .page-content {
215
+ max-width: 48rem;
216
+ margin: 0 auto;
217
+ }
218
+
219
+ .page-content h1 {
220
+ font-size: 2rem;
221
+ font-weight: 700;
222
+ margin-bottom: 1rem;
223
+ }
224
+
225
+ .page-content p {
226
+ color: var(--color-text-muted);
227
+ line-height: 1.6;
228
+ margin-bottom: 1.5rem;
229
+ }
230
+
231
+ .guide-section {
232
+ margin-top: 2rem;
233
+ }
234
+
235
+ .guide-section h2 {
236
+ font-size: 1.25rem;
237
+ font-weight: 600;
238
+ margin-bottom: 0.75rem;
239
+ }
240
+
241
+ .code-block {
242
+ background: var(--color-surface);
243
+ border: 1px solid var(--color-border);
244
+ border-radius: 8px;
245
+ padding: 1rem;
246
+ font-family: var(--font-mono);
247
+ font-size: 0.8125rem;
248
+ line-height: 1.6;
249
+ overflow-x: auto;
250
+ white-space: pre;
251
+ }
252
+
253
+ .not-found {
254
+ flex: 1;
255
+ display: flex;
256
+ flex-direction: column;
257
+ align-items: center;
258
+ justify-content: center;
259
+ text-align: center;
260
+ gap: 0.5rem;
261
+ }
262
+
263
+ .not-found h1 {
264
+ font-size: 4rem;
265
+ font-weight: 800;
266
+ color: var(--color-text-muted);
267
+ }
268
+
269
+ .not-found p {
270
+ color: var(--color-text-muted);
271
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
+ "jsx": "preserve",
8
+ "jsxImportSource": "solid-js",
9
+ "strict": true,
10
+ "noEmit": true,
11
+ "isolatedModules": true,
12
+ "esModuleInterop": true,
13
+ "skipLibCheck": true,
14
+ "types": ["vite/client"]
15
+ },
16
+ "include": ["bare/src", "modern/src"]
17
+ }