π§ note - still under construction π§
A template for Newspeak House fellows to publish field notes from a Matrix channel to the fellowship website. Each fellow gets their own repo, their own export, and their own content.json that the site pulls in at build time.
- Connects to your Matrix field-notes channel and fetches the full message history
- Keeps only emoji-tagged root posts and their thread replies
- Maps each post to a type (
journal,link,field_note, etc.) based on its leading emoji - Auto-extracts keywords from your text using YAKE
- Validates the output and excludes items with data issues
- Commits
content.jsonto your repo -- the site picks it up at build time
Create a dedicated Matrix account for the bot (e.g. @yourname-field-notes:matrix.campaignlab.uk):
-
Register β Log into your homeserver (e.g. Element for matrix.campaignlab.uk) and create a new account, or ask an admin to create one for you.
-
Invite the bot to your room β The bot can only read rooms it's a member of. From your field-notes channel, invite the bot user (or have a room admin do it).
-
Choose auth method:
- Password β Easiest for GitHub Actions. Use the bot's login password.
- Access token β In Element: All settings β Help & about β Access token. Copy the token (starts with
syt_). Use this instead of a password if you prefer not to store the password in secrets.
-
Get the room ID β In Element: click the room name β "Room info" (or "View room address"). Use the room ID (
!abc123:server) or alias (#field-notes:server).
Click "Use this template" on GitHub to create your own copy (e.g. nwspk/yourname-field-notes).
Go to Settings > Secrets and variables > Actions and add:
| Secret | Required | Description |
|---|---|---|
MATRIX_USER |
yes | Bot user id (@bot:server) |
MATRIX_PASSWORD |
yes* | Bot password |
MATRIX_ACCESS_TOKEN |
yes* | Or use a token instead of password |
MATRIX_ROOM_ID |
yes | Your field-notes room id or alias |
MATRIX_HOMESERVER |
Default: https://matrix.campaignlab.uk |
|
SITE_REPO |
Site repo to rebuild (e.g. nwspk/2025.newspeak.house) |
|
SITE_DEPLOY_TOKEN |
GitHub PAT with repo dispatch access |
* Provide either MATRIX_PASSWORD or MATRIX_ACCESS_TOKEN.
The SITE_REPO and SITE_DEPLOY_TOKEN secrets are optional -- when set, the workflow will trigger a rebuild of the fellowship site after each export so your new posts appear automatically.
The workflow runs daily at 6 AM UTC and can also be triggered manually from the Actions tab.
To test locally:
pip install -r requirements.txt
cp .env.example .env # fill in your credentials
python bot.py exportOnce the first export runs, your content.json is available at:
https://raw.githubusercontent.com/nwspk/yourname-field-notes/main/content.json
The fellowship site fetches this URL at build time to display your posts. See docs/SITE_INTEGRATION.md for the integration spec (schema, fetch pattern, rendering notes).
Start each post with an emoji so the bot classifies it correctly.
| Emoji | Type | Use for |
|---|---|---|
| π | link | Bare URL or [title](url) with no extra prose |
| π₯ | journal | Short reading notes -- lists, quotes, brief reflections |
| π | field_note | Longer reflections, analysis, "Field Note:" posts |
| π‘ | idea | Ideas, brainstorms |
| πΎ | project | Tools, apps, projects you're tracking |
| β | question | Questions to explore |
| π | blog_post | Link to a published blog post (e.g. Substack) |
- Links vs journal: Use π for bare links. If you add more than a short caption, use π₯.
- Journal vs field note: π₯ for short notes; π for longer reflective pieces.
- Blog posts: Use π with a link to your Substack (or other blog) post.
Keywords are auto-extracted from your post text -- no need to add them manually. You can also include #hashtags anywhere in a post and they'll be merged with the auto-extracted keywords.
π https://example.com/article
π₯ Homework from Matt -- tell me 1 thing from each section
π Field Note: On the legitimacy of the governance module
π‘ An app that forwards newsletters to this channel #automation
π https://yourname.substack.com/p/my-post-title
content.json contains:
{
"messages": [
{
"id": "$event_id",
"ts": 1771110622252,
"type": "journal",
"body": "π₯ Notes on ...",
"formatted_body": "<p>π₯ Notes on ...</p>",
"parent_id": null,
"keywords": ["civic tech", "governance"]
}
],
"processed_ids": ["$event_id", "..."],
"last_processed_ts": 1771110622252
}Types: journal, link, question, idea, project, field_note, blog_post, reply
python bot.py export # one-shot: fetch history, write content.json, exit
python bot.py run # daemon: stay online, export on !export command| File | Purpose |
|---|---|
bot.py |
Matrix bot -- connects, fetches history, writes content.json |
export.py |
Core logic -- filters, classifies, and transforms messages |
validate_export.py |
Validates output and excludes flagged items |