Setting Up Syndication (POSSE)
This guide walks you through setting up syndication — automatically cross-posting your content to Bluesky and Mastodon when you publish. In IndieWeb terms, this is called POSSE: Publish on your Own Site, Syndicate Elsewhere.
Your site is the canonical source. Syndication copies go out to the platforms where people will actually see them, with a link back to the original on your site.
How It Works
There are two ways content gets syndicated:
-
Via Micropub — when you publish from an app like Quill, you choose which platforms to syndicate to using checkboxes. The syndication happens automatically after your content is committed to GitHub.
-
Via direct commit — when you write a markdown file and push it to GitHub yourself, add
syndicate: trueto the frontmatter. A webhook picks up the new file and syndicates it.
Both paths use the same underlying syndication code. Both are optional — if you don't configure any platform tokens, the feature stays invisible.
Before You Start
You'll need:
- This site deployed to Cloudflare Pages (see Setting Up Your IndieWeb Site)
- A Bluesky account (if you want to syndicate there)
- A Mastodon account (if you want to syndicate there)
- Access to the Cloudflare dashboard for your project
You can set up one platform or both. Each one is independent.
Setting Up Bluesky
Bluesky uses app passwords to let other services post on your behalf. An app password is a separate credential from your main login — if you ever need to revoke access, you can delete the app password without changing your account password.
Create a Bluesky App Password
- Log in to bsky.app
- Click on Settings
- Select Privacy and Security and click App passwords
- Click Add app password
- Give it a name you'll recognize, like "IndieWeb Site"
- Click Create app password
- Bluesky will show you the password once — it looks like
xxxx-xxxx-xxxx-xxxx. Copy it immediately. You won't be able to see it again. If you lose it, delete the app password and create a new one.
Add Bluesky Config
Two pieces of configuration are needed: your handle (not a secret, goes in your code) and the app password (a secret, goes in the Cloudflare dashboard).
wrangler.toml
Open wrangler.toml and uncomment the Bluesky lines in the [vars] section:
BLUESKY_HANDLE = "yourname.bsky.social"
Replace yourname.bsky.social with your actual Bluesky handle — without the @ sign. Just the domain-style handle. If you're using a custom domain as your handle, use that instead (e.g. example.com).
The BLUESKY_PDS_URL line can stay commented out — it defaults to https://bsky.social, which is correct unless you're running your own Personal Data Server.
Cloudflare Dashboard
- Go to the Cloudflare dashboard
- Click Workers & Pages in the left sidebar
- Click on your Pages project
- Go to Settings > Variables and Secrets
- Click Add
- Set the type to Secret
- Name it
BLUESKY_APP_PASSWORDand paste the app password you copied earlier - Click Save
- Trigger a new deployment — push a commit or retry the latest deploy. Secrets don't take effect until the next deployment.
Setting Up Mastodon
Mastodon uses access tokens to grant posting permission. You'll create an application on your Mastodon instance and use its token.
Create a Mastodon Application
- Log in to your Mastodon instance (e.g. mastodon.social)
- Go to Preferences (click your avatar, then Preferences or Settings)
- In the left sidebar under Development, click New application
- Fill in:
- Application name — something like "IndieWeb Site"
- Scopes — uncheck everything except
write:statuses. This is the minimum permission needed. Your site only needs to post statuses — it doesn't need to read your timeline, follow people, or access your account.
- Click Submit
- Click on the application name to see its details
- You'll see three values: Client key, Client secret, and Your access token. You only need Your access token — the other two are for OAuth flows that we don't use. Copy the access token.
Add Mastodon Config
Same pattern as Bluesky: instance URL in your code, access token in the dashboard.
wrangler.toml
Open wrangler.toml and uncomment the Mastodon line in the [vars] section:
MASTODON_INSTANCE_URL = "https://mastodon.social"
This is just the base URL of your instance — not your profile URL and not your handle. No @username path, just the domain. The access token already identifies your account, so the instance URL only tells the code where to send the request.
Replace mastodon.social with whatever instance you're on (e.g. hachyderm.io, fosstodon.org, etc.).
Cloudflare Dashboard
- Go to the Cloudflare dashboard
- Click Workers & Pages > your project > Settings > Variables and Secrets
- Click Add
- Set the type to Secret
- Name it
MASTODON_ACCESS_TOKENand paste the access token you copied earlier - Click Save
- Trigger a new deployment
Setting Up the Webhook (Optional)
The webhook enables syndication for content you create by writing markdown files and pushing to GitHub — the "direct commit" path. If you only publish through Micropub apps, you can skip this.
Create a Webhook Secret
The webhook secret is a shared password between GitHub and your site. It proves that incoming webhook requests are actually from GitHub and not someone else. Pick any random string — the longer and more random, the better.
An easy way to generate one:
- Go to generate.plus/en/base64 and generate a random string
- Or run
openssl rand -base64 32in your terminal
Copy whatever you generate. You'll need it in two places.
Add the Secret to Cloudflare
- Go to the Cloudflare dashboard
- Click Workers & Pages > your project > Settings > Variables and Secrets
- Click Add
- Set the type to Secret
- Name it
GITHUB_WEBHOOK_SECRETand paste your random string - Click Save
- Trigger a new deployment
Configure the GitHub Webhook
- Go to your repository on github.com
- Click Settings (the repository settings, not your account settings)
- Click Webhooks in the left sidebar
- Click Add webhook
- Fill in:
- Payload URL —
https://your-site.pages.dev/webhook(replace with your actual site URL) - Content type — select application/json
- Secret — paste the same random string you added to Cloudflare
- Which events? — select Just the push event
- Payload URL —
- Click Add webhook
GitHub will send a ping to verify the connection. If your site is deployed with the secret in place, you should see a green checkmark next to the webhook.
Using the Webhook
When you create a new markdown file and want it syndicated, add syndicate: true to the frontmatter:
---
title: My New Post
date: 2026-02-23
tags:
- posts
syndicate: true
---
Your post content here.
Push the commit. The webhook will pick up the new file, see syndicate: true, and post to whichever platforms you've configured. After syndication succeeds, the file will be updated with a syndicatedTo array containing the URLs of the cross-posted copies.
If you omit syndicate: true (or set it to false), the file is published to your site only. No cross-posting happens.
Test It
Micropub Path
- Go to quill.p3k.io and sign in with your site URL
- You should see checkboxes for Bluesky and/or Mastodon (whichever you configured)
- Write a test note, check the syndication boxes, and publish
- Check Bluesky and Mastodon — your note should appear on both, with a link back to your site
Direct Commit Path
- Create a test note in
src/notes/withsyndicate: truein the frontmatter - Commit and push to your main branch
- Check Bluesky and Mastodon after a few seconds
If the checkboxes don't appear in Quill, the most likely cause is that your secrets haven't taken effect yet. Make sure you triggered a new deployment after adding them.
How Syndicated Posts Look
Your content is formatted differently depending on the type:
- Posts (articles): The title in quotes, followed by the URL. e.g.
"My New Post"with a link tohttps://your-site.pages.dev/posts/my-new-post/ - Notes: The note content, followed by the URL
- Bookmarks:
Bookmarked: Titlewith the bookmarked URL, followed by a link to the bookmark page on your site
Checklist
After completing the steps above, verify that everything is working:
- [ ] (Bluesky)
BLUESKY_HANDLEis set inwrangler.toml - [ ] (Bluesky)
BLUESKY_APP_PASSWORDsecret is set in Cloudflare - [ ] (Mastodon)
MASTODON_INSTANCE_URLis set inwrangler.toml - [ ] (Mastodon)
MASTODON_ACCESS_TOKENsecret is set in Cloudflare - [ ] (Webhook)
GITHUB_WEBHOOK_SECRETsecret is set in Cloudflare - [ ] (Webhook) Webhook is configured in GitHub repo settings pointing to
/webhook - [ ] Quill shows syndication checkboxes when you sign in
- [ ] A test post appears on your configured platforms