{"id":49965781,"url":"https://github.com/nithamitabh/dispatch","last_synced_at":"2026-05-18T05:43:39.256Z","repository":{"id":321988496,"uuid":"1087862978","full_name":"nithamitabh/dispatch","owner":"nithamitabh","description":"A CI/CD Newsletters for your Blog Apps,Enterprise Updates,Indie Hackers,Teams with Private repos","archived":false,"fork":false,"pushed_at":"2025-11-01T20:42:23.000Z","size":117,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-01T21:18:46.138Z","etag":null,"topics":["cicd","mailservice","mdx","newsletters"],"latest_commit_sha":null,"homepage":"https://dispatch-silk.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nithamitabh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-01T19:52:49.000Z","updated_at":"2025-11-01T20:42:21.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/nithamitabh/dispatch","commit_stats":null,"previous_names":["nithamitabh/dispatch"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/nithamitabh/dispatch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nithamitabh%2Fdispatch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nithamitabh%2Fdispatch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nithamitabh%2Fdispatch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nithamitabh%2Fdispatch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nithamitabh","download_url":"https://codeload.github.com/nithamitabh/dispatch/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nithamitabh%2Fdispatch/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33166730,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-17T22:39:12.733Z","status":"online","status_checked_at":"2026-05-18T02:00:06.436Z","response_time":71,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cicd","mailservice","mdx","newsletters"],"created_at":"2026-05-18T05:43:38.028Z","updated_at":"2026-05-18T05:43:39.244Z","avatar_url":"https://github.com/nithamitabh.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ⚡ Dispatch - CI/CD for Newsletters\n\n\u003e **Write in Markdown. Push to GitHub. We handle the rest.**  \n\u003e Automate your newsletter publishing with GitHub integration.\n\n[![Next.js](https://img.shields.io/badge/Next.js-16.0.1-black?style=flat\u0026logo=next.js)](https://nextjs.org)\n[![Supabase](https://img.shields.io/badge/Supabase-Auth%20%2B%20DB-3ECF8E?style=flat\u0026logo=supabase)](https://supabase.com)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.0-blue?style=flat\u0026logo=typescript)](https://www.typescriptlang.org/)\n[![Tailwind CSS](https://img.shields.io/badge/Tailwind-4.0-38bdf8?style=flat\u0026logo=tailwind-css)](https://tailwindcss.com)\n\n---\n\n## 🚀 Quick Start\n\n```bash\n# Install dependencies\nnpm install\n\n# Set up environment variables\ncp .env.example .env.local\n\n# Run development server\nnpm run dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000) to see the app.\n\n---\n\n## 📦 Tech Stack\n\n- **Framework:** [Next.js 16](https://nextjs.org) (App Router)\n- **Database \u0026 Auth:** [Supabase](https://supabase.com)\n- **Styling:** [Tailwind CSS 4](https://tailwindcss.com)\n- **Language:** TypeScript\n- **Deployment:** [Vercel](https://vercel.com)\n\n---\n\n## 🗺️ Development Roadmap\n\n### 🧱 Phase 1 — Core Dashboard (Next.js + Supabase)\n\n**Goal:** Basic user dashboard, login, and repo connection.\n\n#### ✅ Completed Features\n\n- [x] 🎨 **Beautiful SaaS Landing Page**\n  - Hero section with animated gradients\n  - Feature cards with hover effects\n  - Responsive design with mobile menu\n  - Stats showcase and \"How It Works\" section\n\n- [x] 🔐 **GitHub OAuth Authentication**\n  - Login page with glassmorphism design\n  - OAuth integration via Supabase\n  - Loading page with real-time status updates\n  - Secure httpOnly cookie session management\n\n- [x] 🌓 **Light \u0026 Dark Theme System**\n  - React Context with localStorage persistence\n  - Amber/cream light theme + Cyan/blue dark theme\n  - Theme toggle component with sun/moon icons\n  - Smooth transitions across all pages\n\n- [x] 📊 **Dashboard Layout**\n  - Sidebar navigation (Home, Publications, Settings)\n  - User profile display with GitHub username\n  - Stats cards with animations\n  - Recent publications list\n  - Getting started checklist\n\n- [x] 📰 **Publications Management**\n  - Create new publication (repo name + webhook secret)\n  - Publications table with GitHub icons\n  - Copy webhook URL button\n  - Delete publication functionality\n  - Empty state with CTA\n\n- [x] ⚙️ **Settings Page**\n  - Theme selector with preview cards\n  - Account settings section\n  - GitHub integration status\n  - Danger zone for account deletion\n\n- [x] 🎯 **User Experience**\n  - Smooth scrolling throughout app\n  - Loading states for async operations\n  - Clean error handling (no console logs)\n  - External features page redirect\n\n#### 🚧 In Progress\n\n- [X] 🔗 **Webhook URL Generation**\n  - Generate unique webhook endpoints per publication\n  - Display webhook setup instructions\n\n- [X] 💾 **Token Storage**\n  - Store GitHub access_token securely in Supabase\n  - Encrypt sensitive tokens\n\n#### 📋 Remaining Phase 1 Tasks\n\n- [X] ✅ **Basic Testing**\n  - Test GitHub OAuth flow end-to-end\n  - Verify publication CRUD operations\n  - Test theme persistence across sessions\n\n---\n\n### ⚙️ Phase 2 — Webhook Trigger (Fast + Reliable)\n\n**Goal:** Receive GitHub push events and queue jobs.\n\n#### 🎯 Planned Features\n\n- [ ] 🪝 **Webhook Endpoint**\n  - `/api/github/webhook` route in Next.js\n  - Validate GitHub signature using shared secret\n  - Parse push event payload\n\n- [ ] 📋 **Job Queue System**\n  - Create `jobs` table in Supabase\n  - Insert job on push: `{ repo, commit, status }`\n  - Simple queue without QStash (Supabase as mini queue)\n\n- [ ] 🔔 **Event Processing**\n  - Detect MDX file changes in push events\n  - Filter relevant commits\n  - Queue processing jobs\n\n---\n\n### 🧠 Phase 3 — Processing Worker (MDX to Email HTML)\n\n**Goal:** Process MDX → HTML for email delivery.\n\n#### 🎯 Planned Features\n\n- [ ] ⏰ **CRON Job / Worker**\n  - Vercel Cron Job or Next.js route\n  - Run every few minutes\n  - Pull next unprocessed job from `jobs` table\n\n- [ ] 📝 **MDX Processing Pipeline**\n  - Fetch `.mdx` file from GitHub API\n  - Parse using `mdx-bundler`\n  - Sanitize HTML with `DOMPurify`\n  - Inline CSS via `juice`\n  - Save HTML to `posts` table\n\n- [ ] 🚀 **Job Status Updates**\n  - Update job status: `pending → processing → completed`\n  - Error handling and retry logic\n  - Webhook status notifications\n\n---\n\n## 🏗️ Project Structure\n\n```\ndispatch/\n├── app/\n│   ├── (auth)/\n│   │   ├── login/          # Login page with GitHub OAuth\n│   │   └── loading/        # OAuth callback loading page\n│   ├── api/\n│   │   ├── auth/           # Authentication endpoints\n│   │   ├── publications/   # Publications CRUD API\n│   │   └── user/           # User profile API\n│   ├── dashboard/\n│   │   ├── publications/   # Publications management\n│   │   ├── settings/       # User settings\n│   │   ├── layout.tsx      # Dashboard wrapper with sidebar\n│   │   └── page.tsx        # Dashboard home\n│   ├── globals.css         # Global styles \u0026 theme\n│   ├── layout.tsx          # Root layout with theme provider\n│   └── page.tsx            # Landing page\n├── components/\n│   ├── ui/                 # Reusable UI components\n│   ├── header.tsx          # App header\n│   ├── theme-provider.tsx  # Theme context provider\n│   └── theme-toggle.tsx    # Theme switcher button\n├── lib/\n│   ├── auth.ts             # Server-side auth helper\n│   └── supabaseClient.ts   # Supabase client config\n└── public/                 # Static assets\n```\n\n---\n\n## 🗄️ Database Schema\n\n### `publications` table\n```sql\nid              uuid PRIMARY KEY\nuser_id         uuid REFERENCES auth.users\nrepo_name       text NOT NULL\nwebhook_secret  text\ncreated_at      timestamptz DEFAULT now()\n```\n\n### `user_tokens` table\n```sql\nuser_id         uuid PRIMARY KEY REFERENCES auth.users\naccess_token    text NOT NULL (encrypted)\ncreated_at      timestamptz DEFAULT now()\n```\n\n### `jobs` table (Phase 2)\n```sql\nid              uuid PRIMARY KEY\npublication_id  uuid REFERENCES publications\ncommit_sha      text NOT NULL\nstatus          text DEFAULT 'pending'\ncreated_at      timestamptz DEFAULT now()\nprocessed_at    timestamptz\n```\n\n### `posts` table (Phase 3)\n```sql\nid              uuid PRIMARY KEY\njob_id          uuid REFERENCES jobs\nhtml_content    text\nmetadata        jsonb\ncreated_at      timestamptz DEFAULT now()\n```\n\n---\n\n## 🌐 Environment Variables\n\n```env\n# Supabase\nNEXT_PUBLIC_SUPABASE_URL=your-project-url\nNEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key\nSUPABASE_SERVICE_ROLE_KEY=your-service-role-key\n\n# GitHub OAuth (configured in Supabase)\n# Callback URL: https://your-domain.com/api/auth/callback\n```\n\n---\n\n## 🤝 Contributing\n\nWe welcome contributions! Here's how you can help:\n\n1. **Fork the repository**\n2. **Create a feature branch:** `git checkout -b feature/amazing-feature`\n3. **Commit your changes:** `git commit -m 'Add amazing feature'`\n4. **Push to the branch:** `git push origin feature/amazing-feature`\n5. **Open a Pull Request**\n\n### Development Guidelines\n\n- Follow the existing code style (TypeScript + ESLint)\n- Add meaningful commit messages\n- Test your changes thoroughly\n- Update documentation as needed\n\n---\n\n## 📄 License\n\nThis project is licensed under the MIT License.\n\n---\n\n## 🔗 Links\n\n- **Live Demo:** [Coming Soon]\n- **Features Documentation:** [https://dispatch-mdx.vercel.app/](https://dispatch-mdx.vercel.app/)\n- **GitHub:** [Repository Link]\n\n---\n\n**Built with ❤️ by the Dispatch team**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnithamitabh%2Fdispatch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnithamitabh%2Fdispatch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnithamitabh%2Fdispatch/lists"}