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