@jskit-ai/agent-docs 0.1.3 → 0.1.4

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.
Files changed (42) hide show
  1. package/DISTR_AGENT.md +11 -1
  2. package/guide/agent/app-extras/assistant.md +1 -1
  3. package/guide/agent/app-extras/realtime.md +1 -1
  4. package/guide/agent/app-setup/a-more-interesting-shell.md +1 -1
  5. package/guide/agent/app-setup/authentication.md +9 -1
  6. package/guide/agent/app-setup/console.md +1 -1
  7. package/guide/agent/app-setup/database-layer.md +1 -1
  8. package/guide/agent/app-setup/initial-scaffolding.md +1 -1
  9. package/guide/agent/app-setup/multi-homing.md +3 -1
  10. package/guide/agent/app-setup/users.md +1 -1
  11. package/guide/agent/app-setup/working-with-the-jskit-cli.md +1 -1
  12. package/guide/agent/generators/advanced-cruds.md +163 -1
  13. package/guide/agent/generators/crud-generators.md +30 -1
  14. package/guide/agent/generators/intro.md +1 -1
  15. package/guide/agent/generators/ui-generators.md +1 -1
  16. package/guide/agent/index.md +1 -1
  17. package/package.json +1 -1
  18. package/reference/autogen/packages/agent-docs.md +18 -0
  19. package/skills/jskit-review/SKILL.md +12 -2
  20. package/templates/APP_BLUEPRINT.md +9 -0
  21. package/templates/WORKBOARD.md +3 -3
  22. package/templates/app/AGENTS.md +15 -3
  23. package/workflow/bootstrap.md +17 -2
  24. package/workflow/feature-delivery.md +19 -3
  25. package/workflow/review.md +9 -3
  26. package/workflow/scoping.md +10 -1
  27. package/workflow/workboard.md +1 -1
  28. package/guide/human/app-extras/assistant.md +0 -693
  29. package/guide/human/app-extras/realtime.md +0 -268
  30. package/guide/human/app-setup/a-more-interesting-shell.md +0 -732
  31. package/guide/human/app-setup/authentication.md +0 -961
  32. package/guide/human/app-setup/console.md +0 -350
  33. package/guide/human/app-setup/database-layer.md +0 -820
  34. package/guide/human/app-setup/initial-scaffolding.md +0 -753
  35. package/guide/human/app-setup/multi-homing.md +0 -793
  36. package/guide/human/app-setup/users.md +0 -402
  37. package/guide/human/app-setup/working-with-the-jskit-cli.md +0 -1047
  38. package/guide/human/generators/advanced-cruds.md +0 -921
  39. package/guide/human/generators/crud-generators.md +0 -554
  40. package/guide/human/generators/intro.md +0 -107
  41. package/guide/human/generators/ui-generators.md +0 -663
  42. package/guide/human/index.md +0 -37
@@ -1,554 +0,0 @@
1
- # CRUD Generators
2
-
3
- CRUD generation in JSKIT is really one workflow split across two generator packages:
4
-
5
- - `crud-server-generator` creates the app-local server/resource package
6
- - `crud-ui-generator` creates the route tree that uses that shared resource contract
7
-
8
- So the real order is always:
9
-
10
- 1. create a real table
11
- 2. scaffold the server package around it
12
- 3. scaffold the UI around the generated resource file
13
-
14
- This chapter uses three examples, in increasing complexity:
15
-
16
- - `contacts`: the baseline full CRUD walkthrough
17
- - `addresses`: a child CRUD with its own routed list page
18
- - `comments`: a child CRUD that lives inside the parent page, with only the child routes being routed
19
-
20
- The examples assume the guide app already has the database and workspace/admin setup from the earlier chapters. That is why the route roots below live under `w/[workspaceSlug]/admin/...`.
21
-
22
- This is the workflow chapter.
23
-
24
- It is meant to answer:
25
-
26
- - which generator do I run first?
27
- - what order do the server and UI steps go in?
28
- - what shape of CRUD should I generate for this feature?
29
-
30
- Once that workflow is clear, continue with [Advanced CRUDs](/guide/generators/advanced-cruds) for the generated package anatomy, ownership model, and customization boundaries.
31
-
32
- ## The two generator packages
33
-
34
- ### `crud-server-generator` `@jskit-ai/crud-server-generator` `(0.1.47)`
35
-
36
- This is the server-side half.
37
-
38
- It introspects a real table and writes an app-local package with things like:
39
-
40
- - repository logic
41
- - service logic
42
- - route registration
43
- - action definitions
44
- - the shared resource module that describes the CRUD contract
45
-
46
- The main subcommand is:
47
-
48
- - `scaffold`
49
-
50
- There is also:
51
-
52
- - `scaffold-field`
53
-
54
- which is for patching one extra field into an already-generated resource module after a schema change.
55
-
56
- ### `crud-ui-generator` `@jskit-ai/crud-ui-generator` `(0.1.22)`
57
-
58
- This is the UI half.
59
-
60
- It reads the generated shared resource module and creates app-owned pages under an explicit route root relative to `src/pages/`.
61
-
62
- The main subcommand is:
63
-
64
- - `crud`
65
-
66
- That command can generate any combination of:
67
-
68
- - `list`
69
- - `view`
70
- - `new`
71
- - `edit`
72
-
73
- That flexibility is what makes the later `comments` example possible.
74
-
75
- ## Understanding ownership filters
76
-
77
- `--ownership-filter` is one of the most important CRUD generator options.
78
-
79
- It is not just "one more flag." It tells JSKIT what kind of ownership the generated CRUD assumes:
80
-
81
- - whether records are shared or owner-scoped
82
- - which owner columns the CRUD expects
83
- - what request context the generated routes and repository use to filter records
84
-
85
- In plain English, it answers:
86
-
87
- - who should be able to see these rows?
88
- - what kind of owner does each row belong to?
89
-
90
- The supported values are:
91
-
92
- | Value | Plain meaning | Typical owner columns |
93
- | --- | --- | --- |
94
- | `auto` | infer ownership from the real table during generation | inferred from table shape |
95
- | `public` | no owner scoping | no `workspace_id` or `user_id` required |
96
- | `user` | rows belong to one user | `user_id` |
97
- | `workspace` | rows belong to one workspace | `workspace_id` |
98
- | `workspace_user` | rows belong to one workspace and one user together | `workspace_id` and `user_id` |
99
-
100
- ### What each value means
101
-
102
- #### `public`
103
-
104
- Choose `public` when the same records should be visible across the app, subject only to the usual route/action permissions.
105
-
106
- This is the right mental model for things like:
107
-
108
- - global lookup tables
109
- - app-wide reference data
110
- - shared configuration records that are not owned by one user or one workspace
111
-
112
- A `public` CRUD does **not** expect owner scoping columns.
113
-
114
- #### `user`
115
-
116
- Choose `user` when each record belongs to one user, regardless of which app surface is showing it.
117
-
118
- This is the right mental model for things like:
119
-
120
- - my own saved items
121
- - my saved views
122
- - my personal preferences records when they are stored as CRUD rows
123
-
124
- The important owner column is:
125
-
126
- - `user_id`
127
-
128
- #### `workspace`
129
-
130
- Choose `workspace` when records belong to the workspace as a whole.
131
-
132
- This is the most common choice for workspace-admin CRUDs such as:
133
-
134
- - contacts
135
- - appointments
136
- - products
137
- - workspace-wide CRM records
138
-
139
- The important owner column is:
140
-
141
- - `workspace_id`
142
-
143
- This is why the chapter's `contacts` example uses `workspace`: the records belong to the workspace, not to one specific member inside it.
144
-
145
- #### `workspace_user`
146
-
147
- Choose `workspace_user` when a record belongs to a workspace **and** to a specific user within that workspace.
148
-
149
- This is the right mental model for things like:
150
-
151
- - personal notes inside a workspace
152
- - per-user workspace drafts
153
- - user-owned workspace artifacts that should not be visible to every workspace member
154
-
155
- The important owner columns are:
156
-
157
- - `workspace_id`
158
- - `user_id`
159
-
160
- This is stricter than plain `workspace`. The row is not only "inside this workspace." It is "inside this workspace, for this user."
161
-
162
- #### `auto`
163
-
164
- `auto` is not a runtime mode. It is a **generation-time inference**.
165
-
166
- When you scaffold against a real table, the generator inspects the table columns and resolves `auto` like this:
167
-
168
- - `workspace_id` and `user_id` present -> `workspace_user`
169
- - `workspace_id` only -> `workspace`
170
- - `user_id` only -> `user`
171
- - neither present -> `public`
172
-
173
- So `auto` is useful when the table already exists and its ownership columns already tell the truth.
174
-
175
- If you already know the intended ownership model and want the command to fail when the table does not match it, choose the explicit value instead of `auto`.
176
-
177
- ### Which one should I choose?
178
-
179
- Use this rule of thumb:
180
-
181
- - choose `public` for shared reference/config data
182
- - choose `user` for "my own" records
183
- - choose `workspace` for workspace-wide business data
184
- - choose `workspace_user` for personal records that still live inside a workspace
185
- - choose `auto` when you are scaffolding from an existing table and want JSKIT to infer ownership from the owner columns already present
186
-
187
- Another useful way to think about it is this:
188
-
189
- - if two different users in the same workspace should normally see the same row, that is probably `workspace`
190
- - if they should **not** normally see the same row, that is probably `workspace_user`
191
- - if the row is not workspace-specific at all, it is probably `public` or `user`
192
-
193
- ### One more important constraint
194
-
195
- Ownership also has to make sense for the target surface.
196
-
197
- In practice:
198
-
199
- - `workspace` and `workspace_user` belong on workspace-enabled surfaces
200
- - `public` and `user` can live on non-workspace surfaces too
201
-
202
- So if you are generating under a route like:
203
-
204
- ```text
205
- w/[workspaceSlug]/admin/...
206
- ```
207
-
208
- then `workspace` is usually the normal default. If you are generating a CRUD for a global operator or account area, `public` or `user` may make more sense.
209
-
210
- ## Example 1: `contacts`
211
-
212
- This is the baseline pattern. If you understand this example, the rest of the chapter becomes much easier.
213
-
214
- ### Step 1: create the table first
215
-
216
- Start with a real table. The server generator reads the database schema; it does not invent it for you.
217
-
218
- Example:
219
-
220
- ```sql
221
- CREATE TABLE contacts (
222
- id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
223
- workspace_id BIGINT UNSIGNED NOT NULL,
224
- full_name VARCHAR(190) NOT NULL,
225
- email VARCHAR(190) NULL,
226
- phone VARCHAR(50) NULL,
227
- notes TEXT NULL,
228
- created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
229
- updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
230
- KEY idx_contacts_workspace_id (workspace_id)
231
- );
232
- ```
233
-
234
- The exact fields will vary by app. What matters for the generator is:
235
-
236
- - the table already exists
237
- - the ownership columns match the ownership filter you are going to choose
238
- - the column names are stable enough to become part of your app's resource contract
239
-
240
- In this table, `workspace_id` is the important ownership clue. That is why the next step uses:
241
-
242
- ```bash
243
- --ownership-filter workspace
244
- ```
245
-
246
- This CRUD is not "my contacts." It is "the workspace's contacts."
247
-
248
- ### Step 2: scaffold the server package
249
-
250
- Now generate the server-side CRUD package:
251
-
252
- ```bash
253
- npx jskit generate crud-server-generator scaffold \
254
- --namespace contacts \
255
- --surface admin \
256
- --ownership-filter workspace \
257
- --table-name contacts
258
- ```
259
-
260
- This creates an app-local package under `packages/contacts/`.
261
-
262
- The most important file from the UI point of view is:
263
-
264
- ```text
265
- packages/contacts/src/shared/contactResource.js
266
- ```
267
-
268
- That file is the shared CRUD contract. The UI generator reads it to decide:
269
-
270
- - which operations exist
271
- - which fields are readable or writable
272
- - which relations are exposed
273
- - how to build the generated pages
274
-
275
- So even though the server scaffold writes many files, the resource file is the bridge between the server and UI halves.
276
-
277
- ### Step 3: scaffold the UI
278
-
279
- Once the resource file exists, generate the UI route tree:
280
-
281
- ```bash
282
- npx jskit generate crud-ui-generator crud \
283
- w/[workspaceSlug]/admin/contacts \
284
- --resource-file packages/contacts/src/shared/contactResource.js \
285
- --id-param contactId \
286
- --display-fields fullName,email,phone
287
- ```
288
-
289
- That creates the baseline CRUD route tree:
290
-
291
- - `w/[workspaceSlug]/admin/contacts/index.vue`
292
- - `w/[workspaceSlug]/admin/contacts/new.vue`
293
- - `w/[workspaceSlug]/admin/contacts/[contactId]/index.vue`
294
- - `w/[workspaceSlug]/admin/contacts/[contactId]/edit.vue`
295
- - shared `_components` files under the same route root
296
-
297
- This is the most important mental model in the whole chapter:
298
-
299
- - `crud-server-generator` creates the reusable CRUD contract and server package
300
- - `crud-ui-generator` turns that contract into app-owned pages
301
-
302
- If you want to see exactly what lands in `packages/contacts/`, which files own repository/service/action logic, and how search/filter customization is supposed to work, continue with [Advanced CRUDs](/guide/generators/advanced-cruds) once this baseline flow is clear.
303
-
304
- ### Why this is the baseline example
305
-
306
- `contacts` is the cleanest first example because nothing fancy is happening yet:
307
-
308
- - it has a normal routed list page
309
- - it has a normal routed view page
310
- - it has normal `new` and `edit` pages
311
- - it uses one straightforward resource contract
312
-
313
- That is the shape to learn first.
314
-
315
- ## Example 2: `addresses`
316
-
317
- Now move to a child CRUD with its own URL.
318
-
319
- This is the right pattern when the child collection deserves its own list page.
320
-
321
- Example route:
322
-
323
- ```text
324
- .../contacts/3/addresses
325
- ```
326
-
327
- In the guide app's real route tree, that becomes:
328
-
329
- ```text
330
- w/[workspaceSlug]/admin/contacts/[contactId]/addresses
331
- ```
332
-
333
- ### Step 1: create the child table
334
-
335
- Example:
336
-
337
- ```sql
338
- CREATE TABLE addresses (
339
- id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
340
- workspace_id BIGINT UNSIGNED NOT NULL,
341
- contact_id BIGINT UNSIGNED NOT NULL,
342
- label VARCHAR(100) NULL,
343
- line_1 VARCHAR(190) NOT NULL,
344
- line_2 VARCHAR(190) NULL,
345
- suburb VARCHAR(120) NULL,
346
- state VARCHAR(80) NULL,
347
- postcode VARCHAR(20) NULL,
348
- created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
349
- updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
350
- KEY idx_addresses_workspace_id (workspace_id),
351
- KEY idx_addresses_contact_id (contact_id)
352
- );
353
- ```
354
-
355
- The important extra column here is `contact_id`. This is what makes the CRUD a child of a contact instead of a top-level resource.
356
-
357
- ### Step 2: scaffold the server package
358
-
359
- ```bash
360
- npx jskit generate crud-server-generator scaffold \
361
- --namespace addresses \
362
- --surface admin \
363
- --ownership-filter workspace \
364
- --table-name addresses
365
- ```
366
-
367
- ### Step 3: scaffold the UI at the child route root
368
-
369
- ```bash
370
- npx jskit generate crud-ui-generator crud \
371
- w/[workspaceSlug]/admin/contacts/[contactId]/addresses \
372
- --resource-file packages/addresses/src/shared/addressResource.js \
373
- --id-param addressId \
374
- --display-fields label,line1,postcode
375
- ```
376
-
377
- That gives you a proper child CRUD with its own list, view, new, and edit pages under the contact route.
378
-
379
- ### The important refinement: parent title handling
380
-
381
- This is where nested CRUD starts to feel real.
382
-
383
- An addresses list page should not show a generic heading like `Addresses`. It should usually show whose addresses these are, for example:
384
-
385
- - `Jane Smith's addresses`
386
- - `Acme Pty Ltd's addresses`
387
-
388
- The awkward case is when there are **no child rows yet**. If the list is empty, you cannot derive the parent title from the first address record.
389
-
390
- That is why JSKIT has `useCrudListParentTitle()`:
391
-
392
- ```js
393
- const parentTitle = useCrudListParentTitle({
394
- listRuntime: records,
395
- resource: uiResource,
396
- recordIdParam: "addressId",
397
- fallbackLoadError: "Unable to load contact.",
398
- notFoundMessage: "Contact not found."
399
- });
400
- ```
401
-
402
- That helper does the nice thing automatically:
403
-
404
- - if the child list already has rows, it derives the parent title from the first child record
405
- - if the child list is empty, it loads the parent record directly
406
-
407
- This is exactly the pattern used in the real app codebase for nested CRUD lists like a contact's pets. It avoids the common broken state where an empty child list loses all context about the parent it belongs to.
408
-
409
- So the `addresses` example is important because it teaches the first truly practical nested-CRUD problem:
410
-
411
- - the route is child-scoped
412
- - the data is child-scoped
413
- - but the page still needs a reliable parent identity even when the child list is empty
414
-
415
- ## Example 3: `comments` in-page
416
-
417
- This is the advanced example.
418
-
419
- Sometimes a child resource is real enough to deserve its own CRUD operations, but **not** important enough to deserve its own full-screen list page.
420
-
421
- Comments are a good example:
422
-
423
- - they matter
424
- - they need persistence
425
- - they may need `view`, `new`, or `edit` routes
426
- - but the main screen is still the contact view page
427
-
428
- So the pattern is:
429
-
430
- - keep the contact page as the real host
431
- - render the comments list inside that page
432
- - route only the child operations underneath it
433
-
434
- ### Step 1: create the table
435
-
436
- Example:
437
-
438
- ```sql
439
- CREATE TABLE comments (
440
- id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
441
- workspace_id BIGINT UNSIGNED NOT NULL,
442
- contact_id BIGINT UNSIGNED NOT NULL,
443
- author_user_id BIGINT UNSIGNED NULL,
444
- body TEXT NOT NULL,
445
- created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
446
- updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
447
- KEY idx_comments_workspace_id (workspace_id),
448
- KEY idx_comments_contact_id (contact_id)
449
- );
450
- ```
451
-
452
- ### Step 2: scaffold the server package
453
-
454
- ```bash
455
- npx jskit generate crud-server-generator scaffold \
456
- --namespace comments \
457
- --surface admin \
458
- --ownership-filter workspace \
459
- --table-name comments
460
- ```
461
-
462
- ### Step 3: make the parent page able to host routed children
463
-
464
- If the contact view page should stay visible while child comment routes render underneath it, first upgrade it into a routed host:
465
-
466
- ```bash
467
- npx jskit generate ui-generator add-subpages \
468
- w/[workspaceSlug]/admin/contacts/[contactId]/index.vue \
469
- --title "Contact" \
470
- --subtitle "View and manage this contact."
471
- ```
472
-
473
- That is the point where the comments example deliberately overlaps with the `ui-generator` chapter. This pattern needs both:
474
-
475
- - CRUD scaffolding for the comments resource
476
- - a routed host in the parent contact page
477
-
478
- ### Step 4: generate only the routed child operations
479
-
480
- Now generate the comments UI without a list page:
481
-
482
- ```bash
483
- npx jskit generate crud-ui-generator crud \
484
- w/[workspaceSlug]/admin/contacts/[contactId]/index/comments \
485
- --resource-file packages/comments/src/shared/commentResource.js \
486
- --operations view,new,edit \
487
- --id-param commentId
488
- ```
489
-
490
- This is the key move.
491
-
492
- By leaving `list` out:
493
-
494
- - you do **not** generate a standalone comments list page
495
- - the host contact page stays responsible for showing the comment list
496
- - the generated child routes still handle things like `new`, `view`, and `edit`
497
-
498
- ### What the host page does
499
-
500
- The host page then renders the comment list directly, usually with lower-level CRUD composables such as:
501
-
502
- - `useCrudList()`
503
- - `useCrudAddEdit()`
504
- - `useCrudView()` when needed
505
-
506
- That is the same general pattern already used in the real app for embedded child records like pet notes: the record list lives inside the main view page, while routed child pages handle the operations that still deserve their own URLs.
507
-
508
- This pattern is useful when the child records are supporting detail rather than a destination in their own right.
509
-
510
- That is the real lesson of the `comments` example:
511
-
512
- - a child CRUD does **not** have to mean "make another full-screen list page"
513
- - you can keep the parent page as the main experience and route only the child operations that benefit from their own URLs
514
-
515
- ## When `scaffold-field` matters
516
-
517
- After the initial scaffold, schema changes are normal.
518
-
519
- Suppose you add a `preferred_name` column to `contacts`. You do not have to regenerate the whole package just to expose that one new writable field.
520
-
521
- That is what `scaffold-field` is for:
522
-
523
- ```bash
524
- npx jskit generate crud-server-generator scaffold-field \
525
- preferredName \
526
- packages/contacts/src/shared/contactResource.js \
527
- --table-name contacts
528
- ```
529
-
530
- Use this when:
531
-
532
- - the CRUD package already exists
533
- - the table has changed
534
- - you want to patch one writable field into the generated resource file
535
-
536
- It is a maintenance tool, not the first step in the workflow.
537
-
538
- ## Summary
539
-
540
- The important thing is not memorizing commands. It is learning the three shapes:
541
-
542
- - `contacts`: a normal top-level CRUD
543
- - `addresses`: a child CRUD with its own routed list page
544
- - `comments`: a child CRUD that lives inside the parent page, with only the child operations routed
545
-
546
- Once you understand those three shapes, the two generator packages stop feeling like separate tools.
547
-
548
- They become one workflow:
549
-
550
- 1. model the table
551
- 2. scaffold the server/resource package
552
- 3. scaffold only the UI shape that the feature actually needs
553
-
554
- The next chapter is [Advanced CRUDs](/guide/generators/advanced-cruds). Read it as the structural follow-on to this one: this chapter teaches how to generate the CRUD, and the next one teaches how to reason about the files you now own.
@@ -1,107 +0,0 @@
1
- # Generators
2
-
3
- By the end of the app-setup chapters, the guide app already has the main structural pieces in place:
4
-
5
- - a real shell
6
- - authenticated users
7
- - a database layer
8
- - operator tooling
9
- - workspace-aware routing
10
-
11
- This section changes focus.
12
-
13
- Generators are the part of JSKIT that write app-owned files on top of installed runtime packages.
14
-
15
- That is different from `npx jskit add package ...`:
16
-
17
- - `add package` installs reusable runtime capability into the app
18
- - `generate ...` creates local pages, components, placements, and support files that your app owns directly
19
-
20
- So the normal flow is:
21
-
22
- 1. install the runtime packages that make the feature possible
23
- 2. decide the exact app-owned route, component, or package you want
24
- 3. run `npx jskit generate ...`
25
- 4. review and keep editing the generated files
26
-
27
- One important detail: generator packages such as `ui-generator`, `crud-server-generator`, and `crud-ui-generator` are tooling surfaces. You normally do **not** add them to your app with `jskit add package ...`. You use them through the CLI, and they mutate your app-owned files.
28
-
29
- This intro is also the shared starting point for the rest of the generators section.
30
-
31
- ## Recap From Previous Chapters
32
-
33
- To get back to the same starting point used in the later generator chapters, run:
34
-
35
- ```bash
36
- SUPABASE_URL=...
37
- SUPABASE_KEY=...
38
- DB_HOST=127.0.0.1
39
- DB_PORT=3306
40
- DB_NAME=exampleapp
41
- DB_USER=exampleapp
42
- DB_PASSWORD=secret
43
-
44
- npx @jskit-ai/create-app exampleapp --tenancy-mode personal
45
- cd exampleapp
46
- npm install
47
-
48
- npx jskit add package shell-web
49
- npx jskit add package auth-provider-supabase-core \
50
- --auth-supabase-url "$SUPABASE_URL" \
51
- --auth-supabase-publishable-key "$SUPABASE_KEY" \
52
- --app-public-url "http://localhost:5173"
53
- npx jskit add bundle auth-base
54
- npx jskit add package database-runtime-mysql \
55
- --db-host "$DB_HOST" \
56
- --db-port "$DB_PORT" \
57
- --db-name "$DB_NAME" \
58
- --db-user "$DB_USER" \
59
- --db-password "$DB_PASSWORD"
60
- npx jskit add package users-web
61
- npx jskit add package console-web
62
- npx jskit add package workspaces-core
63
- npx jskit add package workspaces-web
64
- npm install
65
- npm run db:migrate
66
- ```
67
-
68
- If you are already continuing from the earlier guide chapters, you are already in the right place and can skip that setup.
69
-
70
- That baseline matters because the later generator examples assume:
71
-
72
- - a shell with placements and routed pages
73
- - authenticated users and user-owned routes
74
- - database-backed runtime packages
75
- - console and workspace surfaces that real generated pages can target
76
-
77
- ## Current generator families
78
-
79
- Right now the guide splits generators into two practical groups:
80
-
81
- - `@jskit-ai/ui-generator` for non-CRUD pages, placed UI, subpage hosts, and generic outlets
82
- - `@jskit-ai/crud-server-generator` plus `@jskit-ai/crud-ui-generator` for end-to-end CRUD scaffolding
83
-
84
- For CRUD work, there are also two guide layers on purpose:
85
-
86
- - [CRUD Generators](/guide/generators/crud-generators) teaches the end-to-end workflow for generating a working CRUD
87
- - [Advanced CRUDs](/guide/generators/advanced-cruds) explains the generated package anatomy, ownership structure, and the safest places to customize it
88
-
89
- The intended reading order is:
90
-
91
- 1. `CRUD Generators`
92
- 2. `Advanced CRUDs`
93
-
94
- ## Why generators matter
95
-
96
- This is one of the main JSKIT ideas:
97
-
98
- - packages own reusable framework/runtime behavior
99
- - generators write the app-local files that make that behavior concrete in your app
100
-
101
- That keeps the runtime reusable without hiding your real app UI behind opaque framework internals.
102
-
103
- ## Next sections
104
-
105
- - [UI Generators](/guide/generators/ui-generators) covers the non-CRUD workflow built around `ui-generator`
106
- - [CRUD Generators](/guide/generators/crud-generators) covers the combined server-and-UI CRUD workflow using `contacts`, nested `addresses`, and in-page `comments`
107
- - [Advanced CRUDs](/guide/generators/advanced-cruds) is the follow-on chapter after `CRUD Generators`, and goes deeper into the generated CRUD structure, ownership boundaries, and search/filter customization