@fastslack/socialkit
v0.1.0
Published
Open-source social media OAuth, token management, and publishing SDK. Connect accounts, auto-refresh tokens, publish content — all self-hosted.
Downloads
44
Maintainers
Readme
@fastslack/socialkit
Open-source social media OAuth, token management, publishing, and credit system SDK for Node.js.
Connect user accounts, auto-refresh tokens, publish content, and manage usage credits — all self-hosted with zero third-party dependency.
Features
- OAuth flows for 7 platforms: LinkedIn, Twitter/X, Instagram, Facebook, TikTok, Threads, YouTube
- AES-256-GCM encrypted token storage
- Automatic token refresh with configurable background scheduler
- Publish content with text, images, and video
- Credit/quota management — define operations, costs, packages, and track usage
- Storage adapters — in-memory (dev) or Prisma (production), or bring your own
- Zero dependencies — only Node.js built-ins + optional Prisma peer dependency
- MIT licensed — genuinely free software
Install
npm install @fastslack/socialkitQuick Start
import { SocialKit, MemoryTokenStore, MemoryCreditStore } from "@fastslack/socialkit";
const kit = new SocialKit({
tokenStore: new MemoryTokenStore(),
creditStore: new MemoryCreditStore(),
encryptionKey: SocialKit.generateKey(),
providers: {
linkedin: {
clientId: process.env.LINKEDIN_CLIENT_ID!,
clientSecret: process.env.LINKEDIN_CLIENT_SECRET!,
callbackUrl: "https://myapp.com/api/social/linkedin/callback",
},
twitter: {
clientId: process.env.TWITTER_CLIENT_ID!,
clientSecret: process.env.TWITTER_CLIENT_SECRET!,
callbackUrl: "https://myapp.com/api/social/twitter/callback",
},
},
operations: [
{ id: "publish:linkedin", name: "Publish to LinkedIn", cost: 1 },
{ id: "publish:twitter", name: "Publish to Twitter", cost: 1 },
{ id: "generate:thread", name: "Generate thread", cost: 3 },
],
packages: [
{ id: "starter", name: "Starter", credits: 50, price: 19, currency: "USD" },
{ id: "pro", name: "Pro", credits: 200, price: 49, currency: "USD" },
],
});OAuth Flow
// 1. Generate auth URL and redirect user
const url = kit.getAuthUrl("linkedin", { userId: "user_123" });
// → redirect user to `url`
// 2. Handle callback (exchange code for tokens, store encrypted)
await kit.handleCallback("linkedin", {
code: req.query.code,
userId: "user_123",
});
// 3. Check connected accounts
const connections = await kit.getConnections("user_123");
// → [{ provider: "linkedin", status: "active", expiresAt: ... }]Publishing
// Publish to one platform
const result = await kit.publish("linkedin", "user_123", {
text: "Hello from SocialKit!",
});
// → { success: true, postId: "...", postUrl: "https://linkedin.com/..." }
// Publish to multiple platforms
const results = await kit.publishAll(
["linkedin", "twitter", "facebook"],
"user_123",
{ text: "Cross-posted with SocialKit!" },
);Token Management
// Get a valid token (auto-refreshes if expiring)
const token = await kit.getToken("user_123", "linkedin");
// Disconnect a platform
await kit.disconnect("user_123", "linkedin");
// Start background token refresh (every 15 min)
kit.startRefreshScheduler();
// Manual refresh cycle
await kit.refreshNow();Credit System
// Add credits
await kit.credits.addCredits("user_123", 100, "purchase", "Starter pack");
// Check balance
const balance = await kit.credits.getBalance("user_123");
// → { balance: 100, totalPurchased: 100, totalUsed: 0 }
// Check if user can afford operations
const canAfford = await kit.credits.canAfford("user_123", [
"publish:linkedin",
"publish:twitter",
]);
// Deduct credits
await kit.credits.deductOne("user_123", "publish:linkedin");
// Bulk deduction
await kit.credits.deduct("user_123", [
"publish:linkedin",
"publish:twitter",
"generate:thread",
]);
// Get transaction history
const history = await kit.credits.getTransactions("user_123");Prisma Adapter (Production)
npm install @prisma/clientAdd the models from node_modules/@fastslack/socialkit/prisma/schema.prisma to your schema, then:
import { SocialKit } from "@fastslack/socialkit";
import { PrismaTokenStore, PrismaCreditStore } from "@fastslack/socialkit/prisma";
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
const kit = new SocialKit({
tokenStore: new PrismaTokenStore(prisma),
creditStore: new PrismaCreditStore(prisma),
encryptionKey: process.env.TOKEN_ENCRYPTION_KEY!,
providers: { /* ... */ },
});Custom Storage Adapter
Implement the TokenStore and/or CreditStore interfaces:
import type { TokenStore, CreditStore } from "@fastslack/socialkit";
class MyTokenStore implements TokenStore {
async save(token) { /* ... */ }
async get(userId, provider) { /* ... */ }
async getAll(userId) { /* ... */ }
async getExpiring(bufferMs, maxFailures) { /* ... */ }
async update(userId, provider, data) { /* ... */ }
async delete(userId, provider) { /* ... */ }
}Token Refresh Schedule
Each platform has different token lifetimes. The refresh scheduler handles them all:
| Platform | Access Token TTL | Refresh Buffer | |---|---|---| | Twitter/X | 2 hours | 30 min before | | YouTube | 1 hour | 10 min before | | TikTok | 24 hours | 2 hours before | | LinkedIn | 60 days | 1 day before | | Instagram | 60 days | 1 day before | | Facebook | 60 days | 1 day before | | Threads | 60 days | 1 day before |
Next.js Integration Example
// app/api/social/[provider]/route.ts
import { kit } from "@/lib/socialkit";
import { getServerSession } from "next-auth";
export async function GET(
req: Request,
{ params }: { params: { provider: string } },
) {
const session = await getServerSession();
const url = kit.getAuthUrl(params.provider, {
userId: session.user.id,
});
return Response.redirect(url);
}
// app/api/social/[provider]/callback/route.ts
export async function GET(
req: Request,
{ params }: { params: { provider: string } },
) {
const session = await getServerSession();
const { searchParams } = new URL(req.url);
await kit.handleCallback(params.provider, {
code: searchParams.get("code")!,
userId: session.user.id,
});
return Response.redirect("/dashboard/connections");
}Generate Encryption Key
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"License
MIT
