halloween-ticket-keepsake

Community@sumino/halloween-ticket-keepsake
Community skill — not reviewed. It was shared by Jagulus and has not been checked by Neta. Read SKILL.md below before letting an agent use it.
Use it in Cohub

Paste this into your agent's chat — it fetches the skill and follows it.

Use the skill: halloween-ticket-keepsake. Run `npx -y @neta-art/neta-search-cli@latest skills use @sumino/halloween-ticket-keepsake --via site` and follow what it prints. Read its complete output, redirecting it to a temporary file first if necessary, and resolve relative paths from the skill directory it prints.
Install from a terminal
npx -y @neta-art/neta-search-cli@latest skills use @sumino/halloween-ticket-keepsake
Summary

A collectible Halloween admission ticket with a cute park scene and tear-off stub in 12 languages.

  • A horizontal ticket with white sawtooth edges: left side shows your character in a Halloween park scene with pumpkins, ghosts, and a castle; right side is a tear-off stub with portrait, barcode, and sticker.
  • The wooden sign's speech bubble and all the stub text switch between 12 languages automatically or by choice, including Arabic support.
  • Works best with a character who has a clear look (memorable hair, outfit, or accessory) and fits a playful Halloween setting.
  • Delivered as a live web page you can share, plus a card on your world board.
SKILL.md
# Halloween Ticket Keepsake

A horizontal 2.02 : 1 admission ticket: a white sawtooth stamp border, a full cute Halloween scene on the left, and a slim tear-off stub on the right carrying the OC's chibi portrait, the title, the meta rows, a barcode and a full-body sticker. The scene is a textless generated illustration; the wooden sign's speech bubble, the whole stub and the page chrome are live HTML, so one ticket speaks twelve languages.

**Live demo:** https://neta.art/w/sumino/sweet-nightmare-park/pipo-halloween-ticket
**Starter:** `templates/` holds the working page (HTML/CSS/JS + fonts); `assets/demo-cover.webp` is the gallery preview.

## What the user gets

- A horizontal keepsake ticket with a white sawtooth/perforated edge, a purple-orange night backdrop with a faint diamond lattice, and a dashed tear line.
- Left: one generated Q-version Halloween park scene holding the world's OC, a small animal companion and 1–3 other named cast members, with jack-o'-lanterns, ghosts, candles, a smiling moon, bats and a castle.
- Right: a slim stub with a transparent chibi portrait, the OC name, the localized title, `ADMIT ONE`, holder/date/gate/price rows, a localized one-line description, a generated barcode and serial, and a transparent full-body chibi sticker.
- A live hand-drawn speech bubble over the scene, in the visitor's language.
- Twelve complete locales, system-language detection, English default and fallback, a manual selector, Arabic RTL.
- A published Work, a Board card, and (on request) a community skill package.

## When to use

Use when the user wants a cute, collectible Halloween ticket / admission stub for a character or world, especially:

- "Halloween ticket", "万圣节门票", "游园券", "副券", "ticket stub";
- a horizontal ticket illustration with a stamp edge and a tear-off side strip;
- a multi-language keepsake page for one OC.

Do not use for:

- a vertical shattered-glass or boat-and-wake poster — use `oc-shattered-glass-storyboard` / `oc-abyss-wake-poster`;
- a branching game or visual novel — `create-avg` / `game-maker`;
- a chat roleplay or companion — `create-roleplay` / `companion-onboarding`;
- a plain illustration with no web presentation — generate an image only.

## Hard rules

0. **Use the sandbox CLI path.** Every `neta` command is `node /mods/neta/neta …` (`neta` may not be on PATH).
1. **Read the OC before drawing.** Use the world's real character atom, its cover and `## 形象参考`. Never reuse the Pipo demo data on another character. Pick the world's recurring protagonist unless the user names one; when the user says "random", choose by matching Halloween motifs.
2. **No text in any generated image.** No letters, numbers, signage writing, watermark or speech bubble. Everything readable is HTML: the bubble, the stub, the barcode, the chrome. One baked-in word kills the locale switch.
3. **The stub is a designed column, not a picture of a column.** Do not ask the image model to draw the stub. The artwork is the left scene only; the stub is CSS.
4. **Sawtooth first.** The white stamp border is a CSS mask on the whole ticket; the inner paper sits inside it. Do not fake it with a dashed border.
5. **One scene, layered.** The left scene must hold foreground (OC + companion + candy props), midground (pumpkins, ghosts, candles), and background (moon, tree, bats, castle), plus a blank hanging wooden sign with open sky beside it.
6. **Twelve complete locales.** English is default and fallback. Every locale has all 15 keys. No half-translated locale, no `undefined`.
7. **Live type only.** The speech bubble, title, meta, description and barcode are HTML. Arabic switches the document to `dir="rtl"` and mirrors the ticket; Arabic must not receive Latin letter-spacing.
8. **Publish and place.** A source page without a published Work and a Board card is not shipped. Place the **web Work** card, never the raw artwork.

## Pipeline

### 0. Read the OC and the world

```bash
node /mods/neta/neta atom list --type character
node /mods/neta/neta atom get "world/characters/<Name>.md"
node /mods/neta/neta find images "<Name>"
```

Record:

- `name` and 3–5 identity features from the cover and `## 形象参考` (hair, horns/ears, eyes, signature garment, prop);
- the OC's signature colour and 3–4 support colours;
- 1–3 other named characters from the same world with one recognisable prop each;
- 1 small animal companion that fits the world (invent one if the world has none);
- the world name and its existing translations.

### 1. Create the page work

```bash
SLUG="<name>-halloween-ticket"            # kebab-case, unique
WORK="works/web/$SLUG"
node /mods/neta/neta work init web "$WORK" --title "<Name> · Halloween Ticket"
# The CLI may normalize works/web -> works/webs; use the printed workDir.
```

Copy the starter:

```bash
cp templates/index.html templates/style.css templates/app.js "$WORK"/
cp templates/content.example.js "$WORK/content.js"
cp -r templates/fonts "$WORK/fonts"
mkdir -p "$WORK/assets"
```

`content.js` is the only per-OC data file. Replace every demo value.

### 2. Generate the three images

Read `references/art-direction.md` for the full scene prompt and the two sticker prompts.

```bash
# left scene, 3:2, textless
NETA_DEFAULT_IMAGE_MODEL=gpt-image-2 node /mods/neta/neta generate image \
  --work-title "<Name> · Halloween ticket scene" \
  --work-description "<one sentence>" \
  --param size=1536x1024 --param quality=high --param output_format=png \
  --image "world/media/studio/characters/<Name>.png" \
  --image "world/media/studio/characters/<Ally>.png" \
  --prompt "$(cat /tmp/<slug>-scene.txt)"

# transparent chibi portrait for the top of the stub
NETA_DEFAULT_IMAGE_MODEL=gpt-image-2 node /mods/neta/neta generate image \
  --param size=1024x1024 --param quality=high --param output_format=png --param background=transparent \
  --image "world/media/studio/characters/<Name>.png" \
  --prompt "$(cat /tmp/<slug>-head.txt)"

# transparent full-body chibi for the bottom of the stub
NETA_DEFAULT_IMAGE_MODEL=gpt-image-2 node /mods/neta/neta generate image \
  --param size=1024x1024 --param quality=high --param output_format=png --param background=transparent \
  --image "world/media/studio/characters/<Name>.png" \
  --prompt "$(cat /tmp/<slug>-body.txt)"
```

Save and compress:

```bash
curl -sL "<scene mediaUrl>" -o /tmp/scene.png
magick /tmp/scene.png -strip -quality 82 "$WORK/assets/scene.webp"
curl -sL "<head mediaUrl>" -o /tmp/head.png
magick /tmp/head.png -trim +repage -bordercolor none -border 24 -resize 520x520 -strip -quality 90 "$WORK/assets/head.webp"
curl -sL "<body mediaUrl>" -o /tmp/body.png
magick /tmp/body.png -trim +repage -bordercolor none -border 24 -resize 520x520 -strip -quality 90 "$WORK/assets/body.webp"
```

The generated images are **ingredients**. Do not place them on the Board.

If the scene gains text, regenerate once with "no text, no letters, no numbers, no speech bubble" repeated last. If a sticker reads creepy, regenerate with "for a young children's sticker book, rosy cheeks, bright sparkle, absolutely not creepy, no dark shadows".

### 3. Fill `content.js`

```js
window.TICKET = {
  name: "PIPO",
  serial: "NO. 1031 · 013",
  accent: "#b8444f",
  langs: { en: { label: "English", short: "EN", dir: "ltr" }, /* … 12 total */ },
  i18n: {
    en: {
      world: "Sweet Nightmare Park",
      eyebrow: "One night only",
      title: "Halloween Ticket",
      admit: "Admit one",
      holder: "Ticket holder",
      date: "Date",
      gate: "Gate",
      price: "Price",
      priceValue: "One sweet dream",
      desc: "Good for one night of harmless screams and far too much candy.",
      bubble: "Trick or treat — or I'll scream!",
      footer: "Screaming Carousel · No. 13",
      note: "A Halloween keepsake from the park that never quite closes.",
      language: "Language",
      close: "Close"
    }
    // … 11 more locales, all keys present
  }
};
```

Rules:

- `name`, `serial` and `OCT 31` are proper nouns / fixed tokens; they stay identical in every locale.
- `title` is the big stub line. Keep it under ~26 characters in Latin scripts and 10 CJK characters; the CSS handles two lines, but one line is better.
- `bubble` is one short spoken line in the OC's voice, 4–8 words; it must fit two lines at 2.15cqw.
- `desc` is one sentence, 60–95 characters; it must fit three lines at 2.55cqw.
- `accent` colours the brand, the admit badge and the language dot. Read it from the OC.
- The page supports `?lang=<code>` for QA/share; a manual choice is saved in `localStorage`.

### 4. Validate

```bash
node scripts/validate-i18n.mjs "$WORK"
```

Exit 1 means fix `content.js`, not the page. Then open `?qa=1` and confirm every locale reports `stubOverflow: 0` and `titleClip: false`.

### 5. QA

Follow `references/qa.md`. At minimum:

- 1440×900 and 390×844;
- every locale, including Arabic; no title, meta or description overflow;
- the speech bubble sits over empty sky, not over a face;
- the sawtooth edge is continuous on all four sides, and the dashed tear line is visible;
- no page scrollbars, no missing key, no `undefined`;
- the mobile ticket stacks scene over stub and still shows the title, admit badge, meta and barcode.

### 6. Publish and place

```bash
node /mods/neta/neta work publish web "$WORK"

node /mods/neta/.agents/skills/board-ops/scripts/place.mjs \
  --title "<Name> · Halloween Ticket" \
  --work "works/webs/<slug>"
```

The publish returns the share link `https://neta.art/w/<user>/<world>/<slug>`. Verify it with `curl -sI` (200) before calling it live. The thumbnail is generated asynchronously.

If the Board read fails with `unknown property preview`, use the hand-written `neta.work` card patch in `references/publishing.md`.

### 7. Package the skill (optional)

If the user asks for a reusable skill, copy this folder to `.agents/skills-drafts/<skill-name>/`, keep the demo as the worked example, write `SKILL.md` in English even when the world is Chinese, then follow `references/publishing.md` to submit it.

## Content model

```
$WORK/
  index.html
  style.css
  app.js
  content.js            # per-OC data; the only file that changes per character
  fonts/                # Baloo 2 + Nunito, self-hosted
  assets/scene.webp     # generated 3:2 textless scene
  assets/head.webp      # transparent chibi portrait
  assets/body.webp      # transparent chibi full body
```

`index.html` and `style.css` are generic. The ticket is `.ticket` (masked sawtooth, 2.02:1) containing `.scene` (flex 1) and `.stub` (30.5%). The stub is a container-query column: portrait 24.5%, body ~57%, full-body 18.5%. All stub type is sized in `cqw`, so it scales with the ticket instead of the viewport.

`app.js` handles detection, fallback, the menu, `dir="rtl"` and the barcode. Do not bake a language into the HTML.

## Pitfalls

- Text in the artwork kills the locale switch. Keep the scene textless and the bubble HTML.
- Drawing the stub inside the image makes the type tiny and untranslatable. The stub must be CSS.
- Percentage padding on the stub resolves against the ticket width, not the stub width — use `cqw` for the stub's inner padding.
- A bubble placed by eye can cover a face. Place it at `left:27%; top:5.5%; width:27%` over the empty sky, and verify with a screenshot.
- A full-body sticker cropped at the frame edge looks broken. Ask for "full figure with empty margin all around".
- Arabic with letter-spacing breaks the joins. Reset `letter-spacing` under `html[dir="rtl"]` and `:lang(ar)`.
- German and Spanish titles run long. Test them; lower the title size per `:lang()` instead of shrinking the whole stub.
- A hard-coded `/public` path, or a hand-written `preview` block, is not a publish.

## Demo

The shipped example is Pipo from *Sweet Nightmare Park*: a white-haired ram-horned chibi with one crimson spiral eye, a tattered cape and a glowing candy crystal, joined by Bandie with a pumpkin bucket, Reapette with a lollipop and a black cat in a pumpkin hat. Title `万圣夜游园券 / Halloween Ticket`. Twelve locales. It is a demo, not a constraint.