Privacy-first, self-hosted social media manager for feeds, cross-posting, scheduling, media, drafts, and local AI assistance across major platforms. NO FEATURE PAYWALL
|
|
3 週間 前 | |
|---|---|---|
| .claude | 3 週間 前 | |
| .github | 1 年間 前 | |
| services | 3 週間 前 | |
| ui | 3 週間 前 | |
| .env.example | 1 ヶ月 前 | |
| .gitignore | 3 週間 前 | |
| LICENSE.txt | 1 年間 前 | |
| README.md | 3 週間 前 | |
| docker-compose.yml | 1 ヶ月 前 | |
| nginx.conf | 3 週間 前 | |
| package-lock.json | 2 年 前 | |
| socialMediaManager.png | 2 年 前 |
A self-hosted, local-first social media management platform. Aggregate feeds from all your platforms, compose and cross-post content, schedule posts with per-account timezone support, and get AI-powered suggestions via a local Ollama instance — all from one privacy-first dashboard.
/calendar-plan; save all posts as drafts or export to CSV| Layer | Technology |
|---|---|
| Frontend | Vue 3, TypeScript, Vite, Tailwind CSS, Pinia, Vue Router, vue-i18n |
| API Gateway | Node.js / Fastify 4 |
| Platform Services | Node.js / Fastify (one per platform) |
| Database | MongoDB 6 |
| Job Queue | Redis + BullMQ |
| AI | Ollama (local) · OpenAI · Groq · Google Gemini |
| Logging | Pino (structured JSON) |
| Reverse Proxy | Nginx |
| Containerization | Docker Compose |
| Service | Port | Description |
|---|---|---|
nginx |
8081 | Reverse proxy — main entry point |
ui |
— | Vue 3 frontend (Vite dev server) |
gateway |
8084 | REST API gateway |
socket |
8085 | WebSocket server (real-time feed updates) |
feed-aggregator |
3010 | Polls feeds from all platforms periodically |
scheduler |
3011 | Scheduled post management (BullMQ) |
twitter |
3001 | Twitter/X integration |
linkedin |
3002 | LinkedIn integration |
mastodon |
3003 | Mastodon integration |
bluesky |
3004 | Bluesky (AT Protocol) integration |
instagram |
3005 | Instagram Graph API |
facebook |
3006 | Facebook Pages Graph API |
pinterest |
3008 | Pinterest API v5 |
tiktok |
3007 | TikTok Content Posting API |
mongodb |
27018 | Database |
redis |
6379 | Cache & job queue |
messageBroker |
5672 / 15672 | RabbitMQ (legacy, largely unused) |
git clone https://github.com/mehmetkirkoca/social-media-manager.git
cd social-media-manager
cp .env.example .env
Edit .env and fill in your API credentials. Minimum required fields:
APP_BASE_URL=http://localhost:8081
# Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
ENCRYPTION_KEY=your_64_hex_char_key_here
# Mastodon (easiest — get token from instance Settings > Development)
MASTODON_INSTANCE_URL=https://mastodon.social
MASTODON_ACCESS_TOKEN=your_token_here
# Bluesky (use an App Password from Settings > App Passwords)
BLUESKY_IDENTIFIER=yourhandle.bsky.social
BLUESKY_APP_PASSWORD=your_app_password_here
docker compose up -d
Open http://localhost:8081 in your browser.
SocialManager supports four AI providers. Switch between them at any time in Settings → AI Integration.
Run Ollama on your host machine and pull a model:
ollama pull llama3.2 # text generation
ollama pull llava # image captioning (vision)
In Settings, set the Ollama endpoint to http://host.docker.internal:11434, test the connection, and click Save.
Go to Settings → AI Integration and open the card for the provider you want:
| Provider | Where to get a key |
|---|---|
| OpenAI (GPT-4o, GPT-4o-mini) | platform.openai.com |
| Groq (Llama 3, Mixtral) | console.groq.com |
| Google Gemini (2.0 Flash, 1.5 Pro) | aistudio.google.com |
Paste your API key and click Connect & Set Active. Keys are stored AES-256-GCM encrypted in MongoDB — no .env editing required. Only one provider is active at a time; switch with the Set as Active button on any configured card.
| Platform | API Cost | Feed | Post | Notes |
|---|---|---|---|---|
| Mastodon | Free | ✅ | ✅ | Easiest — open REST API |
| Bluesky | Free | ✅ | ✅ | App Password auth, no OAuth needed |
| Free | ✅ | ✅ | Register an app at reddit.com/prefs/apps | |
| Twitter/X | Paid ($100/mo Basic) | ⚠️ | ✅ | Free tier limited; OAuth 2.0 in pipeline |
| Free | ⚠️ | ✅ | Personal feed read not available; env var token for now | |
| Free | ✅ | ✅ | Business/Creator account + Facebook Page required | |
| Free | ✅ | ✅ | Facebook Page required (personal timelines not supported) | |
| YouTube | Free | ✅ | ❌ | Subscription feed only; publishing in pipeline |
| Free | ✅ | ✅ | OAuth via Settings UI; boards as destinations; image required for pins | |
| TikTok | Free | ✅ | ✅ | OAuth 2.0 PKCE via Settings UI; video required for posts; auto token refresh |
| Google Business | Free | — | — | In pipeline |
Both Instagram and Facebook share one Facebook Developer App. You set it up once, then connect everything from the Settings UI — no token copying required. Tokens are stored encrypted (AES-256-GCM) in MongoDB.
Facebook Login for Business:
Under Client OAuth Settings, add to Valid OAuth Redirect URIs:
http://localhost:8081/api/auth/meta/callback
Required permissions (Development mode — no App Review needed for your own accounts):
| Permission | Used for |
|---|---|
pages_manage_posts |
Post to Facebook Page |
pages_read_engagement |
Read Facebook Page feed |
instagram_basic |
Read Instagram media |
instagram_content_publish |
Publish Instagram posts |
instagram_manage_insights |
Required alongside content_publish |
Tokens are stored encrypted in MongoDB — no .env editing required.
| Token | Expiry | How it is handled |
|---|---|---|
| Short-lived user token | 1–2 hours | Exchanged automatically during OAuth |
| Long-lived user token | ~60 days | Stored encrypted; reconnect via Settings when it expires |
| Page access token | Never expires | Fetched during OAuth and stored encrypted |
A banner appears in the Dashboard and Settings when any Meta token expires within 7 days.
Instagram publishing: Every post requires at least one
imageUrlorvideoUrl. Text-only posts are not supported by the Instagram Graph API.
LinkedIn currently uses a personal access token stored in .env. A full OAuth 2.0 flow is in the pipeline.
Add your redirect URI under OAuth 2.0 Settings:
http://localhost:8081/api/auth/linkedin/callback
Until the OAuth flow is built, generate a token manually:
w_member_social, r_liteprofile, r_emailaddress.envLINKEDIN_ACCESS_TOKEN=your_token_here
Note: Manual tokens expire after 60 days. A full OAuth 2.0 connection flow (similar to the Meta flow) is planned in the pipeline — once built, you will connect LinkedIn from the Settings UI with one click and tokens will be refreshed automatically.
Pinterest uses a standard OAuth 2.0 authorization code flow. Tokens are stored encrypted (AES-256-GCM) in MongoDB. Each Pinterest board becomes a separate posting destination in Compose.
In your app's Authentication settings, add to Redirect URIs:
http://localhost:8081/api/auth/pinterest/callback
Required scopes:
| Scope | Used for |
|---|---|
pins:read |
Read existing pins |
pins:write |
Create new pins |
boards:read |
List boards for destination picker |
user_accounts:read |
Verify connected account |
Each selected board now appears as a destination in the Compose view.
.env editing required.TikTok uses OAuth 2.0 with PKCE (Proof Key for Code Exchange). Tokens are stored AES-256-GCM encrypted in MongoDB and auto-refreshed when they expire (~24 h access token, ~365 day refresh token).
In your app's Login Kit settings, add to Redirect URIs:
http://localhost:8081/api/auth/tiktok/callback
Required scopes (request these in Login Kit):
| Scope | Used for |
|---|---|
user.info.basic |
Display connected username |
video.list |
Fetch your TikTok feed |
video.publish |
Publish video posts |
After submitting for review, note your Client Key and Client Secret from the app dashboard.
PULL_FROM_URL API — TikTok fetches the video from your media server asynchronously..env editing required.The Find Nearby feature on the Competitors page uses the Google Places API to search for local businesses near a given address or area — useful for brick-and-mortar businesses, agencies managing local clients, or anyone wanting to track nearby competition.
The key is stored AES-256-GCM encrypted in MongoDB. Once configured, the Find Nearby button appears in the Competitors page. Enter a location (city, suburb, postcode, or street address) and an optional business type, then click Search to get up to 5 local competitor suggestions with websites pre-filled.
Workspaces let you run multiple independent social media presences from the same SocialManager instance — separate brands, agencies managing client accounts, or personal vs. business use.
Each workspace has its own:
Global credentials set in Global Settings (/global-settings) are shared:
Note: The
defaultworkspace cannot be deleted. Deleting a workspace permanently removes all its scoped data.
Every API request carries an X-Workspace-Id header set by the Pinia useWorkspaceStore. The gateway reads this header and scopes all database reads/writes to that workspace. Platform service calls pass the header through so feed fetches and posts are also workspace-aware.
ui/src/locales/xx.ts (copy en.ts and translate)In ui/src/locales/index.ts:
import xx from './xx'
// Add to messages: { en, tr, xx }
// Add to SUPPORTED_LOCALES: { code: 'xx', label: '...', flag: '🇽🇽' }
Done — the language appears in the NavBar dropdown automatically
services/{platform}/ with index.js, package.json, DockerfileBasePlatformService and implement fetchFeed(), publishPost(), getStatus()docker-compose.ymlfeed-aggregator and scheduler environment variables and PLATFORM_SERVICES mapsPLATFORM_META in ui/src/stores/platforms.tsactivePlatforms default set in ui/src/stores/feed.tsplatforms.{key} to both locale files (en.ts, tr.ts).
├── services/
│ ├── utils/ # Shared: BasePlatformService, MongoDB, RabbitMQ, logger, crypto
│ │ ├── BasePlatformService.js
│ │ ├── MongoDBConnector.js
│ │ ├── RabbitMQConnector.js
│ │ ├── RabbitMQListener.js
│ │ ├── RabbitMQProducer.js
│ │ ├── logger.js # Pino createLogger(service) factory
│ │ └── crypto.js # AES-256-GCM encryptToken / decryptToken
│ ├── gateway/ # API gateway (credentials, OAuth, AI, analytics, competitors, calendars)
│ ├── socket/ # WebSocket server
│ ├── feed-aggregator/ # Periodic feed polling
│ ├── scheduler/ # BullMQ scheduled post worker
│ ├── twitter/
│ ├── linkedin/
│ ├── mastodon/
│ ├── bluesky/
│ ├── instagram/
│ ├── facebook/
│ ├── pinterest/
│ └── tiktok/
├── ui/
│ └── src/
│ ├── views/ # Dashboard, Compose, Scheduler, Settings, Media, Analytics,
│ │ # CalendarPlan, Competitors
│ ├── components/
│ ├── stores/ # Pinia: feed, compose, platforms, ai, hashtags, competitors
│ ├── utils/ # timezone.ts (IANA list + UTC conversion)
│ ├── locales/ # i18n: en, tr
│ └── router/
├── docker-compose.yml
├── nginx.conf
├── .env.example
└── CLAUDE.md # Developer context for AI coding sessions