relationship-network

Verified@yijun/relationship-network
Use it in Cohub

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

Use the skill: relationship-network. Run `npx -y @neta-art/neta-search-cli@latest skills use @yijun/relationship-network --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.
Use in Neta Studio Open it in Neta Studio and see what people made with it.
Install from a terminal
npx -y @neta-art/neta-search-cli@latest skills use @yijun/relationship-network
Summary

Turn your world's characters into a draggable 3D map of who loves, protects, schemes against or is related to whom.

  • Get an interactive web page you can publish, with 8 to 16 of your characters linked by labeled bonds such as love, rivalry or family.
  • Drag to spin the map, scroll to zoom, and click a character to light up their direct ties; a 2D view is one tap away.
  • Also includes chapters, a table of how each pair feels about each other, a bond test, character cards and a search box.
  • Works on phones too, and every view can be shared with a link.
  • Shines with a cast of characters who already have portraits and notes about each other; you can restyle it to match your world's look afterwards.
SKILL.md
# Relationship Network

Build an interactive character-to-character relationship map from this world's characters, publish it as a web Work, and hand over the Work card.

**Language:** write every name, description, relationship label, chapter label and the page title in the language of **the user's message**, and set `meta.lang` to it (`zh` `en` `ja` `es` `pt` `ru`; the page UI has these six built in, other languages fall back to English UI). The page has one language only — no language switch. Reply to the user in their language.

`<skill-dir>` is the folder this SKILL.md sits in (the directory `skills use` printed).

## When to use / when not

Use when the user wants to see how the characters of this world relate: a relationship map, network, CP chart or bond chart they can explore.

Do not use for: a single static image or poster of relationships (say this skill builds an interactive web page, and stop); maps of places, timelines or factions without characters (say this skill maps characters only, and stop).

## Inputs

| Item | Required | Counts as given when |
|---|---|---|
| Characters | yes | The world has characters in `world/characters/`, or the user names or describes the characters. "Everyone" / no names counts as given when the world has characters (pick 8–16 of the most connected). |
| Which characters | no | Names the user lists. Default: 8–16 characters (never more than 20). |
| World skin | no | Only after delivery: the user says yes to the skin you offered, or asks to restyle / theme / match the world's look. |
| Focus / storylines | no | Groupings the user mentions become `chapters`. Default: 3–5 chapters picked from the story when there are 10+ characters. |

Missing characters (empty world, nothing described) → ask once who should be in the network, then stop. All given → build to delivery without asking.

## Steps

1. **Read the world**: `node /mods/neta/neta atom list --type character` (`atom get <id>` for details).

2. **Create the Work, import characters and portraits**
   ```bash
   cd /workspace
   node /mods/neta/neta work init web works/web/<slug>-network --title "<title>"
   REF=<the data.workDir it printed>      # may be normalised to works/webs/… — use what it printed
   python3 <skill-dir>/scripts/import_world.py --work "$REF" --lang <user language> [--only Name1,Name2]
   ```
   Reads only `world/characters/` and writes the skeleton `$REF/graph.json` (id, name, role, bio, and each character's relationship notes in `notes`). Portraits are each character's own cover, cropped into `$REF/assets/portraits/`. Look at the contact sheet it prints (`/tmp/<work>-portraits.png`); if a face was missed, add `"avatarCrop": {"x": .5, "y": .3, "size": .5}` (face centre and square size, as fractions) to that character and run `--recrop <id>`. Leave `$REF/meta.json` untouched.

3. **Write the relationships**: edit `$REF/graph.json` following `<skill-dir>/reference/schema.md` — `meta` (title / subtitle / center), `groups`, `relationTypes` (4–8), `relations` (2–6 per character), optional `chapters`. Give each `label` a concrete, story-specific name; make the two `affinity` directions differ where the story does; use only what the world or user says — never invent plot. Delete every `notes` field when done.

4. **Build**: `python3 <skill-dir>/scripts/build.py "$REF"`. It validates the data and writes `$REF/index.html` and `$REF/neta/`. Any `✗` must be fixed (for example a location used as a character node). That is the whole check — no screenshots needed.

5. **Publish**: `node /mods/neta/neta work publish web "$REF" --thumbnail-wait 4000`. On `world_slug_required`, follow the printed hint once and retry.

## Deliver

One route: a **web Work**, registered with `neta work init web` / `neta work publish web` as above.

Reply in the user's language and describe the map in the world's own terms — who stands at the centre, which bonds and fault lines it traces. Mention characters without a portrait in one clause. No file paths or counts.

Hand over through the `interaction-components` skill as a full `<interaction-json>` link block on its own line: `{"type": "work", "workId": "<preview.workId from $REF/meta.json>"}` — never a made-up id, never a `studio-route`. Then close following the **next-steps** skill, with this as the first suggestion: **dress the map in this world's own look** — one concrete line naming the look you would pick (e.g. "neon on black for this rain-soaked city"). Do not apply it until the user says yes.

## Re-skin (next step)

When the user accepts the skin or asks to restyle the map:

1. **Read the world's look**: `node /mods/neta/neta config get` (style), the world description, a few character covers.
2. **Write `meta.theme`** in `$REF/graph.json` — only these fields (format in `reference/schema.md`):
   `name`, `bg`, `text`, `accent` (three `#RRGGBB` colours), `font` (`sans` | `serif` | `mono`), `texture` (`dots` | `grid` | `none`).
   Pick them from this world, not a generic preset: e.g. cyberpunk → near-black, cold white, neon accent, `mono`, `grid`; ink-wash / xianxia → rice paper, ink black, vermilion, `serif`, `none`; gothic → deep plum, parchment, candle gold, `serif`. Relationship and faction colours stay as they are.
3. **Build and publish** the same `$REF` again (steps 4–5). `build.py` derives every other colour and rejects low contrast — on `✗`, adjust the three colours and rebuild.
4. **Reply** in one sentence naming the look, and hand over the same Work card.

To go back to the default NETA look, delete `meta.theme` and rebuild.

## Out of scope

- Character nodes only. Locations, items, events and factions never become nodes; they may only appear in descriptions or relationship labels.
- Portraits come only from the characters' own covers or image URLs the user gives. No image generation, no uploads; a character without a portrait gets a pixel placeholder.
- Do not change world settings, and do not delete files that existed before the run.
- Do not modify characters, memory, installed scripts or existing Works. Edit only `$REF/graph.json` and `$REF/assets/portraits/`; `index.html` and `neta/` are generated by the build. Never edit `<skill-dir>/template/`.
- Skins change only `meta.theme`; never write CSS, background images or fonts into the page.
- Nothing beyond the one Work.

## When to stop

- No characters in the world and none described: ask once who should be in the network, then stop.
- Asked for a static image, a poster or a non-character map: say this skill builds an interactive character relationship page, and stop.
- `build.py` reports `✗` you cannot resolve from the world's own information: tell the user what is missing and stop — do not make it up.
- Never hand over without publishing, or with a card that is not the published Work.

## Page reference

- Network view defaults to a 3D orbit: drag to orbit with damping, scroll to zoom, Shift / middle-drag to pan, auto-rotates after 10 s idle, the camera follows the selected character; bottom-right toggles 2D. Hover / select lights up first-degree ties and half-lights second-degree ones.
- Mobile: swipe sideways to orbit, pinch to zoom; character and bond cards open as a bottom sheet with the map still visible; narrow screens drop the subtitle, search and type filters.
- Also: relationship-type filters, chapters (a dropdown), affinity matrix, bond test, character cards, bond cards, highlights, "draw a pair", search, and shareable links (`#c= #r= #v= #m= #ch=`).
- Visuals use NETA Core Tokens (light canvas with dot grid, pixel keys and badges); `meta.theme` re-colours them per world. Maintainers refresh tokens with `scripts/sync_tokens.sh`.