Skip to content

Marketplace architecture

💭 v2.0+

This is a vision document describing how the marketplace + sync stack works when it ships post-1.0. The v1.0 architectural decisions (all-patches-as-references data model, .stardustshow/ bundle format, extension API sandbox) are made with this in mind so we don’t have to break them when it lands.

Skip for v1.0. All of this is v2.0+. Documented here so future planning has the reference and v1.0 architecture stays compatible.

Hard constraints (non-negotiable)

These survive any architectural revision:

  1. The app works fully without the marketplace. No login required for the app itself. No connectivity required to load shows, load patches, or play.
  2. Anonymous downloads stay available. Free content can always be fetched without an account.
  3. No mandatory cloud lock-in. Users own their library data; the marketplace is a distribution channel, not a hostage situation.
  4. Self-hostable. A team or community can run their own instance of the marketplace server. The protocol is open. AGPL-licensed.
  5. AGPL-compatible. The marketplace server (and Stardust itself) must remain AGPL-licensable — including paid content distribution. Where a Merchant of Record sits, it sits cleanly.

The three tiers

Tier 1 — Community sharing v1.x bridge

Free, no payments, anonymous-ok. The v1.x bridge step.

  • Upload + download shows, patches, rig components, themes, layouts, SFZ packs
  • Search / browse / filter / tag
  • Ratings + reviews
  • Creator pages
  • Reporting / moderation tooling

This validates the content-delivery side without the payment plumbing. The full marketplace builds on top of it.

Tier 2 — Marketplace v2.0 (or v1.5)

Tier 1 plus:

  • Creator-set pricing
  • Payment processing via Merchant of Record (Lemon Squeezy / Polar.sh)
  • License verification (downloads tied to purchaser’s account)
  • Tax compliance (US sales tax, EU VAT, ROW)
  • Creator payouts
  • Refunds + disputes
  • Verified creator badges

Tier 3 — Cloud sync + collaboration v2.0+

Per-account, CRDT-backed:

  • Show backup to cloud
  • Library sync across user’s devices
  • Multi-MD collaboration on shared shows (CRDT-backed real-time)
  • Hot-spare rig sync (LAN-primary, cloud-fallback)
  • Multi-keyboardist position sync (LAN-primary)
  • Optional: cloud-rendered backing track previews, cloud-stored crash reports

Architectural principles

  • Local-first, cloud-optional — every cloud feature additive, never gates
  • Self-hostable — open-source server side (AGPL ethos). Community/enterprises can run their own marketplace + sync instance. Stardust hosts the canonical instance.
  • Pluggable account system — anonymous downloads (free content), Stardust account (canonical), self-hosted account (federated), future OIDC bring-your-own-provider
  • No tracking, no ads, no dark patterns — telemetry opt-in only, analytics aggregate-only, payment data only where required

Merchant of Record

Stardust does not build payment infrastructure from scratch. Payments are processed by a Merchant of Record (MoR) that handles:

  • Credit card processing
  • Tax compliance (VAT, sales tax, digital services tax)
  • Chargebacks and refunds
  • Cross-border regulatory compliance
  • Anti-fraud

Candidate providers:

  • Lemon Squeezy — strong indie-friendly terms, mature API
  • Polar.sh — open-source-aligned, growing
  • Paddle — bigger, more enterprise, but solid MoR

The MoR holds the payment flow; Stardust holds the content delivery. Sellers get paid by the MoR (minus fees); buyers get a license token from the MoR that the Stardust server redeems against the content.

LayerRecommendationWhy
APIRust + Axum (or Go + Chi if team grows beyond Rust)Type safety, perf, single binary, matches engine stack
DatabasePostgreSQL on Neon (serverless) or self-hostedBoring, reliable; Neon branching for staging
Object storageCloudflare R2S3-compatible, no egress fees (huge for marketplace downloads), cheap
CDNCloudflareFree tier covers a lot; integrates with R2
Real-time messagingSoketi (Pusher protocol) or raw WebSocket via AxumSoketi if want client library ecosystem; raw WS if want zero deps
SearchMeilisearch (self-hosted) or Postgres full-textMeilisearch fast + typo-tolerant; PG full-text fine for marketplace v1
AuthClerk (managed) or self-hosted Ory KratosClerk = ship fast; Ory = full control + self-hosted
PaymentsLemon Squeezy or Polar.sh (Merchant of Record)MoR handles tax compliance globally — do NOT build yourself
Email transactionalResend or PostmarkCheap, reliable
Crash reporterGlitchTip (self-hosted Sentry-compatible)Open source, no per-event fees
Site analyticsPlausible (managed or self-hosted) or UmamiPrivacy-first, no cookie banner
HostingFly.io or Railway for API; Cloudflare Pages for marketing/docsCheap, low cognitive overhead, scales reasonably

See Infrastructure choices for the “why not AWS/GCP” rationale.

Data flow on purchase

Buyer ←──────── Stardust marketplace server ────────→ Seller
↑ ↑ ↑
│ pays │ license + delivery │ uploads + receives payout
↓ ↓ ↓
Merchant of Record (MoR)
  1. Buyer clicks Purchase in the marketplace UI inside Pit
  2. Pit opens the MoR’s checkout (in-app webview or external browser)
  3. Buyer pays the MoR
  4. MoR posts a success webhook to the Stardust marketplace server
  5. Stardust server issues a license token to the buyer’s account
  6. Pit fetches the asset, validates the license, installs to the global library

License model

Each paid purchase produces a license token held in the user’s Stardust account. The token authorizes:

  • Download of the asset
  • Use of the asset across all the user’s installs
  • Receipt of updates (within the subscription window if subscription-based)

License tokens are stored in the user’s Stardust account and cached locally so the app keeps working without network access. The marketplace server only needs to be reachable for purchase, install, and update — not for running content that’s already installed.

What’s sold

The marketplace is a distribution surface for library entries (per Patch library) and extensions:

AssetFreePaid
Patches — single library entries
Patch packs — curated collections
Show templates — full .stardustshow bundles for common works
Click tracks — for public-domain works
SFZ packs — sample-based instruments via v0.14.0’s native SFZ player
Extensions — TS / WASM bundles
Plugin bundles — recipes that install groups of free pluginsrarely

Paid content can be one-time-purchase or subscription (typically annual, for content that gets updated like maintained click tracks for active touring productions).

Sync architecture — CRDT (Automerge)

Three patterns considered:

  • Last-write-wins (LWW) — simple; data loss on conflict
  • Operational Transform (OT) — server resolves edits; needs always-on server
  • CRDTs (Automerge, Yjs) — edits merge mathematically; works offline + P2P + via server

Recommendation: CRDTs (Automerge).

Reasons:

  • Local-first principle satisfied — works fully offline, sync when reconnected
  • Multi-device for one user — same show on laptop + studio Mac sync automatically
  • Multi-user collaboration — two MDs editing the same show resolve cleanly
  • Hot-spare rig — same sync protocol, just over LAN
  • Multi-keyboardist position sync — same protocol, ephemeral state
  • Mature — Automerge 2 production-ready
  • Open source — MIT/Apache, no licensing concerns

The show file format is amenable to CRDTs: node-based graph + reference-based patches = exactly the shape CRDTs handle well. Migration from “save whole document” to “CRDT-backed document with change history” is non-trivial but pays off across many features.

Self-hosted instances

The marketplace server is open source under AGPL. A theatre company, conservatory, or content distributor can run their own instance — useful for:

  • Private content (commissioned shows, in-house patch libraries)
  • Regional content (a country-specific show ecosystem)
  • Pre-public-launch testing

Self-hosted instances can federate with the canonical Stardust marketplace (v2.0+) so content is searchable across instances; or stay private.

Phasing

PhaseVersionsWhat ships
v1.0 (no cloud)through v1.0.0Pit fully local. No account. No marketplace. No sync.
Bridgev1.1 – v1.3Anonymous share hub: upload as public URL, download with link. No accounts, no payments. Cloudflare-only stack. Foundation before commerce.
Marketplace v1v1.5 (or v2.0)Tier 2: full marketplace with accounts, paid content, Lemon Squeezy MoR, creator pages. ~3–4 months dedicated.
Sync + collaborationv2.0 (or v2.x)Tier 3: CRDT migration, cloud backup, multi-device sync, real-time collab, hot-spare LAN, multi-keyboardist LAN. ~6 months.
Federation / self-hostv2.xDocumented self-hosted marketplace server; federated identity. marketplace.stardust.org canonical; others run their own.

Rough cost projection

Canonical marketplace instance scaled to ~10k users / 1k creators / 100k downloads per month:

ServiceCost
Fly.io (API + workers)$30–80
Neon PostgreSQL$20–50
Cloudflare R2 (storage + CDN)$20–100
Clerk auth (10k MAU)$0–25
Lemon Squeezy5% + $0.50 per transaction (no fixed)
Plausible analytics$9
GlitchTip crash$0 self-hosted
Total fixed~$80–270/month
Plus transaction feesVariable

Affordable for indie. Lemon Squeezy MoR fee is the biggest cost but covers global tax compliance.

ADRs needed when marketplace work starts

  • ADR: Marketplace tech stack + Merchant of Record selection
  • ADR: CRDT vs OT vs LWW for sync
  • ADR: User accounts + identity (managed vs self-hosted, federation)
  • ADR: Self-hosting + federation model
  • ADR: Content moderation policy + enforcement tooling

What to do now (before any work)

  • Don’t build any of it for v1.0. Pit shipping local-first is right; cloud after.
  • Reserve domains: marketplace.stardust.org, accounts.stardust.org, api.stardust.org
  • Add stubs to v2.0+ backlog (done in the roadmap)
  • Design data model with sync in mind — all-patches-as-references already helps; CRDT-friendliness is a free side-effect of structured normalized data
  • Be careful about file format — the .stardustshow/ bundle format (folder) is more CRDT-friendly than monolithic JSON (individual files sync independently)
  • Keep an ADR drafts folder for future-you

What NOT to do

Don’t build a Stardust account requirement into v1.0 “just in case.” Local-first means local-first. Adding cloud features later doesn’t need account migration — the local install just starts offering optional account features.

What this is NOT

  • Not an exclusivity deal. Sellers can list the same content elsewhere.
  • Not a DRM system. Content is downloaded as files; copying is technically possible. Licensing is enforceable but not bulletproof — and we don’t pretend otherwise.
  • Not a curated-only walled garden. Anyone can publish. Curation surfaces (editor’s picks, featured collections) layer on top.
  • Not an enterprise CMS. It’s a marketplace, not a content management platform.