Members-only posts (Clerk)
Mark a post as members-only and everyone still sees its title, summary and photo, but only signed-in members can read the text. Visitors sign in (or sign up, free) on Clerk’s hosted pages, and come straight back to the post.
Templates: all, on their blog, journal, news or stories posts (a site made earlier gets it with npx wptom update).
Service: Clerk (free plan available; see Clerk’s pricing for larger
member counts).
Settings: PUBLIC_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY.
How it works
Section titled “How it works”- The switch. In the content editor, a post has a Members only switch (next to Draft). Off by default.
- The public page. A members-only post’s normal address (e.g.
/journal/<slug>) shows the date, title, summary and photo, then a panel saying the post is for members, with a Sign in to read button. The text itself isn’t in that page at all. - The members page. The button leads to
/members/<slug>. That page is rendered on the server for every request: Clerk checks whether the visitor is signed in. A signed-out visitor is sent to Clerk’s sign-in page and, after signing in, back to the post with its full text. A signed-in member sees the text right away. - No Clerk script on your site. Signing in happens on Clerk’s hosted pages (its Account
Portal). Your own pages load no Clerk JavaScript, so they stay as fast as before; the check
runs on the server, only on
/members/…pages. - The text stays private. A members-only post’s text is left out of the search index,
llms.txtand the AI chat’s knowledge (they get the title and summary only). Search engines can’t sign in, so they never see it either. - The account link. Under the post, members get a link to their account page on Clerk, where they edit their profile and sign out.
The panel’s texts are in Interface texts → Journal → Members (or your template’s blog or stories group): badge, title, text, button, the “not open yet” note and the account link.
Without keys
Section titled “Without keys”The switch and the panel work. Sign in to read leads to a page with the post’s title and the “members area isn’t open yet” note, and a link back. Nobody can read the text.
Hosting: it needs a server
Section titled “Hosting: it needs a server”The members pages are rendered on request, so the site needs a host that runs server code. On Vercel this works out of the box (the page becomes a Vercel Function; the rest of the site stays static). The EmDash variant on Cloudflare renders on request anyway. A purely static host without functions can’t serve members-only posts.
1. Create a Clerk application
Section titled “1. Create a Clerk application”- Sign up at clerk.com and click Create application.
- Name it after your site; members see this name on the sign-in page.
- Choose how members sign in: Email (Clerk sends a code or link; no password to remember) is the simplest. Add Google or other social logins if you like. You can change this later under Configure → User & authentication.
- Create it. Clerk shows the keys of its development instance.
Who can join: by default anyone can sign up. To invite only certain people, switch the sign-up mode to restricted or waitlist under Configure → Restrictions and invite members from Users.
2. Add the keys
Section titled “2. Add the keys”From Configure → API keys (or the quick-start screen), copy both keys into .env:
PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...CLERK_SECRET_KEY=sk_test_...PUBLIC_CLERK_PUBLISHABLE_KEY(pk_test_…now,pk_live_…later): public, it tells the server which Clerk application to use.CLERK_SECRET_KEY(sk_test_…, latersk_live_…): secret, server only. Never commit it.
Restart npm run dev.
3. Mark a post
Section titled “3. Mark a post”In the content editor, open a post, turn on Members only, and Save.
4. Try it on your computer
Section titled “4. Try it on your computer”- Open the post at its normal address. You should see the title, summary and photo, then the members panel instead of the text.
- Click Sign in to read. Clerk’s sign-in page opens on an
accounts.devaddress with your application’s name. - Sign up with your email and the code Clerk sends. You land back on
/members/<slug>with the whole post, and a link to your account. - Open the account link: Clerk’s account page, where you can sign out. After signing out,
/members/<slug>sends you to sign-in again. - Search your site for a word that is only in the members-only text: it isn’t found.
Members you create in development exist only in the development instance; they don’t carry over to production.
5. Go live on your own domain
Section titled “5. Go live on your own domain”The development instance is for testing (its pages show a “development mode” note). For the live site, create a production instance on your domain:
- In Clerk, click the instance switcher (top of the dashboard) → Create production instance. You can clone the development settings.
- Enter your site’s domain. Clerk shows the DNS records to add (CNAME records, among them
clerk.<your-domain>andaccounts.<your-domain>). - Add those records where your domain’s DNS is managed (on Vercel: Domains → your domain → DNS Records), then click Verify in Clerk. Wait until every record and the certificates are confirmed.
- If you offer social logins, set up your own OAuth credentials for production as Clerk describes on that screen.
- Copy the production keys (
pk_live_…,sk_live_…) into Vercel, Settings → Environment Variables, asPUBLIC_CLERK_PUBLISHABLE_KEYandCLERK_SECRET_KEY. Keep the test keys in your.env. - Redeploy (the publishable key is written in at build time).
- On the live site, sign in once from a members-only post.
Clerk’s sign-in and account pages then live on accounts.<your-domain>, under your own
domain. Ad blockers don’t block them, unlike the development instance’s pages, and members see
your domain all the way. The account link under each post follows automatically.
Turn it off
Section titled “Turn it off”- For one post: turn its Members only switch off. The text appears on the public page again after the next deploy.
- Entirely: remove both Clerk variables in Vercel and redeploy. Members-only posts then show the “not open yet” note, and Clerk’s code doesn’t run at all.
Troubleshooting
Section titled “Troubleshooting”| What you see | Why, and what to do |
|---|---|
| “The members area isn’t open yet” | PUBLIC_CLERK_PUBLISHABLE_KEY isn’t set where the site was built: restart npm run dev, or add it in Vercel and redeploy |
| An error page instead of Clerk’s sign-in | CLERK_SECRET_KEY is missing or belongs to another instance (a sk_test_ key with a pk_live_ key, or the other way round). Both keys must come from the same instance |
| Continue on Clerk’s sign-in does nothing | A browser extension blocks the development instance’s accounts.dev pages. Try a private window; on your live site use a production instance on your own domain |
| After signing in, you’re asked to sign in again | The keys come from different Clerk applications, or the browser blocks Clerk’s cookies for your domain. Check both keys, and try another browser |
| Signed in, but the public post still shows the panel | That’s by design: the public page never contains the text. Members read it at /members/<slug>, where Sign in to read leads |
/members/<slug> sends you to the public post |
The post isn’t marked Members only (or the change isn’t deployed yet) |
| The production instance won’t verify | The DNS records aren’t in place yet, or a proxy (e.g. Cloudflare’s orange cloud) is on for the Clerk records. Turn the proxy off for them and wait a few minutes |