loly 0.1.0

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 ADDED
@@ -0,0 +1,374 @@
1
+ # loly
2
+
3
+ ![npm](https://img.shields.io/npm/v/loly)
4
+ ![license](https://img.shields.io/npm/l/loly)
5
+
6
+ Modern full-stack web framework with streaming SSR, async server components, islands architecture, and fine-grained reactivity.
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install loly
12
+ # or
13
+ yarn add loly
14
+ # or
15
+ pnpm add loly
16
+ ```
17
+
18
+ ## Quick Start
19
+
20
+ Create a new project structure:
21
+
22
+ ```
23
+ my-app/
24
+ ├── src/
25
+ │ └── app/
26
+ │ ├── layout.tsx
27
+ │ └── page.tsx
28
+ └── package.json
29
+ ```
30
+
31
+ **src/app/layout.tsx:**
32
+ ```tsx
33
+ import type { LayoutProps } from "loly";
34
+
35
+ export default function Layout({ children }: LayoutProps) {
36
+ return (
37
+ <>
38
+ <nav>Navigation</nav>
39
+ <main>{children}</main>
40
+ </>
41
+ );
42
+ }
43
+ ```
44
+
45
+ **src/app/page.tsx:**
46
+ ```tsx
47
+ export default function Home() {
48
+ return <h1>Hello, loly!</h1>;
49
+ }
50
+ ```
51
+
52
+ Start the development server:
53
+
54
+ ```bash
55
+ npx loly dev
56
+ ```
57
+
58
+ ## Core Concepts
59
+
60
+ ### File-based Routing
61
+
62
+ loly uses a file-based routing system similar to Next.js. Routes are defined by the file structure in `src/app/`:
63
+
64
+ ```
65
+ src/app/
66
+ ├── layout.tsx # Root layout
67
+ ├── page.tsx # Home page (/)
68
+ ├── about/
69
+ │ └── page.tsx # /about
70
+ └── users/
71
+ └── [id]/
72
+ └── page.tsx # /users/:id
73
+ ```
74
+
75
+ **Dynamic routes:**
76
+ - `[id]` - Single dynamic segment
77
+ - `[...slug]` - Catch-all route
78
+ - `[[...slug]]` - Optional catch-all
79
+ - `(group)` - Route groups (not in URL)
80
+
81
+ **Route files:**
82
+ - `page.tsx` - Page component
83
+ - `layout.tsx` - Layout component (wraps child routes)
84
+ - `route.ts` - API route handler
85
+
86
+ ### SSR and Streaming
87
+
88
+ loly supports two rendering strategies:
89
+
90
+ **SSR Strategy** - Full page streaming:
91
+ ```tsx
92
+ import { renderPageStream } from "loly";
93
+
94
+ const result = await renderPageStream({
95
+ pathname: "/",
96
+ searchParams: {},
97
+ params: {},
98
+ }, routeConfig, appDir);
99
+ ```
100
+
101
+ **RSC Strategy** - SPA navigation with partial updates:
102
+ ```tsx
103
+ import { renderPageContent } from "loly";
104
+
105
+ const result = await renderPageContent({
106
+ pathname: "/",
107
+ searchParams: {},
108
+ params: {},
109
+ }, routeConfig, appDir);
110
+ ```
111
+
112
+ ### Islands Architecture
113
+
114
+ Use islands to selectively hydrate components on the client:
115
+
116
+ ```tsx
117
+ import { defineIsland, state } from "loly-jsx";
118
+
119
+ const CounterIsland = defineIsland("Counter", function Counter() {
120
+ const [count, setCount] = state(0);
121
+ return <button onClick={() => setCount(count + 1)}>{count}</button>;
122
+ });
123
+
124
+ // In your page
125
+ export default function Page() {
126
+ return (
127
+ <div>
128
+ <h1>Server-rendered content</h1>
129
+ <CounterIsland client:load />
130
+ </div>
131
+ );
132
+ }
133
+ ```
134
+
135
+ ## Features
136
+
137
+ ### Development Server
138
+
139
+ Start a development server with hot reload:
140
+
141
+ ```bash
142
+ loly dev [dir] [port]
143
+ ```
144
+
145
+ The dev server:
146
+ - Watches for file changes
147
+ - Supports hot module replacement
148
+ - Provides error overlays
149
+ - Handles TypeScript/JSX automatically
150
+
151
+ ### Build System
152
+
153
+ Build your application for production:
154
+
155
+ ```bash
156
+ loly build [dir] [--out-dir=<path>] [--dev]
157
+ ```
158
+
159
+ The build process:
160
+ - Scans routes from `src/app/`
161
+ - Builds client bundle with rspack
162
+ - Builds server files with esbuild
163
+ - Generates route manifests
164
+ - Optimizes assets
165
+
166
+ ### API Routes
167
+
168
+ Create API endpoints using `route.ts` files:
169
+
170
+ **src/app/api/users/route.ts:**
171
+ ```tsx
172
+ import type { Request, Response } from "express";
173
+
174
+ export async function GET(req: Request, res: Response) {
175
+ const users = await fetchUsers();
176
+ return res.json(users);
177
+ }
178
+
179
+ export async function POST(req: Request, res: Response) {
180
+ const data = await req.json();
181
+ const user = await createUser(data);
182
+ return res.json(user);
183
+ }
184
+ ```
185
+
186
+ Routes support: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`
187
+
188
+ ### Image Optimization
189
+
190
+ Use the `Image` component for optimized images:
191
+
192
+ ```tsx
193
+ import { Image } from "loly";
194
+
195
+ export default function Page() {
196
+ return (
197
+ <Image
198
+ src="/hero.jpg"
199
+ alt="Hero image"
200
+ width={800}
201
+ height={600}
202
+ quality={90}
203
+ />
204
+ );
205
+ }
206
+ ```
207
+
208
+ Features:
209
+ - Automatic format optimization (WebP, AVIF)
210
+ - Responsive images
211
+ - Lazy loading
212
+ - Image caching
213
+
214
+ ### Client Bootstrap
215
+
216
+ Bootstrap your client application:
217
+
218
+ ```tsx
219
+ import { bootstrapClient } from "loly/client";
220
+
221
+ bootstrapClient({
222
+ routes: [
223
+ { path: "/", component: () => import("./app/page") },
224
+ { path: "/about", component: () => import("./app/about/page") },
225
+ ],
226
+ });
227
+ ```
228
+
229
+ ## Project Structure
230
+
231
+ ```
232
+ my-app/
233
+ ├── src/
234
+ │ ├── app/ # App directory (routes)
235
+ │ │ ├── layout.tsx # Root layout
236
+ │ │ ├── page.tsx # Home page
237
+ │ │ └── [routes]/ # Route segments
238
+ │ ├── components/ # Shared components
239
+ │ └── globals.css # Global styles
240
+ ├── public/ # Static assets
241
+ ├── .loly/ # Build output (generated)
242
+ │ ├── dist/ # Production build
243
+ │ └── client/ # Client bundle
244
+ └── package.json
245
+ ```
246
+
247
+ ## API Reference
248
+
249
+ ### Server
250
+
251
+ - `startDevServer(options)` - Start development server
252
+ - `startProdServer(options)` - Start production server
253
+ - `renderPageStream(context, config, appDir)` - Render page with streaming
254
+ - `renderPageContent(context, config, appDir)` - Render page content (RSC)
255
+ - `BaseServer` - Base server class for custom implementations
256
+
257
+ ### Router
258
+
259
+ - `scanRoutes(appDir)` - Scan routes from app directory
260
+ - `matchRoute(pathname, config)` - Match route by pathname
261
+ - `extractParams(pathname, route)` - Extract route parameters
262
+
263
+ ### Build
264
+
265
+ - `buildProject(options)` - Build project for production
266
+ - `generateRoutesManifest(config, projectDir, appDir)` - Generate route manifest
267
+ - `generateBootstrap(projectDir, routes)` - Generate client bootstrap
268
+
269
+ ### Client
270
+
271
+ - `bootstrapClient(options)` - Bootstrap client application
272
+ - `navigate(to, options?)` - Navigate programmatically
273
+
274
+ ### Components
275
+
276
+ - `Image` - Optimized image component
277
+
278
+ ### Utilities
279
+
280
+ - `getEnv(key)` - Get environment variable
281
+ - `getPublicEnv()` - Get public environment variables
282
+ - `generatePublicEnvScript()` - Generate script tag for public env
283
+
284
+ ## CLI Commands
285
+
286
+ ```bash
287
+ # Development
288
+ loly dev [dir] [port]
289
+
290
+ # Build
291
+ loly build [dir] [--out-dir=<path>] [--dev]
292
+
293
+ # Production server
294
+ loly start [dir] [port]
295
+ ```
296
+
297
+ ## Environment Variables
298
+
299
+ Create a `.env` file in your project root:
300
+
301
+ ```env
302
+ # Public variables (exposed to client)
303
+ # Use any prefix you want, e.g. LOLY_PUBLIC_API_URL or VITE_API_URL
304
+ LOLY_PUBLIC_API_URL=https://api.example.com
305
+
306
+ # Private variables (server only)
307
+ DATABASE_URL=postgresql://...
308
+ API_SECRET=secret
309
+ ```
310
+
311
+ Access in your code:
312
+
313
+ ```tsx
314
+ import { getEnv, getPublicEnv } from "loly";
315
+
316
+ // Server only
317
+ const dbUrl = getEnv("DATABASE_URL");
318
+
319
+ // Public (available on client)
320
+ const apiUrl = getPublicEnv().PUBLIC_API_URL;
321
+ ```
322
+
323
+ ## Examples
324
+
325
+ ### Page with Layout
326
+
327
+ **src/app/layout.tsx:**
328
+ ```tsx
329
+ import type { LayoutProps } from "loly";
330
+
331
+ export default function Layout({ children }: LayoutProps) {
332
+ return (
333
+ <>
334
+ <nav>Navigation</nav>
335
+ <main>{children}</main>
336
+ </>
337
+ );
338
+ }
339
+ ```
340
+
341
+ **src/app/page.tsx:**
342
+ ```tsx
343
+ export default function Home() {
344
+ return <h1>Home Page</h1>;
345
+ }
346
+ ```
347
+
348
+ ### Dynamic Route
349
+
350
+ **src/app/users/[id]/page.tsx:**
351
+ ```tsx
352
+ import type { PageProps } from "loly";
353
+
354
+ export default function UserPage({ params }: PageProps) {
355
+ return <h1>User {params.id}</h1>;
356
+ }
357
+ ```
358
+
359
+ ### API Route
360
+
361
+ **src/app/api/hello/route.ts:**
362
+ ```tsx
363
+ import type { Request, Response } from "express";
364
+
365
+ export async function GET(req: Request, res: Response) {
366
+ return res.json({ message: "Hello" });
367
+ }
368
+ ```
369
+
370
+ ## Links
371
+
372
+ - [Repository](https://github.com/MenvielleValen/loly)
373
+ - [Homepage](https://loly.dev)
374
+