create-kywi-app 0.3.1 → 0.4.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 +16 -0
- package/assets/agent-patterns.md +294 -0
- package/assets/kywi-collections-skill.md +73 -0
- package/assets/kywi-content-model-skill.md +94 -0
- package/assets/kywi-personalization-skill.md +72 -0
- package/lib/templates.mjs +166 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -64,6 +64,22 @@ next.config.mjs the FULL config to consume core (transpilePac
|
|
|
64
64
|
.env.example DATABASE_URL + AUTH_SECRET
|
|
65
65
|
.gitignore
|
|
66
66
|
README.md project-specific quick start (createdb, migrate, seed, dev, /admin, admin.features)
|
|
67
|
+
AGENTS.md guidance for AI agents working on this site: an app-specific
|
|
68
|
+
header (where things live, the /admin URL, the CLI, the three
|
|
69
|
+
scaffolded Claude Code skills) + Kywi's official building
|
|
70
|
+
patterns (docs/agents/AGENT-PATTERNS.md, verbatim)
|
|
71
|
+
CLAUDE.md thin pointer that sends a Claude Code session to AGENTS.md first,
|
|
72
|
+
plus a nudge toward the kywi-content-model skill (and the other
|
|
73
|
+
two scaffolded skills)
|
|
74
|
+
.claude/skills/kywi-content-model/SKILL.md Claude Code project skill: design a CONTENT-MODEL.md and get
|
|
75
|
+
owner sign-off before creating types or entering content — loaded
|
|
76
|
+
automatically by Claude Code, a pre-build checklist for other agents
|
|
77
|
+
.claude/skills/kywi-collections/SKILL.md Claude Code project skill: build any collection (testimonials,
|
|
78
|
+
logos, posts, products, …) as folder + feed + Feed Display — loaded
|
|
79
|
+
automatically when adding a collection
|
|
80
|
+
.claude/skills/kywi-personalization/SKILL.md Claude Code project skill: confirm the use case, then
|
|
81
|
+
build audiences, page variants, or A/B experiments — loaded
|
|
82
|
+
automatically when the owner wants personalization or A/B testing
|
|
67
83
|
lib/kywi.ts server runtime: DB, API handler, content scope (memoised)
|
|
68
84
|
lib/config.ts re-export of kywi.config
|
|
69
85
|
middleware.ts auth gate + session refresh + cookie→bearer bridge (over core/host)
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# Kywi Patterns — building sites end users can maintain
|
|
2
|
+
|
|
3
|
+
Guidance for agents building Kywi sites. These are opinions, not rules — a
|
|
4
|
+
developer can overrule any of them — but they encode what Kywi is *for*: sites
|
|
5
|
+
that get handed to non-developers who keep them alive without you. Follow them
|
|
6
|
+
unless the project has a stated reason not to.
|
|
7
|
+
|
|
8
|
+
## The core principle
|
|
9
|
+
|
|
10
|
+
**If a non-developer might ever want to change it, model it in the CMS — don't
|
|
11
|
+
hardcode it.** Every hardcoded testimonial array, pasted-in logo grid, or
|
|
12
|
+
copy-edited JSX headline is a future support request. The test before writing
|
|
13
|
+
any markup: *"When the site owner wants this different next month, do they
|
|
14
|
+
edit content in the admin, or do they need a developer?"* If the answer is
|
|
15
|
+
"developer," reach for one of the patterns below instead.
|
|
16
|
+
|
|
17
|
+
Static code is for structure and brand chrome. Content — anything with words,
|
|
18
|
+
images, prices, names, dates — belongs in Kywi.
|
|
19
|
+
|
|
20
|
+
## Before you build: design the content model and get sign-off
|
|
21
|
+
|
|
22
|
+
The most expensive failure in a CMS build is a poorly planned content model —
|
|
23
|
+
types bolted on mid-build, collections discovered after their items were
|
|
24
|
+
entered as free-form pages, taxonomy retrofitted onto a hundred nodes. Content
|
|
25
|
+
entry is the costly part; planning is cheap. So **start every new site (or any
|
|
26
|
+
significant new content area) by proposing the content model and getting the
|
|
27
|
+
owner's sign-off before creating types or entering content.**
|
|
28
|
+
|
|
29
|
+
Produce a short `CONTENT-MODEL.md` at the project root covering:
|
|
30
|
+
|
|
31
|
+
- **Content inventory → types.** Every repeated shape, with its proposed type
|
|
32
|
+
(built-in page vs. custom), fields (name, field type, required), and
|
|
33
|
+
relationships. One table per type.
|
|
34
|
+
- **Site tree sketch.** Top-level pages and a folder per collection (§1).
|
|
35
|
+
- **Feeds.** Name, source type, taxonomy filter, sort/limit, and which pages
|
|
36
|
+
display each one.
|
|
37
|
+
- **Taxonomy.** The category sets and expected tags (§3).
|
|
38
|
+
- **Reusable components.** The sections that will appear on multiple pages (§4).
|
|
39
|
+
- **Maintenance notes.** Who edits what; whether review workflow (§9), i18n
|
|
40
|
+
(§11), or scheduling (§10) apply.
|
|
41
|
+
- **Open questions** for the owner.
|
|
42
|
+
|
|
43
|
+
Present it, iterate, and get explicit approval — then build in playbook order.
|
|
44
|
+
Keep the file updated as the model evolves; it's the site's living map.
|
|
45
|
+
|
|
46
|
+
Proportionality applies (this is guidance, not law): a single-page brochure
|
|
47
|
+
site needs a few sentences of confirmation, not a document. But anything
|
|
48
|
+
involving custom types, collections, or more than a handful of pages deserves
|
|
49
|
+
the full proposal — ten minutes of sign-off beats re-entering fifty nodes.
|
|
50
|
+
|
|
51
|
+
## Quick decisions
|
|
52
|
+
|
|
53
|
+
| You're about to… | Do this instead |
|
|
54
|
+
|---|---|
|
|
55
|
+
| Hardcode a list (testimonials, logos, posts, products, team) | Folder of nodes + a Feed + the Feed Display module (§1) |
|
|
56
|
+
| Create one-off pages with identical field shapes | A custom content type + one node per item (§2) |
|
|
57
|
+
| Filter/group content by topic, industry, audience | Categories & tags, queried by feeds (§3) |
|
|
58
|
+
| Copy-paste a CTA/banner/snippet across pages | Save it as a reusable component (§4) |
|
|
59
|
+
| Write page sections as JSX | Build them as layout sections/modules the owner can edit (§5) |
|
|
60
|
+
| Hand-code a `<form>` | Build it in the Forms admin, place the Form module (§6) |
|
|
61
|
+
| Drop images into `/public` | Upload to the Media library (§7) |
|
|
62
|
+
| Build segment-specific or experimental UI unprompted | Ask the owner first — offer personalization/A-B with examples (§8) |
|
|
63
|
+
| Let everyone publish straight to the live site | Configure groups + review workflow (§9) |
|
|
64
|
+
| "Launch this next Tuesday" by deploying on Tuesday | Scheduled publishing / a changeset (§10) |
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 1. Collections: folders + feeds + Feed Display
|
|
69
|
+
|
|
70
|
+
**The workhorse pattern.** Any repeating set of items that appears somewhere on
|
|
71
|
+
the site — customer logos, testimonials, recent blog posts, products, portfolio
|
|
72
|
+
pieces, team members, FAQs, press mentions — is a collection, and collections
|
|
73
|
+
are never hardcoded.
|
|
74
|
+
|
|
75
|
+
- **Structure:** a folder in the Site Tree per collection (`/testimonials`,
|
|
76
|
+
`/customers`, `/work`), one content node per item. Items that need their own
|
|
77
|
+
public page (blog posts, portfolio pieces) live at real paths; items that are
|
|
78
|
+
only ever displayed in aggregate (logos, quotes) still get nodes — their pages
|
|
79
|
+
just aren't linked.
|
|
80
|
+
- **Query:** create a Feed (admin → Feeds): pick the content type, filter by
|
|
81
|
+
taxonomy, sort, and limit ("6 most recent posts", "testimonials tagged
|
|
82
|
+
`homepage`").
|
|
83
|
+
- **Display:** place the **Feed Display** module wherever the collection should
|
|
84
|
+
render — home page hero strip, interior sidebars, a `/blog` index. One feed
|
|
85
|
+
can feed many pages.
|
|
86
|
+
- **Why it wins:** the owner adds a testimonial by creating one node. Every
|
|
87
|
+
page showing that feed updates. No layout edits, no deploys.
|
|
88
|
+
|
|
89
|
+
Advanced: product catalogs and portfolios are the same pattern with a richer
|
|
90
|
+
custom type (§2) and taxonomy-driven feeds per category (§3). Multiple feeds
|
|
91
|
+
over one collection give different slices (featured vs. all, per-category).
|
|
92
|
+
|
|
93
|
+
## 2. Structured data: custom content types
|
|
94
|
+
|
|
95
|
+
When several nodes share the same shape — recipes (ingredients, steps, prep
|
|
96
|
+
time), team profiles (role, bio, headshot, links), products (price, SKU,
|
|
97
|
+
gallery), case studies (client, industry, outcome) — define a **custom content
|
|
98
|
+
type** so the shape is enforced and the data is queryable, instead of burying
|
|
99
|
+
it in free-form body text.
|
|
100
|
+
|
|
101
|
+
**Default: create types in the admin (Type Designer), not in kywi.config.ts.**
|
|
102
|
+
Admin-created types are runtime-managed: the site owner can add a field next
|
|
103
|
+
year ("dietary tags on recipes") without a developer or a migration. Reserve
|
|
104
|
+
config-defined types (`contentTypes` in `kywi.config.ts`) for schema the
|
|
105
|
+
*developer* must own — shapes that code depends on, reviewed in git, migrated
|
|
106
|
+
by `kywi migrate`. When in doubt, admin-created.
|
|
107
|
+
|
|
108
|
+
- Fields available include text, textarea, rich text, date, image, URL, email,
|
|
109
|
+
JSON, and relationship (with a target type — e.g. a recipe's `author` →
|
|
110
|
+
profile). Title can be made optional per type.
|
|
111
|
+
- **Combine with §1:** the type gives you structure; a feed over the type gives
|
|
112
|
+
you the listing (`/recipes` index, an intranet's people directory); each
|
|
113
|
+
node's own page is the detail view. Listing + detail with zero custom code.
|
|
114
|
+
- Don't shadow built-in fields (slug, body) with custom ones — Kywi will block
|
|
115
|
+
it; use the built-ins.
|
|
116
|
+
|
|
117
|
+
## 3. Taxonomy: categories & tags
|
|
118
|
+
|
|
119
|
+
Categories and tags are the cross-cutting organization layer over §1 and §2.
|
|
120
|
+
Use **categories** for a site's stable sections (Recipes: Breakfast / Dinner /
|
|
121
|
+
Dessert) and **tags** for freeform, evolving labels (gluten-free, quick,
|
|
122
|
+
featured).
|
|
123
|
+
|
|
124
|
+
- Feeds filter by taxonomy, so "show featured testimonials on the home page"
|
|
125
|
+
is: tag the nodes `featured`, point the feed at the tag. The owner curates
|
|
126
|
+
the home page by tagging — never by editing the page.
|
|
127
|
+
- Prefer taxonomy-driven feeds over separate folders when items belong to
|
|
128
|
+
multiple groupings (a recipe is both `quick` and `vegetarian`; a folder can
|
|
129
|
+
only hold it once).
|
|
130
|
+
|
|
131
|
+
## 4. Reusable components: edit once, propagate everywhere
|
|
132
|
+
|
|
133
|
+
Anything designed once and used on multiple pages — CTA bands, promo banners,
|
|
134
|
+
newsletter signup blocks, campaign snippets, "as seen in" strips — should be a
|
|
135
|
+
**reusable component**, not copy-pasted sections.
|
|
136
|
+
|
|
137
|
+
- In the layout editor, select the module and **Save as Component**; insert it
|
|
138
|
+
elsewhere from the component picker. Placed instances are **live
|
|
139
|
+
references**: editing the source component updates every page that uses it.
|
|
140
|
+
- **Detach** an instance when a page genuinely needs a one-off variant — it
|
|
141
|
+
becomes an independent copy from that point on.
|
|
142
|
+
- Rule of thumb: the second time you paste the same section, stop and make it
|
|
143
|
+
a component. The owner should be able to update the sitewide CTA in one
|
|
144
|
+
place, ten minutes before their webinar.
|
|
145
|
+
|
|
146
|
+
## 5. Page layouts & modules — not hardcoded JSX
|
|
147
|
+
|
|
148
|
+
Pages the owner should be able to restructure — landing pages, the home page,
|
|
149
|
+
campaign pages — should be built **in the layout editor** (sections, columns,
|
|
150
|
+
modules), rendered through Kywi's layout renderer. A scaffolded app already
|
|
151
|
+
renders saved layouts on every content page; keep it that way.
|
|
152
|
+
|
|
153
|
+
- The built-in module palette (hero, cards, CTA, testimonial, feed display,
|
|
154
|
+
pricing, FAQ, forms, comments, media…) covers most marketing-site needs.
|
|
155
|
+
- Brand-specific blocks the palette lacks: build a **custom module** once
|
|
156
|
+
(`defineModule` in `kywi.config.ts` + a React component registered in the
|
|
157
|
+
host's module map — the scaffold's `lib/modules.tsx` shows the shape). The
|
|
158
|
+
developer owns the component; the owner places and configures instances.
|
|
159
|
+
- Create **saved layouts** (Layouts admin) as page templates — "Landing page",
|
|
160
|
+
"Case study" — so new pages start from a consistent skeleton instead of a
|
|
161
|
+
blank canvas.
|
|
162
|
+
- Hand-written JSX pages are fine for genuinely fixed chrome (a bespoke 404,
|
|
163
|
+
legal boilerplate shells) — but if marketing will ever want to swap a
|
|
164
|
+
headline, it's a layout page.
|
|
165
|
+
|
|
166
|
+
## 6. Forms: always the Forms builder
|
|
167
|
+
|
|
168
|
+
Never hand-code a `<form>`. Build forms in the Forms admin (fields, multi-step,
|
|
169
|
+
success message, notification emails, optional reCAPTCHA via Settings →
|
|
170
|
+
Security) and place them with the **Form / Form Embed** modules, which submit
|
|
171
|
+
through Kywi's pipeline into admin → Submissions.
|
|
172
|
+
|
|
173
|
+
- The owner edits fields, recipients, and the thank-you message without code.
|
|
174
|
+
- Submissions are stored, browsable, and exportable — a hand-rolled form that
|
|
175
|
+
emails someone is data loss with extra steps.
|
|
176
|
+
|
|
177
|
+
## 7. Media: the library, not /public
|
|
178
|
+
|
|
179
|
+
All owner-managed imagery — logos, hero images, headshots, product shots —
|
|
180
|
+
goes through the Media library (upload, alt text, automatic variants,
|
|
181
|
+
on-demand resize). Reserve `/public` for build-time brand assets (favicon,
|
|
182
|
+
font files) that only change when the code does.
|
|
183
|
+
|
|
184
|
+
The difference matters at handover: the owner can swap a hero image in the
|
|
185
|
+
library; they cannot ship a new `/public` file.
|
|
186
|
+
|
|
187
|
+
## 8. Personalization & A/B testing — offer it, don't default to it
|
|
188
|
+
|
|
189
|
+
Kywi ships a full personalization stack: **audiences** (rule-based, plus an
|
|
190
|
+
optional self-identification widget), **page variants** targeted per audience,
|
|
191
|
+
and **A/B experiments** with stable per-visitor assignment and recorded
|
|
192
|
+
exposures. Most sites don't need it on day one — and unrequested
|
|
193
|
+
personalization is complexity the owner didn't ask to maintain.
|
|
194
|
+
|
|
195
|
+
**The agent's job is to surface the capability, not to assume it.** When
|
|
196
|
+
scoping a build, ask the owner whether any of these fit, with examples:
|
|
197
|
+
|
|
198
|
+
- *"Should returning visitors see a different home-page hero than first-timers
|
|
199
|
+
(e.g. 'Welcome back — pick up where you left off')?"*
|
|
200
|
+
- *"Do you serve distinct segments (agencies vs. freelancers, industries,
|
|
201
|
+
regions) that should get tailored messaging on key pages?"*
|
|
202
|
+
- *"Would you like visitors to self-identify (e.g. 'I'm a developer / I'm a
|
|
203
|
+
marketer') and see content ordered for them?"*
|
|
204
|
+
- *"Is there a headline, CTA, or pricing presentation you'd like to A/B test
|
|
205
|
+
before committing?"*
|
|
206
|
+
|
|
207
|
+
If yes, principles: personalize **sections and modules**, not whole sites; the
|
|
208
|
+
default variant must stand alone (personalization is progressive enhancement);
|
|
209
|
+
one experiment per conversion goal, and let it conclude before layering more.
|
|
210
|
+
If no, skip it — the machinery is there when they grow into it.
|
|
211
|
+
|
|
212
|
+
## 9. Editorial workflow: drafts, review, versions
|
|
213
|
+
|
|
214
|
+
For any site with more than one author — or an owner who wants a safety net —
|
|
215
|
+
configure the workflow rather than letting everything publish directly:
|
|
216
|
+
|
|
217
|
+
- **Groups & permissions:** editors write (`draft → Submit for Review`),
|
|
218
|
+
a smaller group approves and publishes. Content-level permissions can gate
|
|
219
|
+
specific sections (e.g. only Legal edits `/legal/*`).
|
|
220
|
+
- Published pages accept **pending revisions** — edits go through review while
|
|
221
|
+
the live page keeps serving — so review doesn't mean taking pages down.
|
|
222
|
+
- Every save records a **version** with restore; approvers see field-level
|
|
223
|
+
diffs. Mention this at handover: "you can always roll back."
|
|
224
|
+
|
|
225
|
+
Solo-owner sites can publish directly — but still enable it before the team
|
|
226
|
+
grows past one.
|
|
227
|
+
|
|
228
|
+
## 10. Scheduling & changesets
|
|
229
|
+
|
|
230
|
+
- Content has schedule fields: publish at a future time, unpublish/expire
|
|
231
|
+
automatically. The background scheduler handles both — "post this Monday 9am"
|
|
232
|
+
is a field, not a calendar reminder.
|
|
233
|
+
- **Changesets** batch related edits (a product launch touching six pages) and
|
|
234
|
+
publish them together, optionally on a schedule. Use one whenever a launch
|
|
235
|
+
spans multiple nodes — partial launches are worse than late ones.
|
|
236
|
+
|
|
237
|
+
## 11. Multilingual sites
|
|
238
|
+
|
|
239
|
+
If the owner needs more than one language, declare `locales` in
|
|
240
|
+
`kywi.config.ts` up front — the scaffold routes locale prefixes (`/es/...`),
|
|
241
|
+
falls back to the default locale, and emits hreflang alternates. Translations
|
|
242
|
+
are per-node in the admin. Retrofitting i18n is far costlier than declaring it
|
|
243
|
+
early, so ask at scoping time.
|
|
244
|
+
|
|
245
|
+
## 12. SEO & the Agent Experience layer
|
|
246
|
+
|
|
247
|
+
- Fill the **SEO tab** on every page that matters (meta title/description,
|
|
248
|
+
og:image); the scaffold maps it into the public head and emits JSON-LD.
|
|
249
|
+
- The AX layer serves `llms.txt`, `llms-full.txt`, `sitemap.xml`, and
|
|
250
|
+
`robots.txt` at the site root out of the box — a Kywi site is legible to
|
|
251
|
+
agents and crawlers by default. Don't remove these routes; they're part of
|
|
252
|
+
the product's value.
|
|
253
|
+
|
|
254
|
+
## Other capabilities worth knowing
|
|
255
|
+
|
|
256
|
+
- **Comments:** a moderated Comments module (submissions land pending) for
|
|
257
|
+
blogs/community pages — ask the owner if discussion fits.
|
|
258
|
+
- **Webhooks** (Web Services → Webhooks): notify external systems on content
|
|
259
|
+
events (rebuild a static mirror, ping Slack, sync a CRM) — signed, retried.
|
|
260
|
+
- **API keys** with enforced scopes: hand a read-only key to a partner or a
|
|
261
|
+
frontend without exposing write access.
|
|
262
|
+
|
|
263
|
+
## Build-order playbook (new site)
|
|
264
|
+
|
|
265
|
+
0. **Propose the content model and get sign-off** ("Before you build", above)
|
|
266
|
+
— nothing else starts until the owner approves it.
|
|
267
|
+
1. **Model first:** custom content types for every repeated shape (§2).
|
|
268
|
+
2. **Structure:** site tree — pages, folders per collection (§1).
|
|
269
|
+
3. **Taxonomy:** categories/tags the feeds will need (§3).
|
|
270
|
+
4. **Media:** upload the brand's assets to the library (§7).
|
|
271
|
+
5. **Templates:** saved layouts + reusable components for the recurring
|
|
272
|
+
sections (§4, §5); custom modules only where the palette falls short.
|
|
273
|
+
6. **Wire collections:** feeds + Feed Display placements (§1).
|
|
274
|
+
7. **Forms:** contact/newsletter/etc. in the builder (§6).
|
|
275
|
+
8. **Workflow:** groups, permissions, review path (§9).
|
|
276
|
+
9. **Ask about** personalization/A-B (§8), comments, webhooks, i18n (§11).
|
|
277
|
+
10. **SEO pass** (§12), then hand over: show the owner where *their* edits
|
|
278
|
+
live — content nodes, feeds, components — and confirm nothing they'll want
|
|
279
|
+
to change requires you.
|
|
280
|
+
|
|
281
|
+
## Anti-patterns (smells)
|
|
282
|
+
|
|
283
|
+
- Creating types and entering content before the owner signed off on a
|
|
284
|
+
content model.
|
|
285
|
+
- A hardcoded array of testimonials/logos/posts in a page component.
|
|
286
|
+
- The same CTA JSX pasted on four pages.
|
|
287
|
+
- A `<form>` that POSTs to a hand-rolled route (or nowhere).
|
|
288
|
+
- Marketing imagery in `/public`.
|
|
289
|
+
- A "blog" that is a folder of `.mdx` files the owner can't edit.
|
|
290
|
+
- One-off content types created in config for shapes the owner will evolve.
|
|
291
|
+
- Personalization built speculatively, with no owner request behind it.
|
|
292
|
+
- Direct-publish-only workflow on a multi-author site.
|
|
293
|
+
|
|
294
|
+
Every one of these has a section above. If you catch yourself mid-smell, refactor to the pattern before handover — it's minutes now, migrations later.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kywi-collections
|
|
3
|
+
description: Use when adding ANY collection to this Kywi site — testimonials, customer logos, blog posts, products, portfolio pieces, team members, FAQs, press mentions — or whenever you catch yourself about to hardcode a repeating list of items in a page. Walks the folder + feed + Feed Display pattern end to end.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Build a collection: folder + feed + Feed Display
|
|
7
|
+
|
|
8
|
+
Collections are never hardcoded. A collection is any set of similar items that
|
|
9
|
+
grows over time and is displayed somewhere — the owner must be able to add an
|
|
10
|
+
item in the admin and see every relevant page update, with no code changes.
|
|
11
|
+
|
|
12
|
+
## Workflow
|
|
13
|
+
|
|
14
|
+
### 1. Recognize the collection
|
|
15
|
+
|
|
16
|
+
About to write an array of testimonials, a grid of logos, a list of cards in
|
|
17
|
+
JSX? Stop — that's a collection. Confirm the shape: what fields does one item
|
|
18
|
+
have, and where on the site do items appear (one page? several? aggregate-only
|
|
19
|
+
or does each item need its own page)?
|
|
20
|
+
|
|
21
|
+
### 2. Model the item type
|
|
22
|
+
|
|
23
|
+
- Items with structure beyond title/body/image (products, recipes, profiles)
|
|
24
|
+
→ create a custom content type first (admin → Content Types; admin-created
|
|
25
|
+
by default so the owner can evolve it). Match the approved `CONTENT-MODEL.md`
|
|
26
|
+
— if this collection isn't in it, update the model and confirm the addition
|
|
27
|
+
with the owner before building.
|
|
28
|
+
- Simple items (a quote + attribution, a logo + link) can use an existing or
|
|
29
|
+
minimal type — don't over-model.
|
|
30
|
+
|
|
31
|
+
### 3. Structure: a folder in the Site Tree
|
|
32
|
+
|
|
33
|
+
Create a folder for the collection (`/testimonials`, `/work`, `/customers`)
|
|
34
|
+
and add the initial nodes inside it. Two gotchas:
|
|
35
|
+
|
|
36
|
+
- **Nodes must be `published`** to appear in public feeds — drafts won't show.
|
|
37
|
+
- Aggregate-only items (logos, quotes) still get nodes; their individual pages
|
|
38
|
+
simply go unlinked. Items needing detail pages (posts, portfolio pieces)
|
|
39
|
+
live at real, linkable paths.
|
|
40
|
+
|
|
41
|
+
### 4. Query: create the Feed
|
|
42
|
+
|
|
43
|
+
Admin → Feeds → new feed: pick the content type, add taxonomy filters if the
|
|
44
|
+
display is a slice ("testimonials tagged `homepage`"), set sort and limit
|
|
45
|
+
("6 most recent"). **Check the feed preview shows the expected items before
|
|
46
|
+
moving on** — an empty preview means a wrong type, unpublished nodes, or a
|
|
47
|
+
taxonomy term that isn't applied to anything yet.
|
|
48
|
+
|
|
49
|
+
Multiple slices of one collection = multiple feeds over the same type
|
|
50
|
+
(featured vs. all; per-category).
|
|
51
|
+
|
|
52
|
+
### 5. Display: place the Feed Display module
|
|
53
|
+
|
|
54
|
+
In the layout editor on each target page, add the **Feed Display** module and
|
|
55
|
+
select the feed. If the same feed placement (with surrounding design) recurs
|
|
56
|
+
on several pages, save the section as a reusable component instead of
|
|
57
|
+
rebuilding it per page.
|
|
58
|
+
|
|
59
|
+
Scaffolded apps hydrate feeds server-side automatically. A hand-built host
|
|
60
|
+
must call `hydrateLayoutFeeds` before rendering `KywiLayout` — if the module
|
|
61
|
+
renders an empty list publicly but previews fine in the admin, missing host
|
|
62
|
+
hydration is the usual cause.
|
|
63
|
+
|
|
64
|
+
### 6. Verify end to end
|
|
65
|
+
|
|
66
|
+
Publish the page, load it publicly, confirm items render. Then the real test:
|
|
67
|
+
**add one more node to the folder and reload — it must appear without touching
|
|
68
|
+
the page.** If it doesn't, the loop isn't closed; fix before moving on.
|
|
69
|
+
|
|
70
|
+
### 7. Handover note
|
|
71
|
+
|
|
72
|
+
Record in `CONTENT-MODEL.md` (feeds table) and tell the owner: "to add a
|
|
73
|
+
<item>, create it in <folder>; it appears on <pages> automatically."
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kywi-content-model
|
|
3
|
+
description: Use BEFORE building out this Kywi site or adding any significant new content area (custom types, collections, structured sections) — designs the content model and gets the owner's sign-off first. The most expensive CMS failure is a poorly planned content model; content entry is costly, planning is cheap.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Design the content model, then get sign-off
|
|
7
|
+
|
|
8
|
+
Do not create content types, enter content, or build page layouts for a new
|
|
9
|
+
site or content area until the owner has approved a content model. This is
|
|
10
|
+
guidance, not law — a single-page brochure site needs a sentence of
|
|
11
|
+
confirmation, not a document — but anything with custom types, collections, or
|
|
12
|
+
more than a handful of pages gets the full treatment.
|
|
13
|
+
|
|
14
|
+
## Workflow
|
|
15
|
+
|
|
16
|
+
### 1. Discovery — ask before proposing
|
|
17
|
+
|
|
18
|
+
Understand the site before modeling it. Ask the owner (batch the questions):
|
|
19
|
+
|
|
20
|
+
- What does the site need to communicate, and to whom?
|
|
21
|
+
- What kinds of content exist or are planned? (posts, products, recipes,
|
|
22
|
+
people, case studies, events, FAQs, testimonials, locations…)
|
|
23
|
+
- Which of those are *collections* — sets of similar items that grow over time?
|
|
24
|
+
- Who maintains the site after handover, and how technical are they?
|
|
25
|
+
- Multiple authors (→ review workflow)? Multiple languages? Timed launches?
|
|
26
|
+
- Any personalization/A-B interest? (Offer examples; don't assume — see
|
|
27
|
+
AGENTS.md §8.)
|
|
28
|
+
|
|
29
|
+
### 2. Draft `CONTENT-MODEL.md` at the project root
|
|
30
|
+
|
|
31
|
+
Use this template:
|
|
32
|
+
|
|
33
|
+
```markdown
|
|
34
|
+
# Content model — <site>
|
|
35
|
+
|
|
36
|
+
## Types
|
|
37
|
+
| Type | Built-in/custom | Purpose | Maintained by |
|
|
38
|
+
|---|---|---|---|
|
|
39
|
+
|
|
40
|
+
### <each custom type>
|
|
41
|
+
| Field | Type | Required | Notes |
|
|
42
|
+
|---|---|---|---|
|
|
43
|
+
|
|
44
|
+
## Site tree
|
|
45
|
+
<top-level pages and a folder per collection, as an indented list>
|
|
46
|
+
|
|
47
|
+
## Feeds
|
|
48
|
+
| Feed | Source type | Filter | Sort/limit | Displayed on |
|
|
49
|
+
|---|---|---|---|---|
|
|
50
|
+
|
|
51
|
+
## Taxonomy
|
|
52
|
+
Categories: <stable sets> · Tags: <expected freeform labels>
|
|
53
|
+
|
|
54
|
+
## Reusable components
|
|
55
|
+
| Component | Used on |
|
|
56
|
+
|---|---|
|
|
57
|
+
|
|
58
|
+
## Maintenance
|
|
59
|
+
Editors/approvers, workflow needs, i18n locales, scheduling needs.
|
|
60
|
+
|
|
61
|
+
## Open questions
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Modeling rules of thumb (full rationale in AGENTS.md):
|
|
65
|
+
|
|
66
|
+
- Repeated shape → custom type, **admin-created by default** (owners can add
|
|
67
|
+
fields later without a developer); config-defined only for developer-owned
|
|
68
|
+
schema.
|
|
69
|
+
- Anything displayed as a list somewhere → collection: folder + feed + Feed
|
|
70
|
+
Display module. Never a hardcoded array.
|
|
71
|
+
- Cross-cutting groupings → categories (stable) and tags (evolving), queried
|
|
72
|
+
by feeds.
|
|
73
|
+
- Sections used on 2+ pages → reusable components.
|
|
74
|
+
- Don't shadow built-in fields (title, slug, body); don't invent a type per
|
|
75
|
+
page — types are for repeated shapes.
|
|
76
|
+
|
|
77
|
+
### 3. Get explicit sign-off
|
|
78
|
+
|
|
79
|
+
Present the proposal and iterate. Ask directly: *"Does this content model
|
|
80
|
+
match how you think about your content, and who will maintain each part?"*
|
|
81
|
+
Get an explicit yes before proceeding. If scope is trivial, a one-paragraph
|
|
82
|
+
summary and a "confirm?" suffices.
|
|
83
|
+
|
|
84
|
+
### 4. Build — only after approval
|
|
85
|
+
|
|
86
|
+
Follow the build-order playbook in AGENTS.md: types → tree/folders → taxonomy
|
|
87
|
+
→ media → layouts/components → feeds → forms → workflow → (ask about
|
|
88
|
+
personalization, comments, i18n) → SEO pass → handover.
|
|
89
|
+
|
|
90
|
+
### 5. Keep the model current
|
|
91
|
+
|
|
92
|
+
`CONTENT-MODEL.md` is a living document. When the model changes later (new
|
|
93
|
+
type, new collection), update the file and re-confirm significant changes with
|
|
94
|
+
the owner. It doubles as the handover map of "where your content lives."
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kywi-personalization
|
|
3
|
+
description: Use when the site owner wants personalization or A/B testing on this Kywi site — audience-targeted content, segment-specific pages, self-identification, or experiments — or before YOU propose any of those. Multi-step - audiences, variants/experiments, preview-token verification, conclusion.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Personalization & A/B testing — confirmed use case first, then build
|
|
7
|
+
|
|
8
|
+
**Never build personalization speculatively.** If the owner hasn't asked,
|
|
9
|
+
offer it with concrete examples and let them decide (returning-visitor hero,
|
|
10
|
+
segment-specific messaging, self-identified content ordering, a CTA test).
|
|
11
|
+
Only proceed with a confirmed use case and a stated success measure.
|
|
12
|
+
|
|
13
|
+
## Workflow
|
|
14
|
+
|
|
15
|
+
### 1. Confirm the use case and what "working" means
|
|
16
|
+
|
|
17
|
+
With the owner, pin down: which segment or hypothesis, which page(s) and
|
|
18
|
+
section(s), and what outcome defines success (a conversion, a click-through, a
|
|
19
|
+
qualitative "the right people see the right message"). Write it down — it
|
|
20
|
+
decides the mechanism and when you're done.
|
|
21
|
+
|
|
22
|
+
### 2. Choose the mechanism
|
|
23
|
+
|
|
24
|
+
- **Known segment, deterministic content** → audience + **page variant**
|
|
25
|
+
("agencies see the agency hero"). No measurement involved.
|
|
26
|
+
- **Hypothesis to measure** → **A/B experiment** ("does the short headline
|
|
27
|
+
convert better?"). Variants + recorded exposures.
|
|
28
|
+
- **Visitor-declared identity** → **self-ID widget** ("I'm a developer / I'm
|
|
29
|
+
a marketer") feeding an audience.
|
|
30
|
+
|
|
31
|
+
### 3. Build the audience (variant and self-ID paths)
|
|
32
|
+
|
|
33
|
+
Admin → Audiences: define the rules, or configure the self-ID widget and its
|
|
34
|
+
fields. Use the audience test tool to confirm the rules match the intended
|
|
35
|
+
visitors before wiring anything to it.
|
|
36
|
+
|
|
37
|
+
### 4a. Page-variant path
|
|
38
|
+
|
|
39
|
+
In the layout editor on the target page: **+ Page Variant** → select the
|
|
40
|
+
audience → edit the variant. Change **only the sections that segment needs** —
|
|
41
|
+
the default variant must remain complete and self-sufficient (personalization
|
|
42
|
+
is progressive enhancement; anonymous visitors get the default).
|
|
43
|
+
|
|
44
|
+
### 4b. Experiment path
|
|
45
|
+
|
|
46
|
+
Admin → Experiments: create the experiment. In the layout, add an A/B
|
|
47
|
+
container with an arm per treatment. Assignment is deterministic per visitor
|
|
48
|
+
(the scaffold's middleware issues a persistent `kywi_visitor` cookie), so a
|
|
49
|
+
visitor sees the same arm on every visit — no client runtime needed.
|
|
50
|
+
|
|
51
|
+
### 5. Verify before calling it done
|
|
52
|
+
|
|
53
|
+
- **Preview tokens** (Audiences → Preview Tokens): view the page *as each
|
|
54
|
+
audience* and confirm the right variant serves.
|
|
55
|
+
- Experiments: two fresh browser profiles should get (possibly) different
|
|
56
|
+
arms, and each profile must get the **same** arm on reload.
|
|
57
|
+
- Confirm exposures are being recorded in the Experiments admin.
|
|
58
|
+
- Load the page as a plain anonymous visitor: the default must be complete.
|
|
59
|
+
|
|
60
|
+
### 6. Run, conclude, promote
|
|
61
|
+
|
|
62
|
+
One experiment per conversion goal; let it reach a conclusion before layering
|
|
63
|
+
another on the same page. When it concludes, **promote the winner into the
|
|
64
|
+
base layout and remove the experiment container** — a site accreting stale
|
|
65
|
+
experiments is a maintenance smell.
|
|
66
|
+
|
|
67
|
+
### 7. Document for handover
|
|
68
|
+
|
|
69
|
+
Record what is personalized where (and why) in `CONTENT-MODEL.md`'s
|
|
70
|
+
maintenance notes. The owner must know a page has variants before they edit
|
|
71
|
+
it — editing only the default of a heavily-personalized page is a classic
|
|
72
|
+
post-handover surprise.
|
package/lib/templates.mjs
CHANGED
|
@@ -32,6 +32,10 @@
|
|
|
32
32
|
* ships session fixes without the app hand-maintaining crypto.
|
|
33
33
|
*/
|
|
34
34
|
|
|
35
|
+
import { readFileSync } from 'node:fs'
|
|
36
|
+
import { dirname, join } from 'node:path'
|
|
37
|
+
import { fileURLToPath } from 'node:url'
|
|
38
|
+
|
|
35
39
|
/** @typedef {{ projectName: string, dbProvider: 'postgresql'|'mysql', authProviders: string[], mode: 'coupled'|'headless'|'decoupled', kywiVersion: string }} Answers */
|
|
36
40
|
|
|
37
41
|
const CORE_RANGE = (v) => `^${v}`
|
|
@@ -1903,6 +1907,11 @@ ${themingBlock}
|
|
|
1903
1907
|
|
|
1904
1908
|
\`\`\`
|
|
1905
1909
|
kywi.config.ts your config: sites, themes, content types, auth, mode, admin.features
|
|
1910
|
+
AGENTS.md guidance for AI agents working on this site (Kywi's building patterns)
|
|
1911
|
+
CLAUDE.md points AI agents to AGENTS.md
|
|
1912
|
+
.claude/skills/kywi-content-model/SKILL.md content-model skill (loaded automatically)
|
|
1913
|
+
.claude/skills/kywi-collections/SKILL.md collections skill (loaded automatically)
|
|
1914
|
+
.claude/skills/kywi-personalization/SKILL.md personalization skill (loaded automatically)
|
|
1906
1915
|
middleware.ts auth gate + session refresh + cookie→bearer bridge
|
|
1907
1916
|
next.config.mjs required Next config to consume @kywi-software/core
|
|
1908
1917
|
lib/kywi.ts server runtime (DB, API handler, content scope)
|
|
@@ -1929,6 +1938,150 @@ function escapeJsxText(value) {
|
|
|
1929
1938
|
return String(value).replace(/[{}<>]/g, (ch) => `{'${ch}'}`)
|
|
1930
1939
|
}
|
|
1931
1940
|
|
|
1941
|
+
// ── Agent guidance (AGENTS.md / CLAUDE.md) ──────────────────────────────────────
|
|
1942
|
+
|
|
1943
|
+
/**
|
|
1944
|
+
* Kywi's canonical building-patterns doc, shipped as a package asset and embedded
|
|
1945
|
+
* verbatim into every generated app's AGENTS.md. Resolved relative to THIS module
|
|
1946
|
+
* (import.meta.url), NOT process.cwd(), so it loads from an installed
|
|
1947
|
+
* create-kywi-app the same as from the monorepo. Kept byte-identical to
|
|
1948
|
+
* docs/agents/AGENT-PATTERNS.md by scripts/sync-agent-patterns.mjs (a drift test
|
|
1949
|
+
* guards it). Cached so repeated buildFileSet() calls don't re-read the file.
|
|
1950
|
+
* @returns {string}
|
|
1951
|
+
*/
|
|
1952
|
+
let _agentPatternsDoc
|
|
1953
|
+
function agentPatternsDoc() {
|
|
1954
|
+
if (_agentPatternsDoc === undefined) {
|
|
1955
|
+
const assetPath = join(dirname(fileURLToPath(import.meta.url)), '..', 'assets', 'agent-patterns.md')
|
|
1956
|
+
_agentPatternsDoc = readFileSync(assetPath, 'utf8')
|
|
1957
|
+
}
|
|
1958
|
+
return _agentPatternsDoc
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
/**
|
|
1962
|
+
* Kywi's Claude Code project skills — each ships as a package asset and is
|
|
1963
|
+
* embedded verbatim into every generated app's .claude/skills/<slug>/SKILL.md
|
|
1964
|
+
* (all modes, in this order). Exported so tests can iterate the same table
|
|
1965
|
+
* instead of duplicating it.
|
|
1966
|
+
* @type {Array<{ slug: string, asset: string }>}
|
|
1967
|
+
*/
|
|
1968
|
+
export const SKILLS = [
|
|
1969
|
+
// Before building anything: design the content model, get owner sign-off.
|
|
1970
|
+
{ slug: 'kywi-content-model', asset: 'kywi-content-model-skill.md' },
|
|
1971
|
+
// When adding any collection: folder + feed + Feed Display, end to end.
|
|
1972
|
+
{ slug: 'kywi-collections', asset: 'kywi-collections-skill.md' },
|
|
1973
|
+
// When the owner wants personalization/A-B: confirm the use case, then build.
|
|
1974
|
+
{ slug: 'kywi-personalization', asset: 'kywi-personalization-skill.md' },
|
|
1975
|
+
]
|
|
1976
|
+
|
|
1977
|
+
/**
|
|
1978
|
+
* Cache of asset filename → file content for scaffolded Claude Code skills,
|
|
1979
|
+
* populated lazily by {@link skillDoc}.
|
|
1980
|
+
* @type {Map<string, string>}
|
|
1981
|
+
*/
|
|
1982
|
+
const _skillDocCache = new Map()
|
|
1983
|
+
|
|
1984
|
+
/**
|
|
1985
|
+
* Read (and cache) one Claude Code skill's SKILL.md asset by filename.
|
|
1986
|
+
* Resolved relative to THIS module (import.meta.url), same mechanism as
|
|
1987
|
+
* {@link agentPatternsDoc}, so it loads from an installed create-kywi-app the
|
|
1988
|
+
* same as from the monorepo. Cached so repeated buildFileSet() calls don't
|
|
1989
|
+
* re-read the file.
|
|
1990
|
+
* @param {string} asset
|
|
1991
|
+
* @returns {string}
|
|
1992
|
+
*/
|
|
1993
|
+
function skillDoc(asset) {
|
|
1994
|
+
if (!_skillDocCache.has(asset)) {
|
|
1995
|
+
const assetPath = join(dirname(fileURLToPath(import.meta.url)), '..', 'assets', asset)
|
|
1996
|
+
_skillDocCache.set(asset, readFileSync(assetPath, 'utf8'))
|
|
1997
|
+
}
|
|
1998
|
+
return _skillDocCache.get(asset)
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
/**
|
|
2002
|
+
* AGENTS.md — a short, app-specific header that orients an agent in THIS generated
|
|
2003
|
+
* app, followed by Kywi's canonical patterns doc verbatim. Mode-aware: only
|
|
2004
|
+
* coupled apps have public-render wiring (lib/site.ts), so the header reflects it.
|
|
2005
|
+
* @param {Answers} a
|
|
2006
|
+
*/
|
|
2007
|
+
function agentsMd(a) {
|
|
2008
|
+
const coupled = a.mode === 'coupled'
|
|
2009
|
+
const modeSentence = coupled
|
|
2010
|
+
? 'This app renders the public site AND serves the admin + API.'
|
|
2011
|
+
: a.mode === 'headless'
|
|
2012
|
+
? 'This app serves the admin + API only (`GET /` returns 404); there is no public rendering here.'
|
|
2013
|
+
: 'This app serves the admin + API only; a separate frontend consumes the API via `@kywi-software/sdk`. There is no public rendering here.'
|
|
2014
|
+
const surfaceLine = coupled
|
|
2015
|
+
? `- \`lib/site.ts\` — public-render helpers (path/locale resolution, feeds,
|
|
2016
|
+
components, personalization) used by \`app/(site)/[[...slug]]/page.tsx\`, which
|
|
2017
|
+
renders every published page at its slug.`
|
|
2018
|
+
: a.mode === 'headless'
|
|
2019
|
+
? `- No public rendering in this mode — \`app/page.tsx\` returns 404. Content is
|
|
2020
|
+
served over the REST API at \`/api/v1\`.`
|
|
2021
|
+
: `- No public rendering in this mode — \`app/page.tsx\` returns 404. Build a
|
|
2022
|
+
separate frontend against the REST API at \`/api/v1\` with \`@kywi-software/sdk\`.`
|
|
2023
|
+
const header = `# Agent guide — ${a.projectName}
|
|
2024
|
+
|
|
2025
|
+
This is a **Kywi CMS** project scaffolded by \`create-kywi-app\` (\`${a.mode}\` mode).
|
|
2026
|
+
${modeSentence}
|
|
2027
|
+
|
|
2028
|
+
## Where things live
|
|
2029
|
+
|
|
2030
|
+
- \`kywi.config.ts\` — project config: sites, themes, content types, auth
|
|
2031
|
+
providers, deployment mode, and \`admin.features\`. Edit it, then re-run
|
|
2032
|
+
\`pnpm migrate\`.
|
|
2033
|
+
- \`app/admin/[[...admin]]/page.tsx\` — mounts Kywi's **full admin**
|
|
2034
|
+
(\`KywiAdminApp\`) at **\`/admin\`**. Every surface — content, media, feeds,
|
|
2035
|
+
forms, audiences, settings, … — is already there; never hand-build admin pages.
|
|
2036
|
+
- \`lib/modules.tsx\` — the custom-module map (\`defineModule\` renderers), shared
|
|
2037
|
+
by the admin editor and the public site.
|
|
2038
|
+
${surfaceLine}
|
|
2039
|
+
- \`middleware.ts\` — auth gate + session refresh, thin wiring over
|
|
2040
|
+
\`@kywi-software/core/host\`.
|
|
2041
|
+
- \`.claude/skills/kywi-content-model/SKILL.md\` — content-model planning
|
|
2042
|
+
skill, loaded automatically before building anything.
|
|
2043
|
+
- \`.claude/skills/kywi-collections/SKILL.md\` — collections skill, loaded
|
|
2044
|
+
automatically when adding any collection.
|
|
2045
|
+
- \`.claude/skills/kywi-personalization/SKILL.md\` — personalization skill,
|
|
2046
|
+
loaded automatically when the owner wants personalization or A/B testing.
|
|
2047
|
+
|
|
2048
|
+
## Running it
|
|
2049
|
+
|
|
2050
|
+
\`\`\`bash
|
|
2051
|
+
pnpm migrate # apply the schema
|
|
2052
|
+
pnpm seed # create the default site + a superadmin (prints credentials)
|
|
2053
|
+
pnpm dev # http://localhost:3000 (admin at /admin)
|
|
2054
|
+
\`\`\`
|
|
2055
|
+
|
|
2056
|
+
## Kywi's building patterns
|
|
2057
|
+
|
|
2058
|
+
Everything below is **Kywi's official guidance** for building sites end users can
|
|
2059
|
+
maintain — read it before adding content, pages, forms, or modules. The rule that
|
|
2060
|
+
matters most: **if a non-developer might ever want to change it, model it in the
|
|
2061
|
+
CMS instead of hardcoding it.**
|
|
2062
|
+
|
|
2063
|
+
---
|
|
2064
|
+
|
|
2065
|
+
`
|
|
2066
|
+
return header + agentPatternsDoc()
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
/**
|
|
2070
|
+
* CLAUDE.md — a thin pointer so a Claude Code session reads AGENTS.md first.
|
|
2071
|
+
* @param {Answers} a
|
|
2072
|
+
*/
|
|
2073
|
+
function claudeMd(a) {
|
|
2074
|
+
return `# ${a.projectName}
|
|
2075
|
+
|
|
2076
|
+
This is a **Kywi CMS** project. **Read \`AGENTS.md\` before building anything** — it
|
|
2077
|
+
holds Kywi's official building patterns and a map of where things live in this app.
|
|
2078
|
+
|
|
2079
|
+
Core principle: **model content in the CMS instead of hardcoding it** — see \`AGENTS.md\`.
|
|
2080
|
+
|
|
2081
|
+
Before building out a new content area, use the \`kywi-content-model\` skill (design the model, get sign-off) — skills in \`.claude/skills/\` also cover collections and personalization.
|
|
2082
|
+
`
|
|
2083
|
+
}
|
|
2084
|
+
|
|
1932
2085
|
/**
|
|
1933
2086
|
* Build the complete map of relative-path → file-content for a project.
|
|
1934
2087
|
* @param {Answers} answers
|
|
@@ -1945,6 +2098,10 @@ export function buildFileSet(answers) {
|
|
|
1945
2098
|
'.env.example': envExample(),
|
|
1946
2099
|
'.gitignore': gitignore(),
|
|
1947
2100
|
'README.md': readme(answers),
|
|
2101
|
+
// agent guidance (every mode): app-specific header + Kywi's canonical patterns
|
|
2102
|
+
// doc verbatim. CLAUDE.md is a thin pointer into AGENTS.md.
|
|
2103
|
+
'AGENTS.md': agentsMd(answers),
|
|
2104
|
+
'CLAUDE.md': claudeMd(answers),
|
|
1948
2105
|
// server runtime + config
|
|
1949
2106
|
'lib/kywi.ts': libKywi(),
|
|
1950
2107
|
'lib/config.ts': libConfig(),
|
|
@@ -1969,6 +2126,15 @@ export function buildFileSet(answers) {
|
|
|
1969
2126
|
'app/robots.txt/route.ts': axRootRoute('robots.txt'),
|
|
1970
2127
|
}
|
|
1971
2128
|
|
|
2129
|
+
// Claude Code project skills (every mode): content-model-first discipline,
|
|
2130
|
+
// collections, and personalization — Claude Code loads each automatically at
|
|
2131
|
+
// the moment it's relevant (see SKILLS above for when-to-use). Verbatim
|
|
2132
|
+
// assets, same readFileSync-from-import.meta.url + cache mechanism as
|
|
2133
|
+
// AGENTS.md above.
|
|
2134
|
+
for (const { slug, asset } of SKILLS) {
|
|
2135
|
+
files[`.claude/skills/${slug}/SKILL.md`] = skillDoc(asset)
|
|
2136
|
+
}
|
|
2137
|
+
|
|
1972
2138
|
if (answers.mode === 'coupled') {
|
|
1973
2139
|
// Public site: an optional catch-all renders "/" (home) and every published
|
|
1974
2140
|
// page at its slug. More-specific /admin and /api routes take precedence.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-kywi-app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Scaffold a new Kywi CMS project — npx create-kywi-app my-site",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"homepage": "https://github.com/Kywi-Software/kywi-cms#readme",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"files": [
|
|
16
16
|
"bin",
|
|
17
17
|
"lib",
|
|
18
|
+
"assets",
|
|
18
19
|
"README.md",
|
|
19
20
|
"LICENSE"
|
|
20
21
|
],
|