|
| 1 | +# AI Grant Crawler - Deployment Playbook |
| 2 | + |
| 3 | +This playbook provides step-by-step instructions for deploying the AI Grant Crawler application to production. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +The AI Grant Crawler is a full-stack application with the following architecture: |
| 8 | + |
| 9 | +- **Backend**: Node.js/Express API deployed to **Railway** (primary) or Fly.io (alternative) |
| 10 | +- **Frontend**: SvelteKit application deployed to **Vercel** |
| 11 | +- **Database**: **Supabase** (PostgreSQL with real-time capabilities) |
| 12 | +- **AI**: **Google Gemini** API for proposal generation |
| 13 | + |
| 14 | +## Prerequisites |
| 15 | + |
| 16 | +Before starting, ensure you have accounts on: |
| 17 | + |
| 18 | +1. **GitHub** - Repository access (https://github.com/Datakult0r/ai-grant-crawler-a2a-pro) |
| 19 | +2. **Railway** - Backend hosting (https://railway.app) |
| 20 | +3. **Supabase** - Database (https://supabase.com) |
| 21 | +4. **Google AI Studio** - Gemini API key (https://aistudio.google.com) |
| 22 | +5. **Vercel** - Frontend hosting (https://vercel.com) |
| 23 | +6. **Fly.io** (optional) - Alternative backend hosting (https://fly.io) |
| 24 | + |
| 25 | +--- |
| 26 | + |
| 27 | +## Step-by-Step Deployment |
| 28 | + |
| 29 | +### Step 1: Configure Supabase |
| 30 | + |
| 31 | +1. **Create a Supabase Project** (if not already done): |
| 32 | + - Go to https://supabase.com/dashboard |
| 33 | + - Click "New Project" |
| 34 | + - Choose organization, name, password, and region |
| 35 | + - Wait for project to initialize |
| 36 | + |
| 37 | +2. **Get Your Credentials**: |
| 38 | + - Go to Project Settings > API |
| 39 | + - Copy the following values: |
| 40 | + |
| 41 | + | Supabase UI Label | Environment Variable | Description | |
| 42 | + |-------------------|---------------------|-------------| |
| 43 | + | Project URL | `SUPABASE_URL` | Your project's API URL (e.g., `https://xxxxx.supabase.co`) | |
| 44 | + | anon public | `SUPABASE_ANON_KEY` | Public API key for client-side access | |
| 45 | + | service_role secret | `SUPABASE_SERVICE_ROLE_KEY` | Private key for server-side operations (keep secret!) | |
| 46 | + |
| 47 | +3. **Apply Database Schema**: |
| 48 | + - Go to SQL Editor in Supabase Dashboard |
| 49 | + - Copy the contents of `backend/schema.sql` |
| 50 | + - Run the SQL to create all tables and RLS policies |
| 51 | + |
| 52 | +4. **Seed Demo Data** (optional): |
| 53 | + - After backend is deployed, run: `npm run seed` from the backend directory |
| 54 | + |
| 55 | +--- |
| 56 | + |
| 57 | +### Step 2: Create Gemini API Key |
| 58 | + |
| 59 | +1. Go to https://aistudio.google.com/app/apikey |
| 60 | +2. Click "Create API Key" |
| 61 | +3. Select or create a Google Cloud project |
| 62 | +4. Copy the generated API key |
| 63 | +5. Save as `GEMINI_API_KEY` |
| 64 | + |
| 65 | +**Note**: The Gemini API key is required for AI proposal generation (Fast Track and Research Track features). |
| 66 | + |
| 67 | +--- |
| 68 | + |
| 69 | +### Step 3: Deploy Backend to Railway (Primary) |
| 70 | + |
| 71 | +Railway uses the `backend/railway.json` configuration with Nixpacks builder. |
| 72 | + |
| 73 | +1. **Create Railway Project**: |
| 74 | + - Go to https://railway.app/dashboard |
| 75 | + - Click "New Project" > "Deploy from GitHub repo" |
| 76 | + - Connect your GitHub account if not already connected |
| 77 | + - Select `Datakult0r/ai-grant-crawler-a2a-pro` |
| 78 | + |
| 79 | +2. **Configure Root Directory**: |
| 80 | + - In project settings, set Root Directory to: `backend` |
| 81 | + |
| 82 | +3. **Set Environment Variables**: |
| 83 | + - Go to Variables tab |
| 84 | + - Add the following: |
| 85 | + |
| 86 | + ``` |
| 87 | + SUPABASE_URL=your-supabase-url-here |
| 88 | + SUPABASE_ANON_KEY=your-supabase-anon-key-here |
| 89 | + GEMINI_API_KEY=your-gemini-api-key-here |
| 90 | + PORT=3000 |
| 91 | + NODE_ENV=production |
| 92 | + LOW_COST_MODE=true |
| 93 | + IS_DEMO=false |
| 94 | + ``` |
| 95 | + |
| 96 | + Optional variables: |
| 97 | + ``` |
| 98 | + OPENROUTER_API_KEY=your-openrouter-key-here |
| 99 | + FIRECRAWL_API_KEY=your-firecrawl-key-here |
| 100 | + RESEND_API_KEY=your-resend-key-here |
| 101 | + ``` |
| 102 | + |
| 103 | +4. **Deploy**: |
| 104 | + - Railway will automatically build and deploy using Nixpacks |
| 105 | + - Build command: `npm install` (automatic) |
| 106 | + - Start command: `npm start` (from railway.json) |
| 107 | + |
| 108 | +5. **Get Backend URL**: |
| 109 | + - Go to Settings > Domains |
| 110 | + - Generate a Railway domain or add custom domain |
| 111 | + - Your backend URL will be: `https://your-app.up.railway.app` |
| 112 | + |
| 113 | +6. **Verify Deployment**: |
| 114 | + ```bash |
| 115 | + curl https://your-app.up.railway.app/health |
| 116 | + curl https://your-app.up.railway.app/version |
| 117 | + curl https://your-app.up.railway.app/metrics |
| 118 | + ``` |
| 119 | + |
| 120 | +--- |
| 121 | + |
| 122 | +### Step 4: Deploy Backend to Fly.io (Alternative) |
| 123 | + |
| 124 | +If using Fly.io instead of Railway: |
| 125 | + |
| 126 | +1. **Install Fly CLI**: |
| 127 | + ```bash |
| 128 | + # macOS |
| 129 | + brew install flyctl |
| 130 | + |
| 131 | + # Linux |
| 132 | + curl -L https://fly.io/install.sh | sh |
| 133 | + ``` |
| 134 | + |
| 135 | +2. **Login and Create App**: |
| 136 | + ```bash |
| 137 | + fly auth login |
| 138 | + cd backend |
| 139 | + fly launch |
| 140 | + ``` |
| 141 | + |
| 142 | +3. **Generate FLY_API_TOKEN** (for CI/CD): |
| 143 | + - Go to https://fly.io/user/personal_access_tokens |
| 144 | + - Click "Create Token" |
| 145 | + - Name it (e.g., "ai-grant-crawler-deploy") |
| 146 | + - Copy the token |
| 147 | + |
| 148 | +4. **Set Secrets**: |
| 149 | + ```bash |
| 150 | + fly secrets set SUPABASE_URL="your-supabase-url-here" |
| 151 | + fly secrets set SUPABASE_ANON_KEY="your-supabase-anon-key-here" |
| 152 | + fly secrets set GEMINI_API_KEY="your-gemini-api-key-here" |
| 153 | + fly secrets set LOW_COST_MODE="true" |
| 154 | + fly secrets set IS_DEMO="false" |
| 155 | + ``` |
| 156 | + |
| 157 | +5. **Deploy**: |
| 158 | + ```bash |
| 159 | + fly deploy |
| 160 | + ``` |
| 161 | + |
| 162 | +6. **Get Backend URL**: |
| 163 | + - Your URL will be: `https://your-app.fly.dev` |
| 164 | + |
| 165 | +--- |
| 166 | + |
| 167 | +### Step 5: Deploy Frontend to Vercel |
| 168 | + |
| 169 | +1. **Import Project**: |
| 170 | + - Go to https://vercel.com/new |
| 171 | + - Import `Datakult0r/ai-grant-crawler-a2a-pro` |
| 172 | + |
| 173 | +2. **Configure Build Settings**: |
| 174 | + - Framework Preset: SvelteKit |
| 175 | + - Root Directory: `frontend` |
| 176 | + - Build Command: `npm run build` |
| 177 | + - Output Directory: `.svelte-kit` |
| 178 | + |
| 179 | +3. **Set Environment Variables**: |
| 180 | + - Go to Project Settings > Environment Variables |
| 181 | + - Add: |
| 182 | + |
| 183 | + ``` |
| 184 | + PUBLIC_API_URL=https://your-backend.up.railway.app/api |
| 185 | + PUBLIC_SUPABASE_URL=your-supabase-url-here |
| 186 | + PUBLIC_SUPABASE_ANON_KEY=your-supabase-anon-key-here |
| 187 | + PUBLIC_IS_DEMO=false |
| 188 | + ``` |
| 189 | + |
| 190 | + **Important**: `PUBLIC_API_URL` must point to your deployed backend URL with `/api` suffix. |
| 191 | + |
| 192 | +4. **Deploy**: |
| 193 | + - Click Deploy |
| 194 | + - Vercel will build and deploy automatically |
| 195 | + |
| 196 | +5. **Get Frontend URL**: |
| 197 | + - Your URL will be: `https://your-app.vercel.app` |
| 198 | + |
| 199 | +--- |
| 200 | + |
| 201 | +## Environment Variables Reference |
| 202 | + |
| 203 | +| Variable | Description | Where to Set | Required | |
| 204 | +|----------|-------------|--------------|----------| |
| 205 | +| `SUPABASE_URL` | Supabase project URL | Backend (Railway/Fly), Frontend (Vercel) | Yes | |
| 206 | +| `SUPABASE_ANON_KEY` | Supabase public API key | Backend (Railway/Fly), Frontend (Vercel) | Yes | |
| 207 | +| `SUPABASE_SERVICE_ROLE_KEY` | Supabase private key | Backend only (for admin operations) | No | |
| 208 | +| `GEMINI_API_KEY` | Google Gemini API key | Backend (Railway/Fly) | Yes | |
| 209 | +| `PORT` | Server port | Backend (Railway/Fly) | Yes (3000) | |
| 210 | +| `NODE_ENV` | Environment mode | Backend (Railway/Fly) | Yes (production) | |
| 211 | +| `LOW_COST_MODE` | Use cheaper AI models | Backend (Railway/Fly) | No (default: true) | |
| 212 | +| `IS_DEMO` | Enable demo mode | Backend (Railway/Fly), Frontend (Vercel) | No (default: false) | |
| 213 | +| `PUBLIC_API_URL` | Backend API URL | Frontend (Vercel) | Yes | |
| 214 | +| `OPENROUTER_API_KEY` | OpenRouter API key | Backend (Railway/Fly) | No | |
| 215 | +| `FIRECRAWL_API_KEY` | Firecrawl scraping API | Backend (Railway/Fly) | No | |
| 216 | +| `RESEND_API_KEY` | Resend email API | Backend (Railway/Fly) | No | |
| 217 | +| `FLY_API_TOKEN` | Fly.io deploy token | GitHub Actions (if using Fly) | No | |
| 218 | + |
| 219 | +--- |
| 220 | + |
| 221 | +## Post-Deployment Checklist |
| 222 | + |
| 223 | +After deployment, verify the following: |
| 224 | + |
| 225 | +1. **Backend Health**: |
| 226 | + - [ ] `/health` returns `{"status":"ok"}` |
| 227 | + - [ ] `/version` returns version info |
| 228 | + - [ ] `/metrics` returns uptime and memory stats |
| 229 | + |
| 230 | +2. **Database Connection**: |
| 231 | + - [ ] `/api/grants` returns grant data |
| 232 | + - [ ] Seed script ran successfully (8 demo grants) |
| 233 | + |
| 234 | +3. **Frontend**: |
| 235 | + - [ ] Discovery page loads grants |
| 236 | + - [ ] "Apply Now" opens proposal strategy modal |
| 237 | + - [ ] Login/signup pages work |
| 238 | + |
| 239 | +4. **AI Features** (requires GEMINI_API_KEY): |
| 240 | + - [ ] Fast Track proposal generation works |
| 241 | + - [ ] Research Track SSE streaming works |
| 242 | + |
| 243 | +--- |
| 244 | + |
| 245 | +## Troubleshooting |
| 246 | + |
| 247 | +### Backend not starting |
| 248 | +- Check Railway/Fly logs for errors |
| 249 | +- Verify all required env vars are set |
| 250 | +- Ensure `PORT` is set to 3000 |
| 251 | + |
| 252 | +### Frontend can't connect to backend |
| 253 | +- Verify `PUBLIC_API_URL` is correct (include `/api` suffix) |
| 254 | +- Check CORS settings in backend |
| 255 | +- Ensure backend is running |
| 256 | + |
| 257 | +### Database errors |
| 258 | +- Verify `SUPABASE_URL` and `SUPABASE_ANON_KEY` are correct |
| 259 | +- Ensure schema.sql has been applied |
| 260 | +- Check RLS policies in Supabase |
| 261 | + |
| 262 | +### AI features not working |
| 263 | +- Verify `GEMINI_API_KEY` is set and valid |
| 264 | +- Check backend logs for API errors |
| 265 | +- Ensure `LOW_COST_MODE` is set appropriately |
| 266 | + |
| 267 | +--- |
| 268 | + |
| 269 | +## Support |
| 270 | + |
| 271 | +For issues or questions: |
| 272 | +- Repository: https://github.com/Datakult0r/ai-grant-crawler-a2a-pro |
| 273 | +- Documentation: See `docs/PRD.md` and `docs/DEPLOYMENT.md` |
0 commit comments