mirror of
https://github.com/PR0M3TH3AN/Artstr-Studio.git
synced 2026-10-27 08:40:39 +00:00
docs: add BOOK_DESIGNER_TUTORIAL.md
Hands-on end-to-end walkthrough for the Book Designer feature —
setup, starting a book (templates / deck-import / scratch), Document
settings, masters + text-frame, Pages overview, designed-page editor,
chapter editor (full feature exercise: tables, task lists, footnotes,
xrefs, {toc}, {index}, ^[term]), cover view, visibility chip,
publishing order, resolver behaviour, Reader Mode, embed integration,
PDF export modal, tokens reference, edge cases to probe, and a
codebase map.
Companion to docs/BOOK_DESIGNER_FEATURE.md (the spec).
Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
1 parent
0651a3e4fc
commit
f50d92043c
1 file changed
+376
@@ -0,0 +1,376 @@
|
||||
# Book Designer — End-to-End Tutorial
|
||||
|
||||
This is the hands-on walkthrough for authoring, publishing, sharing,
|
||||
and exporting a book in Artstr Studio. For the full spec see
|
||||
`BOOK_DESIGNER_FEATURE.md`.
|
||||
|
||||
---
|
||||
|
||||
## 0. Setup (one-time)
|
||||
|
||||
- Sign in with a Nostr extension (top-right). For private-publish testing the
|
||||
extension needs NIP-44 or NIP-04 (most modern extensions do).
|
||||
- In **Project Metadata** (left sidebar, any mode) set a **Title** and
|
||||
**Category**. The book uses these for the manifest's d-tag and tag set.
|
||||
|
||||
---
|
||||
|
||||
## 1. Start a new book
|
||||
|
||||
In the **Template** tab on the left, pick the **Book** entry. The canvas
|
||||
switches to the Pages overview.
|
||||
|
||||
Three ways to start:
|
||||
|
||||
- **Starter template** — when Pages overview is empty, four cards appear
|
||||
(US Trade 6×9 / A5 / A4 / Square 8×8). Click one. The book is seeded with
|
||||
a default master + text-frame, a starter chapter, and a "Title page"
|
||||
designed entry.
|
||||
- **Convert from deck** — if you have an existing deck (Deck mode →
|
||||
slides), click **→ Convert to book** in the deck-sorter toolbar. *Or* a
|
||||
"Convert deck to book" card appears on the empty Pages overview if a
|
||||
deck exists. Each slide becomes one designed page (letterbox-fit into the
|
||||
trim).
|
||||
- **From scratch** — skip the starter cards. Use `+ Add page`,
|
||||
`+ Add chapter`, or open `Document settings…`.
|
||||
|
||||
---
|
||||
|
||||
## 2. Document settings
|
||||
|
||||
Open via the book sidebar → **Document settings…**.
|
||||
|
||||
- **Book size**: preset (US Trade / US Letter / A5 / A4 / Square) or
|
||||
**Custom** to enter arbitrary trim/bleed/paper-thickness.
|
||||
- **Spine width**: derived from page count × paper thickness by default,
|
||||
or toggle off to enter manually.
|
||||
- **Cover layout**: include spine? include back?
|
||||
- **Page numbering**: enabled / startAt / firstNumberedPage / format
|
||||
(use `{n}` or `Page {n}` etc).
|
||||
- **Typography** (expand the `<details>` block): override fonts / sizes /
|
||||
weights / colours per element — body, h1–h6, blockquote, codeBlock,
|
||||
inlineCode, link, list, hr. **Reset to defaults** restores the v1
|
||||
stylesheet.
|
||||
|
||||
---
|
||||
|
||||
## 3. Masters
|
||||
|
||||
Open via the book sidebar → **Manage masters…**.
|
||||
|
||||
A master is a reusable underlay applied beneath every page that uses it.
|
||||
The starter template gives you one ("Body pages") with a text-frame
|
||||
already added.
|
||||
|
||||
- Click a master row's **Edit** → master-edit mode. The canvas now binds
|
||||
to `book-master:<id>`. Add headers, page-numbers, etc.
|
||||
- Use the **+ Text frame** button (visible only in master-edit) to add
|
||||
the reflow target if missing.
|
||||
- Header / page-number text layers can use **tokens** — literal in the
|
||||
master, resolved at render time per page:
|
||||
- `{page-number}`, `{page-count}`, `{physical-page-count}`
|
||||
- `{book-title}`, `{book-author}`
|
||||
- `{chapter-title}`, `{chapter-number}`
|
||||
- Click **← Back to masters** to leave the master.
|
||||
|
||||
---
|
||||
|
||||
## 4. Pages overview
|
||||
|
||||
Each tile is one manifest entry — a designed page or a reflow chapter
|
||||
segment.
|
||||
|
||||
Tile hover reveals actions (top-right):
|
||||
- 📄 proof PDF (just this entry)
|
||||
- ⎘ duplicate
|
||||
- × delete
|
||||
- master-picker dropdown (per-tile override)
|
||||
|
||||
Toolbar buttons:
|
||||
- `+ Add page` — blank designed page.
|
||||
- `+ Add 10 pages` — bulk.
|
||||
- `+ Add chapter` — reflow entry; opens the chapter editor immediately.
|
||||
- `+ Import page` — paste an `naddr` / `nevent` to another author's
|
||||
`casewrap-page` event. Imports as a `ref:`-only entry; layers paint
|
||||
via the resolver.
|
||||
- `▶ Read` — Reader Mode.
|
||||
- `Export PDF…` — export modal.
|
||||
|
||||
Drag tiles to reorder.
|
||||
|
||||
---
|
||||
|
||||
## 5. Designed page editor
|
||||
|
||||
Click a designed-page tile → opens the canvas. Top bar shows
|
||||
**← Back to Pages**, **← / →** prev/next, **Publish**, **📄 Proof PDF**,
|
||||
**⚡ Free / N sats**.
|
||||
|
||||
- Add layers like any other Artstr canvas — text, shape, image, QR,
|
||||
pixel-art, linked design.
|
||||
- Master layers render underneath at 55 % opacity (non-interactive while
|
||||
page-editing).
|
||||
- Tokens in *master* layers resolve to this page's context; the same
|
||||
tokens in this page's own text layers stay literal.
|
||||
|
||||
---
|
||||
|
||||
## 6. Chapter editor (reflow)
|
||||
|
||||
Click a chapter tile → markdown-on-left, preview-on-right.
|
||||
|
||||
The textarea upgrades to **CodeMirror** with markdown syntax
|
||||
highlighting + smart Enter (auto-continues list bullets, breaks out of
|
||||
the list on an empty item).
|
||||
|
||||
### Try every feature in one chapter
|
||||
|
||||
```markdown
|
||||
# Chapter Title
|
||||
|
||||
A paragraph. **Bold**, *italic*, `inline code`.
|
||||
|
||||
## Sub-heading
|
||||
|
||||
Cross-ref: see [the intro](#chapter-1) and [the index](#index).
|
||||
|
||||
A ^[GFM table] example:
|
||||
|
||||
| Col 1 | Col 2 |
|
||||
|-------|-------|
|
||||
| a | b |
|
||||
|
||||
A task list:
|
||||
|
||||
- [ ] todo
|
||||
- [x] done
|
||||
- nested item
|
||||
|
||||
A footnote ref[^1] in the middle of a sentence.
|
||||
|
||||
[^1]: This is a footnote definition.
|
||||
|
||||
{toc}
|
||||
|
||||
{index}
|
||||
```
|
||||
|
||||
What this exercises:
|
||||
- `{toc}` → renders as a heading list with page numbers.
|
||||
- `{index}` → sorted list of every `^[term]` marker in the book.
|
||||
- `^[term]` → invisible in body; registers in the index.
|
||||
- `[^N]` + `[^N]: def` → superscripted ref + "Footnotes" section
|
||||
appended to the chapter.
|
||||
- `[text](#chapter-3)` / `[text](#some-heading)` → gets `(p. 12)`
|
||||
appended.
|
||||
- GFM tables, task lists, nested lists all paginate.
|
||||
|
||||
### Chapter source-bar buttons
|
||||
|
||||
- **Import from Nostr** — paste an `naddr` / `nevent` / `note` / hex
|
||||
pointing at a NIP-23 (or encrypted) article; pulls into
|
||||
`chapterMarkdown`.
|
||||
- **Publish chapter** — mints a `kind-30023` (public) or `kind-30078`
|
||||
encrypted (private) article event under `chapter:<slug>` or
|
||||
`book-chapter:<entry-id>`. Re-publishes replace in place.
|
||||
- **↻ Refresh** — re-fetches a linked chapter (live or pinned).
|
||||
- **Pin to current** / **Set to live** — freezes a specific event id
|
||||
vs follows the d-tag.
|
||||
- **Unlink** — disconnects the textRef.
|
||||
- **📄 Proof PDF** — exports just this chapter's paginated pages.
|
||||
|
||||
### Readouts
|
||||
|
||||
Top right of the chapter editor shows word count + paginated page count
|
||||
+ first warning ("Block too tall for the text-frame", "Long word
|
||||
doesn't fit", etc). If you see a warning, your text-frame is too narrow
|
||||
or your prose has a word longer than a column.
|
||||
|
||||
---
|
||||
|
||||
## 7. Cover view
|
||||
|
||||
Pages overview → **Cover** tab.
|
||||
|
||||
- Spec summary + spread preview (back / spine / front panels).
|
||||
- **Edit cover** → canvas widens to the full spread. Layers land on
|
||||
`book-cover-front` by default; the layer-target dropdown switches
|
||||
between **Front cover / Spine / Back cover**.
|
||||
- **Publish cover** (top-bar) → `kind-30078` with `role:'cover-spread'`.
|
||||
|
||||
---
|
||||
|
||||
## 8. Visibility chip
|
||||
|
||||
Bottom of the book sidebar. Two states:
|
||||
|
||||
- **Public** (default) — every event publishes plain-text.
|
||||
- **🔒 Private** — manifest + every sidecar publish goes through the
|
||||
encrypted envelope (AES-256-GCM, with the AES key NIP-44/NIP-04-wrapped
|
||||
to *your own* pubkey only). The chip is disabled if your extension
|
||||
lacks encryption capability. Publish-buttons show 🔒 to make this
|
||||
visible from inside any editor.
|
||||
|
||||
---
|
||||
|
||||
## 9. Publishing flow
|
||||
|
||||
Per-surface publishes are **independent** — you can publish a single
|
||||
page without touching the manifest. To make the whole book discoverable
|
||||
as one event, also publish the manifest.
|
||||
|
||||
**Recommended order:**
|
||||
|
||||
1. Open each chapter → **Publish chapter**.
|
||||
2. Open each designed page → **Publish page**.
|
||||
3. Open the cover → **Publish cover**.
|
||||
4. Manage masters → publish each master via **Edit** → top-bar
|
||||
**Publish master**.
|
||||
5. **Publish** in the top app bar → publishes the `casewrap-book`
|
||||
manifest with `link` tags pointing at every sidecar.
|
||||
|
||||
The book sidebar shows **⚠ Manifest has unsaved changes** when any
|
||||
spec / order / list change diverges from the last published manifest.
|
||||
|
||||
---
|
||||
|
||||
## 10. Resolver (on re-open)
|
||||
|
||||
When you reload the page or open the book on another device:
|
||||
|
||||
- Autosave restores `state.book` from local storage.
|
||||
- The resolver fetches every referenced page / master / cover / chapter
|
||||
from your relays.
|
||||
- Cached events come from `localStorage` first (warm re-opens paint
|
||||
instantly; cap 2 MB total content, LRU evicted).
|
||||
- A background probe checks each ref for a newer upstream version →
|
||||
tiles get a yellow **↑ Update** chip; click to apply.
|
||||
- Force-refresh: book sidebar → **↻ Refresh from Nostr**.
|
||||
|
||||
---
|
||||
|
||||
## 11. Reader Mode
|
||||
|
||||
Pages overview → **▶ Read**.
|
||||
|
||||
- Click left half of the page = back, right half = forward.
|
||||
- Keyboard:
|
||||
- **← / →** flip
|
||||
- **Space / PageDown** advance
|
||||
- **PageUp** back
|
||||
- **Home / End** first / last
|
||||
- **Esc** exits
|
||||
- **☰ TOC** toggles the chapter-heading sidebar.
|
||||
- Page counter + progress bar in the footer.
|
||||
- Pages cache as you flip; forward flips prefetch the next two.
|
||||
|
||||
---
|
||||
|
||||
## 12. Embed (share publicly)
|
||||
|
||||
Once the manifest is publicly published, the resulting `naddr` works in
|
||||
the embed iframe:
|
||||
|
||||
```html
|
||||
<iframe
|
||||
src="https://your-host/#/embed/<naddr-here>"
|
||||
width="600" height="900"></iframe>
|
||||
```
|
||||
|
||||
URL params:
|
||||
- `?page=N` — deep-link to a starting page (1-based)
|
||||
- `?controls=0` — hide prev/next/fullscreen
|
||||
- `?attr=0` — hide the author chip
|
||||
- `?open=0` — hide the "Open in Artstr ↗" link
|
||||
|
||||
The embed renders a cut-down Reader Mode (no TOC).
|
||||
|
||||
---
|
||||
|
||||
## 13. PDF export
|
||||
|
||||
Pages overview → **Export PDF…** opens the modal:
|
||||
|
||||
- **Pages**: All, custom range (from–to), or current.
|
||||
- **Include cover spread**: yes/no.
|
||||
- **Include bleed**: extends each PDF page to trim + 2×bleed (centered).
|
||||
- **Crop marks**: L-shaped marks at each trim corner (printer guidance).
|
||||
- **Output**: single file vs `<name>-interior.pdf` + `<name>-cover.pdf`
|
||||
split.
|
||||
- **Filename pattern**.
|
||||
|
||||
Reflowed prose using **Georgia / Times / Helvetica / Arial / Courier /
|
||||
monospace** families emits as real PDF text (vector, selectable,
|
||||
searchable). Other fonts fall back to vector raster, and the warning
|
||||
summary lists which families fell back.
|
||||
|
||||
**Proof one page** (📄 button on any tile or in any editor toolbar) →
|
||||
one-click PDF of just that entry. No modal.
|
||||
|
||||
---
|
||||
|
||||
## 14. Tokens reference
|
||||
|
||||
Resolve at render time using the manifest's context.
|
||||
|
||||
| Token | Where it resolves |
|
||||
|-------------------------|-----------------------------------------------------------|
|
||||
| `{page-number}` | This page's number under `spec.pageNumbering` rules. |
|
||||
| `{page-count}` | Total numbered pages in the book. |
|
||||
| `{physical-page-count}` | Total physical pages (including skipped-number entries). |
|
||||
| `{book-title}` | `state.meta.title`. |
|
||||
| `{book-author}` | Cached profile display name, falling back to short npub. |
|
||||
| `{chapter-title}` | The chapter this page belongs to. |
|
||||
| `{chapter-number}` | The chapter's ordinal. |
|
||||
| `{toc}` *(standalone)* | Auto-generated TOC with page numbers. |
|
||||
| `{index}` *(standalone)*| Auto-generated alphabetical index with page numbers. |
|
||||
|
||||
Inline markers (in chapter markdown):
|
||||
- `[^N]` … `[^N]: definition` → footnote ref + chapter-end definition.
|
||||
- `^[term]` → invisible index marker; appears in `{index}`.
|
||||
- `[text](#anchor)` → cross-reference; rewritten to `[text (p. N)]`.
|
||||
|
||||
---
|
||||
|
||||
## 15. Edge cases worth probing
|
||||
|
||||
- **Private round-trip** — switch to 🔒 Private, publish a chapter,
|
||||
reload the page. The resolver should decrypt + repaint.
|
||||
- **Cross-device** — publish the manifest publicly, paste the `naddr`
|
||||
into the embed route on a different browser → it should resolve and
|
||||
render.
|
||||
- **Spec change → spine shift** — open Document settings, change paper
|
||||
thickness or page count, look at the cover panel — spine width
|
||||
should re-derive immediately.
|
||||
- **TOC accuracy** — TOC page numbers are computed pre-expansion
|
||||
(chapter-start granularity). Expect a 1–2 page offset for the TOC
|
||||
chapter itself once expanded.
|
||||
- **Reflow overflow** — drop a `# Heading` near the end of a chapter
|
||||
that doesn't have room. The `keepWithNext` rule should push it to
|
||||
the next page.
|
||||
- **Imported chapter from someone else** — import an existing NIP-23
|
||||
article, then click **Publish chapter** — should confirm before
|
||||
clobbering and mint your own d-tag.
|
||||
- **Token resolution** — put `{page-number} of {page-count}` in a
|
||||
master text layer; verify the rendered numbers update as you add /
|
||||
remove pages.
|
||||
|
||||
---
|
||||
|
||||
## 16. Where to find things in the codebase
|
||||
|
||||
Single file: `src/index.html`.
|
||||
|
||||
- Pagination engine: `function paginateChapter`
|
||||
- Reader Mode: `function openBookReader`
|
||||
- PDF export: `async function exportBookToPdf`
|
||||
- Resolver: `async function resolveBookSidecars`
|
||||
- Disk cache: `BOOK_SIDECAR_CACHE_KEY`
|
||||
- Manifest payload: `function bookManifestPayload`
|
||||
- Token substitution: `function substituteBookTokens`
|
||||
- TOC builder: `function _computeBookTocEntries`
|
||||
- Index builder: `function _computeBookIndexEntries`
|
||||
- Cross-refs: `function _computeBookSlugToPageMap`
|
||||
- Footnotes: `function _processBookFootnotes`
|
||||
|
||||
Spec: `docs/BOOK_DESIGNER_FEATURE.md`.
|
||||
Reference in new issue
Block a user