Skip to content

TryGhost/ActivityPub

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Β 

Ghost Ghost

Β 

ActivityPub

A multi-tenant ActivityPub server for Ghost, built with Fedify. This service makes it possible for independent websites to publish their content directly to the Fediverse, enabling networked publishing to the open social web.

Running locally for development

All requests to /.ghost/activitypub/*, /.well-known/webfinger and /.well-known/nodeinfo are proxied to this ActivityPub service using nginx. All other requests are forwarded to Ghost. This setup has only been tested on macOS using Docker for Mac and OrbStack.

Setup

  1. Install Ghost using Install from source instructions
  2. Expose your local port 80 (nginx) with Tailscale (or ngrok)
    • Use tailscale funnel 80 or ngrok http 80 to expose your local port 80 (not 2368!), on which nginx will be running
  3. Configure Ghost
    • In the Ghost monorepo, create a config.local.json file under ghost/core/config.local.json, with the following configuration:
    {
        "url": <Tailscale or ngrok URL from step 2>
    }
    
  4. Start the ActivityPub Service
    • Run yarn dev && yarn logs in the root directory of this project
  5. Start Ghost
    • Run yarn dev in the Ghost monorepo
    • If you were already running Ghost locally, make sure to restart it!

πŸ—οΈ Architecture & Development Guidelines

For AI assistants: See AGENTS.md for comprehensive guidance with code examples. For developers: See Architecture Decision Records in /adr for detailed rationale.

Core Architecture Patterns

This service follows Domain-Driven Design with specific patterns:

  • Immutable Entities with Events (ADR-0003) - Entities return new instances with domain events
  • Result Type Pattern (ADR-0004) - Use Result<T, E> for explicit error handling
  • Error Objects in Results (ADR-0005) - Enhanced Result types with contextual error objects
  • Class-Based Architecture (ADR-0006) - All components use classes with dependency injection
  • Repository Pattern (ADR-0007) - Services orchestrate logic, repositories handle data access
  • View Pattern for Reads (ADR-0008) - Optimized read queries separate from write path
  • Hash-Based Lookups (ADR-0009) ⚠️ - ActivityPub IDs use SHA256 hashes
  • Decorator Routing (ADR-0010) - Routes defined via decorators

Project Structure

src/
β”œβ”€β”€ account/            # Immutable entities
β”œβ”€β”€ post/               # Being migrated to immutable
β”œβ”€β”€ activity-handlers/  # Class-based handlers
β”œβ”€β”€ http/api/           # REST controllers
β”œβ”€β”€ core/               # Shared utilities
└── dispatchers.ts      # Legacy - don't add here

⚠️ Critical Gotchas

1. Database lookups MUST use SHA256 hashes (ADR-0009)

  • Never use where('ap_id', apId) - it returns empty results silently!
  • Always use whereRaw('ap_id_hash = UNHEX(SHA2(?, 256))', [apId])
  • Applies to: ap_id, domain (with LOWER), ap_inbox_url (with LOWER)

2. Result types require helper functions

  • Use isError(result), getValue(result), getError(result)
  • Never destructure directly like [error, value]

3. Services must use repositories

  • Views can query DB directly (read optimization)
  • Services MUST go through repositories (write path)

4. Dependency injection names must match

  • Parameter accountService β†’ registered as 'accountService'
  • Parameter db β†’ registered as 'db'

5. Avoid these anti-patterns:

  • Adding to dispatchers.ts β†’ create new handler classes
  • Using AccountType β†’ use Account entity
  • Direct DB queries in services β†’ use repositories
  • String comparisons for AP IDs β†’ use hash lookups

For complete code examples demonstrating correct patterns, see AGENTS.md.

Code formatting + linting

We use Biome for code formatting and linting.

If you use VS Code, you can install the Biome extension to get inline feedback.

To enable auto-formatting on save, you'll need to set the default formatter to Biome and enable Format on Save in your VS Code settings.

Running Tests

  • Run yarn test to execute tests within a Docker Compose stack.

Populating the DB

The below command will populate the DB with ~5000 followers for the activitypub host

  • Run docker compose run scripts populate-activitypub-db

Migrations

docker compose run migrate or docker compose run migrate-testing will run the up migrations against your dev or testing db respectively.

If you would like to run other commands you can run docker compose exec -it migrate /bin/bash or docker compose exec -it migrate-testing /bin/bash - This will drop you into a shell with the migrate binary available as well as a MYSQL_DB environment variable that is correctly formated for use as the -database argument to the migrate binary

Β 

Copyright & license

Copyright (c) 2013-2025 Ghost Foundation - Released under the MIT license. Ghost and the Ghost Logo are trademarks of Ghost Foundation Ltd. Please see our trademark policy for info on acceptable usage.

About

A full-featured ActivityPub server for networked publishing with Ghost

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

  •  

Packages