Hyphen User Guides

Paywall & Access

How content gating works end-to-end — access levels, the magazine access ladder, entitlement resolution, content access rules, metered preview, and where every access setting is configured.

Version 2.1|Updated 2026-06-23|Site Administrators, Editorial Directors, QA Teams

What Is the Paywall & Access System

The paywall is the part of the platform that decides, every time someone opens an article or magazine issue on the Reader Portal, whether they may read the full content or whether they hit a gate (a sign-in prompt or a subscribe prompt).

It does this by comparing two things:

  1. What the content requires — the article's (or issue's) access level, set by editors in the Admin Console.
  2. What the reader is entitled to — the entitlements that come from the reader's subscription plan (or the absence of one, for anonymous and free readers).

When the reader's entitlements satisfy what the content requires, the article renders in full. When they don't, the reader sees a paywall gate with a message and a call-to-action button (Sign in / Subscribe / Upgrade).

This single guide covers both halves of the system:

  • The Paywall & Access settings page in the Admin Console (master on/off switch, preview length, gate messages, content-protection, session limits, and Content Access Rules), and
  • The content-driven access model — per-article access levels, the four-tier magazine access ladder, and how entitlements are resolved at render time.

Go to the settings page: Admin Console → Platform & Settings → Reader Portal → Paywall & Access.

The paywall end-to-end. Access requirements (per-article level, issue defaults, content rules) and reader entitlements (plan) both live in Postgres; the Reader Portal resolves them at render time into allow / gate.

Who Uses This System

RoleWhat They Do
Site AdministratorEnables/disables the paywall; sets preview length, messages, protection, session limits; manages Content Access Rules; defines plan entitlements.
Editorial Director / EditorSets each article's Access Level in the Article Editor; sets a magazine issue's default access and per-article TOC overrides.
QA TeamVerifies gates appear correctly for anonymous, free, and subscribed readers across articles and issues.

How It Works (Behind the Scenes)

The access decision is resolved at render time on the Reader Portal — nothing is "baked in" when an article is published. That means changing a plan's entitlements or a content rule takes effect for the next page load, without re-publishing content.

The data path:

  1. Authoring (Admin Console). An editor sets an article's Access Level (free / restricted_free / premium_limited / subscriber_only) in the Article Editor. For magazine content, an admin sets the issue default access level and optional per-article TOC overrides in the Issue Editor. Admins define plan entitlements in Subscription Plans and optional Content Access Rules on the Paywall & Access page.
  2. Storage (Postgres / Prisma). Article access level is stored as the AccessLevel enum on the Article row (access_level). Issue defaults live on the Issue row; TOC overrides live on issue_articles.access_level_override. Plan entitlements live in the plan's features JSON plus dedicated columns. Content rules live in content_access_rules. Article rows are mirrored to Strapi for content delivery, but the access level is owned by Postgres.
  3. Reader resolution (Reader Portal). When a reader requests an article or issue, the portal builds the reader's ResolvedEntitlements (from their active subscription, or DEFAULT_READER_ENTITLEMENTS for anonymous/free), resolves the effective access level of the content, and calls a pure decision function (decideArticleAccess / decideIssueAccess in reader-portal/src/lib/magazineAccess.ts).
  4. Outcome. The decision is one of: allow, redirect_to_login, redirect_to_subscribe, redirect_to_issue, or not_found. The page renders the article, shows the metered preview with a paywall overlay, or redirects.
  5. Crawler verification. Search-engine crawlers are allowed to see full content for indexing — but only after the request's IP is verified against published crawler ranges (reader-portal/src/lib/crawlerVerification.ts), which blocks User-Agent spoofing used to bypass the paywall.
Render-time access resolution. The Reader Portal resolves both the reader's entitlements and the content's effective access level on every request, then runs a pure decision function.

Access Levels & Entitlement Resolution

This section explains the concepts the whole system is built on: the access levels, how a reader's entitlements are represented, and the order in which everything is resolved.

The access levels

Articles use a single four-value enum, AccessLevel, stored on the article (and reused for magazine issues and TOC overrides):

Access Level (AccessLevel)Who can readEntitlement required
freeEveryone, including anonymous readersNone
restricted_freeAnyone who signs in (free account) for web articles; for magazines, holders of the restricted-magazine bitaccessRestrictedMagazines (magazine path) / sign-in (web metered path)
premium_limitedReaders within their monthly premium quota / with the premium-limited magazine bitaccessPremiumLimitedMagazines + premium quota
subscriber_onlyActive paid subscribers with digital-issue accessaccessDigitalIssues (and hasAccess)

Note on naming. The Article Editor and the AccessLevel enum use these four canonical values. The older Content Access Rules UI and some labels still surface friendly aliases (e.g. "Registered", "Subscriber", "Institutional"); these map onto the same gating behaviour. The four enum values above are authoritative for new content.

Reader entitlements

Every reader is resolved to a ResolvedEntitlements object (reader-portal/src/lib/entitlements.ts). Anonymous and unsubscribed readers get DEFAULT_READER_ENTITLEMENTS (hasAccess: false, every access bit false, metered limits 0). Key fields the paywall reads:

FieldTypeMeaning
hasAccessbooleanReader has an active access source (paid / gift / institutional / complimentary / bulk). The master gate — false for anonymous & free.
accessDigitalIssuesbooleanFull magazine / digital-issue access (drives subscriber_only).
accessRestrictedMagazinesbooleanGrants the restricted_free magazine tier.
accessPremiumLimitedMagazinesbooleanGrants the premium_limited magazine tier.
accessPremiumArticlesbooleanGrants premium web articles (quota-governed).
premiumArticlesPerMonthnumberPremium-limited monthly quota (-1 = unlimited, 0 = blocked).
monthlyArticleLimit / articlesReadThisMonthnumber / numberMetered web-article quota (null = unlimited, 0 = blocked).
monthlySubscriberOnlyLimit / subscriberOnlyReadThisMonthnumber / numberIndependent subscriber-only quota.
planSortOrdernumberDrives the "Upgrade to [next plan]" CTA (-1 = no plan).

The platform (Hyphen) is the source of truth for entitlements — they are derived from the reader's subscription, never from the billing provider directly.

Entitlement resolution order

For a plain web article the portal compares the article's accessLevel against the reader's entitlements (boolean bit + relevant quota). For a magazine article the effective access level is resolved through a cascade first, then graded against the four-tier ladder.

The effective access level cascade (resolvePerArticleAccessLevel / resolveEffectiveArticleAccessLevel, mirrored admin-side):

effectiveAccessLevel = IssueArticle.accessLevelOverride   (TOC row override, if set — always wins)
                     ?? Issue.accessLevel                 (the issue default)
                     ?? Article.accessLevel               (the article's own level)

The resolved level is then graded against the four-tier ladder (decideIssueAccess / decideArticleAccess):

Effective levelBit requiredAnonymous viewerSigned-in, missing the bit
freenoneallow (incl. anonymous)allow
restricted_freeaccessRestrictedMagazinesredirect to /loginredirect to /subscribe
premium_limitedaccessPremiumLimitedMagazinesredirect to /loginredirect to /subscribe
subscriber_onlyaccessDigitalIssues (+ hasAccess)redirect to /loginredirect to /subscribe
Access resolution. Web articles compare access level to entitlement + quota; magazine articles resolve an effective level (override → issue default → article) then grade it against the ladder. A valid preview token or a verified crawler IP bypasses the gate.

Key resolution rules

  • Override always wins. A per-article TOC accessLevelOverride is authoritative — it beats the article's own level and Content Access Rules, even when more permissive (a free override makes that one article open to everyone, bypassing the magazine gate).
  • Free is never penalised. A free article/issue is readable by everyone including paid subscribers — the anti-downgrade rule. Marking an article free overrides magazine tier inheritance.
  • Parent-issue cascade. A child article in a gated issue inherits the gate before per-article rules run — "children can be more restrictive but never more permissive than the parent."
  • Per-issue entitlement is additive. A reader explicitly granted a specific issue (hasIssueEntitlement) reads it even after their broad subscription lapses (within the grant window).
  • Subscriber check is strict. subscriber_only requires hasAccess && accessDigitalIssues, so a stale CANCELED subscription doesn't leak access via the plain bit.

Metered preview, preview tokens & coupons

  • Metered preview. Gated web articles render a preview (first N words / characters / paragraphs) with a paywall overlay rather than a hard redirect. Anonymous readers have metered limits of 0 (blocked after the preview). The premium-limited and subscriber-only quotas are independent counters. When the quota window resets depends on the plan: for a paid plan the window is anchored to the subscription's currentPeriodStart, so the counter resets on each renewal (a reader who renews mid-month gets a fresh allotment that day, not on the 1st); a free plan uses the calendar-month anchor (the 1st of each UTC month), because the free subscription is a single perpetual period (currentPeriodEnd = 2099-12-31) that never renews; institutional readers anchor to the institution's startDate (falling back to the calendar month for legacy rows with no start date).
  • Preview tokens. Editors can preview unpublished/gated content via a signed HMAC preview token (reader-portal/src/lib/preview/articlePreviewToken.ts, issuePreviewToken.ts), scoped to one slug, valid for 4 hours. A valid token bypasses the gate — used for editorial review and for sharing drafts.
  • Coupons. Coupons influence access indirectly, by changing what subscription a reader buys (discount / split-payment at checkout). A coupon does not itself flip an article's gate; once it results in an active subscription, the resulting entitlements drive access. See the Marketing and Subscriptions guides.

Legacy back-compat

Older articles may still carry a magazineAccess enum (exclusive / free_to_magazine) from the previous three-option model. It is honored at read time (exclusive → subscriber_only, free_to_magazine → free/registered) and retired as articles are re-saved — no migration required. A plan with accessDigitalIssues: true but the two newer magazine bits unset is treated at read time as also having accessRestrictedMagazines and accessPremiumLimitedMagazines (a read-time shim, no data mutated).

The visible_in_listings magazine tier. Magazine articles are normally hidden from public home/section/tag/search/related listings (they live behind the issue). Setting an article's magazine access to visible_in_listings lets that one article appear in public listings while still belonging to the issue — but only once its parent issue is in a portal-visible status (published or archived). Crucially, a visible_in_listings article does not run the legacy magazine gate: it gates on its own accessLevel exactly like a Web Exclusive article (free → open to all; gated → metered/redirect by entitlement). Use it to surface a standout magazine piece on the home page without exposing the rest of the issue. See the Magazine guide for the authoring side.


The Paywall & Access Settings Page

The settings page (Platform & Settings → Reader Portal → Paywall & Access) has these sections in order:

  1. Paywall Settings — master on/off switch.
  2. Content Preview — how much content to show before gating.
  3. Paywall Messages — what readers see at the gate (Registration + Subscribe variants).
  4. Content Protection — download / print / copy restrictions.
  5. Session Limits — max simultaneous logins.
  6. Content Access Rules — override access for sections, categories, tags, or authors.
  7. Save Changes (at the bottom).

Section 1 — Paywall Settings

The subscriber-only paywall gate as seen by a logged-out reader on the Reader Portal
The paywall gate a logged-out reader sees on gated content. The message and CTA come from the Paywall Messages section below.

The Enable Paywall toggle is the master switch. When off, every article is readable by everyone regardless of its access level. When on, access levels and the rules below are enforced. Use the toggle (not per-article edits) to temporarily open the whole site, then remember to turn it back on.

Section 2 — Content Preview

Controls how much of a gated article a non-entitled reader sees before the gate.

  • Preview TypeWords, Characters (HTML tags excluded), or Paragraphs. Changing the type resets the count to a sensible default (200 words / 500 characters / 3 paragraphs).
  • Preview Count — whole number; 0 hides all content immediately. 150–200 words or 2–3 paragraphs is a common starting point.

Section 3 — Paywall Messages

Two blocks because different readers need different prompts:

  • Registration block — shown to anonymous (not signed in) visitors. Fields: Registration Message, CTA Button Text (default Sign in free), CTA Button URL (default /register).
  • Subscribe block — shown to signed-in readers without a qualifying subscription. Fields: Subscribe Message, CTA Button Text (default Subscribe Now), CTA Button URL (default /subscribe).

Leave a message blank to use the platform default. The Subscribe gate shows an upgrade CTA ("Upgrade to [Next Plan]" linking to /subscribe?plan=...) when the reader is on a paid plan below the top tier; otherwise the generic CTA falls back to "Subscribe".

Gate copy defaults. When no admin message is set, the subscribe/metered gate uses Hyphen brand-voice defaults: the headline reads "We'll keep this page bookmarked." for both the subscriber-only and metered states; the metered body reads "Beyond this page lies more stories, languages, and literary discoveries. Subscribe now to continue reading." The registration gate headline is "Pause here for now." with the single CTA "Sign in or Create an Account", and the restricted-free state shows "Free Article Limit Reached" with "Register for Free". There is no secondary "View subscription plans" link under the gate — the primary CTA already routes to /subscribe. Anything you type into the message/CTA fields overrides these defaults.

Section 4 — Content Protection

Three checkboxes — Disable image downloads (all content), Disable printing (all content), and Disable copy/paste & text selection (all content).

Site-wide enforcement. These deterrents are enforced by a single global controller (ContentProtectionController, mounted in the Reader Portal root layout) that applies them to every reader page — free and premium alike — independent of the Enable Paywall master switch. Turning a checkbox on protects the whole portal; turning it off lifts it everywhere.

How each toggle behaves:

  • Disable image downloads — blocks the native image drag and the right-click "Save image as…" over images (suppresses the context menu over img / picture / canvas).
  • Disable printing — hides page content from the print renderer via an @media print rule (substituting a copyright notice) plus a best-effort Ctrl/Cmd+P keyboard guard.
  • Disable copy/paste & text selection — blocks copy, cut, text selection, and the context menu across the page. Editable fields are exempted (search box, sign-in form, comment boxes stay fully usable), so turning this on does not break forms.

These are client-side deterrents only — a determined user with developer tools can still extract content. They raise the bar against casual copying, printing, and image saving, which is what the requirement asks for. Enable for reproduction-sensitive literary content; leave off for news where readers quote.

Section 5 — Session Limits

Max Simultaneous Logins (1–10) is the global fallback for the number of devices a reader can be signed in on at once. If the reader's active plan defines its own Max Devices (Subscription Plans → Limits & Quotas), the plan value wins. Set this global value for free/registered readers with no plan.

Section 6 — Content Access Rules

Rules override the access level for a whole group of content (section / category / tag / author) regardless of each article's own level.

  • Each rule targets a content type + a content ID/slug (e.g. fiction), and applies an access level.
  • When multiple rules match, the lowest priority number wins.
  • Rules can be toggled off without deleting; they save immediately (Add/Update Rule), independent of the page's Save Changes button.
  • A per-article TOC override still beats a Content Access Rule.

Add a rule via Add Rule (top-right of the card): Rule Name, Priority (lower wins), Content Type, Content ID/Slug (use the Strapi slug, not the title), Access Level.


Configuration Reference

Where every access setting lives, what it controls, its type, defaults, and the UI path.

Content access (set by editors)

SettingWhat it doesTypeValues / DefaultWhere configured (UI path)Role
Article Access LevelRequired level to read this web articleenum AccessLevelfree (default), restricted_free, premium_limited, subscriber_onlymandatoryAdmin → Content → Article Editor → Access LevelEditor / Editorial Director
Issue default accessDefault tier applied to every article in the issue's TOCenum AccessLevelfree / restricted_free / premium_limited / subscriber_only (optional; falls back to article level)Admin → Magazine → Issue Editor → Configuration → "Default access for articles in this issue"Admin / Editor
Per-article TOC overrideOverrides one article's level inside an issue; always winsenum AccessLevel?empty = inherit issue default; any tier overridesAdmin → Magazine → Issue Editor → TOC tab → per-row Access overrideAdmin / Editor

Plan entitlements (what grants access)

SettingWhat it doesTypeDefaultWhere configuredRole
accessDigitalIssuesFull magazine / subscriber_only accessbooleanfalseSubscription Plans → [Plan] → Access & EntitlementsAdmin
accessRestrictedMagazinesGrants restricted_free magazine tierbooleanfalseSubscription Plans → Access & EntitlementsAdmin
accessPremiumLimitedMagazinesGrants premium_limited magazine tierbooleanfalseSubscription Plans → Access & EntitlementsAdmin
accessPremiumArticles + Premium-Limited Monthly LimitPremium web articles + monthly quotaboolean + intfalse / 0Subscription Plans → Limits & QuotasAdmin
Subscriber-Only Monthly Limit (monthlySubscriberOnlyLimit)Quota for subscriber-only articlesint?null (unlimited); 0 blocksSubscription Plans → Limits & QuotasAdmin
Max DevicesPer-plan simultaneous logins (overrides global)intfrom planSubscription Plans → Limits & QuotasAdmin

Paywall behaviour (site-wide)

SettingWhat it doesTypeDefaultWhere configuredRole
Enable PaywallMaster gating on/offbooleanonPaywall & Access → Paywall SettingsSite Admin
Preview Type / CountLength of free previewenum / intWords / 200Paywall & Access → Content PreviewSite Admin
Registration / Subscribe message + CTAGate copy and buttonstext / urlplatform defaultsPaywall & Access → Paywall MessagesSite Admin / Editorial Director
Content ProtectionDisable image download / print / copy + selection — applies site-wide to all content, independent of the Enable Paywall switch3× booleanoffPaywall & Access → Content ProtectionSite Admin
Max Simultaneous LoginsGlobal device fallbackint (1–10)1Paywall & Access → Session LimitsSite Admin
Content Access RulesGroup-level access overridesrule listnonePaywall & Access → Content Access RulesSite Admin
Preview token4h HMAC bypass for editorial reviewgenerated linkn/aArticle/Issue editor preview actionEditor
CouponDiscount that drives which subscription is bought (indirect access)couponnoneMarketing → CouponsMarketing Admin

Dependencies & Impact

The paywall sits at the intersection of several modules. Changes here ripple outward:

  • Editorial — editors set each article's Access Level; this is the primary input to web-article gating. A miscategorised article is either over-exposed or wrongly locked.
  • Magazine — issue default access + per-article TOC overrides drive the four-tier ladder; this guide and the Magazine guide share that ladder. Flipbook delivery has its own cover-only preview gate.
  • Subscriptions — plan entitlements (accessDigitalIssues, magazine bits, quotas) are what grants access. Changing a plan's entitlements changes who gets through the gate on the next page load.
  • Reader Management — a reader's active subscription, gift/comp/institutional grants, and per-issue entitlements determine their ResolvedEntitlements.
  • Marketing — coupons and campaigns influence access indirectly by driving subscription purchases; CTA URLs on the gate route to marketing/checkout pages.

Impact notes: Turning the master paywall off exposes all gated content immediately. Content Protection is separate — its three toggles are enforced site-wide independently of the paywall switch, so turning the paywall off does not disable copy/print/download protection (and vice versa). Setting a plan's quota to 0 blocks that tier for all its readers. Editing a Content Access Rule or plan entitlement takes effect at next render — no re-publish needed. Crawler verification means SEO indexing keeps working even with the paywall on, as long as crawler IPs verify.


FAQ