A simple blog system using microservices
- Microservices-based architecture (Users, Posts, Comments, Web)
- Minimalist web UI (feed, profiles, login, signup)
- AI co-authoring for posts (OpenAI integration)
- Tagging and tag-based filtering for posts
- ActivityPub federation (Fediverse support: actors, inbox/outbox, followers, following, WebFinger)
- Persistent key and follower management for ActivityPub
- REST API for all major features
- GitHub Actions CI for Go tests
- Licensed under AGPL v3
- Services
- Web Interface
- AI Co-authoring Feature
- Tag Features
- Getting Started
- API Endpoints
- ActivityPub & Federation Support
- Project Structure
The project consists of the following microservices:
- Users: User management (create, read, update, delete)
- Posts: Post management (create, read, delete, list, tag management, AI co-authoring)
- Comments: Comment management (create, read, delete, list)
- Web: REST API and web app that uses all other services
A minimalist web interface for the blog, located in web/static/
:
index.html
: Main feed, create posts, view posts and commentslogin.html
: User login pagesignup.html
: User registration pageprofile.html
: User profile, posts, and comments
Everything is server side rendered
The blog includes an AI co-authoring feature that allows users to generate post content with the help of AI. When creating a post, users can:
- Enter a title and a brief description or outline of what they want to write about
- Click "Write with AI" to generate a full post based on their description
- Edit the generated content before posting
To use the AI co-authoring feature, you need to set your OpenAI API key as an environment variable:
export OPENAI_API_KEY=your_openai_api_key
Then start the posts service. The service will log whether the AI co-authoring feature is enabled based on the API key configuration.
The blog allows you to:
- Add tags to posts
- Remove tags from posts
- Filter the feed to show posts with a specific tag
- Browse all available tags
- Go 1.24 or higher
- Micro v5 (master branch)
To install Micro CLI:
go install github.com/micro/micro/v5@master
Make sure that $GOPATH/bin
(or $HOME/go/bin
) is in your PATH
so you can use the micro
command.
If you have Micro installed, you can run all services at once from the project root:
micro run
Browse to http://localhost:8080
GET /posts
: List all postsGET /posts/:id
: Get a post by IDPOST /posts
: Create a new post{ "title": "Post title", "content": "Post content" }
GET /comments
: List all comments (optionally filter bypost_id
query param)POST /comments
: Add a comment{ "content": "Comment content", "post_id": "post_id" }
GET /users
: List all usersGET /users/:id
: Get a user by IDPOST /users
: Create a new user{ "name": "User Name", "email": "[email protected]" }
POST /signup
: Register a new user (and log in){ "name": "User Name", "email": "[email protected]", "password": "plaintextpassword" }
POST /login
: Log in as a user{ "email": "[email protected]", "password": "plaintextpassword" }
POST /logout
: Log out the current userGET /users/me
: Get the current session user info
POST /posts/:id/tags
: Add a tag to a post{ "tag": "tagname" }
DELETE /posts/:id/tags/:tag
: Remove a tag from a postGET /tags
: Get all available tagsGET /tags?post_id=:id
: Get tags for a specific postGET /posts/by-tag/:tag
: Get posts with a specific tag
This blog platform supports ActivityPub federation, allowing your blog to participate in the decentralized social web (Fediverse).
- ActivityPub Actor: Each user is discoverable as an ActivityPub actor at
/users/:username/actor
. - Inbox/Outbox: Implements
/users/:username/inbox
and/users/:username/outbox
for receiving and publishing activities. - Followers/Following: Exposes
/users/:username/followers
and/users/:username/following
endpoints. Followers are stored persistently. - WebFinger Discovery: Supports
/.well-known/webfinger
for user discovery by remote servers. - Federated Posting: When a user is followed by remote Fediverse users, new posts are automatically sent as ActivityPub
Create
activities to all followers' inboxes. - Persistent Follower Storage: Followers are stored using
go-micro.dev/v5/store
for reliability and scalability. - Inbox Accepts: Handles incoming
Follow
requests and responds withAccept
activities. - Outbox: Exposes all user posts as ActivityPub
Create
activities for remote consumption.
- When a remote user follows a blog user, their inbox URL is stored as a follower.
- When a new post is published, a
Create
activity is sent to all followers' inboxes. - Followers are managed in persistent storage, not just in memory.
- The outbox endpoint lists all posts as ActivityPub activities for the user.
GET /.well-known/webfinger?resource=acct:[email protected]
– WebFinger discoveryGET /users/alice/actor
– ActivityPub actor for AlicePOST /users/alice/inbox
– Receive ActivityPub activities (Follow, Like, etc.)GET /users/alice/outbox
– List Alice's posts as ActivityPub Create activitiesGET /users/alice/followers
– List Alice's followers
To enable ActivityPub federation, you must set the DOMAIN
environment variable to your public domain name (e.g. example.com
). This is required so that outgoing ActivityPub activities use the correct URLs for your actors and posts.
Example:
export DOMAIN=example.com
- The
DOMAIN
variable should be set in the environment for all services (especiallyusers
,posts
, andweb
). - If running locally for testing, you can use
localhost
or your local IP, but federation will only work with a public domain.
After setting DOMAIN
, start your services as usual:
micro run
Your blog will now be discoverable and federated on the Fediverse using your configured domain.
- HTTP signatures for outgoing federation are now implemented (recommended for production).
- Follower management is persistent and robust.
- The platform is compatible with Mastodon, Friendica, and other Fediverse software.
blog/
├── comments/ # Comments service
│ ├── handler/ # Request handlers
│ ├── main.go # Entry point
│ └── proto/ # Protobuf definitions
├── posts/ # Posts service
│ ├── handler/
│ ├── main.go
│ └── proto/
├── users/ # Users service
│ ├── handler/
│ ├── main.go
│ └── proto/
└── web/ # REST API and static web UI
├── main.go # REST API server
└── static/ # Static web UI (index.html, login.html, signup.html, profile.html)