@kywi-software/core 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/AGENT-PATTERNS.md +294 -0
- package/README.md +11 -0
- package/package.json +2 -1
|
@@ -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.
|
package/README.md
CHANGED
|
@@ -7,6 +7,17 @@ app. See the [root README](https://github.com/Kywi-Software/kywi-cms#readme) for
|
|
|
7
7
|
an orientation to the whole project, and `packages/core/src/config/types.ts`
|
|
8
8
|
for the full config shape.
|
|
9
9
|
|
|
10
|
+
## For agents building with Kywi
|
|
11
|
+
|
|
12
|
+
[`AGENT-PATTERNS.md`](./AGENT-PATTERNS.md) (shipped with this package) is Kywi's
|
|
13
|
+
official guidance for agents building Kywi sites. The core principle: **if a
|
|
14
|
+
non-developer might ever want to change it, model it in the CMS instead of
|
|
15
|
+
hardcoding it** — content, collections, forms, and page sections belong in Kywi
|
|
16
|
+
so the site owner can maintain them without a developer. A scaffolded
|
|
17
|
+
`create-kywi-app` project embeds this doc in its `AGENTS.md`. It is a verbatim
|
|
18
|
+
copy of `docs/agents/AGENT-PATTERNS.md` in the monorepo (kept in sync by
|
|
19
|
+
`scripts/sync-agent-patterns.mjs`); edit the canonical there, not this copy.
|
|
20
|
+
|
|
10
21
|
## Install
|
|
11
22
|
|
|
12
23
|
```bash
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kywi-software/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Kywi CMS core — schema generator, REST API, and admin UI for Next.js.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
"files": [
|
|
25
25
|
"dist",
|
|
26
|
+
"AGENT-PATTERNS.md",
|
|
26
27
|
"README.md",
|
|
27
28
|
"LICENSE"
|
|
28
29
|
],
|