Skip to content

brightbeanxyz/brightbean-studio

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

468 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

BrightBean Studio

Open-source social media management for creators, agencies, and SMBs.

CI License: AGPL-3.0 Python 3.12+ Django 5.x

Free hosted version at brightbean.xyz/studio


About BrightBean Studio

BrightBean Studio is an open-source, self-hostable social media management platform built for creators, agencies and SMBs. It does what Sendible, SocialPilot, or ContentStudio do, but free and without per-seat, per-channel, or per-workspace limits. Plan, compose, schedule, approve, publish, and monitor content across Facebook, Instagram, LinkedIn, TikTok, YouTube, Pinterest, Threads, Bluesky, Google Business Profile, and Mastodon from a single multi-workspace dashboard.

It's for people managing many client accounts under one roof who'd rather own their social stack than pay $100–300/month to a SaaS vendor. Every feature is available to every user. No paid tier, no feature gate, no upsell.

A free hosted version is available at brightbean.xyz/studio. You can also deploy it yourself with a one-click button on Heroku, Render, or Railway, run it on your own VPS via Docker, or run it locally. All platform integrations talk directly to the official first-party APIs using your own developer credentials, so there's no aggregator middleman, no vendor lock-in, and no third party sitting between you and your data.

Features

Multi-workspace & teams Unlimited orgs → workspaces → members. Granular RBAC with custom roles, invitations, and a separate Client role for external collaborators.
Content composer Rich editor with per-platform caption/media overrides, version history, reusable templates, content categories & tags, a Kanban idea board.
Calendar & scheduling Visual calendar with recurring weekly posting slots per account and named queues that auto-assign posts to the next available slot.
Publishing engine Direct first-party API integrations (no aggregator), automatic retries, per-account rate-limit tracking, and a 90-day publish audit log.
Approval workflows Configurable stages (none / optional / internal / internal + client), threaded internal & external comments, reminders, and a full audit trail.
Unified social inbox Comments, mentions, DMs, and reviews from every connected platform in one place, with sentiment analysis, assignments, threaded replies, and historical backfill.
Analytics Per-post and channel-level performance from every connected platform's native API, with KPI cards, 7/30/90-day trend charts, and a sortable all-posts table for views, engagement, follower growth, reach, and watch time.
Media library Org- and workspace-scoped libraries with nested folders, auto-generated platform-optimized variants, and alt text.
Client portal Passwordless 30-day magic-link access so clients can approve or reject posts without creating an account.
Notifications In-app, email, and webhook delivery with per-user preferences for every event type.
Security & ops Encrypted token & credential storage, Google SSO, Sentry support, and a 14-day reversible org-deletion grace period. 2FA (TOTP) is on the roadmap.
White-label friendly Per-workspace branding (logo, colors) and workspace defaults for hashtags, first comments, and posting templates.

A quick look

Calendar view
Visual calendar - drag-and-drop scheduling with recurring slots and queues.
Post editor
Post editor - composer with per-platform overrides and previews.
Idea kanban board
Idea board - Kanban workflow to keep track of all your post ideas.
Connected platforms
Connect anything - 10+ first-party integrations, no aggregator.
Analytics dashboard
Performance analytics - per-post and channel-level metrics with KPI cards and trend charts.

Supported Platforms

Platform Publish Comments DMs Insights
Facebook
Instagram
Instagram (Direct)
LinkedIn (Personal)
LinkedIn (Company)
TikTok
YouTube
Pinterest
Threads
Bluesky
Google Business Profile
Mastodon

Hosted Version

A free hosted version of Brightbean Studio is available at brightbean.xyz/studio. It runs the same codebase as this repository, with no setup or maintenance required.

If you'd rather self-host, choose one of the options below.

One-Click Deploy

Heroku Render Railway
Deploy to Heroku Deploy to Render Deploy on Railway

After deploying, set these environment variables in your platform's dashboard:

Variable Required Description
DJANGO_SETTINGS_MODULE Auto-set config.settings.production. Set if deployment config has not placed it.
SECRET_KEY Auto-generated Django secret key. Set automatically by the deploy button.
ENCRYPTION_KEY_SALT Auto-generated Encryption salt. Set automatically by the deploy button.
DATABASE_URL Auto-provisioned PostgreSQL connection string. Set automatically.
ALLOWED_HOSTS Yes Your app's domain, e.g. your-app.herokuapp.com
APP_URL Yes Full public URL, e.g. https://your-app.herokuapp.com
STORAGE_BACKEND No Set to s3 for S3/R2 storage. Default: local. Heroku, Render, and Railway have ephemeral filesystems, so uploaded files are lost on redeploy without S3.
S3_ENDPOINT_URL If using S3 S3-compatible endpoint URL
S3_ACCESS_KEY_ID If using S3 S3 access key
S3_SECRET_ACCESS_KEY If using S3 S3 secret key
S3_BUCKET_NAME If using S3 S3 bucket name
EMAIL_HOST No SMTP server for sending invitations and password resets
EMAIL_PORT No SMTP port (default: 587)
EMAIL_HOST_USER No SMTP username
EMAIL_HOST_PASSWORD No SMTP password
GOOGLE_AUTH_CLIENT_ID No For Google OAuth login. Get from Google Cloud Console → Credentials.
GOOGLE_AUTH_CLIENT_SECRET No Google OAuth secret

For social media API keys, see Platform Credentials. Full variable reference: .env.example.

Quick Start (Docker)

git clone https://github.com/brightbeanxyz/brightbean-studio.git
cd brightbean-studio
cp .env.example .env

Edit .env - change DATABASE_URL to point to the Docker service name:

DATABASE_URL=postgres://postgres:postgres@postgres:5432/brightbean

Then start everything:

docker compose up -d --build
docker compose exec app python manage.py migrate
docker compose exec app python manage.py createsuperuser

Tailwind compiles automatically via the tailwind Compose service. First build takes ~60–90 seconds (running npm install in a fresh container); subsequent starts are instant. Watch progress with docker compose logs -f tailwind.

Open http://localhost:8000 - you're running.

Fully Local Development (without Docker)

Run everything natively - no Docker, no PostgreSQL install. Uses SQLite for the database.

Prerequisites

  • Python 3.12+
  • Node.js 20+

Setup

1. Clone and configure

git clone https://github.com/brightbeanxyz/brightbean-studio.git
cd brightbean-studio
cp .env.example .env

2. Switch to SQLite

Open .env and replace the DATABASE_URL line:

DATABASE_URL=sqlite:///db.sqlite3

That's it - no database server to install or manage.

3. Set up Python

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

4. Set up Tailwind CSS

cd theme/static_src
npm install
cd ../..

5. Run database migrations

python manage.py migrate

6. Create your admin account

python manage.py createsuperuser

7. Start the app (3 terminal tabs)

Tab 1 - Tailwind watcher:

cd theme/static_src && npm run start

Tab 2 - Django dev server:

source .venv/bin/activate
python manage.py runserver

Tab 3 - Background worker:

source .venv/bin/activate
python manage.py process_tasks

Open http://localhost:8000 and log in with the superuser you created.

Daily workflow (Docker-free)

source .venv/bin/activate                # activate Python env
python manage.py runserver               # start web server
# (open another tab)
python manage.py process_tasks           # start worker

Note: SQLite is fine for local development and small deployments. For production or heavy concurrent usage, switch to PostgreSQL.

Running Tests

pytest

With coverage:

pytest --cov=apps --cov-report=term-missing

Linting & Type Checking

ruff check .                             # lint
ruff format --check .                    # format check
mypy apps/ config/ --ignore-missing-imports  # type check

Auto-fix lint issues:

ruff check --fix .
ruff format .

Production Deployment

Docker Compose on a VPS (recommended)

# On your server:
git clone https://github.com/brightbeanxyz/brightbean-studio.git
cd brightbean-studio
cp .env.example .env
# Edit .env:
#   SECRET_KEY=<generate a random 50+ char string>
#   DEBUG=false
#   ALLOWED_HOSTS=yourdomain.com
#   APP_URL=https://yourdomain.com
#   DATABASE_URL=postgres://postgres:<strong-password>@postgres:5432/brightbean

docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
docker compose exec app python manage.py createsuperuser

This starts 5 containers: app (Gunicorn), worker, PostgreSQL, Caddy (auto-HTTPS), and a one-shot migrate container that runs database migrations automatically on startup. Edit the Caddyfile with your domain.

To update:

git pull
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build

Other Platforms

Platform Config file Notes
Heroku Procfile + app.json Deploy-button ready. Must use Basic+ dynos (Eco dynos break the worker).
Railway railway.toml Three services: web, worker, managed PostgreSQL.
Render render.yaml Blueprint with web, worker, PostgreSQL. Must use paid tier.

All platforms with ephemeral filesystems require STORAGE_BACKEND=s3 - see .env.example for S3 configuration.

See architecture.md for detailed per-platform instructions and cost breakdowns.

Project Structure

brightbean-studio/
├── config/
│   ├── settings/
│   │   ├── base.py            # Shared settings
│   │   ├── development.py     # Local dev overrides
│   │   ├── production.py      # Production hardening
│   │   └── test.py            # Test overrides
│   ├── urls.py                # Root URL configuration
│   ├── wsgi.py
│   └── asgi.py
├── apps/
│   ├── accounts/              # Custom User model, auth, OAuth, sessions
│   ├── organizations/         # Organization management
│   ├── workspaces/            # Workspace CRUD
│   ├── members/               # RBAC, invitations, middleware, decorators
│   ├── settings_manager/      # Configurable defaults with cascade logic
│   ├── credentials/           # Platform API credential storage (encrypted)
│   └── common/                # Shared: encrypted fields, scoped model managers
├── providers/                 # Social platform API modules (one file per platform)
├── templates/                 # Django templates
│   ├── base.html              # Layout with sidebar + nav
│   └── components/            # Reusable HTMX partials
├── static/
│   └── js/                    # Vendored HTMX + Alpine.js
├── theme/                     # django-tailwind theme app
│   └── static_src/
│       ├── src/styles.css     # Tailwind directives
│       └── tailwind.config.js
├── Dockerfile
├── docker-compose.yml         # Dev: app + worker + postgres
├── docker-compose.prod.yml    # Prod override: adds Caddy, uses Gunicorn
├── Caddyfile                  # Reverse proxy + auto-HTTPS config
├── .env.example               # All environment variables
├── Procfile                   # Heroku
├── app.json                   # Heroku deploy button
├── railway.toml               # Railway config
└── render.yaml                # Render blueprint

Settings selection: The DJANGO_SETTINGS_MODULE environment variable controls which settings file Django uses. The defaults are already wired for each context: manage.py uses development, wsgi.py/asgi.py use production, and pytest uses test (via pyproject.toml). Docker Compose files and platform deploy configs (Heroku, Render) also set it explicitly. You only need to override it manually if you want a non-default module for a specific command, e.g. DJANGO_SETTINGS_MODULE=config.settings.production python manage.py check --deploy.

Platform Credentials

To connect social media accounts, you need API credentials from each platform's developer portal. You can set these via environment variables in .env (see .env.example) or, per organization, through the Django admin at {APP_URL}/admin/Credentials → Platform credentials (superuser only). If a platform is configured in both places, the .env value takes precedence.

Admin UI access (superuser only): The Django admin at {APP_URL}/admin/ (for example https://brightbean.example.com/admin/) is restricted to superuser accounts — only a superuser can view or edit platform credentials there. If you don't already have one, create a superuser, then sign in and open Credentials → Platform credentials:

python manage.py createsuperuser
# Docker: docker compose exec app python manage.py createsuperuser

Redirect URI: When registering your app on any platform, set the OAuth redirect URI to:

{APP_URL}/social-accounts/callback/{platform}/

For example, if your APP_URL is https://brightbean.example.com, the Facebook redirect URI would be https://brightbean.example.com/social-accounts/callback/facebook/.

TikTok: use the slug social1 instead of tiktok — TikTok rejects redirect URIs containing their brand name. See the TikTok section.

Meta (Facebook, Instagram, Threads)

Facebook, Instagram, and Threads all use the same Meta app credentials.

  1. Go to Meta for Developers and create a new app (type: Business)

  2. Under App Settings → Basic, copy your App ID and App Secret

  3. In the App Dashboard, go to Use cases and add the following four use cases. For each use case, click into it and go to Permissions and features to add the required optional permissions:

    Use case: "Manage everything on your Page" (Facebook)

    • This use case auto-includes business_management, pages_show_list, and public_profile
    • Add these optional permissions: pages_manage_posts, pages_read_engagement, pages_read_user_content, pages_manage_metadata, read_insights

    Use case: "Messenger from Meta" (Facebook Messaging)

    • Required to enable the pages_messaging permission, which is not available under the "Manage Pages" use case
    • Add the optional permission: pages_messaging

    Use case: "Manage messaging & content on Instagram" (Instagram)

    • Add these permissions: instagram_basic, instagram_content_publish, instagram_manage_comments, instagram_manage_insights

    Use case: "Access the Threads API" (Threads)

    • This use case auto-includes threads_basic
    • Add these optional permissions: threads_content_publish, threads_manage_insights, threads_manage_replies
  4. Under Facebook Login → Settings → Valid OAuth Redirect URIs, add the following redirect URIs:

    {APP_URL}/social-accounts/callback/facebook/
    {APP_URL}/social-accounts/callback/instagram/
    {APP_URL}/social-accounts/callback/threads/
    
  5. Set the environment variables:

    PLATFORM_FACEBOOK_APP_ID=your-app-id
    PLATFORM_FACEBOOK_APP_SECRET=your-app-secret
    

Instagram (Direct, via Instagram Login)

The Instagram (Direct) connector uses the Instagram API with Instagram Login - a separate OAuth flow from the Facebook Login-based Instagram connector above. It works with Professional Instagram accounts (Business or Creator) without requiring a linked Facebook Page.

Account-type requirement: Personal Instagram accounts have no API access since the Instagram Basic Display API was retired on 2024-12-04. Users must convert their account to Professional first (free, in IG Settings → Account type and toolsSwitch to professional account).

  1. In the same Meta app, go to Use cases and add the "Instagram API" use case
  2. Under API setup with Instagram Login, note your Instagram App ID and Instagram App Secret (these are different from your Facebook App ID/Secret)
  3. Go to Permissions and features and add the required permissions:
    • instagram_business_basic, instagram_business_content_publish, instagram_business_manage_comments, instagram_business_manage_messages, instagram_business_manage_insights
  4. Under API setup with Instagram Login → Step 4: Set up Instagram business login, click Set up and add the redirect URI (must match exactly, including the trailing slash):
    {APP_URL}/social-accounts/callback/instagram_login/
    
  5. Under API setup with Instagram Login → Step 3: Configure webhooks, set:
    • Callback URL: {APP_URL}/webhooks/instagram_login/
    • Verify token: the value of INSTAGRAM_LOGIN_WEBHOOK_VERIFY_TOKEN from your .env (any random string; generate one and set the env var before clicking Verify and save). After verification, subscribe to the messages, comments, and mentions fields.
  6. Set the environment variables:
    PLATFORM_INSTAGRAM_APP_ID=your-instagram-app-id
    PLATFORM_INSTAGRAM_APP_SECRET=your-instagram-app-secret
    INSTAGRAM_LOGIN_WEBHOOK_VERIFY_TOKEN=your-random-verify-token
    

LinkedIn

Brightbean Studio supports two LinkedIn paths. Pick whichever your LinkedIn dev app can obtain - or both, on separate apps.

Path A - Personal-only (any individual developer can do this):

  1. Go to the LinkedIn Developer Portal and create a new app (no Company Page verification required).
  2. Under Products, request access to (both auto-approved):
    • Sign In with LinkedIn using OpenID Connect
    • Share on LinkedIn
  3. Under Auth, add the redirect URI:
    {APP_URL}/social-accounts/callback/linkedin_personal/
    
  4. Scopes: openid, profile, email, w_member_social.
  5. Set the environment variables:
    PLATFORM_LINKEDIN_PERSONAL_CLIENT_ID=your-client-id
    PLATFORM_LINKEDIN_PERSONAL_CLIENT_SECRET=your-client-secret
    

Limitations of Path A: access tokens last ~60 days and LinkedIn does not issue refresh tokens for these scopes - users must manually reconnect every ~60 days. Inbox / comment-reading is not available for personal accounts on this path.

Path B - Company Pages (also enables full Personal features):

  1. Go to the LinkedIn Developer Portal and create a new app.
  2. Verify the app's association with a LinkedIn Company Page.
  3. Under Products, request access to:
    • Community Management API (restricted - requires LinkedIn review)
  4. Under Auth, add both redirect URIs:
    {APP_URL}/social-accounts/callback/linkedin_personal/
    {APP_URL}/social-accounts/callback/linkedin_company/
    
  5. Scopes:
    • Personal: r_basicprofile, w_member_social, r_member_social
    • Company: r_basicprofile, w_member_social, w_organization_social, r_organization_social, rw_organization_admin
  6. Set the environment variables:
    PLATFORM_LINKEDIN_COMPANY_CLIENT_ID=your-client-id
    PLATFORM_LINKEDIN_COMPANY_CLIENT_SECRET=your-client-secret
    

If you set only the Path B (Company) credentials, Brightbean Studio automatically reuses them for personal connections too - refresh tokens (365-day) and inbox both work. You only need Path A vars if you have a separate Personal-only app.

Note: "Sign In with LinkedIn using OpenID Connect" / "Share on LinkedIn" and "Community Management API" are mutually exclusive on a single LinkedIn app. You need separate apps for Path A and Path B.

Backwards compatibility: the legacy PLATFORM_LINKEDIN_CLIENT_ID / PLATFORM_LINKEDIN_CLIENT_SECRET env vars are still honored as a fallback for both linkedin_personal and linkedin_company - existing self-hosters keep working without changes. The legacy credentials are assumed to be CM-approved; if your legacy app is OIDC-only, migrate it to PLATFORM_LINKEDIN_PERSONAL_*.

TikTok

  1. Go to the TikTok Developer Portal and create a new app
  2. Add the products Login Kit and Content Posting API
  3. Configure the redirect URI — use social1, not tiktok (TikTok rejects URIs containing their brand name):
    {APP_URL}/social-accounts/callback/social1/
    
  4. Required scopes: user.info.basic, user.info.profile, user.info.stats, video.publish, video.upload, video.list
  5. Note: TikTok uses Client Key (not Client ID). Copy the Client Key and Client Secret from your app dashboard
  6. Set the environment variables:
    PLATFORM_TIKTOK_CLIENT_KEY=your-client-key
    PLATFORM_TIKTOK_CLIENT_SECRET=your-client-secret
    
  7. For production review, record the demo video against a TikTok Sandbox showing every requested scope in use.

Google (YouTube, Google Business Profile)

YouTube and Google Business Profile share the same Google Cloud credentials.

  1. Go to the Google Cloud Console and create a new project (or select an existing one)
  2. Enable the following APIs under APIs & Services → Library:
    • YouTube Data API v3 (for YouTube)
    • My Business Account Management API, My Business Business Information API, and Google My Business API (for Google Business Profile)
  3. Go to APIs & Services → Credentials and create an OAuth 2.0 Client ID (type: Web application)
  4. Add the following redirect URIs under Authorized redirect URIs:
    {APP_URL}/social-accounts/callback/youtube/
    {APP_URL}/social-accounts/callback/google_business/
    
  5. Copy the Client ID and Client Secret
  6. Required scopes:
    • YouTube: https://www.googleapis.com/auth/youtube.upload, https://www.googleapis.com/auth/youtube.readonly, https://www.googleapis.com/auth/youtube.force-ssl, https://www.googleapis.com/auth/yt-analytics.readonly
    • Google Business Profile: https://www.googleapis.com/auth/business.manage
  7. Set the environment variables:
    PLATFORM_GOOGLE_CLIENT_ID=your-client-id
    PLATFORM_GOOGLE_CLIENT_SECRET=your-client-secret
    

Pinterest

  1. Go to the Pinterest Developer Portal and create a new app
  2. Under your app settings, add the redirect URI:
    {APP_URL}/social-accounts/callback/pinterest/
    
  3. Copy the App ID and App Secret
  4. Required scopes: user_accounts:read, boards:read, pins:read, pins:write
  5. Set the environment variables:
    PLATFORM_PINTEREST_APP_ID=your-app-id
    PLATFORM_PINTEREST_APP_SECRET=your-app-secret
    

Bluesky

No developer app registration needed. Users connect by entering their Bluesky handle and an App Password:

  1. Log in to Bluesky
  2. Go to Settings → Privacy and Security → App Passwords
  3. Create a new app password and use it when connecting your account in Brightbean Studio

Mastodon

No developer app registration needed. Brightbean Studio automatically registers an OAuth application on each Mastodon instance when a user connects their account. Users just need to enter their instance URL (e.g., mastodon.social).

Inbox: Backfill Historical Messages

See the Supported Platforms matrix above for per-platform inbox capabilities.

To import historical messages (e.g., from the last 7 days):

python manage.py backfill_inbox --days 7

Options:

  • --days N - Number of days to backfill (default: 7)
  • --platform NAME - Only backfill a specific platform (e.g., youtube, linkedin, tiktok)
  • --account-id UUID - Only backfill a specific account

API & MCP for Agents

BrightBean Studio ships a REST API and an MCP (Model Context Protocol) server so agents and scripts can read analytics, manage media, and create or schedule posts. Both share the same authentication, permission model, rate limits, and audit log. Pick whichever protocol fits your client.

Base URL: {APP_URL}/api/v1/ (e.g. https://your-studio.example.com/api/v1/)

Authentication

Issue an API key from Organization → API Keys. Keys are workspace-scoped, can be allowlisted to specific social accounts, and inherit a subset of the issuer's workspace permissions. Revocation takes effect immediately. Send the key as a Bearer token:

Authorization: Bearer bb_studio_...

Permission keys: create_posts, publish_directly, upload_media, view_analytics. Each endpoint requires the relevant permission; missing permissions return 403.

Rate Limits

Scope Limit
Per-key writes 120 / min
Per-key reads 300 / min
Per-workspace aggregate 1000 / min

Rate-limit responses (429) include Retry-After, X-RateLimit-Limit, and X-RateLimit-Remaining headers.

REST Endpoints

Method Path Purpose Permission
GET /me Inspect caller scope and workspace permissions
GET /accounts List connected social accounts
POST /posts Create a draft or scheduled post create_posts (+ publish_directly to schedule)
GET /posts/{post_id} Read a single post
PATCH /posts/{post_id} Update draft fields create_posts
POST /posts/{post_id}/schedule Schedule a draft create_posts + publish_directly
POST /posts/{post_id}/cancel Revert a scheduled post to draft create_posts
GET /analytics/accounts/{account_id} Channel analytics summary (7/30/90-day window) view_analytics
GET /analytics/posts/{post_id} Post analytics with per-platform metrics view_analytics
POST /media Upload a media file (multipart) upload_media
GET /media/{media_id} Retrieve a media asset
GET /media List media assets (filter, paginate)
POST /mcp JSON-RPC 2.0 endpoint for MCP clients

All write endpoints accept idempotency_key (or Idempotency-Key header) for safe retries.

MCP Tools

The MCP server lives at POST {APP_URL}/api/v1/mcp and speaks JSON-RPC 2.0 over Streamable HTTP. It implements the standard initialize, tools/list, tools/call, and ping methods. Tools:

Tool Purpose Permission
list_accounts List social accounts this API key can act on
create_draft Create a draft post (caption, title, media, first comment) create_posts
schedule_post Create and schedule a post in one step create_posts + publish_directly
schedule_draft Schedule an existing draft create_posts + publish_directly
get_post Retrieve a post with aggregate status and per-platform state
cancel_post Revert a scheduled post back to draft create_posts
search_media Find media assets by query, type, tags, or folder
get_media Retrieve a single media asset by ID
upload_media Upload a small base64-encoded file (≤ 1 MB raw). For larger files, use REST POST /media. upload_media
get_account_analytics Channel analytics over a rolling 7–90 day window view_analytics
get_post_analytics Per-platform metrics for a single post (safe for polling drafts) view_analytics

Connecting an MCP client

The server is at {APP_URL}/api/v1/mcp and supports two authentication modes — pick whichever your client uses.

Claude Desktop (and other native OAuth connectors). In Claude Desktop open Settings → Connectors → Add custom connector, name it, and enter the server URL {APP_URL}/api/v1/mcp. Claude registers itself (Dynamic Client Registration) and opens a browser to log in to BrightBean Studio and approve access — no API key required. Any Studio user can connect; the connection acts with their own workspace permissions (read-only roles get the read tools, while posting/scheduling/uploading require the matching permission), operating on their last-active workspace. Requires Studio to be served over a public https URL.

Claude Code, Cursor, custom agents (static API key). Point the client at the same URL and send an API key as a Bearer token (Authorization: Bearer bb_studio_...). For Claude Code:

claude mcp add --transport http brightbean {APP_URL}/api/v1/mcp \
  --header "Authorization: Bearer bb_studio_..."

Pre-built agent skill

Don't want to wire up your own client? The companion brightbean-studio-agent repository hosts a holistic agent skill that drives BrightBean Studio end-to-end through the REST API and MCP tools documented above.


Tech Stack

Layer Technology
Backend Django 5.x
Frontend Django templates, HTMX, Alpine.js
CSS Tailwind CSS 4 via django-tailwind
Database PostgreSQL 16+
Background jobs django-background-tasks (no Redis required)
Auth django-allauth (email + Google OAuth)
Media Pillow (images), FFmpeg (video)
Deployment Docker, Gunicorn, Caddy

Troubleshooting

Docker: postgres container is unhealthy Wait 10-15 seconds after docker compose up for the health check to pass, then retry your command. Check logs with docker compose logs postgres.

python manage.py migrate fails with connection errors Make sure PostgreSQL is running and healthy. For Docker: docker compose ps should show postgres as "healthy". For local: verify the DATABASE_URL in .env matches your setup.

Tailwind CSS changes not appearing Make sure the Tailwind watcher is running: cd theme/static_src && npm run start. If styles still don't update, try npm run build for a full rebuild.

OAuth callback errors ("redirect URI mismatch") The redirect URI registered on the platform must exactly match {APP_URL}/social-accounts/callback/{platform}/. Check that APP_URL in .env matches the URL you're accessing (including http vs https and port number).

Background tasks not running (posts not publishing) Make sure the worker is running: python manage.py process_tasks. In Docker: check docker compose logs worker.

Contributing

See CONTRIBUTING.md for development setup, coding guidelines, and how to submit pull requests.

Security

To report a security vulnerability, see SECURITY.md. Do not open a public issue.

License

AGPL-3.0 - see LICENSE for details.

About

Open-source, self-hostable social media management platform. Schedule, publish, and manage content across 10+ platforms from a single dashboard. Free alternative to Buffer, Sendible, and SocialPilot.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors