Postlume

AI social media scheduler SaaS: plan, write, approve and publish posts to nine networks from one calendar. Next.js 16, PostgreSQL and Docker.

Version 1.0.0 · 16 October 2026

1. Welcome

Thank you for buying Postlume. This guide takes you from the download to a running site with your own name, your own keys and your first paying customer. You do not need to write code. Every step that needs a terminal shows the exact command.

Postlume is a complete software-as-a-service product. Your customers sign up, create a workspace, add brands, connect their social accounts and schedule posts. You run the site, set the plans and keep the money.

What is inside

Screenshots

The app (what your customers use)

Dashboard
Dashboard
Composer with AI writer
Composer with the AI writer
Calendar month view
Calendar, month
Calendar week view
Calendar, week with open queue slots
Queue
Queue and time slots
Approvals
Approvals
Media library
Media library and AI images
Bulk upload
Bulk CSV upload with row checks
Analytics
Analytics
Connected accounts
Connected accounts
Team
Team and roles
Billing
Billing
Settings
Brands and settings
Dark mode
Dark mode

The admin panel (what you use)

Admin overview
Overview
AI and network keys
AI and network keys
Setup check
Setup check
Plans editor
Plans editor
Branding
Branding
Users
Users

Public pages

Landing page
Landing page (can be switched off)
Sign in
Sign in

The screenshots come from our live demo, which runs in demo mode: the banner at the top and the one-click demo sign-in only appear in demo mode, never on your site.

2. Requirements

Third-party services

Postlume talks to the services below only when you add their keys. Each provider has its own pricing tiers, limits and terms, and you (the buyer) are responsible for any costs and for following each provider's rules. Prices change; check each provider's own pricing page before you launch.

ServiceUsed forWhere to get keysCost notes
X (Twitter) APIPosting to X, follower countsdeveloper.x.comX sells API access in tiers; posting volume depends on your tier. Some tiers are paid.
LinkedInPosting to LinkedIn profileslinkedin.com/developersOwn terms and rate limits.
Meta (Facebook, Instagram, Threads)Pages, Instagram business accounts, Threadsdevelopers.facebook.comApp review needed before other people can connect.
Google (YouTube, Google sign-in)YouTube uploads, “Continue with Google”console.cloud.google.comYouTube Data API has a daily quota; more quota needs an audit.
TikTokVideo and photo postsdevelopers.tiktok.comPosts are private until TikTok audits your app.
PinterestPinsdevelopers.pinterest.comTrial access first, standard access after review.
BlueskyPosts (users connect with an app password)No keys neededOwn terms and rate limits.
OpenAI, Anthropic, Google GeminiAI captions, rewrites, hashtags, ideas, imagesOpenAI, Anthropic, Google AI StudioBilled per use by the provider. Plan credits in Postlume limit how much each customer can use.
StripeSubscriptions, checkout, customer portaldashboard.stripe.comStripe charges a fee per payment.
SMTP provider (any)Invites, approvals, password resetsYour email providerOwn pricing.
S3-compatible storage (optional)Media filesAWS S3, Cloudflare R2, Backblaze B2, MinIOOwn pricing. Not needed: files can stay on your server.
HostingYour server and domainAny VPS providerOwn pricing.

Fonts: the fonts are downloaded once when the site is built and then served from your own server, so visitors' browsers never contact Google Fonts.

3. Quick start (Docker)

  1. Unzip the download and open a terminal in the postlume folder.
  2. Copy the settings file:
    cp .env.example .env
  3. Open .env in a text editor and fill in three values:
    • APP_URL: the address you will open, for a test on your computer http://localhost:3000.
    • APP_SECRET: a long random string. Make one with openssl rand -hex 32. Never change it later.
    • POSTGRES_PASSWORD: any password of letters and digits.
  4. Start everything:
    docker compose up -d
    The first start builds the images and takes a few minutes. Docker then starts PostgreSQL, runs the database migrations, starts the website and the worker.
  5. Open APP_URL in your browser. The install wizard opens (next section).

Check that everything runs: docker compose ps shows web and worker as running and migrate as exited with code 0. Logs: docker compose logs -f web worker.

4. Install wizard and sample data

The first visit opens /install. It has five short steps:

  1. Check: confirms the database is reachable and up to date.
  2. Your admin account: name, email and password of the site owner (you).
  3. Your site: product name, tagline and support email. You can change them later in Admin → Branding.
  4. Sample data: load the “Fernwood Coffee” sample workspace (four brands, nine demo accounts, two months of posts, approvals and numbers) so every page has content while you explore. Remove it any time in Admin → Setup check → Remove sample data.
  5. Done: go to the admin panel or the app.

The wizard locks itself once an admin exists. A second admin can be added later by changing a user's role in Admin → Users.

5. Put it online (VPS, HTTPS)

  1. Point your domain (for example social.example.com) to the server's IP address with an A record.
  2. Copy the postlume folder to the server (for example with scp or git), then fill in .env as in the quick start, with APP_URL=https://social.example.com and DOMAIN=social.example.com.
  3. Open ports 80 and 443 on the server's firewall.
  4. Start with the HTTPS profile:
    docker compose --profile https up -d
    Caddy gets a free Let's Encrypt certificate for DOMAIN and forwards traffic to the website.

Already run Traefik, Nginx or another proxy? Skip the HTTPS profile and forward your domain to port WEB_PORT (default 3000) on the server.

6. Other hosting

Without Docker (Node.js)

cd postlume
cp .env.example .env          # set DATABASE_URL, APP_URL and APP_SECRET
pnpm install
pnpm prisma:migrate:deploy    # creates the tables
pnpm prisma:seed              # plans and default settings
pnpm build
pnpm start                    # the website on port 3000
pnpm worker                   # in a second terminal: publishes scheduled posts

Keep pnpm start and pnpm worker running with a process manager such as systemd or pm2 (pm2 start "pnpm start" --name postlume-web, pm2 start "pnpm worker" --name postlume-worker).

Vercel and other serverless hosts

The website runs on Vercel with a managed PostgreSQL database (Neon, Supabase, Railway, …) and an S3 bucket for media (serverless hosts have no lasting disk). The worker must run somewhere that stays on, for example a small VPS or a Railway or Render worker with the same .env, because scheduled posts are published by it, not by the website.

7. Setup check

Admin → Setup check lists every part of the site with a green, amber or red mark: database, app address, app secret, the worker's last heartbeat, email, payments, file storage, AI and each social network. It also lists every key from .env with a short explanation. Run pnpm run doctor (or docker compose run --rm worker node_modules/.bin/tsx --conditions=react-server src/scripts/doctor.ts) for the same check in a terminal.

8. Connect social networks

Each network needs an “app” that you create once in that network's developer portal. Your customers then click Connect an account and sign in on the network; they never see your keys.

X (Twitter)

  1. Open the X developer portal, create a project and an app.
  2. In User authentication settings choose OAuth 2.0, type “Web App”, permissions Read and write.
  3. Callback URL: <APP_URL>/api/connect/x/callback. Website: your APP_URL.
  4. Copy the OAuth 2.0 Client ID and Client Secret into X_CLIENT_ID and X_CLIENT_SECRET.

Scopes used: tweet.read tweet.write users.read media.write offline.access. Posting volume depends on your X API tier.

LinkedIn

  1. Create an app at linkedin.com/developers/apps (it must be linked to a LinkedIn Page).
  2. Under Products, add Sign In with LinkedIn using OpenID Connect and Share on LinkedIn.
  3. Under Auth, add the redirect URL <APP_URL>/api/connect/linkedin/callback.
  4. Copy the Client ID and Primary Client Secret into LINKEDIN_CLIENT_ID and LINKEDIN_CLIENT_SECRET.

Scopes used: openid profile w_member_social (posts to the member's own profile).

Facebook Pages and Instagram

  1. Create a Business app at developers.facebook.com/apps.
  2. Add Facebook Login for Business and, for Instagram, the Instagram product (Instagram API with Facebook Login).
  3. In Facebook Login → Settings, add both redirect URIs: <APP_URL>/api/connect/facebook/callback and <APP_URL>/api/connect/instagram/callback.
  4. Copy the App ID and App Secret into FACEBOOK_CLIENT_ID and FACEBOOK_CLIENT_SECRET. Instagram uses the same keys.
  5. Before other people can connect, submit the app for App Review with these permissions: pages_show_list, pages_manage_posts, pages_read_engagement, business_management, instagram_basic, instagram_content_publish.

Instagram accounts must be business or creator accounts linked to a Facebook Page. Instagram needs an image or a video on every post; Postlume checks this before scheduling. Media must be reachable from the internet at APP_URL, so Instagram only works on a public HTTPS address.

Threads

  1. In the Meta developer portal create an app with the Access the Threads API use case.
  2. Add the redirect URI <APP_URL>/api/connect/threads/callback.
  3. Copy the Threads app ID and secret into THREADS_CLIENT_ID and THREADS_CLIENT_SECRET.

Scopes used: threads_basic,threads_content_publish.

YouTube

  1. In Google Cloud Console create a project and enable the YouTube Data API v3.
  2. Set up the OAuth consent screen, then create an OAuth client ID of type “Web application”.
  3. Authorised redirect URI: <APP_URL>/api/connect/youtube/callback.
  4. Copy the client ID and secret into YOUTUBE_CLIENT_ID and YOUTUBE_CLIENT_SECRET.

YouTube needs a video on every post (YouTube decides whether a short vertical video is shown as a Short). Scopes used: youtube.upload and youtube.readonly. Uploads count against the daily API quota; Google's verification is needed before the public can connect.

TikTok

  1. Create an app at developers.tiktok.com and add Login Kit and Content Posting API (Direct Post).
  2. Redirect URI: <APP_URL>/api/connect/tiktok/callback. Verify your domain for “pull from URL” media.
  3. Copy the client key and client secret into TIKTOK_CLIENT_ID and TIKTOK_CLIENT_SECRET.

Until TikTok audits your app, posts can only be private: keep TIKTOK_PRIVACY=SELF_ONLY, then change it to PUBLIC_TO_EVERYONE. TikTok posts need a video or photos.

Pinterest

  1. Create an app at developers.pinterest.com/apps.
  2. Redirect URI: <APP_URL>/api/connect/pinterest/callback.
  3. Copy the App ID and secret into PINTEREST_CLIENT_ID and PINTEREST_CLIENT_SECRET.

Pins go to the account's first board unless a board is chosen in the account settings. Scopes used: boards:read,pins:read,pins:write,user_accounts:read. Pins need an image or a video.

Bluesky

No app keys. Your customers connect with their handle and an app password (Bluesky → Settings → Privacy and security → App passwords). Postlume never asks for their main password. BLUESKY_SERVICE changes the server only for self-hosted Bluesky servers.

What Postlume does and does not do on the networks

9. AI writer and images

Pick the provider in Admin → AI and network keys (or AI_PROVIDER) and add its key. Without a key, the built-in demo writer fills captions from simple templates so every button works.

ProviderCaptions, rewrites, hashtags, ideasImagesDefault models
OpenAIYesYesgpt-5-mini, gpt-image-1
AnthropicYesUses the OpenAI or Gemini key if one is setclaude-opus-5-5
Google GeminiYesYesgemini-2.5-flash, gemini-2.5-flash-image

Change the models in the admin or with AI_TEXT_MODEL and AI_IMAGE_MODEL. Credits: every AI action costs credits (default: caption 10, rewrite 5, hashtags 3, ideas 20, image 40), set in the admin. Each plan includes a monthly number of credits, which resets every billing month. Credits protect your AI bill: a customer cannot spend more than their plan allows.

10. Email

Set SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS and MAIL_FROM with the details from any email provider (Postmark, SendGrid, Amazon SES, Mailgun, your host's mailbox). Without SMTP_HOST, emails (invitations, approval requests, password resets) are written to the server log so nothing is lost while you test. Admin → Email and storage → Send a test email checks the settings.

11. File storage

By default media files are stored on the server in the uploads folder (a Docker volume called uploads). To store them in a bucket, set S3_BUCKET, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_REGION and, for Cloudflare R2, Backblaze B2 or MinIO, S3_ENDPOINT. Files are always served through the site (/api/files/…), so the bucket can stay private. Images are capped at 20 MB, videos at MAX_UPLOAD_MB (default 200).

12. Plans and payments (Stripe)

  1. Edit the plans in Admin → Plans: name, monthly and yearly price, trial days and limits (brands, accounts, seats, posts per month, AI credits, storage) and features (approval flow, bulk upload, AI images, analytics export). 0 means unlimited.
  2. Add STRIPE_SECRET_KEY. Stripe prices are created automatically the first time a plan is sold, in CURRENCY.
  3. In Stripe → Developers → Webhooks add the endpoint <APP_URL>/api/stripe/webhook with the events checkout.session.completed, invoice.paid, invoice.payment_failed and customer.subscription.deleted, then copy its signing secret into STRIPE_WEBHOOK_SECRET.
  4. Turn on the customer portal in Stripe's billing settings so customers can change cards and cancel from the Billing page.

Without Stripe keys, Billing uses a demo checkout: choosing a plan switches it at once and records a demo payment, so you can try the whole flow.

Charging your customers for Postlume needs the Envato Extended licence (see Licence).

13. Using Postlume

Workspaces, brands and roles

Each customer gets a workspace (their team and their plan). A workspace holds brands; each brand has its own social accounts, time zone, brand voice for the AI, queue slots and calendar. The brand switcher sits at the top of the sidebar.

RoleCan do
OwnerEverything, including billing.
AdminEverything except billing: brands, accounts, team, approve posts.
EditorWrite, schedule and publish posts, manage media.
ContributorWrite posts and send them for approval; they never publish on their own.
ViewerSee the calendar, posts and analytics.

Write and schedule a post

  1. Click Create post. Choose the accounts under Post to.
  2. Write the caption, or describe the post in one line in the AI assistant box, pick a tone and click Write caption: three variations appear; click one to use it. Shorter, Hashtags and Image work the same way.
  3. Open a network's tab (for example “X · customise”) to write a version just for that network. The counters and checks show what each network allows.
  4. Add media from the library or upload new files. Add a first comment if you like.
  5. Choose Next queue slot, Pick a time or Post now, then click the orange button. Contributors see Send for approval instead.

Queue and time slots

Each brand has weekly time slots (for example 8:00, 12:15 and 17:00 on weekdays) in its own time zone. Add to queue puts a post in the next free slot. Change slots with Edit on the Queue page. Pause queue stops publishing for that brand until you resume; posts wait. The Failed tab lists posts that could not be published, with the reason and a Retry button.

Calendar

Month, week and list views, filtered by network and status. Drag a post to another day to move it (the time of day stays). The week view can show open queue slots; click one to fill it.

Approvals

Posts sent for approval wait on the Approvals page with automatic checks (caption length, required media, planned time) and comments. Owners and admins click Approve and schedule, Request changes (with a note) or Reject. An approval that arrives after the planned time goes out in the next minute. The approval flow is a plan feature.

Bulk CSV upload

Upload a CSV file to schedule many posts at once. Download the template from the Bulk upload page. Columns (the header names matter, the order does not):

ColumnRequiredExampleNotes
dateYes2026-11-02In the brand's time zone.
timeYes09:30 or 5:00 PM
accountsNoinstagram;facebookNetwork names or handles, separated by ;. Empty = every connected account.
captionYesOur autumn menu is here.Use quotes when the caption has commas or new lines.
media_urlNohttps://example.com/photo.jpgPublic image or video address; downloaded into the media library.
first_commentNoMenu link in bio

Every row is checked before anything is scheduled: dates in the past, unknown accounts, captions that are too long, networks that need media, and duplicates of posts that already exist. Only ready rows are scheduled (or sent for approval for contributors). Up to 500 rows per file.

Analytics

Impressions, engagements, engagement rate, follower growth and clicks for 7, 30 or 90 days, numbers per network, top posts and a heat map of the best times to post. Export CSV downloads the numbers (a plan feature).

Media library

Upload JPG, PNG, WEBP, GIF, MP4, MOV and WEBM files, or create AI images in four sizes (square, portrait, story, wide). Storage per workspace is a plan limit.

14. The admin panel

Open it from the user menu or at /admin (site admins only).

15. Rebrand: name, logo, colours, fonts

Admin → Branding changes the whole site without touching code: product name, tagline, support email, logo for light and dark mode, the brand colour, the heading and body fonts (Bricolage Grotesque, Figtree, Inter, DM Sans, Manrope, Space Grotesk, Fraunces), and whether the public landing page is shown (off = visitors go straight to Sign in). NEXT_PUBLIC_APP_NAME locks the name if you prefer to set it in .env.

For deeper changes, the colour tokens for light and dark mode live in src/app/globals.css, the landing page in src/app/page.tsx and src/components/landing/, and the favicon in public/icon.svg.

16. The worker

The worker is a small background process (pnpm worker, the worker container). It:

Only one worker does the work at a time (a database lock), so starting a second one by mistake is safe. If the worker stops, posts wait and are published when it starts again; Admin → Setup check shows when it last ran.

17. Every key, explained

All settings live in .env (copied from .env.example). Only the first three are required.

KeyRequiredWhat it does
Required
DATABASE_URLYesPostgreSQL connection string. The Docker stack builds it from the POSTGRES_* keys.
APP_URLYesPublic address of your site without a trailing slash, e.g. https://social.example.com. Used in emails, OAuth callbacks and media links.
APP_SECRETYesA long random string (32+ characters) that encrypts saved keys and tokens. Generate one with openssl rand -hex 32. Never change it after launch.
Docker stack
POSTGRES_DBYesDatabase name the Docker stack creates.
POSTGRES_USERYesDatabase user the Docker stack creates.
POSTGRES_PASSWORDYesDatabase password (letters and digits only; it goes into a URL).
WEB_PORT-Host port for the website (default 3000).
DOMAIN-Your domain for automatic HTTPS with the optional Caddy profile.
Email
SMTP_HOST-SMTP server for invites, approvals and password resets. Empty = emails are written to the server log.
SMTP_PORT-SMTP port, usually 587 (STARTTLS) or 465 (SSL).
SMTP_USER-SMTP user name.
SMTP_PASS-SMTP password or API key.
SMTP_SECURE-"true" for SSL on port 465. Leave empty to decide from the port.
MAIL_FROM-Sender, e.g. "Postlume <hello@example.com>".
File storage
S3_BUCKET-S3-compatible bucket for media. Empty = the local uploads folder (a Docker volume).
S3_ENDPOINT-Endpoint for MinIO, Cloudflare R2 or Backblaze B2. Leave empty for AWS S3.
S3_REGION-Bucket region (default us-east-1; R2 uses auto).
S3_ACCESS_KEY_ID-Access key for the bucket.
S3_SECRET_ACCESS_KEY-Secret key for the bucket.
UPLOAD_DIR-Local uploads folder when no bucket is set (default ./uploads).
MAX_UPLOAD_MB-Largest video upload in MB (default 200; images are capped at 20).
Payments
STRIPE_SECRET_KEY-Stripe secret key (dashboard.stripe.com → Developers → API keys). Empty = demo checkout.
STRIPE_WEBHOOK_SECRET-Signing secret of the webhook pointing at <APP_URL>/api/stripe/webhook.
CURRENCY-Three-letter currency for new Stripe prices (default usd).
AI
AI_PROVIDER-openai, anthropic or gemini. Can also be chosen in Admin → AI and network keys.
OPENAI_API_KEY-OpenAI key (platform.openai.com → API keys): captions and images.
ANTHROPIC_API_KEY-Anthropic key (console.anthropic.com): captions. Images then use the OpenAI or Gemini key if set.
GEMINI_API_KEY-Google AI Studio key (aistudio.google.com): captions and images.
AI_TEXT_MODEL-Override the text model (defaults: gpt-5-mini, claude-opus-5-5, gemini-2.5-flash).
AI_IMAGE_MODEL-Override the image model (defaults: gpt-image-1, gemini-2.5-flash-image).
Sign-in
GOOGLE_CLIENT_ID-Google OAuth client for “Continue with Google”. Empty = the button is hidden.
GOOGLE_CLIENT_SECRET-Secret of the Google OAuth client.
Social networks
X_CLIENT_ID-X app ID / client ID (developer.x.com). Empty = the demo provider for X.
X_CLIENT_SECRET-X app secret. Can also be saved in Admin → AI and network keys.
LINKEDIN_CLIENT_ID-LinkedIn app ID / client ID (linkedin.com/developers). Empty = the demo provider for LinkedIn.
LINKEDIN_CLIENT_SECRET-LinkedIn app secret. Can also be saved in Admin → AI and network keys.
FACEBOOK_CLIENT_ID-Facebook and Instagram app ID / client ID (developers.facebook.com). Empty = the demo provider for Facebook and Instagram.
FACEBOOK_CLIENT_SECRET-Facebook and Instagram app secret. Can also be saved in Admin → AI and network keys.
THREADS_CLIENT_ID-Threads app ID / client ID (developers.facebook.com, Threads use case). Empty = the demo provider for Threads.
THREADS_CLIENT_SECRET-Threads app secret. Can also be saved in Admin → AI and network keys.
YOUTUBE_CLIENT_ID-YouTube app ID / client ID (console.cloud.google.com). Empty = the demo provider for YouTube.
YOUTUBE_CLIENT_SECRET-YouTube app secret. Can also be saved in Admin → AI and network keys.
TIKTOK_CLIENT_ID-TikTok app ID / client ID (developers.tiktok.com, the client key). Empty = the demo provider for TikTok.
TIKTOK_CLIENT_SECRET-TikTok app secret. Can also be saved in Admin → AI and network keys.
PINTEREST_CLIENT_ID-Pinterest app ID / client ID (developers.pinterest.com). Empty = the demo provider for Pinterest.
PINTEREST_CLIENT_SECRET-Pinterest app secret. Can also be saved in Admin → AI and network keys.
TIKTOK_PRIVACY-SELF_ONLY until TikTok audits your app, then PUBLIC_TO_EVERYONE.
BLUESKY_SERVICE-Bluesky server (default https://bsky.social). Bluesky needs no app keys.
Advanced
DEMO_MODE-Leave empty. "true" turns on the public-demo mode: one-click demo sign-in, demo providers everywhere, no outgoing email.
NEXT_PUBLIC_APP_NAME-Locks the product name (otherwise set in Admin → Branding).
WORKER_INTERVAL_SECONDS-How often the worker looks for due posts (default 15).

18. File structure

postlume/
  docker-compose.yml        the one-command install (PostgreSQL, migrations, website, worker, optional Caddy)
  Dockerfile                builds the website image and the worker/migrations image
  .env.example              every setting, explained
  src/
    app/                    pages (Next.js App Router)
      (auth)/               sign in, sign up, password reset, invitations
      app/                  the customer app: dashboard, compose, calendar, queue, approvals, media, bulk, analytics, …
      admin/                the admin panel
      install/              the install wizard
      api/                  file serving, uploads, OAuth callbacks, Stripe webhook, CSV exports, health check
      actions/              server actions (forms and buttons)
    components/             interface parts, one folder per area
    lib/
      server/               business logic: posts, publisher, plans, payments, storage, email, AI, keys
      server/networks/      one adapter per social network
      server/ai/            AI providers and the demo writer
    database/
      prisma_client/        database schema and migrations
      seed/                 plans, default settings and the sample workspace
    worker/                 the background worker
    scripts/doctor.ts       the terminal setup check
    tests/                  test setup and helpers
  e2e/                      browser smoke tests (Playwright)

19. Develop and test

pnpm install
pnpm dev               # http://localhost:7471 (change the port in package.json)
pnpm worker            # in a second terminal
pnpm lint              # Biome
pnpm typecheck         # TypeScript
pnpm test              # Vitest: runs against a temporary schema in your database and removes it afterwards
pnpm e2e               # Playwright smoke tests against a running site (E2E_BASE_URL)

Change the database with Prisma: edit src/database/prisma_client/schema.prisma, then pnpm prisma:migrate:dev --name your_change.

20. Updating

  1. Back up the database: docker compose exec postgres pg_dump -U postlume postlume > backup.sql.
  2. Replace the files with the new version, keeping your .env (and your own changes).
  3. Run docker compose up -d --build. Migrations run automatically before the website starts.

21. Security

22. FAQ and troubleshooting

The site shows the install wizard again.

The database has no admin user: DATABASE_URL points to a new or empty database.

Posts stay “Scheduled” after their time.

The worker is not running. Check docker compose ps and docker compose logs worker, or Admin → Setup check.

A network says “redirect URI mismatch”.

The callback URL in the network's app must match <APP_URL>/api/connect/<network>/callback exactly, including https and no trailing slash. Check APP_URL too.

Instagram or TikTok cannot fetch the media.

These networks download media from your site. APP_URL must be a public HTTPS address, not localhost.

“Not enough AI credits”.

The workspace used its monthly credits. Raise the plan's credits in Admin → Plans, change credit costs in Admin → AI and network keys, or wait for the next billing month.

Emails do not arrive.

Without SMTP_HOST they are written to the log (docker compose logs web). With SMTP, use Admin → Email and storage → Send a test email to see the error.

How do I make a second site admin?

Admin → Users → change the user's site role to Admin.

Where are my uploads?

In the Docker volume postlume_uploads (or your S3 bucket). Back it up with your database.

23. Credits

Postlume is built on these open-source projects. Thank you to their authors.

ProjectLicence
Next.js, ReactMIT
PrismaApache-2.0
Tailwind CSS, shadcn/ui, Base UI, tw-animate-css, tailwind-merge, clsxMIT
class-variance-authorityApache-2.0
Lucide iconsISC
Simple Icons (network logos; the trademarks belong to their owners)CC0 1.0
sonner, next-themes, zod, pg, stripe-node, Anthropic SDKMIT
AWS SDK for JavaScriptApache-2.0
NodemailerMIT-0
dotenvBSD-2-Clause
Fonts: Bricolage Grotesque, Figtree, Inter, DM Sans, Manrope, Space Grotesk, Fraunces (Google Fonts)SIL Open Font License 1.1
Development tools: TypeScript, Biome, Vitest, Playwright, tsxApache-2.0 / MIT

The sample data uses generated artwork. The coffee photos on our live demo are preview only and are not part of the download.

24. Licence

Postlume is sold under the Envato Market licences. In short: the Regular licence covers one end product whose users are not charged. A SaaS where your customers pay for plans needs the Extended licence. Read the full terms on Envato's licence page before you launch. The open-source parts listed in Credits keep their own licences (see LICENSE.txt).

25. Changelog

1.0.0 · 16 October 2026

26. Support

Questions, problems or ideas: use the Support tab on the item's page. Please include your Postlume version, how you installed it (Docker or Node), what you did, what you expected and any error from docker compose logs web worker (remove keys and passwords first). Support covers questions about the item's features and fixing bugs; it does not include custom changes or installing on your server.