Platform concepts
This is Cursiva's mental model: a small set of concepts that combine to describe any learning experience, from a standalone piece of text to a complete program. Understanding how they connect prevents you from duplicating material and creating conflicting rules.
Content is the central unit
A content is the platform's only publishable unit. It brings together, in a single piece, five responsibilities: identity (slug, tags, theme), editorial body, access, format, and commercial configuration. Everything else in Cursiva — enrollments, purchases, reviews, quiz history, and references — points to a content's stable id.
Each content is a single row in the database, updated in place. It holds two states:
| State | What it is | Who reads it |
|---|---|---|
Draft (content) | The editable working version | The team, in the editor |
Published (publishedContent) | The frozen copy from the last publish | Learners |
Publishing copies the draft into the published state, records the date, and recomputes derived facts. There are no version rows: the learner always reads the latest publish, and progress survives because it is anchored to stable section identifiers, not to version numbers.
Three shapes of the same content
The same kind of object takes on three roles, depending on how it is configured and composed:
- Standalone lesson — a content that stands on its own. It is read end to end, without depending on others. Published and listed, it appears as a card in the catalog.
- Sellable material — a content with a price. Access goes through checkout; without a price, enrollment is direct (or becomes a request, if it requires approval).
- Composition — a content that references other contents. Instead of copying lessons into several courses, it points to the originals and becomes a course, path, or program assembled from reusable pieces.
Composition through references
A reference is an edge that links a parent content to a child content. You insert it in the editor, and it carries three pieces of information:
| Reference field | Meaning |
|---|---|
key | The id of the referenced content (what the edge points to) |
slug | The URL segment, owned by the parent course (the child can be renamed without breaking the parent) |
title | A snapshot of the title, used in breadcrumbs without loading the child |
A content's references form a directed graph. On publish, this graph is recomputed and sanitized: each edge only survives if the target is a published content from the same organization. This discards — by rendering the reference inert — three dangerous cases:
- Targets from another organization — prevents an enrolled learner from reading someone else's paid or unlisted material for free.
- Targets with no published version — prevents a card that could never be completed, leaving the course forever incomplete.
- Deleted targets — prevents dangling edges.
In addition, cycles are removed: a content cannot reference another one that already reaches it. The result is always an acyclic intra-organization graph. Publishes within the same organization are serialized (by a lock), so that two simultaneous publishes don't jointly form a cycle.
Continuous navigation under a single enrollment
A composition can have any depth of nesting, but the learner enrolls only once, in the root content — the sellable unit. There is no separate enrollment for each sub-content.
From the root, the learner navigates continuously across the entire referenced tree. The platform resolves each URL segment against the enrolled tree (the shallowest match wins) and builds the breadcrumb along the shortest path from the root to the open module. A module is only accessible if it belongs to that person's active enrollment tree.
Access and progression
Access determines who can get in. Progression determines what becomes available after someone is already in. The two rules are independent: a learner can have access to the entire course and still find modules released over time (drip) or by prerequisite.
| Concept | Responsibility |
|---|---|
| Publishing | Defines the version visible to the learner |
| Listing | Defines whether the content appears in the catalog |
| Access | Defines who can get in (price, approval, seat limit) |
| Enrollment | Links a person to a content (the learner row) |
| Progress | Records completed sections by stable id |
| Drip | Releases steps after an interval |
| Prerequisite | Requires completing another step before releasing |
Access derives above all from price: free content allows direct enrollment; with a price, access goes through checkout. Additional layers can require approval (free enrollment becomes a request) and impose a seat limit. Progress is stored as the set of completed section ids; because completion is always recomputed against the current ids, removed sections drop out of the calculation and genuinely new sections honestly reopen the content.
Completing a tree
A composed content is only considered complete when all of its own sections are done and every referenced content, at any depth, is also complete. It is this whole-tree completion, starting from the root, that unlocks the certificate.
Learners and members
Two distinct populations coexist in an organization, and the distinction must always stay clear:
| Role | Who they are | Link |
|---|---|---|
| Learner | A student enrolled in a content | learner row (person + content) |
| Member | Someone on the team who runs the operation | Organization member |
The same user can be a learner in one organization and a member in another — they are independent links. Enrollment is idempotent: enrolling again returns the existing row. Only an active enrollment grants access; canceled, refunded, or past-due enrollments keep the row (for history) but do not open the content.
Member roles and the content's three functions
At the organization level, owner and admin hold structural authority and pass any content check. Below that, authority over a content is assigned by function, and each function corresponds to a member's role on the content's owning team (content.teamId):
| Function (domain) | Team role | What it authorizes |
|---|---|---|
content | editor | Edit the body, publish, tags, theme, format |
finance | finance | Price, coupons, refunds, listing, installments |
community | community | Manage communities, moderate, act as tutor |
A content can be owned by a person (personal content) or a team — never both at the same time. The owning person holds all functions over their content. Owner-level actions (transferring ownership, deleting), however, require the owning person or an organization admin — no team role reaches that level.
Organizational structure
The organization is the operation's main space; it is the source of the public catalog and the producer pages. Within it:
- Teams segment people and responsibilities. The team that owns a content is the authority over it, and the per-member roles (editor, finance, community) provide the granularity described above.
- Communities (cohorts) bring learners together around a shared context, with their own discussion. When you enable discussion on an atemporal course, a default open community is created automatically; temporal courses use dated communities.
Temporal and atemporal content
A content is either atemporal (self-directed) or temporal (organized into dated cohorts):
| Model | How it works |
|---|---|
| Atemporal | The learner advances at their own pace; drip counts from enrollment |
| Temporal | Enrollment links the learner to a dated community (cohort); content is released starting from the cohort's start |
Temporal courses can open cohorts automatically, with configurable duration, seat limit, and tutor. The tutor can be fixed or drawn in rotation from the members of the owning team who carry the community role.