CursivaDocs
Publish & access

Publishing and access

Publishing puts a version of the content into circulation for learners; access decides who gets in and under what conditions. In Cursiva, each piece of content is a single sellable unit, and these two decisions — publishing and granting access — live separately from the editorial body.

How publishing works

Every piece of content is a single row in the database, edited in place. It holds two documents:

DocumentRole
contentThe editable draft — what the team sees in the editor.
publishedContentThe snapshot the learner reads — a copy of content, written by Publish.

While you edit, the learner sees nothing new. When you Publish, Cursiva copies the current draft into publishedContent, stamps publishedAt, and recomputes the facts derived from publishing (the reference edges and the stable sectionIds). Before the first publish, publishedContent is null: the content exists, but no one can read it or enroll.

What Publish does, step by step

  1. Verifies that you have edit rights in the content domain.
  2. Recomputes the reference edges from the document being published.
  3. Under a per-organization advisory lock (held until the transaction commits), writes the snapshot, the publication date, the valid edges, and the sectionIds.

The per-organization lock serializes simultaneous publishes within the same organization. Without it, two pieces of content publishing at the same time could each pass the cycle check against the other's previous state and, on write, form a cycle. Under the lock, the second publish only proceeds after the first has committed its edges.

Rules applied to references on publish

The reference graph is computed over the published content. When publishing, Cursiva keeps only the edges whose target is safe and makes them inert otherwise:

Edge droppedReason
Target in another organizationPrevents bypassing the paywall by reading another organization's paid/unlisted content for free.
Target with no published versionAvoids an inert card that would make the course permanently uncompletable.
Deleted targetThe target no longer exists.
Reference that would create a cycleKeeps the graph a DAG within the organization.
Self-reference (to itself)Removed before the other checks.

A dropped edge does not break the page: the referenced module's card appears inert, with no link, instead of taking the learner to a 404.

Visibility: listed vs. unlisted

Publishing makes content readable by link. Discovery is a separate decision, controlled by the Listed field.

StateIn the catalogBy direct linkTypical use
Published and listedYes — appears in the marketplace and the organization's catalogYesMain course, sellable on its own.
Published and unlistedDoes not appear as a cardYesA module that only exists inside a course, or an offer sellable by link only.

The public catalog lists only content that is published AND listed, newest to oldest. Modules that only make sense inside a course stay unlisted and never appear as standalone cards — but they remain sellable by direct link when they have a price.

Toggling visibility sits on the boundary between catalog and finance: both the content role and the finance role can turn it on or off.

The access rule

Access is a property of the sellable unit — the content's price — and not of the edges between pieces of content. Course composition is bundling: the parent is what gets sold; monetization is not a concern of each edge.

The core rule is short: free content is readable; priced content shows a sales preview until purchase.

Access scenarioWhat the learner sees
Free content, not enrolledThe full body, readable without enrolling. Enrolling only starts recording progress.
Free content, enrolledThe full body, with progress, drip release, and course navigation.
Priced content, not purchasedThe sales preview: header, marketing preamble, and the module cards. Section content is withheld.
Priced content, already purchasedThe full body, like an enrolled learner.
Free child of a paid parentReadable on its own page — it works as a sample of the paid course (the sample funnel).
Module of a course you are enrolled inThe nested course view, under the single root enrollment, respecting drip release.
Refunded / delinquent enrollmentNo access — the row is kept for history and reactivation, but grants no reading.

The sales preview

For priced content not yet purchased, Cursiva assembles the public sales view: the header, the preamble (marketing content before the first step), and the module cards stay visible, so the curriculum shows up. Section content is withheld — it belongs to the course. When something has been withheld, the preview is marked as gated and an enrollment prompt invites the visitor in.

Sample: free child of a paid parent

Because access follows each piece of content's price, a free module referenced by a paid course is fully readable on its own page. This is intentional: that free child works as a sample of the paid course. A visitor who lands on a module segment under a course they are not enrolled in is taken to the module's canonical page — where a free child is read in full and a priced child shows its own sales preview.

Composition = bundling

Referencing content assembles a course from existing pieces. Enrollment happens once, at the root (the sellable unit): there is no separate sign-up per sub-content, at any nesting depth. The learner navigates continuously through the tree under that single enrollment. Access to any module reachable through the root's published tree follows from the root enrollment — never from buying each module in isolation.

Drip release: drip and prerequisites

Within a course, each step has a release rule. The rule lives on the edge (owned by the parent document), so the same child content is paced independently in each course. Two mechanics combine:

  • Drip (time delay) — releases the step after an interval. The delay is measured in hours (afterHours) and counts from an anchor.
  • Prerequisites — explicit dependencies: the step only opens when the required steps are completed.

Drip anchors

AnchorCounts from
enroll (default)The learner's enrollment date.
prevThe completion of the immediately preceding step in the path ("after the last section").

A step anchored on prev whose predecessor is not yet completed has no anchor — it stays locked, and the timer only starts when the predecessor is completed.

In temporal courses (with dated cohorts), drip anchors on the learner's cohort start, not the enrollment date — the whole cohort is released together. When the learner has no cohort, the anchor falls back to the enrollment.

How sections and modules differ

The availability evaluator applies per-step-type semantics:

Step typeRelease rule
Section (title/heading)Prerequisites. requires: null defaults to the immediately preceding step (sequential); [] = always open; [ids] = all listed ones completed.
Module (reference)The edge's rule: drip (afterHours, anchored on enroll or prev) plus explicit prerequisites. A module is never locked by mere order in the document.

A prerequisite id that no longer exists in the content is treated as satisfied (fail-open), so a removed or stale target never locks the learner out forever. Prerequisites are kept acyclic: the "Release after" selector in the editor refuses a choice that would create a cycle.

What the learner perceives

Each step of the path carries a state: available (the rule was satisfied), locked, the lock reason (drip or prerequisite) and, for drip, the unlockAt instant when it opens. The reader delivers only the released steps — the content of locked steps is never sent to the client, so there is no "reading ahead." Steps locked by drip show a live countdown until unlock.

Enrollment, approval, and seats

Publishing enables enrollment, but the way in depends on the configuration:

  • Free, open entry — the learner enrolls directly (answering the intake form, if there is one).
  • Free, with approval — self-signup is closed: people request to join and the team approves. Each request carries the intake answers and becomes an enrollment once approved.
  • Priced — the learner pays first and lands in the queue (when there is approval); a rejection refunds automatically. Buyers skip the intake by definition — the payment is the form.
  • Seat limit — when set, the page shows the remaining seats Cal-style ("3 seats left") before the click, and new enrollments are serialized so they never oversell the limit.

Enrollment is idempotent: enrolling again returns the existing row. A refunded or delinquent enrollment keeps the row (for history and reactivation on re-payment), but grants no access while it is not active.

Sharing and embedding

Once published, the content's canonical link (/{organization}/{content}) is what you share. It generates rich link cards (title, description, and cover) when pasted into WhatsApp, LinkedIn, or X — that unfurl is the creator's ad. Unlisted content stays link-only and gets noindex.

Module links stay within the main course's URL space (/{organization}/{course}/{segment}), preserving the continuity of enrollment and navigation at any depth. The Embed setting offers a way to present the content in another context; see the settings page for the embedding details.

Keep exploring