From event-marketing
Build and deploy a personalized agenda generator website for a conference — a here.now-hosted page that lists sessions in a filterable grid, lets visitors describe who they are in natural language to get "Great fit / Good fit" recommendations, lets them add sessions to a personalized agenda, and publishes the agenda as a shareable here.now link. Also supports a marketer-driven flow where Claude curates and deploys a standalone personalized agenda for a specific named attendee (a customer or prospect VIP). Use whenever the user asks to build a conference agenda site, a session picker, a personalized schedule tool, an agenda recommender, or wants to make a custom agenda page for a specific person attending a conference. Trigger on phrases like "agenda generator", "session picker", "personalized agenda", "build an agenda site", "conference website with filterable sessions", "make a custom agenda for <person>", "share an agenda with <person>", "publish to here.now". Do NOT trigger for general workback/prep timelines (use workback-schedule) or single-event venue selection (use venue-research).
How this skill is triggered — by the user, by Claude, or both
Slash command
/event-marketing:agenda-generatorThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Generates a self-contained, here.now-hostable website that:
Generates a self-contained, here.now-hostable website that:
Great fit / Good fit / Maybe and sorts by fit.The same skill also supports a marketer-driven workflow: "Make an agenda for " → Claude picks sessions, writes a standalone personalized agenda HTML file, deploys it to here.now, and hands back the link to share.
Everything is hosted on here.now. The skill installs the here-now skill if it isn't already available, then invokes it to deploy.
| User intent | Operation |
|---|---|
| "Build an agenda site for " / first run | create |
| "Update the sessions" / new CSV | refresh-sessions |
| "Change the branding" / new reference site | rebrand |
| "Redeploy" / "Push to here.now again" | deploy |
| "Make an agenda for " / "Curate sessions for " | curate |
| "Show me the deployed URL" / "What's the link?" | info |
Default to create if there is no active project, info otherwise.
Before any operation, figure out which project folder applies:
agenda.json, switch to it.create, run the first-run flow (Step 2).State lives in the project folder. The skill does not maintain global cross-thread state.
create)Ask for these in a single follow-up if any are missing:
acme-summit-2026.here.now). Confirm before deploying.Always ask for the parent directory where the project folder should live. Do not assume a default. Examples: ~/Desktop/conferences, ~/Documents/marketing/conferences.
Slug the folder as <YYYY>-<kebab-cased-conference-name> (e.g., 2026-acme-summit).
Confirm the full path with the user, then create:
<parent-dir>/<project-slug>/
agenda.json # source of truth: sessions, tags, branding, event meta
agenda.html # generated, deployed page
sessions.csv # original CSV the user provided (saved verbatim)
brand.json # extracted design tokens (colors, fonts, logo, hero img)
personalized/ # standalone personalized agendas curated by Claude (see Step 8)
<persona-slug>.html
assets/ # any saved logos, hero images, etc.
.heredotnow/ # here.now project state (CLI creates this on first deploy)
Then report:
Accept any reasonable CSV layout. Map columns into this canonical session shape:
{
"id": "session-001",
"title": "string",
"abstract": "string",
"speakers": ["string", ...],
"start": "2026-09-15T09:00:00",
"end": "2026-09-15T10:00:00",
"room": "string",
"track": "string",
"tags": { "format": ["talk"], "level": ["intermediate"], "topic": ["AI", "agents"] }
}
Use case-insensitive header matching. Common synonyms:
| Canonical | Accepted headers |
|---|---|
id | id, session_id, code, ref |
title | title, name, session, session_title |
abstract | abstract, description, summary, blurb |
speakers | speaker, speakers, presenter(s), host(s), facilitator(s) |
start | start, start_time, starts_at, begin, time |
end | end, end_time, ends_at, finish |
room | room, location, venue, stage |
track | track, theme, stream |
If a column maps to speakers and has multiple names separated by ,, ;, &, and, or +, split into an array.
If start is provided but end isn't, ask the user for a default session length and apply it.
If no id column exists, generate session-001, session-002, … in file order.
Any column not in the canonical list above is a tag column. Examples: Track, Level, Format, Topic, Audience, Persona, Day, Industry.
For each tag column:
,, ;, |, /).tags under its slug (e.g., Audience Level → audience_level).The page generates one filter chip group per tag column, with one chip per distinct value, sorted by frequency descending.
If a row is missing a title, has no parseable date when other rows have dates, or has a tag cell that doesn't look like a list (e.g., free-form sentence), surface it to the user in a single batch and ask whether to:
Do not silently invent values.
Always save the user-supplied CSV verbatim as <project>/sessions.csv so the user can re-run with edits.
Goal: produce a brand.json that the HTML template reads to skin itself.
{
"name": "Acme Summit 2026",
"logo_url": "assets/logo.svg",
"hero_image_url": "assets/hero.jpg",
"colors": {
"primary": "#2A5BD7",
"primary_text": "#FFFFFF",
"accent": "#FFB547",
"bg": "#FAFAF7",
"panel": "#FFFFFF",
"text": "#111111",
"muted": "#666666",
"border": "#E5E5E5",
"great_fit": "#0E7A35",
"good_fit": "#9A6700"
},
"fonts": {
"heading": "\"Söhne\", -apple-system, sans-serif",
"body": "\"Inter\", -apple-system, sans-serif",
"mono": "ui-monospace, monospace"
},
"radius": "10px",
"vibe": "polished, editorial, lots of whitespace"
}
If the user supplied a JSON token file or CSS, parse it directly:
colors, tokens.color, palette, theme. For fonts look for font, typography.fontFamily.--primary, --bg, --text, etc. from :root. Pull font-family from body.If the input is a docs URL (Storybook, ZeroHeight, Figma published file), use WebFetch to read the page and pull whatever color hexes and font names are visibly listed. If extraction is sparse or ambiguous, tell the user what you found and ask whether to use those or override with the branding reference.
Use WebFetch to load the reference. Extract:
rgb(), rgba(), and CSS custom properties on :root. Rank by frequency and pick a primary (most-used non-neutral), bg (most-used near-white/near-black), text (highest contrast with bg).font-family declarations from inline styles and linked stylesheets. Identify the heading family (used on h1/h2) and the body family.<link rel="icon"> and prominent <img> tags in the header. Save the URL; offer to download into assets/logo.<ext>.<meta property="og:image">. Save into assets/hero.<ext>.When values are uncertain, default to a clean editorial neutral palette and a system font stack, and tell the user what was uncertain so they can override.
Always show the user the extracted palette and font choices before writing brand.json for the first time. One short table or list. Ask: "Look right, or tweak?"
{
"event": {
"name": "Acme Summit 2026",
"start_date": "2026-09-15",
"end_date": "2026-09-17",
"location": "San Francisco, CA",
"subdomain": "acme-summit-2026"
},
"brand": { /* contents of brand.json */ },
"tag_columns": [
{ "key": "track", "label": "Track", "values": ["AI", "Security", "Platform"] },
{ "key": "level", "label": "Level", "values": ["Beginner", "Intermediate", "Advanced"] },
{ "key": "format", "label": "Format", "values": ["Talk", "Workshop", "Panel"] }
],
"sessions": [ /* canonical session objects from Step 3 */ ],
"fit_config": {
"anthropic_api_key_configured": false,
"model": "claude-haiku-4-5-20251001",
"great_threshold": 0.65,
"good_threshold": 0.40
},
"deploy": {
"url": null,
"last_deployed_at": null
}
}
Use Edit for incremental changes. Use Write only when generating the file for the first time.
After every change to agenda.json, regenerate agenda.html.
Read the template at assets/agenda-template.html (relative to this skill's folder). The template contains a single placeholder {{DATA}} inside a <script id="agenda-data" type="application/json"> tag. Substitute it with the full agenda.json payload.
The template is self-contained — all CSS and JS inline, no external dependencies beyond optionally <link>-ing the brand fonts via Google Fonts when the font name is a known web font.
Rendered page behavior (informational — the template handles this, not the skill):
brand.colors.primary as accent, brand fonts, brand logo on the left, conference name + dates as title.brand.hero_image_url is set.tag_columns entry. Clicking a chip toggles it. AND across groups, OR within a group.Great fit or Good fit ribbon (or nothing) and the grid is sorted by fit then time.{ picks: [session_ids], for: "<name>", note: "<optional>" } into a URL-safe base64 string in the URL hash. Clicking copies the full URL to clipboard and shows a toast. The URL stays on the same here.now domain.#a=<base64> in the URL, it renders the personalized agenda view: just the picks, in time order, with the conference branding intact, and a "Build my own agenda" button that drops back into the full picker.The HTML is read-only in the sense that the user does not hand-edit it — all source data lives in agenda.json.
Before any deploy step, check whether the here-now skill is available (look for it in the skill list visible in this session). If it isn't, install it.
npx is on PATH (command -v npx).npx skills add heredotnow/skill --skill here-now -gcurl -fsSL https://here.now/install.sh | bashhere-now skill should be invocable via the Skill tool. If it still isn't, ask the user to restart their session or check that the install completed cleanly.Never assume the install is needed — only run it if here-now isn't already listed in available skills.
Once here-now is available, invoke it via the Skill tool with the project folder path and the subdomain from agenda.json. Pass the request as:
Deploy the static site at
<project-folder>/to here.now at the subdomain<subdomain>. The entry point isagenda.html. Also include theassets/andpersonalized/subfolders. Return the live URL when done.
When the here-now skill returns the live URL, write it into agenda.json at deploy.url and deploy.last_deployed_at, then tell the user:
#a=… URL fragment without any further deploysdeploy after editing sessions will push an update to the same URLFor refresh-sessions, rebrand, or deploy, regenerate agenda.html first (Step 6), then call the here-now skill again with the same folder and subdomain. here-now is responsible for handling diffs and updating the existing site.
curate flowTriggered when the user says things like:
Read agenda.json. For each session, score fit against the persona description:
great / good / maybe / skip with a one-line reason, and pick a slate that:
great then good,mandatory).Write <project>/personalized/<persona-slug>.html. Reuse the same agenda-template.html, but pass a smaller payload where:
agenda.json is the same conference data (so branding is preserved),picks is preset to the chosen session IDs,for is the persona display name,note is the optional greeting,The persona slug is kebab-case of the display name, deduped if necessary (bob-ciso-f100-fs, bob-ciso-f100-fs-2, …).
Deploy via the here-now skill so the file lives at https://<subdomain>.here.now/personalized/<persona-slug>.html (or whatever URL shape here-now produces). Add an entry to agenda.json at deploy.personalized[] with { slug, display_name, url, picked_session_ids, created_at } so the user can list and audit prior curations later.
Hand the URL to the user with a one-line summary: who it's for, how many sessions, total run time, any conflicts.
If the user says "update Bob's agenda" or "swap session X for session Y in ", look up the slug in agenda.json's deploy.personalized[], edit the picks, regenerate the HTML, redeploy. The URL stays the same.
refresh-sessionsUser points at a new CSV (or the same path with edits). Re-parse (Step 3), diff against the existing sessions, surface adds/removes/changes:
+ added: 3 new sessions
- removed: 1 session ("Closing fireside") — appears in personalized agenda for "Bob, CISO" — confirm?
~ changed: 2 sessions (time updated)
Ask the user to approve before writing. After write, regenerate agenda.html, regenerate any affected personalized pages (warn the user when a previously-picked session was removed — those personalized agendas now have a gap), and redeploy.
rebrandUser points at a new reference site or design system. Re-extract brand tokens (Step 4), confirm the diff, write brand.json, regenerate agenda.html and all personalized HTML files, redeploy.
The deployed page scores sessions client-side. Two modes:
When the user submits a persona description on the live page:
cisos → ciso, engineering → engineer/engineers).title.abstract.fit = 0.55 * tag_score + 0.25 * title_score + 0.20 * abstract_score.fit_config.great_threshold and fit_config.good_threshold. Anything below good_threshold is unranked.If agenda.json.fit_config.anthropic_api_key_configured is true, the page detects an ANTHROPIC_API_KEY cookie set at deploy time (the here-now skill handles secret injection — never embed a raw key in the HTML). On fit-search submit:
claude-haiku-4-5-20251001 with the persona description and all sessions (id + title + abstract + tags only — no time/room).great / good / skip and produce a one-sentence reason.Great fit / Good fit ribbons with the model's reason on hover.When the user runs create, ask whether to enable API mode. If yes, prompt them to provide the API key — pass it to the here-now skill as a deploy-time secret rather than writing it to disk. Default is off.
infoPrint a short status block:
Acme Summit 2026 — 2026-09-15 to 2026-09-17
Live at: https://acme-summit-2026.here.now
Sessions: 47 Tracks: 5 Speakers: 38
Last deployed: 2026-05-18 14:32 (3 days ago)
Personalized agendas (3):
- Bob, CISO @ F100 Financial Services — 5 sessions — https://acme-summit-2026.here.now/personalized/bob-ciso-f100-fs.html
- Sarah, Head of Marketing @ Series-B SaaS — 4 sessions — …
- Dimitri, VP Eng @ ScaleUp — 6 sessions — …
agenda.html or agenda.json — secrets always go through the here-now skill's secret-injection mechanism.sessions.csv.npx claudepluginhub zuddl/claude-plugin-event-marketing --plugin event-marketingCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.