Membership platform for creators
Sovereign Creator
A membership platform for creators — a direct alternative to sites like Patreon. Fans join by paying one set price that the creator sets, creators keep more of what their audience pays, and the content policy sits closer to an R rating than to YouTube's: mature work is welcome, adult material is not what this is. It carries its own object storage and its own player instead of an embedded third-party host, because the premise is a business question rather than a technical one — a third-party platform's content rules and takedown decisions govern your business, and its player address is shareable around your paywall. Holding the storage layer is the only way to own the audience, the storage and the terms.
Next.js 15 and React 19 on Node, a SQLite catalogue, and media on a local disk or in any S3-compatible bucket behind one interface. The payload is delivered through short-lived signed URLs minted after a server-side entitlement check, and nothing here is open for use by the public.
- One set membership price
- Signed-URL delivery
- Creators keep more
- Four access gates
The interface is demonstrated as a self-contained static build. It runs entirely in the browser: no server, no network, no accounts, no playback and no data of its own. Every entry in it is illustrative demonstration metadata, and the rights values on those entries are placeholders rather than clearance records.
/demo/, captured from this directory in headless Chrome. The demonstration is a static build with no server behind it; it is not the product referring to itself.How it works
One membership, one storage layer, one decision
Two content models share one security core. Creator pages are the primary model — a creator's own posts, gated by the membership tier a fan buys. A catalogue is the second: a browsable set of entries that carries the same tier gate, plus a rights record wherever the content is licensed rather than owned.
An entry is a row with access attached
Every entry carries its creator, its publication state and the membership tier required to read it, plus, where content is licensed, a rights record: status, holder, territory and expiry. The catalogue is browsable by search and filtered by type and date.
The client never holds a durable media address
Every image and video element points at the platform's own media route, which re-checks entitlement at fetch time and only then mints an address that expires. A render-time check alone would be defeated by a cached page render, or by a membership lapsing between the render and the fetch.
Four questions, decided separately
May this viewer watch it, may the platform offer it here and now, has this viewer confirmed they are old enough for it, and how many streams does the account hold. Each is its own pure function with its own reason, and playback requires all four. Collapsing them would mean a licence expiry and a lapsed membership produced the same denial.
The access model
Four gates, four separate decisions
Three of the four refusals are deliberately indistinguishable from a missing entry. The exception is concurrency, which is the one condition a viewer can actually fix, so hiding it would just look like a broken player.
Entitlement 404
Decided by a pure function with no database, no network and no clock of its own — everything it needs is passed in. Membership, tier rank and draft state are the inputs; the single bridge from the database to that function is one file long, so the complete set of rules that grant access is two files long. The rank comparison is written to fail closed, so a non-finite rank cannot slip through a text column.
Availability 404
Rights status, licence term, scheduling window and licence territory, decided separately from entitlement so a licence expiry and a lapsed membership do not produce the same denial. Unlicensed material is refused unconditionally and is not governed by any configuration flag. An unknown region fails closed for a title whose licence names territories.
Age 404
R is the platform's ceiling, so this is a confirmation rather than an identity check: an R-rated entry asks the viewer to confirm they are 18 or older. The record stores a verdict and a timestamp and has nowhere to put a name, a date of birth or a document number, and the page says plainly that it is a self-declaration rather than statutory age verification.
Concurrency 409
Two simultaneous streams per account by default. A playback session is a cookie and a limited sharer can rotate it, so this raises the cost of sharing rather than preventing it. Sessions expire by going quiet, so a closed tab frees its slot within a heartbeat window instead of holding it forever.
What is different
The parts that carry the weight
Each of these is a mechanism in the repository, not a policy statement: a threshold, a route or a signature that can be read in the source tree.
The signature covers the key and the expiry
Media addresses are signed with an HMAC over the object key and the expiry together, so neither can be swapped for another entry's key or extended by editing the address. Object keys are validated against a strict character set and then containment-checked after resolution.
A manifest is never served raw
An HLS manifest is a plain-text list of addresses, so handing a player the stored file would teach it every segment key and leave the paywall guarding only the manifest. Nested playlists are rewritten to route back through the same gated endpoint, segment and key references become short-lived signed addresses, and a crafted manifest cannot reach another entry's prefix.
Withheld means removed, not greyed out
An entry the platform may not offer is omitted from the grid, the collections, the watchlist and the detail page; its artwork, stream and captions return the same not-found as a missing entry too, because a subtitle file is a transcript of the work. Posters stay public for entries that are offerable but unaffordable, or the grid would be unbrowsable. That line is asserted end to end.
The rights labels are shown to the audience
Entries read Owned, Licensed, Public domain, Rights unclear or Not cleared, and the full record is shown to the operator. This is the most deliberate decision in the project: an audience for licensed work cares about provenance, and an operator should not be able to forget what they are carrying.
The storage layer is a seam, not a dependency
The local disk driver and the S3-compatible driver sit behind one interface, and the entitlement code path above them is identical either way. The bucket stays private in both cases; a short-lived signed address is the only way in.
Withheld content never reaches the render layer
A locked entry is projected through a view whose body is empty unless the viewer is entitled, so the text is never a component property at all. The repository holds a regression test for this, because the first version was correct on screen while the locked text sat in the page source.
The numbers
Counted from the repository, not rounded up
Every figure below is stated in the product's own README, seed script or configuration defaults.
Under the hood
What it is built from
- Stack
- Next.js 15 route handlers and React 19 server components on Node, in TypeScript, managed with pnpm. The delivered site you are reading is plain HTML and CSS with no framework at all.
- Surfaces
- A catalogue and search at
/browse, per-entry pages, curated collections, a watchlist, an operator console for records, artwork, video, rights and the clearance queue, a creator studio, a join and login path, a public notice intake and an age step. - Storage
- Local disk by default, or any S3-compatible bucket: Cloudflare R2, Backblaze B2, Amazon S3 or MinIO. The bucket is private; a presigned address is the only way in, and a lifecycle rule is recommended to expire orphaned objects.
- Data
- A SQLite catalogue holding content records, rights fields, artwork and video assets, captions, tiers, memberships, notices and an audit log. A backup command takes a consistent snapshot plus a rights, notices and audit manifest.
- Payments
- Simulated. No card is collected, no processor is integrated and no money moves. The join and cancel endpoints are shaped so that only the writer of a membership row would change when a real acquirer is chosen.
- Accounts
- Email and password, hashed with scrypt, behind signed stateless session cookies. There is no email verification and no password reset, because both need a mail provider.
- Delivery
- Byte-range seeking, resume position and a watchlist. Multi-rendition playback by rewriting manifests; captions are WebVTT served through the entitlement gate. No DRM and no adaptive packaging are built in.
- Tested by
- The 287 unit tests and 177 end-to-end checks above, run against both a development server and a production build. The end-to-end suite drives real cookies, byte ranges, forged signatures, extended expiries, swapped object keys, path traversal and the not-found policy.
- Blocked on
- Three things before real content could sit behind it: the payment path, which is a business decision rather than a build one; a real age-assurance step for mature work, since the current method is a self-declaration; and a moderation pipeline with hash matching, a reporting path and a human review queue.
Status
Where this stands
- There is no public access to Sovereign Creator. This page is a description and a status report, and the demonstration at
/demo/is a static build. There is no hosted instance to sign in to, no account you can create here, no stream you can request from this site, and no payment path that takes money. - The software is built and covered by its own tests. The catalogue, search and filters, tier gating, memberships, signed-URL playback with byte-range seeking, rights tracking, collections, the operator console, the notice workflow and creator pages are all implemented in the repository, and both test suites pass against a production build.
- Payments are simulated. Any signed-in user can grant themselves the top tier for nothing. That is the documented point of the stub and also the reason nothing of value should be gated behind this build until a signature-verified webhook replaces it.
- The demonstration catalogue is not a clearance record. The entries are illustrative metadata chosen so that browsing and filtering have something meaningful to show, but the rights values on them are placeholders chosen to exercise every branch of the rights dashboard, and the video files are generated placeholders rather than real works.
- The age step is a self-declaration and says so. The gate, the storage, the redirect and the fail-closed behaviour all work, but the method is a confirmation, not an identity check, and the page states that rather than implying otherwise. Wiring a real age-assurance vendor changes only where the verdict comes from.
- Its own known gaps are documented rather than hidden: no DRM, no adaptive streaming, no content moderation pipeline, rate limiting that is database-backed but per-host, uploads buffered in memory, and a session model with no per-device revocation.
What this is not
Limits stated plainly
- Not a licence to publish anything. The rights fields are bookkeeping, not clearance. Where a creator carries work they did not make, a self-curated catalogue cannot reach the user-generated-content safe harbour, because there is no user whose direction is being followed.
- Not DRM and not anti-piracy. Any scheme that lets a browser play a video lets that browser capture it. The concurrency limit and the signed addresses raise the cost of sharing; they do not prevent it, and a session is only a cookie.
- Not geoblocking. Territory enforcement reads country headers that are client-controlled, so it is only meaningful behind an edge that overwrites them, and no header check defeats a virtual private network. It is accurate bookkeeping.
- Not a compliance posture. Nothing here is legal advice. The rights fields record what a creator can substantiate; they are not a clearance service, and they do not settle who is responsible for what a member uploads or a creator publishes.
- Not a money flow yet. No processor is integrated anywhere in the tree, so the join and cancel endpoints move no money, and picking an acquirer is a decision that precedes any deployment.
Questions about Sovereign Creator
Tell us what broke, or what you expected instead. The feedback form is on the studio's main site, since this address is only the product page. The working codebase is called PatronLite.
