unichronic/postificus

Write once. Publish everywhere

โ˜… 1Forks 1GoGitHub โ†—Compare

Project website โ†—

README

Postificus: Centralized Content Distribution Engine

Go Version React Docker Redis Status

Postificus is a high-performance, event-driven content engine designed to solve the fragmentation of technical blogging. It allows authors to write content once and orchestrate its distribution across a disparate ecosystem of platforms (Medium, Dev.to, LinkedIn) while strictly enforcing SEO authority via Canonical URLs.

๐Ÿš€ Architecture

The system moves beyond simple API scripting by implementing a Multi-Stage Resilience Pipeline.

1. The Core (Backend)

Built with Go and Echo, the backend is split into two services for scalability:

  • API Service (cmd/api): Handles REST endpoints, authentication, and job enqueuing. High throughput, low latency.
  • Worker Service (cmd/worker): Consumes jobs from Redis (via Asynq) and executes heavy automation tasks. This isolation prevents browser automation from blocking HTTP requests.

2. The Interface (Frontend)

A modern, distraction-free writing experience built with React, Vite, and TailwindCSS.

  • Editor: Powered by Tiptap, offering a Notion-like rich text experience.
  • Real-time Status: Polls the backend for publication status across all platforms.

๐Ÿ›ก๏ธ The "Unstoppable" Delivery System

Unlike standard cross-posters that fail when an API goes down, Postificus implements a Hierarchical Fallback Strategy:

Priority Method Description
1. Primary Direct API Uses official REST APIs (e.g., Dev.to). Fastest and most reliable.
2. Last Resort Stealth Automation The "Nuclear Option." Uses Go-Rod to launch a headless browser, bypass bot detection, log in, and physically type the content into the editor. Used for platforms without write APIs (like LinkedIn personal profiles).

โœจ Key Features

๐Ÿง  Core Backend

  • Event-Driven Architecture: Decoupled ingestion and processing layers.
  • SEO Guardrails: Automatically manages rel=canonical tags to protect your domain authority.
  • Concurrency Control: Worker pools are rate-limited per domain to prevent IP bans.

๐Ÿ•ต๏ธ Browser Automation

  • Stealth Mode: Uses rod-stealth to strip navigator.webdriver flags, allowing the bot to pass as a human user on Single Page Applications (SPAs).
  • Headless Production: Automatically detects production environments (Docker/Render) to run headlessly, while keeping the UI visible for local debugging.

๐Ÿš€ Getting Started

Follow these instructions to set up the project locally.

Prerequisites

  • Go: v1.24 or higher
  • Node.js: v20 or higher (for frontend)
  • Docker: (Optional) For containerized execution
  • Redis: Required for the task queue (if running locally without Docker)
  • PostgreSQL: Required for the database (if running locally without Docker)

Installation

  1. Clone the repository

    git clone https://github.com/unichronic/postificus.git
    cd postificus
  2. Configure Environment Copy the example environment file and fill in your credentials:

    cp .env.example .env

    Note: You will need to obtain session cookies/tokens for Dev.to, Medium, and LinkedIn manually from your browser dev tools if you plan to use the automation features.

Running with Docker (Recommended)

The easiest way to run the entire stack (DB, Redis, API, Worker, Frontend) is using Docker Compose.

docker-compose up --build

The application will be available at:

Local Development

If you prefer to run services individually for development:

  1. Start Dependencies (DB & Redis)

    docker-compose up -d db redis rabbitmq
  2. Run the Backend (API)

    go run cmd/api/main.go
  3. Run the Worker (in a separate terminal)

    go run cmd/worker/main.go
  4. Run the Frontend

    cd frontend
    npm install
    npm run dev

โ˜๏ธ Deployment

The system is architected for a modern cloud stack:

  • Backend: Deployed as a Docker container on Render.
    • Note: Requires a custom Dockerfile to include Chromium dependencies.
  • Frontend: Deployed as a static SPA on Vercel (or any static host).
  • Database: Supabase Postgres (Direct connection).
  • Auth: Supabase Auth (JWTs validated by API).
  • Cache/Queue: Redis Cloud.
  • Task Queue: CloudAMQP (RabbitMQ).
  • Object Storage: Supabase Storage (S3-compatible).
  • Monitoring: Grafana Cloud (Agent + remote_write).

Production Environment Variables

Make sure these are set in Render (or your hosting dashboard):

  • DATABASE_URL (Supabase Direct URL with sslmode=require)
  • REDIS_URL (Redis Cloud URL. Use redis:// for non-TLS, rediss:// for TLS)
  • RABBITMQ_URL (CloudAMQP amqps:// URL)
  • SUPABASE_URL
  • SUPABASE_STORAGE_BUCKET
  • S3_ENDPOINT, S3_ACCESS_KEY, S3_SECRET_KEY
  • DEFAULT_USER_ID (use 00000000-0000-0000-0000-000000000001 until Auth is wired)

๐Ÿ› ๏ธ Tech Stack

  • Language: Golang 1.24
  • Frontend: React, Vite, TailwindCSS
  • Web Framework: Echo v4
  • Task Queue: Asynq (Redis)
  • Browser Automation: Go-Rod (Stealth + CDP)
  • Database: Supabase Postgres (pgx)
  • Auth: Supabase Auth
  • Infrastructure: Render, Redis Cloud, CloudAMQP, Supabase Storage, Grafana Cloud

Contributors

unichronic

Issues