diy-candy-gift-bag

Community@rain/diy-candy-gift-bag
Community skill — not reviewed. It was shared by caramel pudding 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: diy-candy-gift-bag. Run `npx -y @neta-art/neta-search-cli@latest skills use @rain/diy-candy-gift-bag --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 @rain/diy-candy-gift-bag
Summary

Turn your character into a 3D candy gift bag you dress up step by step and share as a web page.

  • Six guided steps: pick your character, shape and colour the bag, add candies, write a card, tie the bow, see the finished bag.
  • Your character appears inside the bag with its background removed, and colours suggested from the character's own look.
  • Tap to add or remove candies, tap the bag to shake them. A full bag politely says no, and sealing needs at least one candy.
  • Write a two-line card, choose paper colour and side, then save the photo of the finished bag or save a draft to reopen later.
  • Works best with a character image that has a clear outline and plain background, such as an original character.
SKILL.md
# DIY candy gift bag

A guided workshop, not a sandbox: six steps, one decision each, a preview that is always live. The finished object is
a 3D bag holding the user's character, with candy, a handwritten card and a tied bow.

## What the user gets

A published web Work. The user can save drafts (each saved bag becomes a "my characters" entry), reopen one, and export
a finished photo.

## Inputs — and when to ask

| Item | Required | Counts as given when | Default |
|---|---|---|---|
| Character image | yes | Attached, or a material cover is named | Ask once, then stop |
| Bag style | no | Named (solid / gradient / shape) | Solid, warm custard yellow |
| Candies | no | Counts or types named | Three of each of the first three kinds |
| Card text / signature | no | Given | Empty card, off |
| Bow colour | no | Named | Cream gold |

Only the character is a stop. Everything else has a default and is editable in the page afterwards.

## The six steps

Keep this order and do not allow skipping ahead:

1. **Character** — upload or pick a saved one; auto-cut the background.
2. **Bag** — solid or two-colour gradient; shape and size presets.
3. **Candy** — tap to add, tap the minus to remove; a full bag refuses more with an inline toast.
4. **Card** — toggle on, choose paper colour, write two lines, pick side (left/right).
5. **Seal** — tie the bow. Sealing is blocked until at least one candy is in the bag; explain why in the toast.
6. **Finished** — the bag closes, confetti, and the export/save actions appear.

Each step has one primary button; its label states the next step, not "next". Back is always available and keeps state.

## Build order

1. **Assets.** Use a GLB bag + bow + candy set if the user has one. If not, build the bag procedurally: a lathed or
   extruded pouch body, a gathered neck, a bow made from two flattened tori and a knot sphere. Keep the whole scene
   under ~120k triangles and under 8 MB of textures.
2. **Stage.** Three.js, perspective camera, portrait framing, soft studio light: one key at 35° up-left, one fill, one
   rim behind the bag. Background is CSS (dots / stripes / gradient / user photo), never a 3D plane.
3. **Upload path.** Downscale to 1400 px long edge. Cut the background with a flood fill from the corners
   (tolerance ≈ 26 per channel, feather 1 px) and keep alpha. If the user's image already has alpha, skip this.
4. **Auto-palette.** Sample the cutout, drop near-white, near-black and low-saturation pixels, cluster the rest into
   two hues, and offer them as the bag's default pair. The user can override. Do not auto-apply a gradient the user
   cannot undo.
5. **Placement.** Put the cutout inside the bag with its feet at 88% of the bag's inner height, width capped at 70% of
   the bag's inner width, and a slight forward tilt. Clip the bag's front panel over the character so the paper reads
   as in front of the body.
6. **Candy physics.** No rigid-body solver. Give each candy a target slot, spring toward it with damping, and add a
   small random spin. When the bag is shaken (a tap on the bag), apply one impulse and let the springs settle.
7. **Card.** Draw on a canvas at **1024 × 726**: paper colour, 2600 grain specks at alpha ≤ 0.05, double frame, then
   the two lines centred. Load the handwriting font with `document.fonts.load` and a 2.5 s timeout; fall back to a
   system cursive face rather than shipping a broken layout.
8. **Export.** Compose the WebGL canvas + background + name strip into one image at 2× the stage size, then download
   as PNG. Use `preserveDrawingBuffer` or render once more immediately before capture — otherwise the canvas is
   blank on some phones.
9. **Drafts.** Keep up to 20 saved bags in IndexedDB (scene state + cutout blob + thumbnail). One entry per bag, with
   the character's name and the date. Reopening restores every step.
10. **Publish** with `neta work init web`, then `neta work publish web`.

## Performance budget (in-app containers)

Cap devicePixelRatio at 2 and total pixels at 2 MP in embedded webviews; when frame time exceeds 22 ms for 30 frames,
step DPR 2 → 1.5 → 1. Keep one texture atlas for candies. Pause the render loop when the tab is hidden.

## Fallbacks

- WebGL unavailable: show a flat 2D bag illustration with the same six steps and the same card export. Say so once.
- No GLB: procedural bag as above; never block the build on a model file.
- Font fails to load: system cursive; the card still exports.
- Storage full: keep the in-memory draft and tell the user only the last bag can be kept.

## Gotchas

- The character must not poke through the bag's back panel. Render order: back panel → character → candies → front
  panel → bow.
- Tie the bow only after the bag mouth closes; animating both at once looks like a bug.
- Keep the seal button disabled with a reason, not silently inert.
- Export on iOS needs a user gesture; never auto-download on load.

## Verify

`node scripts/verify.mjs <work-dir>` checks: entry, no remote assets, the six step ids, the seal gate, the card canvas
size, the export function, and the asset budget.

Then walk the six steps with a fresh image, try sealing with zero candy, reopen a draft, and export one photo. Report
what you ran.

## Deliver

Publish the Work, put its card on the Board, and hand it over with an interaction-components card whose target is
the Work — the id comes from the publish output.

## Out of scope

No world-setting changes, no deletion of existing files, no real payment or shipping, and no generated character art
unless asked.

## Language

Reply in the user's language, whatever language this file is in — every message, the final handover included. Page
labels, step names and toasts follow the user's language through a small locale map; the card keeps whatever the user
typed.