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 +373 -0
- package/bin/webspresso.js +790 -0
- package/index.js +34 -0
- package/package.json +59 -0
- package/src/file-router.js +520 -0
- package/src/helpers.js +275 -0
- package/src/server.js +180 -0
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
|