This guide contains all technical documentation for developers working with Bebop, including architecture details, API reference, and platform integration setup.
- Architecture Overview
- Development Setup
- API Reference
- Database Schema
- Platform Integrations Setup
- Testing
- Deployment
Bebop is a Next.js 15 application with React 19, using MongoDB for data persistence and Clerk for authentication.
- Framework: Next.js 15 with App Router
- Frontend: React 19, TypeScript, Tailwind CSS, shadcn/ui
- Database: MongoDB with Prisma ORM
- Authentication: Clerk
- Storage: AWS S3 (optional) or local filesystem
- Analytics: Privacy-first custom implementation
User Input → React Components → API Routes → Prisma ORM → MongoDB
↓ ↓
Client Hooks External APIs (GitHub, Dev.to, etc.)
src/
├── app/ # Next.js pages and API routes
├── components/ # React components
├── lib/ # Business logic and utilities
├── hooks/ # Custom React hooks
└── types/ # TypeScript definitions
- Node.js 18.17 or later
- MongoDB (local or Atlas)
- Git
Create .env.local in the root directory:
# Database
DATABASE_URL="mongodb://localhost:27017/bebop"
# Clerk Authentication (Required)
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="pk_..."
CLERK_SECRET_KEY="sk_..."
NEXT_PUBLIC_CLERK_SIGN_IN_URL="/sign-in"
NEXT_PUBLIC_CLERK_SIGN_UP_URL="/sign-up"
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL="/"
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL="/"
# AWS S3 (Optional - for media storage)
AWS_ACCESS_KEY_ID=""
AWS_SECRET_ACCESS_KEY=""
AWS_REGION="us-east-1"
AWS_S3_BUCKET=""
# Application
NEXT_PUBLIC_APP_URL="http://localhost:3000"
# Platform APIs (Optional - add as needed)
GITHUB_TOKEN=""
DEVTO_API_KEY=""
HASHNODE_API_KEY=""
HASHNODE_PUBLICATION_ID=""# Install dependencies
npm install
# Generate Prisma client
npx prisma generate
# Push schema to MongoDB
npx prisma db push
# Start development server
npm run devnpm run dev # Development server (port 3000)
npm run build # Production build
npm run start # Production server
npm run lint # ESLint
npm test # Run tests
npm run test:smoke # Smoke tests only
npm run test:quick # Quick test summary
npx prisma studio # Database GUI// GET /api/topics - List all topics
// POST /api/topics - Create new topic
// GET /api/topics/[id] - Get single topic
// PUT /api/topics/[id] - Update topic
// DELETE /api/topics/[id] - Delete topic// GET /api/campaigns - List campaigns
// POST /api/campaigns - Create campaign
// GET /api/campaigns/[id] - Get campaign details
// PUT /api/campaigns/[id] - Update campaign
// DELETE /api/campaigns/[id] - Delete campaign// POST /api/publish - Publish to platforms
// POST /api/publishing-plans - Create scheduled publication
// POST /api/publishing-plans/process-scheduled - Process due items
// POST /api/scheduler/trigger - Manual scheduler trigger// POST /api/analytics/track - Track events
// GET /api/analytics/metrics - Get analytics data// GET /api/media - List media files
// POST /api/media - Upload media
// DELETE /api/media/[id] - Delete media
// POST /api/media/sync - Sync S3 mediaAll API routes use Clerk authentication middleware. Include authorization headers:
const response = await fetch('/api/topics', {
headers: {
'Authorization': `Bearer ${token}`
}
});model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
clerkId String @unique
email String
topics Topic[]
campaigns Campaign[]
media Media[]
settings Json?
}
model Topic {
id String @id @default(auto()) @map("_id") @db.ObjectId
title String
content String
description String?
tags String[]
status String @default("draft")
userId String @db.ObjectId
user User @relation(fields: [userId], references: [id])
campaignIds String[] @db.ObjectId
campaigns Campaign[] @relation(fields: [campaignIds], references: [id])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Campaign {
id String @id @default(auto()) @map("_id") @db.ObjectId
name String
description String?
status String @default("draft")
goals String[]
userId String @db.ObjectId
user User @relation(fields: [userId], references: [id])
topicIds String[] @db.ObjectId
topics Topic[] @relation(fields: [topicIds], references: [id])
publishingPlans PublishingPlan[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model PublishingPlan {
id String @id @default(auto()) @map("_id") @db.ObjectId
campaignId String @db.ObjectId
campaign Campaign @relation(fields: [campaignId], references: [id])
topicId String @db.ObjectId
platform String
scheduledFor DateTime
status String @default("scheduled")
publishedUrl String?
error String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}-
Get Your API Token
- Log in to Hashnode
- Go to Account Settings → Developer
- Click "Generate New Token"
- Copy the token
-
Get Your Publication ID
- Visit your Hashnode blog
- The URL format is:
yourblog.hashnode.devor custom domain - Go to Blog Dashboard → Settings
- Find your Publication ID in the URL or settings
-
Configure in Bebop
- Go to Settings → Integrations → Hashnode
- Enter your API Token
- Enter your Publication ID
- Click "Test Connection"
- Save configuration
-
Publishing Options
- Draft: Save as draft on Hashnode
- Published: Publish immediately
- Tags: Automatically synced from your topics
- Cover Image: First image in content used as cover
-
Get Your API Key
- Log in to Dev.to
- Go to Settings → Extensions
- Scroll to "DEV API Keys"
- Generate new key with description "Bebop"
- Copy the API key
-
Configure in Bebop
- Go to Settings → Integrations → Dev.to
- Enter your API Key
- Click "Test Connection"
- Save configuration
-
Publishing Options
- Draft: Creates unpublished article
- Published: Publishes immediately
- Series: Can be linked to Dev.to series
- Tags: Up to 4 tags, auto-formatted
- Canonical URL: Set to maintain SEO
-
Get Your API Key
- Log in to Beehiiv
- Go to Settings → API
- Click "Create API Key"
- Name it "Bebop Integration"
- Copy the API key
-
Get Your Publication ID
- In Beehiiv dashboard, go to your publication settings
- The Publication ID starts with
pub_and can be found in:- Publication settings URL
- API documentation for your publication
- Browser developer tools when viewing your publication
-
Configure in Bebop
- Go to Settings → Beehiiv Integration
- Enter your API Key
- Enter your Publication ID (format:
pub_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) - Click "Test Connection"
- Save configuration
-
Publishing Features
- Newsletter Posts: Creates newsletter posts directly
- Draft/Published: Control publication status
- Rich Content: Full HTML content support
- Subtitles: Optional post descriptions
-
Requirements
- Enterprise Plan: Post creation API requires Beehiiv Enterprise
- Beta API: Feature is in beta and subject to change
- Rate Limits: Respect Beehiiv's API rate limits
-
Get App Password
- Log in to Bluesky
- Go to Settings → App Passwords
- Click "Add App Password"
- Name it "Bebop"
- Copy the generated password
-
Configure in Bebop
- Go to Settings → Integrations → Bluesky
- Enter your handle (e.g.,
yourname.bsky.social) - Enter the app password
- Click "Test Connection"
- Save configuration
-
Publishing Features
- Thread Support: Long content auto-threaded
- Mentions: Auto-linked @mentions
- Links: Automatic link cards
- Images: Up to 4 images per post
-
Get Access Token
- Log in to your Mastodon instance
- Go to Settings → Development
- Click "New Application"
- Name: "Bebop"
- Scopes:
read,write:statuses,write:media - Save and copy the access token
-
Configure in Bebop
- Go to Settings → Integrations → Mastodon
- Enter your instance URL (e.g.,
https://mastodon.social) - Enter your access token
- Click "Test Connection"
- Save configuration
-
Publishing Features
- Content Warnings: Optional CW support
- Visibility: Public, unlisted, followers-only
- Polls: Create polls (if instance supports)
- Media: Images with alt text
src/__tests__/
├── smoke/ # Quick smoke tests
│ ├── api.smoke.test.ts
│ ├── components.smoke.test.tsx
│ └── scheduler.smoke.test.ts
├── integration/ # Full integration tests
└── unit/ # Unit tests
# All tests
npm test
# Smoke tests only
npm run test:smoke
# With UI
npm run test:ui
# Test specific file
npm test -- api.smoke.test.ts
# Test coverage
npm test -- --coverage// Example smoke test
import { describe, it, expect } from 'vitest';
describe('Publishing API', () => {
it('creates publishing plan', async () => {
const response = await fetch('/api/publishing-plans', {
method: 'POST',
body: JSON.stringify({
campaignId: 'test-campaign',
topicId: 'test-topic',
platform: 'devto',
scheduledFor: new Date()
})
});
expect(response.ok).toBe(true);
});
});-
Fork & Connect
# Fork the repo, then in Vercel: - Import Git Repository - Select your fork - Configure environment variables - Deploy -
Environment Variables
- Add all variables from
.env.local - Set
NODE_ENV=production - Configure domain settings
- Add all variables from
-
Post-Deployment
- Verify MongoDB connection
- Test Clerk authentication
- Check platform integrations
-
Build for Production
npm run build
-
Using PM2
npm install -g pm2 pm2 start npm --name "bebop" -- start pm2 save pm2 startup -
Using Docker
FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY . . RUN npm run build EXPOSE 3000 CMD ["npm", "start"]
docker build -t bebop . docker run -p 3000:3000 --env-file .env.local bebop
- Set strong session secrets
- Configure CORS properly
- Enable rate limiting
- Set up error monitoring (Sentry)
- Configure backup strategy
- Use MongoDB replica set
- Set up SSL/TLS
- Configure CDN for media
MongoDB Connection Failed
# Check MongoDB is running
mongosh --eval "db.version()"
# Verify connection string
mongodb://localhost:27017/bebopClerk Authentication Issues
- Verify API keys are correct
- Check allowed origins in Clerk dashboard
- Ensure webhook endpoints are configured
Platform Publishing Fails
- Verify API keys/tokens are valid
- Check rate limits
- Review platform-specific requirements
- Check error logs in PublishingPlan records
Build Failures
# Clear cache and rebuild
rm -rf .next node_modules
npm install
npm run buildSee CONTRIBUTING.md for contribution guidelines.
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Last Updated: December 2024 | Bebop Version: 0.4.0