SOURCE / PINNED RELEASE
Made of little things.
Black Site Map Editor
- Release
- 32a57733b7e9…
- Author-recorded commit
- 3f54890f542f…
- License
- LICENSE
- Author’s source reference
- nostr://npub1ye5ptcxfyyxl5vjvdjar2ua3f0hynkjzpx552mu5snj3qmx5pzjscpknpr/wss%3A%2F%2Fgit.shakespeare.diy%2F/black-site-map-editor
Archive hash verified: 7a4b1abbac7db5b0…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
# Black Site editor brief
Purpose: create, edit, manage and remix Black Site v1 maps, preserving every field of the game schema.
Authority: identity supplies the connected viewer and live account changes; OUTBOX discovers kind 35858 maps and kind 10063 server lists, publishes native map events and kind 5 deletions; RESOURCE downloads and verifies JSON bytes; UPLOAD sends exact JSON blobs to Blossom and reports completion. STORAGE optionally saves drafts scoped by viewer. No relay escape hatch, direct network, signing or shell implementation.
Hard requirements: identity, outbox, resource, upload for published-map management. Offline authoring remains usable when a preview harness supplies incomplete methods. Optional storage failures must be visible; theme is unused. Login is performed in the host, never by borrowing the creator key.
Flows: new map; built-in template; own-map discovery/edit/update; public discovery/remix; complete tile/layer editing; plain-language object controls; undo/redo; playable route validation; save/reopen drafts; exact-byte upload and publish/retry; owner-only deletion; a step-by-step Help tutorial in vertical tabs (Help button or F1; opens once automatically for new players when storage is available, and never over an incoming map request). Existing remixes retain root, parent and author credit on updates. Account changes cancel stale loading/publishing UI and never attach another account's map to the new account.
Visual direction: preserve Black Site's tactical terminal: dark olive ground, subtle lime grid, lime selection, gold objectives, red guards, squared thin borders and Bahnschrift/Arial Narrow typography. The map dominates the workspace; collapsible terrain, structure, cover and mission tool groups and inspector belong to the same game HUD. App-owned colors remain identical in both host themes and without theme support.
Layout: desktop map workspace with tools and selected-object inspector; metadata, appearance, deployment options, map files and sharing live in a dedicated Map Settings modal. Phone tabs switch between map/tools/details/library; touch targets 44px. Canvas supports tile placement and rectangle drags, pan and zoom, plus explicit zoom/fit controls. At 200×160 show a useful enlarge-frame notice (editor needs 280×240); keep document intact on resize. Check 320×560, 900×600, full screen, touch portrait/landscape. The Help modal keeps vertical step tabs at every size; below 600px they collapse to a numbered rail.
Player-facing language: map authors do not need to know the map format. Show named objects, terrain, mission settings, guard options and deployment controls. Hide internal identifiers, raw documents, array notation, protocol names, hashes, event receipts and relay/server fields. Keep validation, format compatibility, signatures and verified upload receipts inside the implementation. Explain problems through the affected object or action and a practical next step. Import/export, if provided, uses a map file rather than exposing a text editor.
Terminology: the editor makes **maps**, one playable layout each (kind 35858), and calls them "map" everywhere. "Mission" names only the objective tool group (insertion, extraction, guards, loot), which matches the game's "mission" for playing one map. Do not use "operation". Campaigns, ordered lists of maps with rules (kind 35859), belong to the game and are not authored here.
Integration: the adjacent soyLI source host supports native map publication and retained map-opening requests. The adjacent game can discover and play authored maps. This source integration is verified locally; public deployment is a separate release step.
Schema attribution: reference game/map contract from adjacent Black Site map-schema project, CC-BY-NC-SA-4.0; retain attribution for copied contract and templates.
## Map-opening intents
Use the official published SDK 0.29.0 receiver `intent.onDelivery` as an optional domain. Advertise exact `napplet:black-site/map-edit`, `napplet:black-site/map-remix`, `napplet:black-site/map-open` and `napplet:black-site/map-new`; accept canonical kind35858 addresses with public relay hints or validated local JSON for new-map handoffs. Queue published requests until identity connects; ask before replacing unsaved work; reject foreign-owner edits and use explicit remix. Delivery never authorizes signing or publishing. Close the receiver on teardown and ignore stale account/workspace loads. The adjacent soyLI source host implements routing; the game-to-editor handoff is verified through the real host. See map-intents.md.
## Keyboard shortcuts
NAP-KEYS is optional. `src/shortcuts.ts` registers every editor action through `keys.register` with a stable `feature.action` id (`map.*`, `edit.*`, `selection.*`, `view.*`, `tool.*`, `help.shortcuts`) and a default-key hint in the shim's `Alt+Ctrl+Meta+Shift+key` format. When the host assigns a binding, that binding replaces the built-in key: the shim delivers the binding, or the host sends the action. When the domain is missing, registration fails, or the host leaves an action unbound, the editor handles the built-in key itself (Ctrl also matches Cmd). It skips keys the shim has already handled with preventDefault. No action fires while its registration is pending, so an action can't be delivered twice. Keystrokes in text fields stay in those fields. Actions don't run while the editor is busy or a dialog is open; the shortcut help (`?`, or the Keys button) is the only exception. Every action still has a button. Button titles and `aria-keyshortcuts` show the binding that's actually active. The Keys button is hidden on touch-only devices. All registrations are closed on `pagehide`.
Map Settings groups controls into five tabs: Map (name, briefing and size), Appearance (terrain and colors), Gameplay (extra scenery and enemies), Files (open/download) and Sharing (notes, tags and remix). Tabs support arrow keys/Home/End, retain values when switching, and keep Done reachable while content scrolls.
Icon direction: a lime folded tactical map with a gold drafting pencil on dark olive. The squared silhouette matches the editor HUD and stays recognizable at favicon size. The listing uses the 512px PNG; browser icons use the same artwork. These app-owned colors do not follow host themes.
## Full-frame map browser
Maps opens a full-frame browser while retaining the editor workspace. My maps shows
owned publications; Following loads the viewer's latest kind 3 contacts and queries
those authors; Global queries maps without an author filter; Templates remains a
local starting point. Signed-out users retain Global and Templates. OUTBOX owns all
reads, including contacts, kind 1111 NIP-22 comments, kind 7 reactions and direct
remix discovery. Comments can be published explicitly through OUTBOX. No new hard
or optional domains, direct network calls, or relay escape hatches are introduced.
Preserve the tactical olive/lime visual language and app-owned theme. Wide frames
use a generous preview grid and two-column details; phones use one scrolling column
and wrapped collection controls. The existing editor minimum remains 280×240.
Cards load raster covers through RESOURCE, or render verified map bytes into a local
canvas. Lazy previews limit simultaneous downloads to four and release object URLs.
Details show briefing, creator, date, notes, tags, reactions, comments, parent/root
links, direct remixes, and owner edit/delete plus signed-in remix actions. Async
results are discarded after selection, account or view changes. Activity explicitly
reports bounded relay coverage; zero results are not a claim of network-wide absence.
The connected viewer's display name and avatar appear at the upper right of both
editor and browser. Public profile reads use OUTBOX kind 0; avatar bytes use
RESOURCE with raster MIME and size checks, and account changes revoke image URLs.
Missing profiles/images retain a readable account and initials fallback.
Publishing opens a dedicated progress dialog after confirmation. It shows prepare,
upload and publication stages with indeterminate progress while the host works,
then retains the success or failure result until acknowledged. Failures include the
original service error under an expandable disclosure, retry using the retained
verified upload, and a download-backup action. Draft-backup failures remain warnings
and never turn a successful public publication into a failed one. Account changes
finish with an explicit check-your-maps message instead of leaving progress stuck.
Map identity is the NIP-01 address `35858:<author pubkey>:<d-tag>`; the JSON
map `id` supplies only its `d` component. Different authors may publish the same
`d` without conflict. First-publication lookups are best effort: failed or
incomplete reads never imply a collision or prevent a new publication. An observed
map at the viewer's exact coordinates still requires opening that map for an
explicit update. Opened-map updates retain the existing stale-revision checks.
