@chidchanun/bcp 0.1.24 → 0.1.25

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 CHANGED
@@ -1,11 +1,80 @@
1
1
  # BCP Framework
2
2
 
3
- BCP Framework is a React full-stack framework with file-based routing, SSR, SPA navigation, API routes, middleware, loaders, guards, form actions, authentication, MySQL primitives, validation, structured errors, logging, file uploads and standalone production builds.
3
+ BCP Framework is a React full-stack framework focused on file-based routing, server rendering, server-side data loading, guarded application flows, API routes, authentication, database access, validation, logging, file uploads, storage adapters and standalone production deployment.
4
4
 
5
- > Current release target: `0.1.24`. BCP is pre-1.0 and each release candidate is validated before the manual npm publish step.
5
+ > **Development target:** `0.1.25`
6
+ >
7
+ > BCP is still pre-1.0. Features documented for the current development target should not be presented as published npm behavior until the release candidate has passed and the matching version has been published.
8
+
9
+ ## Overview
10
+
11
+ BCP provides a single application model for React pages and server code:
12
+
13
+ ```text
14
+ Browser
15
+
16
+ BCP middleware / security
17
+
18
+ Route guard
19
+
20
+ Loader / action / API route
21
+
22
+ React SSR
23
+
24
+ Hydration / SPA navigation
25
+ ```
26
+
27
+ The framework is designed so application code can stay close to the route that owns it:
28
+
29
+ ```text
30
+ app/
31
+ ├─ layout.tsx
32
+ ├─ page.tsx
33
+ ├─ dashboard/
34
+ │ ├─ guard.ts
35
+ │ └─ users/
36
+ │ └─ [id]/
37
+ │ ├─ loader.ts
38
+ │ ├─ actions.ts
39
+ │ └─ page.tsx
40
+ └─ api/
41
+ └─ upload/
42
+ └─ route.ts
43
+ ```
44
+
45
+ ## Current capabilities
46
+
47
+ | Area | Capability |
48
+ | --- | --- |
49
+ | Application | React SSR, hydration, layouts, metadata, SPA navigation |
50
+ | Routing | Static, dynamic, catch-all, optional catch-all and route groups |
51
+ | Server data | `loader.ts`, request-scoped server APIs |
52
+ | Mutations | Route-owned `actions.ts` and `<Form>` |
53
+ | Authorization | `guard.ts`, `requireAuth()`, `requireRole()` |
54
+ | Authentication | JWT cookie sessions and auth helpers |
55
+ | Middleware | Middleware System v2 with onion execution |
56
+ | Validation | Typed validation helpers and structured validation errors |
57
+ | Error handling | HTTP error helpers and consistent error responses |
58
+ | Database | MySQL pool/query helpers, transactions and migrations |
59
+ | Logging | Structured logger, request logger and request IDs |
60
+ | Uploads | Multipart parsing, file validation and safe local persistence |
61
+ | Storage | `StorageAdapter`, local storage adapter and file delivery |
62
+ | Caching | Response cache and revalidation primitives |
63
+ | Developer tools | `doctor`, `inspect`, updater and route inspection |
64
+ | Production | Standalone server build with production middleware pipeline |
65
+
66
+ ## Requirements
67
+
68
+ - Node.js `24.11` or newer
69
+ - React `19`
70
+ - npm
71
+
72
+ Database features currently target MySQL.
6
73
 
7
74
  ## Quick start
8
75
 
76
+ Create a new application:
77
+
9
78
  ```bash
10
79
  npx create-bcp-app@latest my-app
11
80
  cd my-app
@@ -18,65 +87,93 @@ Default development URL:
18
87
  http://localhost:3000
19
88
  ```
20
89
 
21
- ## CLI
90
+ A generated project normally exposes scripts such as:
22
91
 
23
- ```bash
24
- bcp dev
25
- bcp routes
26
- bcp build
27
- bcp start
28
- bcp doctor
29
- bcp doctor --json
30
- bcp inspect
31
- bcp inspect --json
32
- bcp update
33
- bcp version
92
+ ```json
93
+ {
94
+ "scripts": {
95
+ "dev": "bcp dev",
96
+ "build": "bcp build",
97
+ "start": "bcp start",
98
+ "routes": "bcp routes",
99
+ "update": "bcp update"
100
+ }
101
+ }
102
+ ```
34
103
 
35
- bcp db create create_users
36
- bcp db migrate
37
- bcp db status
38
- bcp db rollback
104
+ ## Packages
105
+
106
+ The public framework package is published as:
107
+
108
+ ```text
109
+ @chidchanun/bcp
39
110
  ```
40
111
 
41
- Microsoft SQL Server also installs a Windows executable named `bcp.exe`. BCP Framework therefore also publishes the collision-free alias:
112
+ Applications normally consume it through the dependency key:
42
113
 
43
- ```powershell
44
- bcp-framework doctor
45
- bcp-framework inspect
46
- bcp-framework dev
47
- bcp-framework build
114
+ ```text
115
+ bcp
48
116
  ```
49
117
 
50
- Normal project npm scripts can continue using `bcp` because npm places `node_modules/.bin` first on the script PATH.
118
+ This keeps imports concise:
119
+
120
+ ```ts
121
+ import {
122
+ Form,
123
+ Link,
124
+ useLoaderData,
125
+ } from "bcp";
126
+ ```
127
+
128
+ Server-only APIs use dedicated entrypoints such as:
129
+
130
+ ```ts
131
+ import {
132
+ cookies,
133
+ logger,
134
+ requestId,
135
+ } from "bcp/server";
136
+ ```
51
137
 
52
138
  ## Project structure
53
139
 
140
+ A typical application can grow into this layout:
141
+
54
142
  ```text
55
143
  app/
56
144
  ├─ layout.tsx
57
145
  ├─ page.tsx
146
+ ├─ login/
147
+ │ └─ page.tsx
58
148
  ├─ dashboard/
59
149
  │ ├─ guard.ts
150
+ │ ├─ page.tsx
60
151
  │ └─ users/
61
152
  │ └─ [id]/
62
153
  │ ├─ loader.ts
63
154
  │ ├─ actions.ts
64
155
  │ └─ page.tsx
65
156
  └─ api/
66
- ├─ hello/
67
- │ └─ route.ts
157
+ ├─ auth/
158
+ │ └─ login/
159
+ │ └─ route.ts
68
160
  └─ upload/
69
161
  └─ route.ts
70
162
 
71
163
  lib/
72
164
  public/
165
+ migrations/
73
166
  bcp.config.ts
74
167
  package.json
75
168
  tsconfig.json
76
169
  ```
77
170
 
171
+ BCP keeps page rendering, route authorization, server data and route mutations close together without requiring one large application router configuration file.
172
+
78
173
  ## Routing
79
174
 
175
+ Page routes are discovered from `app/**/page.tsx`.
176
+
80
177
  ```text
81
178
  app/page.tsx /
82
179
  app/about/page.tsx /about
@@ -88,9 +185,26 @@ app/(admin)/settings/page.tsx /settings
88
185
 
89
186
  Static routes have priority over dynamic and catch-all routes.
90
187
 
91
- ## Server data
188
+ API routes use `route.ts`:
189
+
190
+ ```text
191
+ app/api/users/route.ts /api/users
192
+ app/api/users/[id]/route.ts /api/users/:id
193
+ ```
194
+
195
+ Read more: [Routing](docs/routing.md)
92
196
 
93
- A route can load server-only data with `loader.ts`:
197
+ ## Layouts and metadata
198
+
199
+ Routes can inherit layouts from parent directories. The framework resolves the layout chain while rendering both development and standalone production requests.
200
+
201
+ Document metadata is route-aware and can be generated alongside the page tree.
202
+
203
+ Read more: [Routing](docs/routing.md)
204
+
205
+ ## Server data loaders
206
+
207
+ Place `loader.ts` next to a page when the route needs server-side data.
94
208
 
95
209
  ```ts
96
210
  // app/users/[id]/loader.ts
@@ -104,7 +218,7 @@ export async function loader({
104
218
  }
105
219
  ```
106
220
 
107
- The page consumes the serializable value with:
221
+ Consume the serializable result in a client page:
108
222
 
109
223
  ```tsx
110
224
  "use client";
@@ -119,14 +233,50 @@ export default function UserPage() {
119
233
  id: string;
120
234
  }>();
121
235
 
122
- return <main>{data.id}</main>;
236
+ return (
237
+ <main>
238
+ User {data.id}
239
+ </main>
240
+ );
123
241
  }
124
242
  ```
125
243
 
126
- Protected route trees can use `guard.ts`, and route-owned mutations can use `actions.ts` with the public `<Form>` client API.
244
+ Read more: [Server Data Loaders](docs/server-data-loaders.md)
245
+
246
+ ## Route guards
247
+
248
+ A route tree can define `guard.ts` to authorize access before the protected route is rendered.
249
+
250
+ Authentication-aware guards are available through `bcp/auth`:
251
+
252
+ ```ts
253
+ import {
254
+ requireRole,
255
+ } from "bcp/auth";
256
+
257
+ export const guard =
258
+ requireRole("admin");
259
+ ```
260
+
261
+ The standalone production pipeline preserves the same active request context used by authentication and server request APIs.
262
+
263
+ Read more:
264
+
265
+ - [Route Guards](docs/route-guards.md)
266
+ - [Auth Route Guards](docs/auth-route-guards.md)
267
+
268
+ ## Form actions
269
+
270
+ Route-owned mutations live in `actions.ts` and can be invoked through the public `<Form>` API.
271
+
272
+ This supports both progressive form submission and SPA action transport while keeping mutation logic server-only.
273
+
274
+ Read more: [Form Actions](docs/form-actions.md)
127
275
 
128
276
  ## Server request APIs
129
277
 
278
+ Request-scoped APIs are exposed through `bcp/server`:
279
+
130
280
  ```ts
131
281
  import {
132
282
  bearerToken,
@@ -139,11 +289,147 @@ import {
139
289
  } from "bcp/server";
140
290
  ```
141
291
 
142
- `requestId()` accepts a valid incoming `X-Request-Id` or generates a stable UUID for the request.
292
+ `requestId()` uses a valid incoming `X-Request-Id` when available or generates a stable UUID for the active request.
293
+
294
+ Read more: [Server Request APIs](docs/server-request-apis.md)
295
+
296
+ ## Authentication and sessions
297
+
298
+ High-level authentication helpers are available through:
299
+
300
+ ```ts
301
+ import {
302
+ auth,
303
+ requireAuth,
304
+ requireRole,
305
+ } from "bcp/auth";
306
+ ```
307
+
308
+ Lower-level JWT cookie session primitives are available through `bcp/server`:
309
+
310
+ ```ts
311
+ import {
312
+ createSession,
313
+ createSessionToken,
314
+ destroySession,
315
+ getSession,
316
+ verifySessionToken,
317
+ } from "bcp/server";
318
+ ```
319
+
320
+ Authentication is intentionally separated from application-specific credential lookup so projects can connect their own user table or identity provider.
321
+
322
+ Read more:
323
+
324
+ - [Authentication](docs/authentication.md)
325
+ - [JWT Cookie Sessions](docs/session-auth.md)
326
+
327
+ ## Middleware
328
+
329
+ Middleware System v2 uses onion-style execution:
330
+
331
+ ```ts
332
+ export async function middleware(
333
+ request,
334
+ context,
335
+ next
336
+ ) {
337
+ const response =
338
+ await next();
339
+
340
+ response.headers.set(
341
+ "x-app",
342
+ "example"
343
+ );
344
+
345
+ return response;
346
+ }
347
+ ```
348
+
349
+ This allows middleware to run logic both before and after downstream route execution.
350
+
351
+ Existing middleware v1 behavior remains supported for compatibility.
352
+
353
+ Read more: [Middleware](docs/middleware.md)
354
+
355
+ ## Validation
356
+
357
+ BCP includes typed validation primitives:
358
+
359
+ ```ts
360
+ import {
361
+ v,
362
+ validateFormData,
363
+ } from "bcp/validation";
364
+ ```
365
+
366
+ Validation can be shared by API routes and form actions without coupling application schemas to the rendering layer.
367
+
368
+ Read more: [Validation](docs/validation.md)
369
+
370
+ ## Error handling
371
+
372
+ Structured HTTP error helpers are exposed through `bcp/error`:
373
+
374
+ ```ts
375
+ import {
376
+ badRequest,
377
+ forbidden,
378
+ notFoundResponse,
379
+ toErrorResponse,
380
+ unauthorized,
381
+ } from "bcp/error";
382
+ ```
383
+
384
+ The common error envelope is:
385
+
386
+ ```json
387
+ {
388
+ "error": {
389
+ "status": 400,
390
+ "code": "BAD_REQUEST",
391
+ "message": "Invalid request"
392
+ }
393
+ }
394
+ ```
395
+
396
+ Read more: [Error Handling](docs/error-handling.md)
397
+
398
+ ## Database
399
+
400
+ Database helpers are exposed through:
401
+
402
+ ```ts
403
+ import {
404
+ db,
405
+ } from "bcp/database";
406
+ ```
407
+
408
+ The database layer provides:
409
+
410
+ - lazy MySQL pool creation,
411
+ - prepared execution,
412
+ - query helpers,
413
+ - transactions,
414
+ - migration status and rollback support.
143
415
 
144
- ## Logging & Observability
416
+ Migration commands:
145
417
 
146
- BCP 0.1.23 introduced structured server logging:
418
+ ```bash
419
+ bcp db create create_users
420
+ bcp db migrate
421
+ bcp db status
422
+ bcp db rollback
423
+ ```
424
+
425
+ Read more:
426
+
427
+ - [Database](docs/database.md)
428
+ - [Database Migrations](docs/database-migrations.md)
429
+
430
+ ## Logging and observability
431
+
432
+ Structured server logging is available through `bcp/server`:
147
433
 
148
434
  ```ts
149
435
  import {
@@ -158,7 +444,11 @@ logger.info(
158
444
  "catalog",
159
445
  }
160
446
  );
447
+ ```
448
+
449
+ Request-scoped logging can automatically include request identity:
161
450
 
451
+ ```ts
162
452
  export async function loader() {
163
453
  const log =
164
454
  await requestLogger({
@@ -176,18 +466,35 @@ export async function loader() {
176
466
  }
177
467
  ```
178
468
 
179
- Configure output with:
469
+ Environment controls:
180
470
 
181
471
  ```env
182
472
  BCP_LOG_LEVEL=debug
183
473
  BCP_LOG_FORMAT=json
184
474
  ```
185
475
 
186
- Supported levels are `debug`, `info`, `warn`, `error` and `silent`. Formats are `pretty` and `json`.
476
+ Supported levels:
477
+
478
+ ```text
479
+ debug
480
+ info
481
+ warn
482
+ error
483
+ silent
484
+ ```
485
+
486
+ Supported formats:
487
+
488
+ ```text
489
+ pretty
490
+ json
491
+ ```
492
+
493
+ Read more: [Logging and Observability](docs/development-logging.md)
187
494
 
188
- ## File Upload
495
+ ## File upload
189
496
 
190
- BCP 0.1.24 adds server-only multipart/file helpers through `bcp/server`:
497
+ BCP `0.1.24` introduced multipart parsing and file validation:
191
498
 
192
499
  ```ts
193
500
  import {
@@ -229,39 +536,31 @@ export async function POST(
229
536
  }
230
537
  );
231
538
 
232
- const saved =
539
+ return Response.json(
233
540
  await saveUploadedFile(
234
541
  file,
235
542
  {
236
543
  directory:
237
544
  "./uploads",
238
545
  }
239
- );
240
-
241
- return Response.json({
242
- fileName:
243
- saved.fileName,
244
- size:
245
- saved.size,
246
- checksumSha256:
247
- saved.checksumSha256,
248
- });
546
+ )
547
+ );
249
548
  }
250
549
  ```
251
550
 
252
551
  Upload helpers provide:
253
552
 
254
553
  - multipart validation,
255
- - total and per-file size limits,
256
- - MIME/extension allowlists,
257
- - optional or required file fields,
554
+ - total request and per-file size limits,
555
+ - MIME and extension allowlists,
556
+ - required/optional file fields,
258
557
  - safe UUID-based storage names,
259
558
  - filename sanitization,
260
559
  - path traversal protection,
261
- - no-overwrite-by-default storage,
560
+ - no-overwrite-by-default persistence,
262
561
  - SHA-256 checksum metadata.
263
562
 
264
- The security gateway enforces `server.bodyLimit` / `BCP_BODY_LIMIT` before request data reaches application handlers. The default is 1 MiB, so applications accepting larger files must raise it explicitly.
563
+ The security gateway applies `server.bodyLimit` / `BCP_BODY_LIMIT` before application upload parsing. Applications accepting larger files must raise that outer limit explicitly.
265
564
 
266
565
  ```ts
267
566
  import {
@@ -276,122 +575,234 @@ export default defineConfig({
276
575
  });
277
576
  ```
278
577
 
279
- MIME type and extension are metadata checks, not content-signature verification. Security-sensitive applications should additionally inspect file content and use malware scanning where appropriate.
578
+ MIME type and extension validation are metadata checks, not content-signature verification. Security-sensitive applications should additionally verify content and use malware scanning where appropriate.
280
579
 
281
- See [File Upload](docs/file-upload.md).
580
+ Read more: [File Upload](docs/file-upload.md)
282
581
 
283
- ## Development route graph recovery
582
+ ## Storage adapters
284
583
 
285
- BCP 0.1.24 fixes a development route/client-bundle synchronization issue that could produce:
584
+ BCP `0.1.25` adds the first application-facing storage abstraction.
286
585
 
287
- ```text
288
- Client bundle was not found for route "/docs/[...slug]".
289
- ```
586
+ ```ts
587
+ import {
588
+ createLocalStorage,
589
+ storeUploadedFile,
590
+ } from "bcp/server";
290
591
 
291
- The problem happened when the actual page topology changed but Windows/editor filesystem events were classified as `change` instead of `add`/`unlink`. The route scanner could see a new route while the incremental client bundle graph still represented the previous route tree.
592
+ const storage =
593
+ createLocalStorage({
594
+ directory:
595
+ "./uploads",
596
+ });
292
597
 
293
- The dev gateway now compares the actual pathname/page/layout graph and automatically refreshes the internal development server/client bundler when topology changes. Manually deleting `.bcp-framework` should no longer be required to recover this state.
598
+ const stored =
599
+ await storeUploadedFile(
600
+ file,
601
+ {
602
+ storage,
603
+ key:
604
+ "avatars/user-101.webp",
605
+ }
606
+ );
607
+ ```
294
608
 
295
- ## Developer diagnostics
609
+ The `StorageAdapter` contract contains:
296
610
 
297
- ```bash
298
- bcp doctor
299
- bcp inspect
611
+ ```text
612
+ put
613
+ stat
614
+ read
615
+ exists
616
+ delete
300
617
  ```
301
618
 
302
- `bcp doctor` checks project structure, BCP/React installations, React renderer parity, duplicate framework copies, environment/config loading, route conflicts and client/server boundaries. Blocking failures return a non-zero exit code.
619
+ Application code can depend on this contract instead of depending directly on filesystem paths.
620
+
621
+ The built-in adapter in `0.1.25` is local filesystem storage. Cloud/object-storage adapters are planned for a later milestone.
303
622
 
304
- `bcp inspect` prints resolved configuration, development env filenames, public variable names, dependency versions and discovered routes.
623
+ Storage keys are logical relative paths. Absolute paths and traversal segments are rejected.
305
624
 
306
- For local release verification, install packed `.tgz` artifacts under the existing `bcp` dependency key. Do not install a second `@chidchanun/bcp` copy next to `node_modules/bcp`, because separate framework copies can split React contexts and produce misleading loader/hook errors.
625
+ Read more: [Storage and File Delivery](docs/storage.md)
307
626
 
308
- ## Validation and errors
627
+ ## Production file delivery
628
+
629
+ Storage objects can be returned through a hardened HTTP response helper:
309
630
 
310
631
  ```ts
311
632
  import {
312
- v,
313
- validateFormData,
314
- } from "bcp/validation";
633
+ createStorageResponse,
634
+ } from "bcp/server";
315
635
 
316
- import {
317
- badRequest,
318
- unauthorized,
319
- toErrorResponse,
320
- } from "bcp/error";
636
+ export async function GET(
637
+ request: Request
638
+ ) {
639
+ return createStorageResponse(
640
+ request,
641
+ storage,
642
+ "documents/report.pdf",
643
+ {
644
+ disposition:
645
+ "attachment",
646
+ downloadName:
647
+ "report.pdf",
648
+ }
649
+ );
650
+ }
321
651
  ```
322
652
 
323
- Structured error responses use the common envelope:
653
+ `createStorageResponse()` supports:
324
654
 
325
- ```json
326
- {
327
- "error": {
328
- "status": 400,
329
- "code": "BAD_REQUEST",
330
- "message": "Invalid request"
331
- }
332
- }
655
+ - `GET`,
656
+ - `HEAD`,
657
+ - `ETag`,
658
+ - `Last-Modified`,
659
+ - `If-None-Match`,
660
+ - `If-Modified-Since`,
661
+ - `If-Range`,
662
+ - single byte ranges with `206 Partial Content`,
663
+ - `304 Not Modified`,
664
+ - `416 Range Not Satisfiable`,
665
+ - safe `Content-Disposition` filenames.
666
+
667
+ The default cache policy is intentionally conservative:
668
+
669
+ ```text
670
+ private, max-age=0, must-revalidate
333
671
  ```
334
672
 
335
- ## Database
673
+ Public immutable caching must be opted into explicitly.
336
674
 
337
- ```ts
338
- import {
339
- db,
340
- } from "bcp/database";
675
+ Multiple byte ranges are intentionally not supported in `0.1.25`.
676
+
677
+ Read more: [Storage and File Delivery](docs/storage.md)
678
+
679
+ ## Caching
680
+
681
+ BCP includes server response caching and revalidation primitives used by development and standalone production runtimes.
682
+
683
+ Read more: [Caching](docs/caching.md)
684
+
685
+ ## Security
686
+
687
+ The framework security layer includes request body limits and production request handling defaults. Application authorization is still the responsibility of route guards and application logic.
688
+
689
+ Storage keys, filenames and MIME metadata must not be treated as authorization decisions.
690
+
691
+ Read more: [Security](docs/security.md)
692
+
693
+ ## Environment and configuration
694
+
695
+ Application configuration lives in:
696
+
697
+ ```text
698
+ bcp.config.ts
341
699
  ```
342
700
 
343
- The database layer provides a lazy MySQL pool, prepared execution, queries and transactions. Database migrations are managed through `bcp db` commands.
701
+ Public environment variables use the prefix:
344
702
 
345
- ## Authentication
703
+ ```text
704
+ BCP_PUBLIC_
705
+ ```
346
706
 
347
- ```ts
348
- import {
349
- auth,
350
- requireAuth,
351
- requireRole,
352
- } from "bcp/auth";
707
+ Server-only environment values remain server-side and are not emitted into browser bundles.
708
+
709
+ Read more: [Configuration](docs/configuration.md)
710
+
711
+ ## Developer tools
712
+
713
+ BCP includes project diagnostics:
714
+
715
+ ```bash
716
+ bcp doctor
717
+ bcp inspect
353
718
  ```
354
719
 
355
- BCP also exposes lower-level JWT cookie session helpers through `bcp/server`.
720
+ `bcp doctor` checks areas such as:
356
721
 
357
- ## Middleware
722
+ - project structure,
723
+ - BCP installation,
724
+ - React / ReactDOM compatibility,
725
+ - duplicate framework copies,
726
+ - environment/config loading,
727
+ - route conflicts,
728
+ - client/server boundaries.
358
729
 
359
- Middleware v2 uses true onion execution:
730
+ `bcp inspect` reports resolved configuration, environment sources, dependencies and discovered routes.
360
731
 
361
- ```ts
362
- export async function middleware(
363
- request,
364
- context,
365
- next
366
- ) {
367
- const response =
368
- await next();
732
+ Read more: [Developer Tools](docs/developer-tools.md)
369
733
 
370
- response.headers.set(
371
- "x-app",
372
- "example"
373
- );
734
+ ## Windows CLI
374
735
 
375
- return response;
376
- }
736
+ Microsoft SQL Server also installs an executable named `bcp.exe` on Windows.
737
+
738
+ BCP therefore publishes the collision-free alias:
739
+
740
+ ```text
741
+ bcp-framework
377
742
  ```
378
743
 
379
- Existing v1 middleware remains supported.
744
+ Inside project npm scripts, `bcp` remains safe because npm puts `node_modules/.bin` at the front of `PATH`.
380
745
 
381
- ## Hydration parity
746
+ For direct PowerShell usage, prefer:
382
747
 
383
- BCP 0.1.20 normalized Windows CRLF/CR source line endings in development instrumentation. BCP 0.1.21 completed SSR/client JSX semantic parity by preserving JSX through the Babel React Refresh pass and allowing esbuild to perform the development JSX transform.
748
+ ```powershell
749
+ npm exec -- bcp-framework doctor
750
+ npm exec -- bcp-framework inspect
751
+ npm exec -- bcp-framework dev
752
+ npm exec -- bcp-framework build
753
+ ```
384
754
 
385
- Multiline quoted JSX attributes are supported without rewriting classes onto a single line or applying `suppressHydrationWarning` as a framework workaround.
755
+ ## CLI reference
386
756
 
387
- ## Production
757
+ ```bash
758
+ bcp dev
759
+ bcp routes
760
+ bcp build
761
+ bcp start
762
+ bcp doctor
763
+ bcp doctor --json
764
+ bcp inspect
765
+ bcp inspect --json
766
+ bcp update
767
+ bcp version
768
+
769
+ bcp db create create_users
770
+ bcp db migrate
771
+ bcp db status
772
+ bcp db rollback
773
+ ```
774
+
775
+ ## Development behavior
776
+
777
+ BCP includes Fast Refresh and deterministic development hydration behavior.
778
+
779
+ Recent stabilization work also covers:
780
+
781
+ - Windows line-ending parity,
782
+ - multiline JSX hydration parity,
783
+ - duplicate BCP installation detection,
784
+ - automatic page-route/client-bundle graph resynchronization,
785
+ - standalone authentication guard request-context parity.
786
+
787
+ A development topology change should no longer require manually deleting `.bcp-framework` to recover a missing client route bundle.
788
+
789
+ Read more: [Hydration](docs/hydration.md)
790
+
791
+ ## Production build
792
+
793
+ Build an application:
388
794
 
389
795
  ```bash
390
796
  npm run build
391
- npm start
392
797
  ```
393
798
 
394
- Standalone output is generated under:
799
+ Start the generated standalone runtime:
800
+
801
+ ```bash
802
+ npm run start
803
+ ```
804
+
805
+ Production output is written under:
395
806
 
396
807
  ```text
397
808
  .bcp-framework/build/
@@ -401,44 +812,71 @@ Standalone output is generated under:
401
812
  └─ server.mjs
402
813
  ```
403
814
 
404
- ## Updating
815
+ The standalone runtime composes production middleware, security, cache, actions, guards, loaders and page rendering into the final HTTP pipeline.
816
+
817
+ Runtime hostname/port overrides can be supplied to `bcp start` without rebuilding the application.
818
+
819
+ Read more: [Deployment](docs/deployment.md)
820
+
821
+ ## Updating BCP
405
822
 
406
823
  ```bash
407
824
  bcp update
408
825
  bcp update --check
409
826
  bcp update --dry-run
410
- bcp update 0.1.24
827
+ bcp update 0.1.25
411
828
  bcp update next
412
829
  ```
413
830
 
414
- Projects published before the updater can bootstrap it once with:
831
+ Projects created before the updater was introduced can bootstrap it once using the public package:
415
832
 
416
833
  ```bash
417
834
  npx @chidchanun/bcp@latest update
418
835
  ```
419
836
 
420
- ## Release validation
837
+ Read more: [Updating](docs/updating.md)
838
+
839
+ ## Framework development
840
+
841
+ When working inside the BCP Framework repository itself:
421
842
 
422
843
  ```bash
844
+ npm install
423
845
  npm run typecheck
424
846
  npm run test:unit
847
+ npm run test:e2e
848
+ npm run test:package
849
+ ```
850
+
851
+ Full release-candidate validation:
852
+
853
+ ```bash
425
854
  npm run rc:check
426
855
  ```
427
856
 
428
- After RC passes, releases are tagged and published manually with the guarded release scripts.
857
+ A version must not be tagged or published until its release candidate and packed-package verification pass.
858
+
859
+ Read more: [Releasing](docs/releasing.md)
860
+
861
+ ## Documentation source
429
862
 
430
- ## Documentation
863
+ The `docs/` directory is the source content intended to feed the future **`bcp-docs-web`** documentation website.
431
864
 
865
+ Start with:
866
+
867
+ - [Documentation Source Map](docs/README.md)
432
868
  - [Getting Started](docs/getting-started.md)
869
+ - [Configuration](docs/configuration.md)
433
870
  - [Application Modules](docs/application-modules.md)
434
871
  - [Routing](docs/routing.md)
435
- - [Server Request APIs](docs/server-request-apis.md)
436
872
  - [Server Data Loaders](docs/server-data-loaders.md)
437
- - [Protected Route Guards](docs/route-guards.md)
873
+ - [Route Guards](docs/route-guards.md)
438
874
  - [Form Actions](docs/form-actions.md)
875
+ - [Server Request APIs](docs/server-request-apis.md)
439
876
  - [Validation](docs/validation.md)
440
877
  - [Error Handling](docs/error-handling.md)
441
878
  - [File Upload](docs/file-upload.md)
879
+ - [Storage and File Delivery](docs/storage.md)
442
880
  - [Authentication](docs/authentication.md)
443
881
  - [Auth Route Guards](docs/auth-route-guards.md)
444
882
  - [JWT Sessions](docs/session-auth.md)
@@ -447,17 +885,58 @@ After RC passes, releases are tagged and published manually with the guarded rel
447
885
  - [Middleware](docs/middleware.md)
448
886
  - [Hydration](docs/hydration.md)
449
887
  - [Developer Tools](docs/developer-tools.md)
450
- - [Development Logging](docs/development-logging.md)
888
+ - [Logging and Observability](docs/development-logging.md)
451
889
  - [Caching](docs/caching.md)
452
890
  - [Security](docs/security.md)
453
891
  - [Deployment](docs/deployment.md)
454
892
  - [Updating](docs/updating.md)
455
893
  - [Releasing](docs/releasing.md)
456
894
 
457
- ## Requirements
895
+ ## Documentation website model
896
+
897
+ When `bcp-docs-web` is built, the recommended top-level information architecture is:
898
+
899
+ ```text
900
+ Getting Started
901
+ Routing & Data
902
+ Authentication
903
+ Database
904
+ Runtime & Infrastructure
905
+ API Reference
906
+ Releases
907
+ ```
908
+
909
+ `docs/README.md` contains the proposed route-to-source mapping for that website.
910
+
911
+ ## Release history
912
+
913
+ Release notes are stored under:
914
+
915
+ ```text
916
+ docs/releases/
917
+ ```
918
+
919
+ Recent milestones:
920
+
921
+ | Version | Milestone |
922
+ | --- | --- |
923
+ | `0.1.20` | Hydration line-ending stabilization |
924
+ | `0.1.21` | Hydration semantic parity |
925
+ | `0.1.22` | Developer tools and diagnostics |
926
+ | `0.1.23` | Logging and observability |
927
+ | `0.1.24` | File Upload Foundation |
928
+ | `0.1.25` | Storage Adapters and File Delivery |
929
+
930
+ ## Roadmap
931
+
932
+ Current planned direction after `0.1.25`:
933
+
934
+ 1. S3-compatible / cloud storage adapter integration.
935
+ 2. Production upload streaming.
936
+ 3. Broader storage adapter ecosystem.
937
+ 4. Additional production hardening as new workloads expose edge cases.
458
938
 
459
- - Node.js 24.11 or newer
460
- - React 19
939
+ Roadmap items are plans, not published API guarantees.
461
940
 
462
941
  ## License
463
942