Quick Start
Meridian requires PostgreSQL 16 and optionally Redis for caching. The fastest way to get started is Docker Compose, which handles everything for you.
Prerequisites: Docker and Docker Compose installed, or Deno 2.x and PostgreSQL 16 for local development.
Open http://localhost:8000 and log in with the default admin credentials. Change these immediately in production.
| Setting | Default |
|---|---|
| Admin Email | admin@meridian.blog |
| Admin Password | changeme123 |
| App Port | 8000 |
Docker Deployment
The included docker-compose.yml sets up PostgreSQL, Redis, and the Meridian app. This is the recommended way to run Meridian in production.
Production Setup
Docker Commands
| Command | Description |
|---|---|
make dev | Start all services (development) |
make stop | Stop all services |
make logs | Tail application logs |
make db-shell | Open PostgreSQL shell |
make db-reset | Reset database (destroys all data) |
Warning: make db-reset destroys all data. Always back up your database before running this in production.
Local Development (Deno)
If you prefer running without Docker, install Deno 2.x and have a PostgreSQL 16 instance available.
Development Commands
| Command | Description |
|---|---|
deno task dev | Dev server with hot reload |
deno task test | Run all tests |
deno task db:migrate | Run database migrations |
deno task db:seed | Seed sample content |
deno fmt | Format code |
deno lint | Lint code |
Configuration
All configuration is via environment variables. Copy .env.example to .env and edit as needed.
Required Variables
Optional Variables
Tip: Without email configured, newsletters log to console — useful for local development.
Stripe Setup
Meridian integrates with Stripe for member subscriptions. You connect your own Stripe account and keep 100% of revenue (minus Stripe's standard processing fees).
- Create a Stripe account
- Add your
STRIPE_SECRET_KEYto.env - Create subscription tiers in the Meridian admin dashboard
- Set up a webhook endpoint at
https://yourdomain.com/api/stripe/webhook - Subscribe to events:
checkout.session.completed,customer.subscription.updated,customer.subscription.deleted,invoice.payment_failed - Add the
STRIPE_WEBHOOK_SECRETto.env
Meridian auto-creates Stripe Products and Prices from your tiers — no manual Stripe dashboard configuration needed beyond the initial API key setup.
Email Setup
Meridian supports multiple email providers for sending newsletters. Resend is recommended for its developer experience and deliverability.
- Create a Resend account and verify your domain
- Set
EMAIL_PROVIDER=resendin your.env - Add your
EMAIL_API_KEY - Set
EMAIL_FROMto your verified sender address
Deliverability: Meridian enforces DKIM/DMARC/SPF and includes one-click unsubscribe headers for Gmail/Yahoo compliance.
Deploy to Railway
Railway provides the simplest deployment experience with managed PostgreSQL and automatic SSL.
- Click the "Deploy on Railway" button on our GitHub repo
- Railway auto-provisions PostgreSQL and Redis
- Set your environment variables in the Railway dashboard
- Add a custom domain (optional, Railway provides a free subdomain)
Estimated cost: Railway's Hobby plan ($5/mo) is sufficient for most publications under 10,000 monthly views.
Deploy to Fly.io
Fly.io deploys your app globally on micro-VMs with automatic edge routing. Great for publications with a global audience.
Deploy to Render
Render auto-deploys from GitHub and offers a free PostgreSQL tier — ideal for getting started at no cost.
- Fork the Meridian repository on GitHub
- Create a new Web Service on Render, connected to your fork
- Add a PostgreSQL database (free tier available)
- Set environment variables in the Render dashboard
- Render auto-deploys on every push to
main
Note: Render's free PostgreSQL tier expires after 90 days. Upgrade to a paid tier for production use.
API Reference
Meridian exposes a REST API for all operations and a GraphQL endpoint for content queries.
Public Endpoints (No Auth)
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/public/site | Site settings and social links |
| GET | /api/public/posts | Published posts (paginated) |
| GET | /api/public/posts/:slug | Single post by slug |
| GET | /api/public/tags | All tags with post counts |
| GET | /api/public/pages/:slug | Static page |
| GET | /api/public/search?q= | Full-text search |
| GET | /api/public/rss | RSS 2.0 feed |
| POST | /api/public/subscribe | Newsletter signup |
Admin Endpoints (JWT Required)
| Method | Endpoint | Description |
|---|---|---|
| GET/POST | /api/posts | List or create posts |
| PUT/DELETE | /api/posts/:id | Update or delete a post |
| GET/POST | /api/pages | List or create pages |
| GET | /api/members | List members |
| POST | /api/newsletters/:id/send | Send a newsletter |
| GET | /api/analytics/dashboard | Dashboard statistics |
| GET/PUT | /api/settings | Site settings |
Stripe Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/stripe/tiers | Active subscription tiers |
| POST | /api/stripe/checkout | Create checkout session |
| POST | /api/stripe/portal | Customer billing portal |
| POST | /api/stripe/webhook | Stripe webhook handler |
GraphQL
Available at /graphql in development mode. Supports content queries with personalization and member context.
Updating Meridian
Pull the latest changes and restart. Migrations run automatically on startup.
Backup first: Always back up your database before updating. pg_dump meridian > backup.sql