Workshop Kit · widget reference
Shippedkeyword-builder
Seeds 8 local-SEO keyword slots from restaurantProfile.cuisine + the city extracted from restaurantProfile.address, then lets the operator edit each row. Four formulas (cuisine+nbhd / dish+nbhd / occasion+nbhd / intent+cuisine+nbhd) appear twice each with different second words. Writes localKeywords as a newline-separated string — same shape the L12 text-input writes today, so the L14 generator + readiness checklist keep working.
Live demo
Type cuisine + neighborhood at the top, click "Refill all 8 slots from profile," then edit each row. Edits go to MuntinContext.localKeywords as a newline-separated string.
No config block needed — reads context, writes localKeywords
Contract
No data attributes beyond data-widget; no inline JSON config. The widget reads cuisine + address from MuntinContext.restaurantProfile and seeds suggestions; operator overrides for either the cuisine OR the neighborhood are typed inline at the top of the widget.
| Behavior | Notes |
|---|---|
Reads restaurantProfile.cuisine |
Pre-fills the cuisine input. Operator can edit inline without changing the profile. |
Reads restaurantProfile.address |
Tries to extract a neighborhood / city via a simple comma-split heuristic. Falls back to a placeholder; operator overrides inline. |
Reads localKeywords |
If the operator typed phrases previously, those WIN on first mount — the seed doesn't overwrite saved work. |
Writes localKeywords |
Newline-separated string with one phrase per line, capped at 8. Same shape as the L12 text-input → existing L14 generator + L14 readiness checklist read it without changes. |
| Refill button | Reseeds all 8 slots from the current cuisine + neighborhood values. Polite-region announcement names what happened. |
| Cuisine dictionary | The dish-suggestion bank covers 12 cuisines (mexican, italian, japanese, chinese, thai, indian, mediterranean, american, french, korean, vietnamese, ethiopian). Unrecognized cuisines fall back to "signature dish" / "house special" placeholders. |
Markup
That's it. The cuisine + neighborhood inputs render inline; the 8 keyword slots seed automatically; edits commit to localKeywords on every input event.
Accessibility
- Each row is a labeled
<input type="text">; the formula name renders as a visible label thataria-describedbypoints at. Screen readers hear "Cuisine + neighborhood — mexican silver spring" without the operator having to inspect the example. - The refill button has a clear action label and announces success via a polite live region: "8 keyword slots refilled from your current profile."
- Tab order: cuisine input → neighborhood input → refill button → 8 keyword rows in order. No focus traps; arrow keys work normally inside text inputs.
Why seed instead of suggest-as-you-type
Autocomplete-as-you-type would feel responsive but hide the formula. The point of L12 is for the operator to internalize the four formulas so they can keep generating new phrases quarterly (per the L16 rhythm). Showing the formula name next to each row is the pedagogical move; the seed is just a starting point operators edit toward what their neighborhood actually searches.
Where it ships
The course-local-seo printable sheet reads from the same localKeywords string, so a quarterly print + walk-incognito-through-Google flow stays unchanged.
Source
/tools/_shared/workshop/keyword-builder.js — ~200 LOC. Exports { tag, contextKeys, mount, serialize } per the Workshop Kit widget contract. Dish-suggestion bank lives at the top of the file as a flat lookup table; neighborhood extraction is a simple comma-split heuristic on the address. The widget writes localKeywords as a string (not an array) to keep wire compatibility with the L12 text-input it replaces and the L14 generator that reads it.