Write in Markdown. Push to GitHub. We handle the rest.
Automate your newsletter publishing with GitHub integration.
# Install dependencies
npm install
# Set up environment variables
cp .env.example .env.local
# Run development server
npm run devOpen http://localhost:3000 to see the app.
- Framework: Next.js 16 (App Router)
- Database & Auth: Supabase
- Styling: Tailwind CSS 4
- Language: TypeScript
- Deployment: Vercel
Goal: Basic user dashboard, login, and repo connection.
-
🎨 Beautiful SaaS Landing Page
- Hero section with animated gradients
- Feature cards with hover effects
- Responsive design with mobile menu
- Stats showcase and "How It Works" section
-
🔐 GitHub OAuth Authentication
- Login page with glassmorphism design
- OAuth integration via Supabase
- Loading page with real-time status updates
- Secure httpOnly cookie session management
-
🌓 Light & Dark Theme System
- React Context with localStorage persistence
- Amber/cream light theme + Cyan/blue dark theme
- Theme toggle component with sun/moon icons
- Smooth transitions across all pages
-
📊 Dashboard Layout
- Sidebar navigation (Home, Publications, Settings)
- User profile display with GitHub username
- Stats cards with animations
- Recent publications list
- Getting started checklist
-
📰 Publications Management
- Create new publication (repo name + webhook secret)
- Publications table with GitHub icons
- Copy webhook URL button
- Delete publication functionality
- Empty state with CTA
-
⚙️ Settings Page
- Theme selector with preview cards
- Account settings section
- GitHub integration status
- Danger zone for account deletion
-
🎯 User Experience
- Smooth scrolling throughout app
- Loading states for async operations
- Clean error handling (no console logs)
- External features page redirect
-
🔗 Webhook URL Generation
- Generate unique webhook endpoints per publication
- Display webhook setup instructions
-
💾 Token Storage
- Store GitHub access_token securely in Supabase
- Encrypt sensitive tokens
- ✅ Basic Testing
- Test GitHub OAuth flow end-to-end
- Verify publication CRUD operations
- Test theme persistence across sessions
Goal: Receive GitHub push events and queue jobs.
-
🪝 Webhook Endpoint
/api/github/webhookroute in Next.js- Validate GitHub signature using shared secret
- Parse push event payload
-
📋 Job Queue System
- Create
jobstable in Supabase - Insert job on push:
{ repo, commit, status } - Simple queue without QStash (Supabase as mini queue)
- Create
-
🔔 Event Processing
- Detect MDX file changes in push events
- Filter relevant commits
- Queue processing jobs
Goal: Process MDX → HTML for email delivery.
-
⏰ CRON Job / Worker
- Vercel Cron Job or Next.js route
- Run every few minutes
- Pull next unprocessed job from
jobstable
-
📝 MDX Processing Pipeline
- Fetch
.mdxfile from GitHub API - Parse using
mdx-bundler - Sanitize HTML with
DOMPurify - Inline CSS via
juice - Save HTML to
poststable
- Fetch
-
🚀 Job Status Updates
- Update job status:
pending → processing → completed - Error handling and retry logic
- Webhook status notifications
- Update job status:
dispatch/
├── app/
│ ├── (auth)/
│ │ ├── login/ # Login page with GitHub OAuth
│ │ └── loading/ # OAuth callback loading page
│ ├── api/
│ │ ├── auth/ # Authentication endpoints
│ │ ├── publications/ # Publications CRUD API
│ │ └── user/ # User profile API
│ ├── dashboard/
│ │ ├── publications/ # Publications management
│ │ ├── settings/ # User settings
│ │ ├── layout.tsx # Dashboard wrapper with sidebar
│ │ └── page.tsx # Dashboard home
│ ├── globals.css # Global styles & theme
│ ├── layout.tsx # Root layout with theme provider
│ └── page.tsx # Landing page
├── components/
│ ├── ui/ # Reusable UI components
│ ├── header.tsx # App header
│ ├── theme-provider.tsx # Theme context provider
│ └── theme-toggle.tsx # Theme switcher button
├── lib/
│ ├── auth.ts # Server-side auth helper
│ └── supabaseClient.ts # Supabase client config
└── public/ # Static assets
id uuid PRIMARY KEY
user_id uuid REFERENCES auth.users
repo_name text NOT NULL
webhook_secret text
created_at timestamptz DEFAULT now()user_id uuid PRIMARY KEY REFERENCES auth.users
access_token text NOT NULL (encrypted)
created_at timestamptz DEFAULT now()id uuid PRIMARY KEY
publication_id uuid REFERENCES publications
commit_sha text NOT NULL
status text DEFAULT 'pending'
created_at timestamptz DEFAULT now()
processed_at timestamptzid uuid PRIMARY KEY
job_id uuid REFERENCES jobs
html_content text
metadata jsonb
created_at timestamptz DEFAULT now()# Supabase
NEXT_PUBLIC_SUPABASE_URL=your-project-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
# GitHub OAuth (configured in Supabase)
# Callback URL: https://your-domain.com/api/auth/callbackWe welcome contributions! Here's how you can help:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
- Follow the existing code style (TypeScript + ESLint)
- Add meaningful commit messages
- Test your changes thoroughly
- Update documentation as needed
This project is licensed under the MIT License.
- Live Demo: [Coming Soon]
- Features Documentation: https://dispatch-mdx.vercel.app/
- GitHub: [Repository Link]
Built with ❤️ by the Dispatch team