🎭 Theater & Live Performance · legal protection

Ghostlight · Jetton

Protect your intellectual property in the rehearsal room. Playwrights upload script drafts to an immutable ledger; collaborators, directors, and literary agents pay 0.01 USDT-on-TON to view, download, or time-stamp notes. Every revision is a new hash, every read is a metered payment, ensuring creators are compensated for the 'litigation-grade' proof of their work's evolution.

TON Jetton paywall· jetton native
Section · Onchain

The primitive.

full primer →

The legal protection payload sits behind an HTTP 402 wall priced in Jettons; directors pay with one Tonkeeper confirmation carrying a one-time memo, and the server unlocks it only after the transfer settles on TON.

Why this primitiveTransitioning from a static NFT 'trophy' to an the Jetton paywall utility transforms ownership into active monetization. Instead of a one-time minting cost, the playwright earns every time their IP is accessed for professional review, turning legal protection into a recurring revenue stream.

Kernel
an HTTP 402 paywall metered in Jettons (USDT-on-TON shape) — the client sends a transfer carrying a one-time memo through TON Connect and the server re-reads the TON indexer to match it before releasing the payload
Drives the UI as
a 'pay to unlock' button that shows the memo, the settled transfer, and a tonscan link
Appendix · Secrets

Required keys.

TON_DEPLOYER_MNEMONIC
24-word testnet seed for the deploy script. Fund it free via the Telegram test giver.
open ↗
TONCENTER_API_KEY
Optional. Higher rate limits on the testnet indexer.
open ↗
TON_RECEIVER_ADDRESS
Collects Jetton paywall payments. Can equal the deployer wallet.
open ↗
TON_JETTON_MASTER
Jetton metered by the paywall. Leave empty to meter in Toncoin.
open ↗
PINATA_JWT
Pins images / JSON / manifests to IPFS.
open ↗

Add these in your Lovable project under Settings → Secrets before pasting the prompt below.

Appendix · Mega-prompt

The build prompt.

Target

Paste into a fresh Lovable project. Make sure all five secrets above are set first. read the build strategy →

Build "Ghostlight · Jetton" in ONE Lovable message. Single-page Jetton-metered paid app on the TON testnet.

CONCEPT
Protect your intellectual property in the rehearsal room. Playwrights upload script drafts to an immutable ledger; collaborators, directors, and literary agents pay 0.01 USDT-on-TON to view, download, or time-stamp notes. Every revision is a new hash, every read is a metered payment, ensuring creators are compensated for the 'litigation-grade' proof of their work's evolution.
Discipline: Theater & Live Performance (legal protection).
Onchain primitive: Jetton micropayments on TON (USDT-on-TON shape, TEP-74 transfers). Why: Transitioning from a static NFT 'trophy' to an the Jetton paywall utility transforms ownership into active monetization. Instead of a one-time minting cost, the playwright earns every time their IP is accessed for professional review, turning legal protection into a recurring revenue stream.

5-CREDIT BUDGET (HARD LIMIT)
- ONE single-page app. No Lovable Cloud, no database, no auth beyond TON Connect.
- NO custom smart contract. Payments settle as ordinary TEP-74 Jetton transfers to your receiver wallet.
- Self-host the verifier as ONE TanStack server route inside the same app (shape below).
- At most ONE AI call per user action (Lovable AI Gateway with LOVABLE_API_KEY, only if AI is part of the idea).
- Skip tests, skip CI, skip docs. Ship the demo.

STACK
- React + Vite + TanStack Start, single page (the index route).
- SSR-safe wallet mount is MANDATORY. Never import @tonconnect/ui-react at module
  scope of a route file — it touches `window` and crashes SSR. Use
  lazy(() => import('./ton-client-entry')) inside <ClientOnly> + <Suspense>, and
  keep <TonConnectUIProvider> inside ton-client-entry.tsx only.
- Publish public/tonconnect-manifest.json ({ url, name, iconUrl }) and pass
  manifestUrl={`${window.location.origin}/tonconnect-manifest.json`}.
- TESTNET IS FORCED: send with `network: CHAIN.TESTNET` and refuse to submit when
  `wallet.account.chain !== CHAIN.TESTNET`, with a 'switch your wallet to testnet' hint.
- Amounts are nanotons as strings ("50000000" = 0.05 TON). A text-comment body is
  beginCell().storeUint(0, 32).storeStringTail(text).endCell().toBoc().toString('base64').
- Read chain state from the public indexer https://testnet.toncenter.com/api/v3
  (/transactions?account=…, /jetton/transfers?address=…). Never poll a wallet for history.
- Contracts live in /contracts, compiled with @ton-community/func-js and deployed with
  @ton/ton + @ton/crypto from a node script — keep them out of the Vite bundle.
- Persistent amber "TON testnet only · no real value moves here" banner at the top of the shell.

PAYWALL PROTOCOL (HTTP 402 + memo verification)
- GET /api/public/ton-paid-content with no PAYMENT-MEMO header returns 402 and a challenge:
    { tonVersion: 1, network: "ton:testnet",
      accepts: [{ scheme: "jetton-transfer", payTo: "<receiver>", asset: "<jetton master>",
                  amount: "<smallest units>", decimals: 6, symbol: "USDT",
                  memoPrefix: "chx-", maxTimeoutSeconds: 900 }] }
- The client mints a one-time memo (`chx-` + 12 hex chars), then sends ONE TON Connect message:
  a TEP-74 `transfer` (op 0x0f8a7ea5) to the payer's jetton wallet with destination = payTo,
  forward_ton_amount > 0 and a forward payload carrying the memo as a text comment.
  Forward TON must be non-zero or the memo never reaches the receiver.
- The client then polls the same endpoint with the `PAYMENT-MEMO` header.
- The SERVER verifies independently — never trust the client's word for a payment:
    GET https://testnet.toncenter.com/api/v3/jetton/transfers?address=<payTo>&direction=in&limit=50
    match jetton_master === asset, amount >= required, decoded_forward_payload comment === memo,
    transaction_aborted === false, and transaction_now within the last 15 minutes.
  Only then return 200 with the payload plus a PAYMENT-RESPONSE header.
- Rate-limit the endpoint per IP and reject memos that do not match /^chx-[a-f0-9]{8,32}$/.
- Toncoin fallback: if no jetton master is configured, verify a plain 0.02 TON transfer with the
  same memo through /transactions?account=<payTo> — identical flow, one config flag.

USER FLOW
1. Connect Tonkeeper (testnet) via TON Connect; free test coins from https://t.me/testgiver_ton_bot.
2. Directors hit the locked legal protection resource -> 402 challenge renders as a step list.
3. One wallet confirmation sends the Jetton transfer with the memo; the app polls until the
   server sees it on-chain, then reveals the payload with a tonscan link.
4. Footer renders: "Built during the Creative AI & Quantum Hackathon organised by StreetKode Fam during Indian Krump Festival 14"

TON SURVIVAL KIT (non-obvious rules — follow all of them)
1. BUFFER: browsers have no `Buffer`, but every TON lib returns one, so
   `cell.toBoc().toString("base64")` throws "Buffer is not defined". Add one helper and
   await it at the top of EVERY function touching @ton/core, @ton/crypto or @ton/ton —
   including the TON Connect path, which is the one people forget:
     export async function ensureBuffer() {
       const g = globalThis as typeof globalThis & { Buffer?: unknown };
       if (g.Buffer) return;
       g.Buffer = (await import("buffer")).Buffer;
     }
2. ADDRESS FLAVOURS: one key renders as four strings. `EQ…`/`UQ…` are the mainnet
   flavours (bounceable / non-bounceable), `kQ…`/`0Q…` are the test-network flavours.
   Never string-compare addresses across flavours — normalise first with
   `Address.parse(a).equals(Address.parse(b))`. Render with an explicit flavour:
     addr.toString({ testOnly: true, bounceable: false, urlSafe: true })
   Send user transfers NON-bounceable (`bounce: false`); a bounceable send to an
   uninitialised wallet returns the funds and the demo looks broken.
3. WALLET VERSION: the same mnemonic derives DIFFERENT addresses per wallet version.
   A 24-word TON phrase -> `WalletContractV4` (workchain 0); a 12-word BIP39 phrase
   (Gram, MyTonWallet) -> `WalletContractV5R1`. Derive both, query balances, and use
   the funded one — do not guess. A TON wallet is itself a contract: it needs ~0.05 TON
   and its first send carries `init` with `seqno: 0`. "Not deployed" is normal for a
   fresh address, not an error.
4. EXPLORER: link everything to https://testnet.tonscan.org/address/<addr> and
   https://testnet.tonscan.org/tx/<hash>. Derive the base URL from config, never hardcode.
5. WALLET REALITY CHECK: mobile Tonkeeper and Gram ship mainnet-only, so a test-network
   demo opened on a phone dead-ends with "your wallet is on TON mainnet". Ship a fallback:
   generate a throwaway wallet in the browser (`mnemonicNew()` from @ton/crypto, mnemonic
   in localStorage, funded from the faucet) and sign locally with `WalletContractV4`.
   Lock that browser-held key to the test network — never let it touch real funds.
6. TONCENTER: v3 rate-limits hard (HTTP 429). Wrap every read in a retry with backoff and
   send `X-API-Key: TONCENTER_API_KEY` on anything user-facing.
7. PAYMENT VERIFICATION: verify SERVER-side only, never trust a client-reported hash.
   Mint a one-time `chx-<hex>` memo, then match the recipient's recent transactions on
   amount >= price, decoded comment === memo, `transaction_aborted === false`, and a
   15-minute freshness window. Comments must be sent as a base64 BOC, not plain text:
     beginCell().storeUint(0, 32).storeStringTail(memo).endCell().toBoc().toString("base64")
8. SSR: mount TON Connect client-side only — `lazy(() => import("./ton-client-entry"))`
   inside `<ClientOnly>` + `<Suspense>`. Importing @tonconnect/ui-react at route module
   scope crashes the server render. `tonconnect-manifest.json` must sit at a public https URL.
9. INSTALL: npm i @tonconnect/ui-react @ton/ton @ton/core @ton/crypto buffer
   (add @ton-community/func-js only when you compile and deploy a FunC contract).
END TON SURVIVAL KIT

REQUIRED SECRETS (Lovable -> Project Settings -> Secrets):
- TON_DEPLOYER_MNEMONIC  24-word testnet wallet seed used by the deploy script. Fund it free: https://t.me/testgiver_ton_bot
- TONCENTER_API_KEY      Optional but recommended for rate limits. Get one from https://t.me/tonapibot
- TON_RECEIVER_ADDRESS   Testnet wallet that collects the Jetton payments (can equal the deployer).
- TON_JETTON_MASTER      Jetton master address metered by the paywall; leave empty to meter in Toncoin.
- PINATA_JWT            IPFS uploads (only if the app pins media). Docs: https://docs.pinata.cloud/llms-full.txt

CREDIT (must appear in the UI footer):
Built during the Creative AI & Quantum Hackathon organised by StreetKode Fam during Indian Krump Festival 14
Appendix · Market

Market sizing.

TAM
$2.4B
The global intellectual property protection and digital rights management market for performance arts and creative writing.
SAM
$180M
The addressable market for playwrights, screenwriters, and dramaturgs engaging in digital script circulation and stage-rights management.
SOM
$12M
The market for independent playwrights and fringe festival participants requiring affordable, instant copyright protection for draft iterations.

Indicative figures for hackathon pitches — refine with your own research before raising.

See also

Adjacent entries.

legal protection
Script Ownership Registry
Mint scripts as NFTs to create an immutable ownership registry for playwrights.
playwright collaboration
DraftFlow · Jetton
Pay-per-contribution script evolution. Every time a playwright pushes a new scene, dialogue tweak, or stage direction, the production pays a $0.01 micro-royalty. This turns the script into a living, metered asset where writers are paid for the act of creation in real-time. Producers unlock specific drafts or 'forks' of a play for rehearsal by paying a settled $0.01 fee per actor access, ensuring the creative sweat equity is instantly monetized and timestamped on-chain.
casting marketplace
StageRead · Jetton
A high-frequency talent scout protocol where every audition tape submission and casting call 'side' download is a micro-settlement. Directors pay $0.01 to unlock a performer's reel, and actors pay $0.01 to commit their encrypted audition data to the chain. This replaces monthly subscription models with a 'pay-per-opportunity' architecture, preventing platform bloat and ensuring only high-intent interactions between talent and production.
lighting rights management
LumenSync · Jetton
A protocol for lighting designers to meter the 'burn' of their intellectual property. Lighting consoles ping the the Jetton paywall endpoint to unlock specific DMX map frames or complex Chamsys/MA3 sequence macros. Venues pay 0.01 USDT-on-TON per cue-trigger or per-minute of 'look' duration, ensuring designers are compensated for every performance without complex manual auditing.