webspresso 0.0.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,373 @@
1
+ # Webspresso
2
+
3
+ A minimal, file-based SSR framework for Node.js with Nunjucks templating.
4
+
5
+ ## Features
6
+
7
+ - **File-Based Routing**: Create pages by adding `.njk` files to a `pages/` directory
8
+ - **Dynamic Routes**: Use `[param]` for dynamic params and `[...rest]` for catch-all routes
9
+ - **API Endpoints**: Add `.js` files to `pages/api/` with method suffixes (e.g., `health.get.js`)
10
+ - **Built-in i18n**: JSON-based translations with automatic locale detection
11
+ - **Lifecycle Hooks**: Global and route-level hooks for request processing
12
+ - **Template Helpers**: Laravel-inspired helper functions available in templates
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install -g webspresso
18
+ # or
19
+ npm install webspresso
20
+ ```
21
+
22
+ ## Quick Start
23
+
24
+ ### Using CLI (Recommended)
25
+
26
+ ```bash
27
+ # Create a new project (Tailwind CSS included by default)
28
+ webspresso new my-app
29
+
30
+ # Navigate to project
31
+ cd my-app
32
+
33
+ # Install dependencies
34
+ npm install
35
+
36
+ # Build Tailwind CSS
37
+ npm run build:css
38
+
39
+ # Start development server (watches both CSS and server)
40
+ webspresso dev
41
+ # or
42
+ npm run dev
43
+ ```
44
+
45
+ > **Note:** New projects include Tailwind CSS by default. Use `--no-tailwind` flag to skip it.
46
+
47
+ ### Manual Setup
48
+
49
+ ```javascript
50
+ // server.js
51
+ const { createApp } = require('webspresso');
52
+ const path = require('path');
53
+
54
+ const { app } = createApp({
55
+ pagesDir: path.join(__dirname, 'pages'),
56
+ viewsDir: path.join(__dirname, 'views'),
57
+ publicDir: path.join(__dirname, 'public')
58
+ });
59
+
60
+ app.listen(3000, () => {
61
+ console.log('Server running at http://localhost:3000');
62
+ });
63
+ ```
64
+
65
+ ## CLI Commands
66
+
67
+ ### `webspresso new <project-name>`
68
+
69
+ Create a new Webspresso project with Tailwind CSS (default).
70
+
71
+ ```bash
72
+ webspresso new my-app
73
+
74
+ # Auto install dependencies and build CSS
75
+ webspresso new my-app --install
76
+
77
+ # Without Tailwind
78
+ webspresso new my-app --no-tailwind
79
+ ```
80
+
81
+ Options:
82
+ - `-i, --install` - Auto run `npm install` and `npm run build:css`
83
+ - `--no-tailwind` - Skip Tailwind CSS setup
84
+
85
+ The project includes:
86
+ - Tailwind CSS with build process
87
+ - Optimized layout template with navigation and footer
88
+ - Responsive starter page
89
+ - i18n setup (en/tr)
90
+ - Development and production scripts
91
+
92
+ ### `webspresso page`
93
+
94
+ Add a new page to your project (interactive prompt).
95
+
96
+ ```bash
97
+ webspresso page
98
+ ```
99
+
100
+ The CLI will ask you:
101
+ - Route path (e.g., `/about` or `/blog/post`)
102
+ - Whether to add a route config file
103
+ - Whether to add locale files
104
+
105
+ ### `webspresso api`
106
+
107
+ Add a new API endpoint (interactive prompt).
108
+
109
+ ```bash
110
+ webspresso api
111
+ ```
112
+
113
+ The CLI will ask you:
114
+ - API route path (e.g., `/api/users` or `/api/users/[id]`)
115
+ - HTTP method (GET, POST, PUT, PATCH, DELETE)
116
+
117
+ ### `webspresso dev`
118
+
119
+ Start development server with hot reload.
120
+
121
+ ```bash
122
+ webspresso dev
123
+ # or with custom port
124
+ webspresso dev --port 3001
125
+ ```
126
+
127
+ ### `webspresso start`
128
+
129
+ Start production server.
130
+
131
+ ```bash
132
+ webspresso start
133
+ # or with custom port
134
+ webspresso start --port 3000
135
+ ```
136
+
137
+ ### `webspresso add tailwind`
138
+
139
+ Add Tailwind CSS to your project with build process.
140
+
141
+ ```bash
142
+ webspresso add tailwind
143
+ ```
144
+
145
+ This command will:
146
+ - Install Tailwind CSS, PostCSS, and Autoprefixer as dev dependencies
147
+ - Create `tailwind.config.js` and `postcss.config.js`
148
+ - Create `src/input.css` with Tailwind directives
149
+ - Add build scripts to `package.json`
150
+ - Update your layout to use the built CSS instead of CDN
151
+ - Create `public/css/style.css` for the compiled output
152
+
153
+ After running this command:
154
+ ```bash
155
+ npm install
156
+ npm run build:css # Build CSS once
157
+ npm run watch:css # Watch and rebuild CSS on changes
158
+ npm run dev # Starts both CSS watch and dev server
159
+ ```
160
+
161
+ ## Project Structure
162
+
163
+ Create your app with this structure:
164
+
165
+ ```
166
+ my-app/
167
+ ├── pages/
168
+ │ ├── locales/ # Global i18n translations
169
+ │ │ ├── en.json
170
+ │ │ └── tr.json
171
+ │ ├── _hooks.js # Global lifecycle hooks
172
+ │ ├── index.njk # Home page (GET /)
173
+ │ ├── about/
174
+ │ │ ├── index.njk # About page (GET /about)
175
+ │ │ └── locales/ # Route-specific translations
176
+ │ ├── tools/
177
+ │ │ ├── index.njk # Tools list (GET /tools)
178
+ │ │ ├── index.js # Route config with load()
179
+ │ │ ├── [slug].njk # Dynamic tool page (GET /tools/:slug)
180
+ │ │ └── [slug].js # Route config for dynamic page
181
+ │ └── api/
182
+ │ ├── health.get.js # GET /api/health
183
+ │ └── echo.post.js # POST /api/echo
184
+ ├── views/
185
+ │ └── layout.njk # Base layout template
186
+ ├── public/ # Static files
187
+ └── server.js
188
+ ```
189
+
190
+ ## API
191
+
192
+ ### `createApp(options)`
193
+
194
+ Creates and configures the Express app.
195
+
196
+ **Options:**
197
+ - `pagesDir` (required): Path to pages directory
198
+ - `viewsDir` (optional): Path to views/layouts directory
199
+ - `publicDir` (optional): Path to public/static directory
200
+ - `logging` (optional): Enable request logging (default: true in development)
201
+
202
+ **Returns:** `{ app, nunjucksEnv }`
203
+
204
+ ## File-Based Routing
205
+
206
+ ### SSR Pages
207
+
208
+ Create `.njk` files in the `pages/` directory:
209
+
210
+ | File Path | Route |
211
+ |-----------|-------|
212
+ | `pages/index.njk` | `/` |
213
+ | `pages/about/index.njk` | `/about` |
214
+ | `pages/tools/[slug].njk` | `/tools/:slug` |
215
+ | `pages/docs/[...rest].njk` | `/docs/*` |
216
+
217
+ ### API Routes
218
+
219
+ Create `.js` files in `pages/api/` with optional method suffixes:
220
+
221
+ | File Path | Route |
222
+ |-----------|-------|
223
+ | `pages/api/health.get.js` | `GET /api/health` |
224
+ | `pages/api/echo.post.js` | `POST /api/echo` |
225
+ | `pages/api/users/[id].get.js` | `GET /api/users/:id` |
226
+
227
+ ### Route Config
228
+
229
+ Add a `.js` file alongside your `.njk` file to configure the route:
230
+
231
+ ```javascript
232
+ // pages/tools/index.js
233
+ module.exports = {
234
+ // Middleware for this route
235
+ middleware: [(req, res, next) => next()],
236
+
237
+ // Load data for SSR
238
+ async load(req, ctx) {
239
+ return { tools: await fetchTools() };
240
+ },
241
+
242
+ // Override meta tags
243
+ meta(req, ctx) {
244
+ return {
245
+ title: 'Tools',
246
+ description: 'Developer tools'
247
+ };
248
+ },
249
+
250
+ // Route-level hooks
251
+ hooks: {
252
+ beforeLoad: async (ctx) => {},
253
+ afterRender: async (ctx) => {}
254
+ }
255
+ };
256
+ ```
257
+
258
+ ## i18n
259
+
260
+ ### Global Translations
261
+
262
+ Add JSON files to `pages/locales/`:
263
+
264
+ ```json
265
+ // pages/locales/en.json
266
+ {
267
+ "nav": {
268
+ "home": "Home",
269
+ "about": "About"
270
+ }
271
+ }
272
+ ```
273
+
274
+ ### Route-Specific Translations
275
+
276
+ Add a `locales/` folder inside any route directory to override global translations.
277
+
278
+ ### Using Translations
279
+
280
+ In templates:
281
+
282
+ ```nunjucks
283
+ <h1>{{ t('nav.home') }}</h1>
284
+ ```
285
+
286
+ ## Template Helpers
287
+
288
+ The `fsy` object is available in all templates:
289
+
290
+ ```nunjucks
291
+ {# URL helpers #}
292
+ {{ fsy.url('/tools', { page: 1 }) }}
293
+ {{ fsy.fullUrl('/tools') }}
294
+ {{ fsy.route('/tools/:slug', { slug: 'test' }) }}
295
+
296
+ {# Request helpers #}
297
+ {{ fsy.q('page', 1) }}
298
+ {{ fsy.param('slug') }}
299
+ {{ fsy.hdr('User-Agent') }}
300
+
301
+ {# Utility helpers #}
302
+ {{ fsy.slugify('Hello World') }}
303
+ {{ fsy.truncate(text, 100) }}
304
+ {{ fsy.prettyBytes(1024) }}
305
+ {{ fsy.prettyMs(5000) }}
306
+
307
+ {# Environment #}
308
+ {% if fsy.isDev() %}Dev mode{% endif %}
309
+
310
+ {# SEO #}
311
+ {{ fsy.canonical() }}
312
+ {{ fsy.jsonld(schema) | safe }}
313
+ ```
314
+
315
+ ## Lifecycle Hooks
316
+
317
+ ### Global Hooks
318
+
319
+ Create `pages/_hooks.js`:
320
+
321
+ ```javascript
322
+ module.exports = {
323
+ onRequest(ctx) {},
324
+ beforeLoad(ctx) {},
325
+ afterLoad(ctx) {},
326
+ beforeRender(ctx) {},
327
+ afterRender(ctx) {},
328
+ onError(ctx, err) {}
329
+ };
330
+ ```
331
+
332
+ ### Hook Execution Order
333
+
334
+ 1. Global `onRequest`
335
+ 2. Route `onRequest`
336
+ 3. Route `beforeMiddleware`
337
+ 4. Route middleware
338
+ 5. Route `afterMiddleware`
339
+ 6. Route `beforeLoad`
340
+ 7. Route `load()`
341
+ 8. Route `afterLoad`
342
+ 9. Route `beforeRender`
343
+ 10. Nunjucks render
344
+ 11. Route `afterRender`
345
+
346
+ ## Environment Variables
347
+
348
+ | Variable | Default | Description |
349
+ |----------|---------|-------------|
350
+ | `NODE_ENV` | `development` | Environment |
351
+ | `DEFAULT_LOCALE` | `en` | Default locale |
352
+ | `SUPPORTED_LOCALES` | `en` | Comma-separated locales |
353
+ | `BASE_URL` | `http://localhost:3000` | Base URL for canonical URLs |
354
+
355
+ ## Development
356
+
357
+ ```bash
358
+ # Install dependencies
359
+ npm install
360
+
361
+ # Run tests
362
+ npm test
363
+
364
+ # Run tests in watch mode
365
+ npm run test:watch
366
+
367
+ # Run tests with coverage
368
+ npm run test:coverage
369
+ ```
370
+
371
+ ## License
372
+
373
+ MIT