mirror of
https://github.com/PR0M3TH3AN/Artstr-Studio.git
synced 2026-11-08 06:30:08 +00:00
docs: publishing tiers + zaps + NWC + JPEG/PDF fallback
Adds a "Publishing & payments" group covering the three tiers, the
Lightning plumbing, and how to wire a wallet up:
- publishing.md — Overview of Public / Private / Premium
with a comparison table; how tipping vs
unlocking differs; replaceability +
republish-vs-fork.
- publishing-public.md — Default tier. Event shape, tag layout,
discoverability, edit-vs-fork.
- publishing-private.md — End-to-end encrypted to self via NIP-44
/ NIP-04. AES-256-GCM pipeline, what stays
visible (pubkey, kind, d-tag), multi-
device decrypt via "Mine" tab, caveats
(no multi-recipient envelopes in v1).
- publishing-premium.md — Zap-gated soft-gate publishing. Soft-gate
key derivation, watermarked preview,
zap-split tags (creator + platform),
buyer unlock flow, My Purchases vault,
honest framing about soft-gate limits.
- zaps.md — NIP-57 lightning payments. Tipping vs
unlocking. How to receive zaps (set
lud16 on profile). Fallback flow without
NWC (BOLT11 + QR + external wallet).
- nwc.md — Nostr Wallet Connect (NIP-47) setup.
CoinOS quickstart, supported wallets,
multi-device sync via NIP-44 encrypted
event, test-connection button, security
model (treat URI like a password + set a
budget).
Plus a "Why JPEG sometimes routes through PDF" section added to
panel-print-save.md, explaining the three fallback cases (CORS-
blocked images, tainted canvas, unsupported mode) and the auto-
switch to the print → PDF path that the browser's print engine
can handle.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
1 parent
ef03f731d1
commit
10a5022e9c
8 files changed
+541
-2
No files matched your search
@@ -0,0 +1,98 @@
|
||||
# NWC — Nostr Wallet Connect setup
|
||||
|
||||
NWC (NIP-47) lets Artstr send Lightning payments through your
|
||||
wallet without leaving the app. Required for one-click zapping +
|
||||
unlocking premium designs.
|
||||
|
||||
## Quick start (CoinOS, recommended)
|
||||
|
||||
CoinOS is a free web-based wallet that supports NWC. Easiest path
|
||||
if you don't already have a Lightning wallet:
|
||||
|
||||
1. Sign up at <https://coinos.io>.
|
||||
2. Open **Settings → Connect** in the CoinOS app.
|
||||
3. Create a new Nostr Wallet Connect link. Set a **budget** that
|
||||
comfortably covers the zaps + unlocks you expect (a few
|
||||
thousand sats is plenty to start).
|
||||
4. Copy the connection string (starts with `nostr+walletconnect://`).
|
||||
5. In Artstr, open **Settings → Lightning wallet**.
|
||||
6. Paste the connection string + click **Connect**.
|
||||
7. The status line confirms the connection + lists the wallet's
|
||||
advertised capabilities (`pay_invoice` is the required one).
|
||||
|
||||
## Other supported wallets
|
||||
|
||||
Any NIP-47 wallet works:
|
||||
|
||||
- **Alby Hub** — self-hosted; nostr-native; great for power users.
|
||||
- **Mutiny** — browser-based, open-source.
|
||||
- **Phoenix** — mobile-first, advertises NWC.
|
||||
- **Cashu.me** — ecash custodial.
|
||||
- **LNbits** — self-hosted; the NWC extension exposes a
|
||||
connection string per wallet.
|
||||
|
||||
In every case the pattern is the same: the wallet generates a
|
||||
`nostr+walletconnect://...` URI that you paste into Artstr.
|
||||
|
||||
## Multi-device sync
|
||||
|
||||
The **Sync this wallet to my Nostr account** checkbox (appears
|
||||
once connected) publishes your NWC URI as a kind-30078 event,
|
||||
encrypted to your own pubkey via NIP-44. On any other device where
|
||||
you sign in with the same Nostr key, Artstr finds the synced event,
|
||||
decrypts it, and auto-reconnects without you pasting the URI
|
||||
again.
|
||||
|
||||
Privacy: the synced event is NIP-44-encrypted to **only your own
|
||||
pubkey**. Relays + other clients can't read the URI — only an
|
||||
extension holding your nsec can decrypt it.
|
||||
|
||||
## Sending a zap with NWC connected
|
||||
|
||||
1. Click the **⚡ Zap** button on any design / page / chapter (or
|
||||
the **Unlock with ⚡ zap** on a premium row).
|
||||
2. Amount picker opens with presets.
|
||||
3. Artstr builds a zap request, gets the BOLT11 invoice from the
|
||||
recipient's LSP, and sends `pay_invoice` through your NWC
|
||||
connection.
|
||||
4. The wallet pays; the LSP issues the zap receipt; the UI
|
||||
refreshes.
|
||||
|
||||
End-to-end usually completes in under 3 seconds.
|
||||
|
||||
## Test connection
|
||||
|
||||
The **Test connection** button (next to Disconnect) runs a
|
||||
zero-amount pay_invoice round-trip to verify the wallet is
|
||||
reachable + capable. Useful before assuming the integration is
|
||||
broken.
|
||||
|
||||
## Capability warnings
|
||||
|
||||
If the wallet doesn't advertise `pay_invoice`, the UI shows an
|
||||
⚠ banner — unlocks will fail. Reconnect via a different wallet's
|
||||
URI or enable `pay_invoice` in the source wallet (most wallets
|
||||
ship it on; some self-hosted setups disable it by default).
|
||||
|
||||
## Security model
|
||||
|
||||
- The connection string contains the wallet's relay URL + a
|
||||
client-side secret key Artstr uses to sign NIP-04 messages to
|
||||
the wallet. **Treat it like a password** — anyone with the URI
|
||||
can send `pay_invoice` up to the configured budget.
|
||||
- Set a **budget** on the wallet side that caps total spending.
|
||||
Most NWC wallets let you renew the budget periodically.
|
||||
- Setting a low per-payment maximum (e.g., 1 000 sats) is a good
|
||||
default for unlocking designs.
|
||||
- Revoking NWC is a one-click action on the wallet side — the URI
|
||||
becomes inert immediately.
|
||||
|
||||
## Caveats
|
||||
|
||||
- NWC over relays adds latency (signed event → relay → wallet →
|
||||
signed receipt → relay → client). Expect 1-3 seconds per zap on
|
||||
a healthy connection.
|
||||
- If the wallet's relay is down, zaps queue but won't complete.
|
||||
The wallet usually has multiple relays as fallbacks.
|
||||
- Mobile browsers sometimes throttle background WebSockets; if
|
||||
zaps time out, foreground the Artstr tab + retry.
|
||||
@@ -33,8 +33,9 @@ publishing to Nostr lives in the top-right Publish flow, not here.
|
||||
## Export
|
||||
|
||||
- **Export JPEG** — direct rasterised export at the artboard's
|
||||
natural pixel size, JPEG-compressed (~0.92 quality). One file
|
||||
per artboard.
|
||||
natural pixel size, JPEG-compressed. The resolution dropdown
|
||||
picks between **Low (96 DPI)**, **Standard (150 DPI)**, and
|
||||
**Print (300 DPI)**.
|
||||
- **Export PNG** — same but as PNG (lossless). Sometimes available
|
||||
only for modes that support transparent backgrounds.
|
||||
- Pixel-art mode has its own dedicated exports (PNG at multiple
|
||||
@@ -43,6 +44,30 @@ publishing to Nostr lives in the top-right Publish flow, not here.
|
||||
- Book mode has its own dedicated **Export PDF…** flow (page range,
|
||||
bleed, crop marks, split output) from the Pages overview toolbar.
|
||||
|
||||
### Why JPEG sometimes routes through PDF
|
||||
|
||||
The direct-JPEG path renders every layer onto a hidden canvas, then
|
||||
extracts the canvas as a JPEG. That fails in three cases:
|
||||
|
||||
1. **CORS-blocked images** — if any image layer's source server
|
||||
doesn't send `Access-Control-Allow-Origin: *`, the browser
|
||||
refuses to embed the pixels in the canvas. The "Render canvas"
|
||||
path can't bypass this; the print engine can.
|
||||
2. **Tainted canvas** — the canvas accepted the image but flagged it
|
||||
"tainted" once it tried to read pixels. Same root cause as #1
|
||||
but caught at a different stage.
|
||||
3. **Unsupported modes** — pixel-art (uses its own dedicated
|
||||
exporter) and standalone decks (which have a multi-slide
|
||||
exporter elsewhere) don't go through this path.
|
||||
|
||||
In any of those cases, the JPEG button automatically opens the
|
||||
**Print → PDF** flow: the browser's print engine has a separate
|
||||
image pipeline that handles cross-origin embeds the canvas can't
|
||||
touch. You'll see a toast explaining the switch ("N image(s)
|
||||
couldn't be embedded directly — switching to the PDF route"). Save
|
||||
the resulting PDF, then re-export it as JPEG from a PDF viewer if
|
||||
you specifically need a flat JPEG.
|
||||
|
||||
## Designer tab
|
||||
|
||||
The Designer tab has a separate `designerPrintSaveFieldset` with
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
# Premium publishing (zap-gated)
|
||||
|
||||
Sell designs for sats. The published event ships a watermarked
|
||||
preview anyone can browse + an encrypted payload only paying
|
||||
viewers can decrypt. Discovery + browsing is public; the design
|
||||
itself is gated.
|
||||
|
||||
## How it works
|
||||
|
||||
1. The full design payload is encrypted via the same AES-256-GCM
|
||||
pipeline as a private publish, but with a special **softgate**
|
||||
key derivation.
|
||||
2. The key derives from public event material (event id, pubkey,
|
||||
d-tag) plus an obfuscated per-epoch pepper baked into the
|
||||
static Artstr client.
|
||||
3. A watermarked JPEG preview (max 720 px long axis, ~50 KB
|
||||
budget) ships in the unencrypted envelope so buyers can see
|
||||
what they'd be unlocking.
|
||||
4. The event publishes with:
|
||||
- `['t', 'casewrap']`, `['t', 'casewrap-<mode>']` — discovery.
|
||||
- `['title', …]`, `['category', …]` — public metadata.
|
||||
- `['premium', 'true']`.
|
||||
- `['zap-gate', 'true']`, `['zap-min', '<sats>']`, `['zap-split', 'required']`.
|
||||
- `['zap', <creator-pubkey>, <relay>, '<weight>']` — creator share.
|
||||
- `['zap', <platform-pubkey>, <relay>, '<weight>']` — platform fee.
|
||||
5. When a buyer's zap receipt for this event lands on relays, the
|
||||
client computes the soft-gate key + decrypts.
|
||||
|
||||
## Soft-gate is "soft"
|
||||
|
||||
Honest framing: this raises friction against drive-by scraping but
|
||||
a determined reverse-engineer can recover the client pepper and
|
||||
decrypt without paying. The mode is for low-trust commercial
|
||||
distribution, not DRM-grade gating. Stronger DRM can swap in later
|
||||
without changing the buyer side.
|
||||
|
||||
## What you need before publishing premium
|
||||
|
||||
- A **lightning address** (`lud16`) on your kind-0 Nostr profile.
|
||||
Set this on any Nostr client that edits your profile metadata
|
||||
(Damus, Amethyst, nos2x, etc). Without it the platform can't
|
||||
route the buyer's payment to you.
|
||||
- A non-empty title + category (same as any publish).
|
||||
- A working artboard preview — the modal renders the watermarked
|
||||
JPEG live + refuses to publish if rendering fails (CORS images
|
||||
etc).
|
||||
|
||||
## Publishing flow
|
||||
|
||||
1. Set Title + Category.
|
||||
2. Click **Publish to Nostr**.
|
||||
3. In the confirm modal:
|
||||
- Keep visibility on **Public**.
|
||||
- Toggle **Zap-gated (premium)** on.
|
||||
- Set the **Minimum zap** in sats (default 100).
|
||||
- Read the split note (creator: 70 %, platform: 30 % by default;
|
||||
see the per-event `zap` tags for the exact split that ships).
|
||||
4. Click **Publish**.
|
||||
|
||||
## How buyers unlock
|
||||
|
||||
In the community browser's **Premium** tab, a locked design shows
|
||||
the watermarked preview + an **Unlock with ⚡ zap** button. Clicking
|
||||
it:
|
||||
|
||||
1. Opens the buyer's connected NWC wallet (see
|
||||
[NWC setup](#/help/nwc)).
|
||||
2. Builds a NIP-57 zap request for the minimum amount.
|
||||
3. Sends `pay_invoice` through the NWC connection.
|
||||
4. On a successful zap receipt, derives the soft-gate key + decrypts
|
||||
the design in-place.
|
||||
5. Caches the decrypted payload in the **My Purchases** vault so
|
||||
later re-visits skip the re-zap.
|
||||
|
||||
## My Purchases vault
|
||||
|
||||
Your unlocks live in a **vault** encrypted to your own pubkey (so
|
||||
they sync across devices the same way private publishes do).
|
||||
Capped at a fixed size; if the vault overflows, the oldest items
|
||||
get evicted with a visible failure rather than silently lost.
|
||||
|
||||
## Editing a premium event
|
||||
|
||||
The same NIP-33 replaceability applies — re-publishing updates the
|
||||
event in place. Existing buyers' vault entries continue working
|
||||
against the new event since the soft-gate key derives from the
|
||||
d-tag, which stays stable.
|
||||
|
||||
## Caveats
|
||||
|
||||
- Decks ship a per-slide watermarked preview (up to 6 slides) so
|
||||
buyers can flip through what they'd unlock; non-deck modes get a
|
||||
single preview JPEG.
|
||||
- The platform fee is currently a fixed 30/70 split on the event's
|
||||
zap tags. Future updates may make this configurable.
|
||||
- The buyer's NWC wallet must support `pay_invoice` (almost all
|
||||
do).
|
||||
|
||||
## Deeper reference
|
||||
|
||||
- Spec: `docs/PREMIUM_DESIGNS_FEATURE.md` in the GitHub repo.
|
||||
@@ -0,0 +1,71 @@
|
||||
# Private publishing
|
||||
|
||||
Encrypted-to-self designs. Same Nostr event format as a public
|
||||
design, but `content` is an encrypted envelope and the metadata
|
||||
tags are stripped down so the design doesn't appear in any
|
||||
community feed.
|
||||
|
||||
## How the encryption works
|
||||
|
||||
1. The full design payload is JSON-serialised.
|
||||
2. Gzipped (when the browser supports `CompressionStream`).
|
||||
3. Encrypted with a fresh AES-256-GCM key.
|
||||
4. The AES key is wrapped to **your own Nostr pubkey** via either
|
||||
NIP-44 (preferred) or NIP-04 (fallback).
|
||||
5. The wrapped key + iv + ciphertext go into an `envelope` JSON
|
||||
object that becomes the event's `content` field.
|
||||
|
||||
Only someone signing with your Nostr key can derive the AES key
|
||||
and decrypt the payload. The event is technically broadcast to all
|
||||
relays, but it's mathematically opaque to everyone else.
|
||||
|
||||
## What's still visible
|
||||
|
||||
- Your **pubkey** (every Nostr event is signed and the pubkey is
|
||||
part of the signature).
|
||||
- The event's `kind`, `created_at`, `d` tag, and `encrypted` tag.
|
||||
- The fact that you published *something* at this time.
|
||||
|
||||
What's **not** visible: title, category, IDs, layers, dimensions,
|
||||
images, or any other payload content.
|
||||
|
||||
## When to use it
|
||||
|
||||
- Working drafts you want backed up across devices but not shared.
|
||||
- Personal projects you don't want indexed.
|
||||
- Sensitive content where even the title shouldn't leak.
|
||||
|
||||
## Editing across devices
|
||||
|
||||
Open Artstr on another device, sign in with the same Nostr
|
||||
extension, and click **Mine** in the community browser. Your
|
||||
private events appear (decrypted lazily as you click them). The
|
||||
**Private** tab specifically filters to your encrypted events.
|
||||
|
||||
## Caveats
|
||||
|
||||
- Requires a Nostr extension that supports NIP-44 or NIP-04
|
||||
encryption. Most do; alby and nos2x both work.
|
||||
- The d-tag for a private design is a random opaque string
|
||||
(`artstr-private-<base36>`) so it can't be guessed. Don't lose
|
||||
the d-tag if you intentionally want to overwrite the event
|
||||
later — it's stored in your project's autosave under
|
||||
`state.privateDTag`.
|
||||
- **Sharing privately with one specific other person** is *not*
|
||||
supported in v1. The current encryption only wraps the AES key
|
||||
to your own pubkey. Multi-recipient envelopes are a future arc.
|
||||
|
||||
## Books
|
||||
|
||||
The book sidebar has its own **🔒 Private** chip. Flipping it
|
||||
encrypts the manifest **and** every sidecar event (pages,
|
||||
masters, cover, chapters) on subsequent publishes. See
|
||||
[Book Designer](#/help/book) for the full sidecar flow.
|
||||
|
||||
A private book's chapter events are kind-30078 (encrypted), not
|
||||
kind-30023 NIP-23 articles, so external NIP-23 readers won't see
|
||||
them — which is the desired behaviour for a private book.
|
||||
|
||||
## Deeper reference
|
||||
|
||||
- Spec: `docs/PRIVATE_PUBLISHING_FEATURE.md` in the GitHub repo.
|
||||
@@ -0,0 +1,79 @@
|
||||
# Public publishing
|
||||
|
||||
The default tier. Plain-text event the relays distribute to anyone
|
||||
who asks for it. Discoverable in the community browser, forkable,
|
||||
embeddable.
|
||||
|
||||
## What the event looks like
|
||||
|
||||
- `kind: 30078` (or `30023` for book chapters).
|
||||
- `tags`:
|
||||
- `['d', '<mode>:<id-or-title>']` — the addressable identifier.
|
||||
Replaceable per NIP-33: re-publishing under the same d-tag
|
||||
replaces the event in place.
|
||||
- `['t', 'casewrap']` + `['t', '<mode-specific>']` (e.g.
|
||||
`casewrap-cover`, `casewrap-deck`, `casewrap-book`).
|
||||
- `['title', '<your title>']`, `['category', '<…>']`,
|
||||
`['language', '<…>']`.
|
||||
- External ID tags when you've filled them in: `['i', 'imdb:…']`,
|
||||
`['i', 'upc:…']`, `['i', 'tvdb:…']`, etc.
|
||||
- `['client', 'Artstr Studio']`.
|
||||
- For books / linked designs: `['p', '<contributor>', …,
|
||||
'design-contributor']` + `['link', '<kind:pubkey:dTag>', …]`.
|
||||
- `content`: JSON-serialised design payload. Every layer, every
|
||||
mode-specific block, every reference.
|
||||
|
||||
## Discoverability
|
||||
|
||||
- Listed in the **community browser** under the New / Popular /
|
||||
Zapped tabs, filterable by category + language.
|
||||
- Searchable via the Search tab + Nostr search relays that index
|
||||
`casewrap` content.
|
||||
- Linked from share URLs: `<host>/#/share/<naddr>` resolves to a
|
||||
read-only view + Fork button.
|
||||
|
||||
## Publishing flow
|
||||
|
||||
1. Set **Title** + **Category** in Project Metadata.
|
||||
2. Click the **Publish to Nostr** button (top right).
|
||||
3. Confirm modal opens with:
|
||||
- A preview pane.
|
||||
- Metadata list (Type / Title / Category / Author / etc).
|
||||
- **Public / Private** radio (defaults to Public).
|
||||
- **Zap-gated (premium)** toggle (defaults off → public free).
|
||||
4. Click **Publish**.
|
||||
5. The event signs through your Nostr extension + broadcasts to
|
||||
the relay list in **Settings → Relays**.
|
||||
|
||||
## Editing a published design
|
||||
|
||||
Loading a public design from the community browser drops you in
|
||||
**edit mode** — the publish button now says "Publish update" and
|
||||
preserves the original d-tag. Republishing replaces the event in
|
||||
place via NIP-33.
|
||||
|
||||
To **fork** instead of edit (so your version becomes a new event
|
||||
under your pubkey), use the community browser's **Fork** action on
|
||||
the design row — it clears the editing state so your next publish
|
||||
mints a fresh d-tag.
|
||||
|
||||
## Forking + attribution
|
||||
|
||||
Linked-design layers from other authors auto-emit:
|
||||
|
||||
- `p` tags for each contributor (so they get notifications + can
|
||||
be discovered as design contributors).
|
||||
- `link` tags so external clients can resolve the sub-designs.
|
||||
|
||||
See the [Credits panel](#/help/panel-credits) for what gets surfaced
|
||||
in-app + at publish time.
|
||||
|
||||
## Caveats
|
||||
|
||||
- Anything you upload as an image layer is embedded in the event
|
||||
payload as a `data:` URL — Nostr relays may reject very large
|
||||
events. For high-res photo layers, prefer publishing the photo
|
||||
somewhere else and linking via an `https://` URL.
|
||||
- Even with private toggles off, the metadata tags (title,
|
||||
category) are public. The encryption only protects the `content`
|
||||
field.
|
||||
@@ -0,0 +1,66 @@
|
||||
# Publishing — overview
|
||||
|
||||
Artstr Studio publishes designs to Nostr instead of a private
|
||||
server. Every published design becomes a kind-30078 event (or
|
||||
kind-30023 for book chapters) that anyone can fetch, fork, or
|
||||
embed.
|
||||
|
||||
There are three visibility tiers:
|
||||
|
||||
| Tier | Who can open it | Use case |
|
||||
|------|-----------------|----------|
|
||||
| **[Public](#/help/publishing-public)** | Anyone with the naddr / nevent. | Default — discoverable in the community browser, forkable. |
|
||||
| **[Private](#/help/publishing-private)** | Only you, via the same Nostr key (any device). | Working drafts, personal projects, archives. End-to-end encrypted. |
|
||||
| **[Premium](#/help/publishing-premium)** | Anyone who pays a one-time zap (sats). | Paid templates / books. Watermarked preview + an unlock CTA. |
|
||||
|
||||
## Choosing a tier
|
||||
|
||||
The choice is made in the **Publish to Nostr** confirm modal:
|
||||
|
||||
- Top of the modal shows a **Public / Private** radio.
|
||||
- A **Zap-gated (premium)** toggle below it (hidden when Private is
|
||||
selected — encrypted designs can't be feed-listed, so gating them
|
||||
for sale doesn't make sense).
|
||||
- The book sidebar has its own **🔒 Private** chip that flips
|
||||
visibility for the whole book + every sidecar event.
|
||||
|
||||
## How the publish event differs per tier
|
||||
|
||||
| | Public | Private | Premium |
|
||||
|---|---|---|---|
|
||||
| Event kind | 30078 | 30078 | 30078 |
|
||||
| `t` tag | `casewrap` + mode-specific | `encrypted` | `casewrap` + `premium` |
|
||||
| `content` field | JSON payload | encrypted envelope | encrypted envelope |
|
||||
| Preview JPEG | none | none | watermarked, embedded |
|
||||
| Discovery | community browser + naddr share | naddr share only | community browser (premium tab) |
|
||||
| Lightning | `zap` tags for tipping | none | `zap` tags split between creator + platform |
|
||||
|
||||
## Tipping vs unlocking (NIP-57 zaps)
|
||||
|
||||
Zaps are NIP-57 lightning payments. Two flavours:
|
||||
|
||||
- **Tipping** — any user can zap any design / page / chapter. Goes
|
||||
100% to the creator's lightning address (no platform share).
|
||||
Works on public, private (for you only), and premium designs.
|
||||
- **Unlocking** — a premium design's zap requirement. The buyer zaps
|
||||
the required minimum; on receipt of a valid zap receipt, the
|
||||
client decrypts the design. Split: creator share + platform fee.
|
||||
|
||||
See [Zaps](#/help/zaps) for the full mechanics + how to enable
|
||||
zapping in your profile.
|
||||
|
||||
## Sending zaps
|
||||
|
||||
You need a **NIP-47 wallet** (Nostr Wallet Connect, or NWC) connected
|
||||
to Artstr so it can sign + send invoice payments without leaving the
|
||||
app. See [NWC setup](#/help/nwc).
|
||||
|
||||
## Editing + republishing
|
||||
|
||||
All published events are **replaceable** (NIP-33). Re-publishing under
|
||||
the same d-tag updates the event in place — old `naddr` share links
|
||||
keep working; `nevent` (snapshot) share links point at the old
|
||||
version.
|
||||
|
||||
The community browser's **Mine** tab shows every event you've
|
||||
published with a "Republish" + "Delete" action per row.
|
||||
@@ -0,0 +1,93 @@
|
||||
# Zaps — NIP-57 lightning payments
|
||||
|
||||
Artstr uses Nostr-native lightning zaps for both tipping creators
|
||||
and unlocking premium designs. Same protocol either way; the
|
||||
difference is who the zap goes to and what the client does on
|
||||
receipt.
|
||||
|
||||
## How zaps work in two paragraphs
|
||||
|
||||
A zap is a kind-9735 receipt event proving that a Lightning
|
||||
payment happened. The flow:
|
||||
|
||||
1. The user (you) signs a kind-9734 **zap request** event with the
|
||||
amount + recipient + intent.
|
||||
2. The recipient's lightning address (`lud16` on their profile)
|
||||
resolves to a LNURL endpoint; the request becomes a BOLT11
|
||||
invoice.
|
||||
3. You pay the invoice from your wallet. The wallet's LSP issues
|
||||
a **zap receipt** event back to the relays.
|
||||
4. Clients that see the receipt update UI (zap-totals, unlock
|
||||
gated content, etc).
|
||||
|
||||
## Tipping any design / page / chapter
|
||||
|
||||
Every design preview pane has a **⚡ Zap** button (visible when
|
||||
the author has a lightning address on their profile). Clicking:
|
||||
|
||||
1. Opens an amount picker (default presets 21 / 100 / 1000 sats +
|
||||
custom).
|
||||
2. Builds + signs the zap request via your Nostr extension.
|
||||
3. Pays through your connected **NWC wallet** (see
|
||||
[NWC setup](#/help/nwc)). If you don't have NWC connected, it
|
||||
falls back to copying the invoice for you to pay manually in
|
||||
any Lightning wallet.
|
||||
|
||||
The zap goes 100% to the author. No platform share.
|
||||
|
||||
## Unlocking a premium design
|
||||
|
||||
Same plumbing, different outcome. The locked design row shows an
|
||||
**Unlock with ⚡ zap** button. Clicking sends the minimum required
|
||||
amount, split between the creator + the platform per the event's
|
||||
`zap` tags (currently 70/30). On receipt:
|
||||
|
||||
1. The client verifies the receipt's amount + recipient match the
|
||||
event's `zap-min` + `zap` tags.
|
||||
2. Derives the soft-gate key from the event metadata.
|
||||
3. Decrypts the payload + saves it to your **My Purchases**
|
||||
vault.
|
||||
|
||||
See [Premium publishing](#/help/publishing-premium) for the publish
|
||||
side.
|
||||
|
||||
## Receiving zaps on your designs
|
||||
|
||||
To get tipped or sold-to:
|
||||
|
||||
1. Sign up at any LN-address service. **CoinOS** (free, web-based)
|
||||
is the easiest: <https://coinos.io>.
|
||||
2. Edit your Nostr kind-0 profile to add `lud16` = your LN address
|
||||
(e.g. `[email protected]`). Any Nostr client that edits profiles
|
||||
works (Damus, Amethyst, primal.net, nos2x options page).
|
||||
3. Wait a few minutes for your profile to propagate to the relays
|
||||
you care about.
|
||||
|
||||
Once `lud16` is set, every published design of yours becomes
|
||||
zap-able automatically — Artstr discovers the lightning address
|
||||
from your profile.
|
||||
|
||||
## Sending zaps without an NWC wallet
|
||||
|
||||
If you don't have NWC connected, the zap modal will:
|
||||
|
||||
- Build the BOLT11 invoice.
|
||||
- Show a QR code + a copy button.
|
||||
- Wait for the invoice to be paid externally (you can pay from any
|
||||
Lightning wallet — Phoenix, Wallet of Satoshi, etc).
|
||||
- Verify the receipt on relays + update the UI.
|
||||
|
||||
This is slower than NWC (you switch apps to pay) but works
|
||||
universally.
|
||||
|
||||
## Tips
|
||||
|
||||
- The **Zapped** tab in the community browser sorts designs by
|
||||
total zap volume — a quick way to find what people are paying
|
||||
for.
|
||||
- Zaps are public on Nostr (the receipt event is signed by the
|
||||
LSP and broadcast). If you want anonymous payment, you'll need a
|
||||
separate Lightning identity.
|
||||
- Failed zaps (invoice paid but receipt never arrives) can be
|
||||
diagnosed via the wallet's transaction log. The LSP issued the
|
||||
receipt; the relays may have dropped it.
|
||||
@@ -12074,6 +12074,12 @@
|
||||
{ slug: 'panel-print-save', title: 'Save / Print', group: 'Sidebar panels', file: 'help/panel-print-save.md' },
|
||||
{ slug: 'panel-credits', title: 'Credits', group: 'Sidebar panels', file: 'help/panel-credits.md' },
|
||||
{ slug: 'panel-tool-options', title: 'Tool Options pane', group: 'Sidebar panels', file: 'help/panel-tool-options.md' },
|
||||
{ slug: 'publishing', title: 'Overview', group: 'Publishing & payments', file: 'help/publishing.md' },
|
||||
{ slug: 'publishing-public', title: 'Public publishing', group: 'Publishing & payments', file: 'help/publishing-public.md' },
|
||||
{ slug: 'publishing-private', title: 'Private publishing', group: 'Publishing & payments', file: 'help/publishing-private.md' },
|
||||
{ slug: 'publishing-premium', title: 'Premium (zap-gated)', group: 'Publishing & payments', file: 'help/publishing-premium.md' },
|
||||
{ slug: 'zaps', title: 'Zaps (NIP-57)', group: 'Publishing & payments', file: 'help/zaps.md' },
|
||||
{ slug: 'nwc', title: 'NWC wallet setup', group: 'Publishing & payments', file: 'help/nwc.md' },
|
||||
];
|
||||
const _docsCache = new Map(); // slug → rendered HTML
|
||||
let _docsActiveSlug = 'index';
|
||||
|
||||
Reference in new issue
Block a user