For publishers
Cryptolect for EmDash — cipher-gated content for your CMS
A drop-in EmDash plugin that adds a cryptolectGated
Portable Text block to your authoring shell. Mark any section of a
post as gated; the plugin emits cipher-encoded HTML for unauthorized
agents and plaintext for authorized ones — no per-route plumbing,
no separate paywall service.
What's EmDash?
EmDash is a modern CMS for the agent-era web — built for publishers, journalists, and indie writers who want their content to read cleanly for both humans and the agents browsing on their behalf. It speaks Portable Text natively and ships a plugin runtime that hooks into authoring, render, and routing without forking the core. Cryptolect plugs into that runtime to add subscription-based agent access on top of EmDash's content model — so the cipher-gating sits next to your post body the same way a pull quote or a code block does.
What the plugin does
- Adds a
cryptolectGatedPortable Text block. Authors pick "Cryptolect Gated" from the slash menu, paste plaintext, and choose a cipher code. On save, the plugin's encode hook calls Cryptolect'sPOST /v1/encodewith your API key and persists the cipher-encodedemojitextin place of the plaintext. The plaintext never lands in your database. - Decodes on render for subscribed agents. A
page:fragmentshook walks the rendered document, finds gated blocks, and either returns plaintext (when the request carries a Cryptolect bearer that grants this cipher) or emits a structured403envelope with cipher metadata and acquisition options. - Registers MCP tools. The plugin exposes
read_gated_post,decode,check_access,list_accessible_ciphers, andget_acquisition_infothrough EmDash's MCP route, so agents discovering your site through MCP get a first-class path to gated content. - Ships an admin settings page. The publisher configures their Cryptolect API key (and optional API base URL override) once, in the EmDash admin shell. Plugin KV stores it encrypted; the key never leaves the server.
Install
pnpm add @cryptolect/emdash-plugin
# or
npm install @cryptolect/emdash-plugin Configure
Register the plugin in your EmDash Studio config and set the API
key in the admin settings page (or via the
CRYPTOLECT_API_KEY environment variable for
automated deploys).
// emdash.config.ts
import { defineConfig } from "emdash";
import { cryptolectPlugin } from "@cryptolect/emdash-plugin";
export default defineConfig({
plugins: [cryptolectPlugin],
});
Environment variables: CRYPTOLECT_API_KEY (required —
mint at app.cryptolect.dev/api-keys),
CRYPTOLECT_BASE_URL (optional — override the
production cluster).
How it renders
Mark a section gated in your post body and the plugin handles
both sides of the request. An anonymous reader (or an agent
without a granting subscription) sees the cipher-encoded
emojitext wrapped in a structured envelope; an
agent on a subscription that grants this cipher sees the
plaintext directly.
// Anonymous request → 403 envelope
{
"error": "cryptolect_gated",
"cipher_code": "pub-abc123",
"emojitext": "🦊🐉🌊🐻🐰🦊🌊🐉…",
"acquire_options": [
{ "type": "subscription", "url": "https://cryptolect.dev/pricing" }
]
}
// Subscribed-agent request → plaintext fragment, decoded server-side
{
"_type": "block",
"children": [{ "_type": "span", "text": "The full plaintext block." }]
}
The envelope is the same contract the agent SDK auto-decodes; if
your readers are running @cryptolect/sdk
they don't have to write any glue code.
Why a separate plugin?
The EmDash plugin is not the agent SDK. It serves a different audience and lives on a different side of the request: publishers install this plugin to gate their content; agent operators install the agent SDK to read it. If you landed here looking for the agent-side integration, that's where to go.
Reference
Cross-cutting reference for the publisher-side surface:
-
@cryptolect/emdash-pluginon npm — release notes, install snippets, and the published type declarations - /docs — protocol reference (cipher envelope contract, error vocabulary, gated request flow)
- emdash.dev — the EmDash CMS itself, including the Portable Text and plugin runtime documentation the gated block plugs into