@digitalocean/mcp 1.0.21 → 1.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,29 +1,116 @@
1
- # Vercel to App Platform Migration Instructions
1
+ # Vercel to App Platform Migration Instructions (v3)
2
+
3
+ 📦 **Version 3 Updates:**
4
+ - **NEW: Step 1.5 - Monorepo Dependency Consolidation** - Critical section on how App Platform handles monorepo dependencies
5
+ - **KEY INSIGHT:** App Platform only installs dependencies from root `package.json` in monorepos
6
+ - **PROACTIVE APPROACH:** Analyze and consolidate dependencies before deployment to avoid build failures
7
+ - **HYBRID STRATEGY:** Combine proactive analysis with fallback iterative fixing for best results
8
+
9
+ ⚠️ **Important: This is a Starter Guide for AI Coding Assistants**
10
+
11
+ This guide helps AI coding assistants (Claude Code, Cursor, Gemini, etc.) collaborate with you to deploy applications to DigitalOcean App Platform.
12
+
13
+ **Constants:**
14
+ - **RETRY_LIMIT:** 3
15
+
16
+ **What this guide IS:**
17
+ - A structured workflow for AI-assisted deployment and migration
18
+ - A comprehensive checklist of steps and considerations
19
+ - Assisted error detection with fix suggestions (up to **RETRY_LIMIT** retry attempts)
20
+ - Truthful about limitations and manual steps required
21
+ - A starting point that handles common scenarios
22
+
23
+ **What this guide IS NOT:**
24
+ - A "magic migration button" that works without human oversight
25
+ - A guarantee of 1:1 feature parity with Vercel
26
+ - A replacement for understanding your application's architecture
27
+ - Suitable for highly complex, non-standard architectures without modifications
28
+ - Fully automated - you remain in control of all decisions
29
+
30
+ **Your role (the human):**
31
+ - Understand your application's architecture and requirements
32
+ - Make decisions about trade-offs and implementation approaches
33
+ - Verify deployment results and test functionality
34
+ - Implement code changes for unsupported features
35
+ - Monitor and validate production deployment
36
+
37
+ **AI assistant's role:**
38
+ - Guide you through the migration process step-by-step
39
+ - Automate repository and infrastructure setup tasks
40
+ - Detect common errors and suggest fixes
41
+ - Provide alternatives for unsupported features
42
+ - Generate configuration files and commands
43
+
44
+ **Success requires active collaboration between you and your AI assistant.**
2
45
 
3
- You are assisting with migrating applications from Vercel to DigitalOcean App Platform using MCP servers. Follow these instructions carefully to ensure a smooth migration.
4
-
5
- ## Initial Setup
46
+ ---
6
47
 
7
- First, ask the user for the name of the Vercel app they want to migrate.
48
+ ## Supported Deployment Scenarios
8
49
 
9
- **Note:** You can repeat this migration process for each additional app they want to move over.
50
+ This guide supports multiple scenarios:
51
+ 1. **Migrating from existing Vercel deployment** - Moving a working Vercel app to App Platform (with or without Vercel CLI access)
52
+ 2. **Deploying from GitHub repository** - App may be running on Vercel, but you just provide the repo to deploy to App Platform
53
+ 3. **Deploying source code directly** - Getting source code working on App Platform (no Vercel deployment required)
54
+ 4. **Deploying without repository access** - Creating new repository or deploying from local source
10
55
 
11
- Then verify:
12
- - You have access to **Vercel MCP server** and **DigitalOcean MCP server**
13
- - **Vercel CLI is installed** (`vercel` command available) - **Required for retrieving environment variables**
14
- - Check if the current directory is a github repository and it is the same as the project that needs to be migrated
15
- - Clone the repository to local disk if code change is needed
16
- - User has confirmed they want to proceed with migration
56
+ Follow these instructions carefully to ensure a smooth deployment.
17
57
 
18
- **Important:** The Vercel CLI is required because the Vercel MCP server does not provide environment variables. Make sure the user has:
19
- 1. Installed Vercel CLI: `npm i -g vercel`
20
- 2. Authenticated: `vercel login`
58
+ ## Initial Setup
21
59
 
22
- **Note:** These instructions use a hybrid approach:
23
- - **Vercel CLI:** Required for environment variables and app inspection
24
- - **Vercel MCP server:** For project information (where available)
25
- - **DigitalOcean MCP server:** Primary method for App Platform operations
26
- - **Fallback options:** `doctl` CLI or [DigitalOcean REST API](https://docs.digitalocean.com/reference/api/digitalocean/)
60
+ ### Determine Deployment Scenario
61
+
62
+ First, determine the user's scenario:
63
+
64
+ 1. **Scenario A: Full Vercel Migration (with credentials)**
65
+ - User has an existing live Vercel app they want to migrate
66
+ - User has access to Vercel account/CLI
67
+ - Ask for the Vercel app name
68
+ - Will use Vercel CLI to pull environment variables and app configuration
69
+ - Will migrate domains and settings
70
+
71
+ 2. **Scenario B: Repository-based Deployment (app may be on Vercel)**
72
+ - User provides a GitHub repository URL
73
+ - App may or may not be currently running on Vercel
74
+ - User says: "Here's my GitHub repo, deploy it to App Platform"
75
+ - No need for Vercel CLI access - work directly from repository
76
+ - Environment variables collected manually from .env.example or user input
77
+
78
+ 3. **Scenario C: Source Code Only (no Vercel, no repo)**
79
+ - User has source code and wants to deploy to App Platform
80
+ - No Vercel deployment exists
81
+ - May or may not have existing GitHub repository
82
+ - Goal is to get the application working on App Platform
83
+
84
+ 4. **Scenario D: No Repository Access**
85
+ - User wants to deploy without giving access to personal/private repo
86
+ - Can create new repository in their account using `gh` CLI
87
+ - Can fork existing repository
88
+ - Can deploy from local source (less recommended)
89
+
90
+ **For most migrations:** Scenario A or B are most common. Scenario B is simpler if user doesn't need/want to provide Vercel credentials.
91
+
92
+ ### Verify Available Tools
93
+
94
+ **Primary Method: CLI Tools (Recommended)**
95
+ - **doctl CLI:** Primary method for App Platform operations (create apps, manage deployments, configure domains)
96
+ - **gh CLI:** For GitHub repository operations (create repo, fork, push code)
97
+ - **Vercel CLI (if migrating from Vercel):** For pulling environment variables and app details
98
+
99
+ **Alternative Method: MCP Servers (Optional)**
100
+ - **Vercel MCP server:** For project information (where available) - Optional
101
+ - **DigitalOcean MCP server:** For App Platform operations - Optional
102
+ - **Note:** CLI tools are preferred and don't require MCP server setup
103
+
104
+ **Verify available tools:**
105
+ - Check `doctl` is installed and authenticated: `doctl auth list`
106
+ - Check `gh` CLI is installed and authenticated: `gh auth status`
107
+ - If migrating from Vercel, check `vercel` CLI is installed: `vercel --version`
108
+
109
+ **Important Notes:**
110
+ - **CLI tools are the primary method** - MCP servers are optional
111
+ - Users don't need MCP servers - `doctl` and `gh` CLI are sufficient
112
+ - If user doesn't have a GitHub repository, we can create one using `gh` CLI
113
+ - If user doesn't want to give repo access, we can deploy from local source or create new repo
27
114
 
28
115
  ## Relevant App Platform Documentations
29
116
 
@@ -33,9 +120,70 @@ Then verify:
33
120
 
34
121
  ## Migration Process
35
122
 
36
- ### Step 1: Get App Information
123
+ ### Step 0: Local Testing and Validation (Recommended)
124
+
125
+ **Before deploying to App Platform, test locally to catch issues early and avoid deployment wait time.**
126
+
127
+ 1. **Verify local environment:**
128
+ - Check Node.js version: `node --version`
129
+ - Check package manager: `pnpm --version`, `npm --version`, or `yarn --version`
130
+ - Verify lockfile exists: `pnpm-lock.yaml`, `package-lock.json`, or `yarn.lock`
131
+
132
+ 2. **Install dependencies locally:**
133
+ - Run: `pnpm install` (or `npm install` or `yarn install`)
134
+ - Verify all dependencies install successfully
135
+ - Check for any errors or warnings
136
+
137
+ 3. **Test build locally:**
138
+ - Run: `pnpm build` (or `npm run build` or `yarn build`)
139
+ - Verify build completes successfully
140
+ - Check for build errors or warnings
141
+ - Verify build output directory exists (`.next` for Next.js, `dist` for others)
142
+
143
+ 4. **Verify build artifacts:**
144
+ - Check build output directory structure
145
+ - Verify static files are generated
146
+ - Check for API routes in build output (if applicable)
147
+ - Verify middleware is compiled (if applicable)
148
+
149
+ 5. **Check for hardcoded values:**
150
+ - Search codebase for hardcoded URLs or Vercel-specific code
151
+ - Verify environment variable usage
152
+ - Check for PORT usage (should use `process.env.PORT`)
153
+
154
+ 6. **Validate database migrations (if applicable):**
155
+ - Check migration files exist
156
+ - Verify database configuration
157
+ - Test migration command (if database available)
158
+
159
+ ### Step 1: Repository Setup
160
+
161
+ #### 1.1 Determine Repository Strategy
162
+
163
+ **Option A: Use Existing Repository (if user has one)**
164
+ - Check if current directory is a git repository: `git remote -v`
165
+ - If repository exists, verify it's accessible
166
+ - Use existing repository URL for App Platform
167
+
168
+ **Option B: Create New Repository (if user wants new repo)**
169
+ - Use `gh` CLI to create new repository: `gh repo create <repo-name> --private --source=. --push`
170
+ - Or: `gh repo create <repo-name> --public --source=. --push`
171
+ - Push current code to new repository
172
+ - Use new repository URL for App Platform
37
173
 
38
- #### 1.1 Prepare Local Environment and Pull Environment Variables
174
+ **Option C: Fork Existing Repository**
175
+ - Use `gh` CLI to fork: `gh repo fork <owner>/<repo-name> --clone=false`
176
+ - Add fork as remote: `git remote add fork https://github.com/<user>/<repo-name>.git`
177
+ - Push to fork: `git push fork main`
178
+ - Use forked repository URL for App Platform
179
+
180
+ **Option D: Deploy from Local Source (if user doesn't want repo access)**
181
+ - Can deploy directly from local source using `doctl apps create --spec app-spec.yaml`
182
+ - Note: This requires manual code updates - recommend using repository for easier updates
183
+
184
+ #### 1.2 Get App Information (If Migrating from Vercel)
185
+
186
+ **Only perform this step if user has existing Vercel deployment:**
39
187
 
40
188
  1. **Create a local migration folder:**
41
189
  - Pattern: `./vercel-migration/<vercel-app-name>-migration/`
@@ -57,34 +205,435 @@ Then verify:
57
205
  - Verify the file was created: `ls -la .env.<environment>`
58
206
  - If unable to pull environment variables, leave them blank or empty when creating the App Platform app
59
207
 
60
- #### 1.2 Get App Details Using Vercel CLI
61
-
62
- 1. **Get app information:**
208
+ 4. **Get app information using Vercel CLI:**
63
209
  - Use `vercel inspect <app-name>` or `vercel ls` to find the app
210
+ - Collect: App name, repository URL, deployment branch, build command, custom domains, etc.
64
211
 
65
- 2. **For this app, collect:**
66
- - App name and ID
67
- - GitHub/GitLab/BitBucket repository URL. This can also be obtained via Vercel MCP.
68
- - Current deployment branch
69
- - Build command
70
- - Output directory (only for static sites)
71
- - Root directory / source_dir for monorepos
72
- - Node.js version or runtime
73
- - **Custom domains** (list all domains attached to this app, including apex and subdomains)
74
- - Any serverless function routes (paths under `/api/*`)
75
- - Cron job configurations
76
-
77
- 3. **Verify environment variables:**
78
- - Check that `.env.<environment>` file exists in your migration folder
79
- - All environment variables should be transferred as it is. Do not change the names.
80
-
81
- 3. **Show the user** what you found and confirm they want to proceed
82
- - Include the list of domains that will need DNS updates
212
+ 5. **Show the user** what you found and confirm they want to proceed
213
+ - Include the list of domains that will need DNS updates (if migrating from Vercel)
83
214
  - **Note:** Build and run commands will be validated in the next step by checking the repository
84
215
 
85
- 4. If the app fails to deploy, fetch logs
86
- - [Retrieve Deployment Logs](https://docs.digitalocean.com/reference/api/digitalocean/#tag/Apps/operation/apps_get_logs)
87
- - Or ask the user to provide build or deploy logs for analysing the error and fix it.
216
+ **If NOT migrating from Vercel (deploying source code directly):**
217
+ - Skip Vercel-specific steps
218
+ - Proceed directly to Step 1.5: Monorepo Dependency Consolidation (if applicable)
219
+
220
+ ---
221
+
222
+ ### Step 1.5: Monorepo Dependency Consolidation (CRITICAL for Monorepos)
223
+
224
+ ⚠️ **IMPORTANT: App Platform Monorepo Behavior**
225
+
226
+ When deploying a monorepo with multiple components, App Platform has a specific behavior that you MUST understand:
227
+
228
+ **Key Insight:**
229
+ - App Platform installs dependencies **only from the root `package.json`**
230
+ - Each component's `source_dir` only affects where build/run commands execute
231
+ - Dependencies in component-specific `package.json` files are NOT automatically installed
232
+ - This means build tools like `tsx`, `typescript`, `pnpm`, etc. must be in root `package.json`
233
+
234
+ **Why This Matters:**
235
+
236
+ If your monorepo structure looks like this:
237
+ ```
238
+ monorepo/
239
+ ├── package.json # Root - App Platform installs dependencies from HERE
240
+ ├── apps/
241
+ │ ├── dashboard/
242
+ │ │ └── package.json # Component - dependencies NOT installed automatically
243
+ │ └── api/
244
+ │ └── package.json # Component - dependencies NOT installed automatically
245
+ ```
246
+
247
+ And `apps/api/package.json` has `tsx` as a dependency, but root `package.json` doesn't, the API build will fail with "command not found: tsx".
248
+
249
+ ---
250
+
251
+ #### 1.5.1: Analyze Monorepo Dependencies (Proactive Approach - Recommended)
252
+
253
+ **Before deploying**, analyze all component package.json files and consolidate dependencies:
254
+
255
+ 1. **Detect if this is a monorepo:**
256
+ - Check for `pnpm-workspace.yaml`, `lerna.json`, `nx.json`
257
+ - Check if root `package.json` has "workspaces" field
258
+ - Look for multiple `package.json` files in subdirectories
259
+
260
+ 2. **If monorepo detected, analyze component dependencies:**
261
+
262
+ ```bash
263
+ # Read all component package.json files
264
+ # Extract dependencies and devDependencies
265
+ # Identify build-time tools needed
266
+ ```
267
+
268
+ 3. **Categorize required packages:**
269
+
270
+ **Build-Time Tools (must be in root devDependencies):**
271
+ - `tsx` - TypeScript execution for Node.js
272
+ - `typescript` - TypeScript compiler
273
+ - `@types/node` - Node.js type definitions
274
+ - `@types/*` - Any TypeScript type packages
275
+ - Build tools: `vite`, `webpack`, `rollup`, `esbuild`
276
+ - Linters: `eslint`, `prettier`
277
+ - Testing: `jest`, `vitest`, `playwright`
278
+
279
+ **Runtime Dependencies (must be in root dependencies):**
280
+ - Framework packages: `next`, `react`, `express`, `vue`
281
+ - Runtime utilities needed by any component
282
+ - Shared packages used across components
283
+
284
+ 4. **Propose root package.json updates to user:**
285
+
286
+ ```
287
+ I detected this is a monorepo with 2 services. App Platform only installs
288
+ dependencies from the root package.json.
289
+
290
+ I need to add these build-time tools to root package.json:
291
+ - tsx (for API TypeScript execution)
292
+ - typescript (for type checking)
293
+ - @types/node (for Node types)
294
+
295
+ Would you like me to:
296
+ A) Add these automatically and proceed
297
+ B) Skip this and let build fail (then fix iteratively)
298
+ C) Review the full dependency list first
299
+ ```
300
+
301
+ 5. **If user approves, update root package.json:**
302
+
303
+ ```bash
304
+ # Merge component dependencies into root package.json
305
+ # Keep existing root dependencies
306
+ # Add missing build tools to devDependencies
307
+ # Add missing runtime deps to dependencies
308
+ ```
309
+
310
+ **Example Transformation:**
311
+
312
+ **Before (will fail on App Platform):**
313
+ ```json
314
+ // Root package.json
315
+ {
316
+ "name": "my-monorepo",
317
+ "private": true,
318
+ "devDependencies": {
319
+ "turbo": "^2.5.5"
320
+ }
321
+ }
322
+
323
+ // apps/api/package.json
324
+ {
325
+ "name": "api",
326
+ "dependencies": {
327
+ "express": "^4.18.2"
328
+ },
329
+ "devDependencies": {
330
+ "tsx": "^4.20.6",
331
+ "typescript": "^5.0.0"
332
+ }
333
+ }
334
+ ```
335
+
336
+ **After (will work on App Platform):**
337
+ ```json
338
+ // Root package.json
339
+ {
340
+ "name": "my-monorepo",
341
+ "private": true,
342
+ "dependencies": {
343
+ "express": "^4.18.2" // Added from api
344
+ },
345
+ "devDependencies": {
346
+ "turbo": "^2.5.5",
347
+ "tsx": "^4.20.6", // Added from api
348
+ "typescript": "^5.0.0", // Added from api
349
+ "@types/node": "^20.0.0" // Added from api
350
+ }
351
+ }
352
+ ```
353
+
354
+ ---
355
+
356
+ #### 1.5.2: Iterative Dependency Fixing (Fallback Approach)
357
+
358
+ If you skip proactive analysis or it misses something:
359
+
360
+ 1. **Let the build attempt**
361
+ 2. **Parse build error logs for missing dependencies:**
362
+
363
+ Common error patterns:
364
+ ```
365
+ /bin/sh: tsx: not found
366
+ /bin/sh: tsc: not found
367
+ Error: Cannot find module 'typescript'
368
+ ```
369
+
370
+ 3. **Suggest fix to user:**
371
+
372
+ ```
373
+ Build failed because 'tsx' is not found.
374
+
375
+ This is a monorepo and App Platform only installs dependencies from
376
+ root package.json.
377
+
378
+ Fix: Add 'tsx' to root package.json devDependencies
379
+
380
+ Would you like me to add it and redeploy?
381
+ ```
382
+
383
+ 4. **Update root package.json and retry:**
384
+ - Add missing package to appropriate section
385
+ - Commit and push changes
386
+ - Redeploy (automatic if `deploy_on_push: true`)
387
+
388
+ 5. **Repeat up to 3 times** for different missing packages
389
+
390
+ ---
391
+
392
+ #### 1.5.3: Trade-offs and Considerations
393
+
394
+ **Approach A: Consolidate All Dependencies (Proactive)**
395
+
396
+ **Pros:**
397
+ - ✅ Works on first deployment
398
+ - ✅ No iteration needed
399
+ - ✅ Predictable behavior
400
+ - ✅ User stays in control (approves changes)
401
+
402
+ **Cons:**
403
+ - ❌ All components get ALL dependencies
404
+ - ❌ Larger `node_modules` in each component
405
+ - ❌ Slower installs
406
+ - ❌ Slightly larger deployment artifacts
407
+
408
+ **When to use:**
409
+ - Small monorepos (2-4 services)
410
+ - "Just make it work" scenarios
411
+ - User wants fast deployment
412
+
413
+ **Approach B: Iterative Fixing (Reactive)**
414
+
415
+ **Pros:**
416
+ - ✅ Only adds truly needed packages
417
+ - ✅ Cleaner dependency tree
418
+ - ✅ Educational for user
419
+
420
+ **Cons:**
421
+ - ❌ Requires multiple deploy attempts (2-5 minutes each)
422
+ - ❌ More complex error detection
423
+ - ❌ Could miss cascading errors
424
+
425
+ **When to use:**
426
+ - Large monorepos with many services
427
+ - Production apps where bundle size matters
428
+ - User wants optimal configuration
429
+
430
+ **Approach C: Hybrid (Recommended)**
431
+
432
+ 1. Proactively analyze and propose changes
433
+ 2. User reviews and approves
434
+ 3. If build still fails, fall back to iterative fixing
435
+ 4. Usually works first time, graceful degradation
436
+
437
+ ---
438
+
439
+ #### 1.5.4: Special Cases
440
+
441
+ **Case 1: Using pnpm workspaces**
442
+
443
+ If `pnpm-workspace.yaml` exists:
444
+ ```yaml
445
+ packages:
446
+ - 'apps/*'
447
+ - 'packages/*'
448
+ ```
449
+
450
+ App Platform buildpack automatically:
451
+ - Detects pnpm from `pnpm-lock.yaml`
452
+ - Runs `pnpm install` at root
453
+ - Respects workspace configuration
454
+
455
+ **Still need**: Build tools in root package.json
456
+
457
+ **Case 2: Using npm/yarn workspaces**
458
+
459
+ If root `package.json` has:
460
+ ```json
461
+ {
462
+ "workspaces": ["apps/*", "packages/*"]
463
+ }
464
+ ```
465
+
466
+ App Platform buildpack automatically:
467
+ - Detects workspaces
468
+ - Runs `npm install` or `yarn install` at root
469
+ - Links workspace packages
470
+
471
+ **Still need**: Build tools in root package.json
472
+
473
+ **Case 3: Components use different runtimes**
474
+
475
+ If dashboard uses `pnpm build` but API uses `tsx src/index.ts`:
476
+ - Both commands must have their dependencies in root
477
+ - `pnpm` must be in root (detected from lockfile)
478
+ - `tsx` must be in root devDependencies
479
+
480
+ ---
481
+
482
+ #### 1.5.5: Implementation Example (AI Assistant Instructions)
483
+
484
+ **When detecting a monorepo:**
485
+
486
+ ```typescript
487
+ // Pseudo-code for AI assistant
488
+
489
+ function analyzeMonorepo(repoPath) {
490
+ // 1. Detect monorepo structure
491
+ const isMonorepo = hasWorkspaceConfig(repoPath);
492
+ if (!isMonorepo) return null;
493
+
494
+ // 2. Find all component package.json files
495
+ const components = findComponents(repoPath);
496
+
497
+ // 3. Extract dependencies from each component
498
+ const allDeps = {
499
+ dependencies: new Set(),
500
+ devDependencies: new Set()
501
+ };
502
+
503
+ for (const component of components) {
504
+ const pkg = readPackageJson(component.path);
505
+
506
+ // Merge runtime dependencies
507
+ Object.keys(pkg.dependencies || {}).forEach(dep =>
508
+ allDeps.dependencies.add({ name: dep, version: pkg.dependencies[dep] })
509
+ );
510
+
511
+ // Merge build-time dependencies
512
+ Object.keys(pkg.devDependencies || {}).forEach(dep =>
513
+ allDeps.devDependencies.add({ name: dep, version: pkg.devDependencies[dep] })
514
+ );
515
+ }
516
+
517
+ // 4. Check what's missing from root
518
+ const rootPkg = readPackageJson(`${repoPath}/package.json`);
519
+ const missing = {
520
+ dependencies: [],
521
+ devDependencies: []
522
+ };
523
+
524
+ allDeps.dependencies.forEach(dep => {
525
+ if (!rootPkg.dependencies?.[dep.name]) {
526
+ missing.dependencies.push(dep);
527
+ }
528
+ });
529
+
530
+ allDeps.devDependencies.forEach(dep => {
531
+ if (!rootPkg.devDependencies?.[dep.name]) {
532
+ missing.devDependencies.push(dep);
533
+ }
534
+ });
535
+
536
+ // 5. Return analysis
537
+ return {
538
+ isMonorepo: true,
539
+ components: components.length,
540
+ missing,
541
+ recommendation: missing.dependencies.length + missing.devDependencies.length > 0
542
+ ? "CONSOLIDATE_DEPENDENCIES"
543
+ : "NO_ACTION_NEEDED"
544
+ };
545
+ }
546
+
547
+ // Then ask user
548
+ if (analysis.recommendation === "CONSOLIDATE_DEPENDENCIES") {
549
+ askUser(`
550
+ Detected monorepo with ${analysis.components} components.
551
+
552
+ App Platform only installs dependencies from root package.json.
553
+
554
+ Missing from root:
555
+ ${formatDependencies(analysis.missing)}
556
+
557
+ Add these to root package.json?
558
+ A) Yes, add automatically
559
+ B) No, I'll handle it manually
560
+ C) Show me the full proposed package.json
561
+ `);
562
+ }
563
+ ```
564
+
565
+ ---
566
+
567
+ #### 1.5.6: Troubleshooting Monorepo Dependency Issues
568
+
569
+ **Symptom:** Build fails with "command not found: tsx"
570
+
571
+ **Diagnosis:**
572
+ ```bash
573
+ # Check build logs
574
+ doctl apps logs <app-id> --type build
575
+
576
+ # Look for:
577
+ /bin/sh: tsx: not found
578
+ /bin/sh: 1: tsx: not found
579
+ ```
580
+
581
+ **Root Cause:** `tsx` is in component `package.json` but not in root
582
+
583
+ **Fix:**
584
+ ```bash
585
+ # Add to root package.json devDependencies
586
+ {
587
+ "devDependencies": {
588
+ "tsx": "^4.20.6"
589
+ }
590
+ }
591
+
592
+ # Commit and push
593
+ git add package.json
594
+ git commit -m "Add tsx to root for App Platform build"
595
+ git push
596
+ ```
597
+
598
+ **Symptom:** Build succeeds but run fails with "Cannot find module 'express'"
599
+
600
+ **Diagnosis:**
601
+ ```bash
602
+ # Check runtime logs
603
+ doctl apps logs <app-id> --type run
604
+
605
+ # Look for:
606
+ Error: Cannot find module 'express'
607
+ ```
608
+
609
+ **Root Cause:** `express` is in component `package.json` but not in root
610
+
611
+ **Fix:**
612
+ ```bash
613
+ # Add to root package.json dependencies (NOT devDependencies)
614
+ {
615
+ "dependencies": {
616
+ "express": "^4.18.2"
617
+ }
618
+ }
619
+ ```
620
+
621
+ ---
622
+
623
+ #### 1.5.7: Validation Checklist
624
+
625
+ Before proceeding to deployment:
626
+
627
+ - [ ] Identified if repository is a monorepo
628
+ - [ ] If monorepo: Analyzed all component package.json files
629
+ - [ ] Identified build-time tools needed (tsx, typescript, etc.)
630
+ - [ ] Identified runtime dependencies needed
631
+ - [ ] Updated root package.json with consolidated dependencies
632
+ - [ ] User approved dependency consolidation
633
+ - [ ] Committed changes to git
634
+ - [ ] Ready to proceed to app spec creation
635
+
636
+ ---
88
637
 
89
638
  ### Step 2: App Migration
90
639
 
@@ -144,19 +693,36 @@ Follow these steps to migrate the app:
144
693
 
145
694
  #### 2.2 Environment Variables
146
695
 
147
- 1. **Use the environment variables pulled from Vercel in Step 1.1:**
148
- - Read the `.env.<environment>` file from the migration folder
696
+ 1. **Collect environment variables:**
697
+
698
+ **If migrating from Vercel:**
699
+ - Read the `.env.<environment>` file from the migration folder (Step 1.1)
149
700
  - Parse all variables from this file
150
- - If no environment variables were pulled, leave blank or empty
701
+ - If no environment variables were pulled, proceed with manual collection
702
+
703
+ **If deploying source code directly (no Vercel):**
704
+ - Check for `.env.example` or `.env.sample` file in project
705
+ - Read `.env.example` to understand required variables
706
+ - Ask user for values for each required variable
707
+ - Generate secure values where needed (e.g., `AUTH_SECRET`)
151
708
 
152
709
  2. **Transform system variables:**
153
710
  - Note: `VERCEL_URL`, `VERCEL_ENV`, any `VERCEL_GIT_*` and Vercel-specific system variables will NOT be available in App Platform
154
711
  - Warn the user if the app depends on these variables
712
+ - Replace `VERCEL_URL` with App Platform URL (set after deployment)
713
+ - Replace `VERCEL_ENV` with `NODE_ENV=production`
155
714
 
156
715
  3. **Prepare environment variables for App Platform:**
157
716
  - Keep the same variable names (except for Vercel-specific ones)
158
- - Mark sensitive variables (API keys, secrets, database passwords) as encrypted
159
- - If unable to retrieve values, leave blank or empty
717
+ - Mark sensitive variables (API keys, secrets, database passwords) as `type: SECRET` in app spec
718
+ - Generate secure random values where needed:
719
+ - `AUTH_SECRET`: `openssl rand -base64 32`
720
+ - `STRIPE_WEBHOOK_SECRET`: User provides or placeholder
721
+ - If unable to retrieve values, ask user or leave blank (app may have defaults)
722
+
723
+ 4. **Database connection string:**
724
+ - If creating managed database in App Platform, use `${db.DATABASE_URL}` reference
725
+ - If using external database, ask user for connection string
160
726
 
161
727
  #### 2.3 Component Type Detection
162
728
 
@@ -195,6 +761,296 @@ Determine the appropriate App Platform component type based on the app's charact
195
761
  - Option A: Single web service (simplest - handles both static and API)
196
762
  - Option B: Separate static site + web service components (more complex setup)
197
763
  - **Recommend Option A** unless user specifically wants separation
764
+ - **See section 2.3.5 below for detailed multi-service architecture guidance**
765
+
766
+ #### 2.3.5 Multi-Service and Monorepo Applications
767
+
768
+ **App Platform supports deploying multiple components in a single app.** This is different from deploying multiple separate apps.
769
+
770
+ **One App with Multiple Components vs Multiple Apps:**
771
+
772
+ | Use One App (Multiple Components) | Use Multiple Apps |
773
+ |-----------------------------------|-------------------|
774
+ | Services in same repository | Services in different repositories |
775
+ | Deploy together on git push | Deploy independently |
776
+ | Shared database connection | Separate databases |
777
+ | Internal communication (fast, no public internet) | Public API communication |
778
+ | Examples: monorepo, microservices, frontend+API+worker | Examples: different products, different teams |
779
+
780
+ **Component Types in One App:**
781
+ - **Multiple web services** (e.g., frontend, API, admin panel)
782
+ - **Static sites + web services** (e.g., marketing site + API)
783
+ - **Workers** (background jobs, queue processors, continuous processes)
784
+ - **Jobs** (one-time tasks, pre-deploy hooks, post-deploy hooks)
785
+ - **Databases** (PostgreSQL, ValKey/Redis)
786
+
787
+ ---
788
+
789
+ **Example 1: Monorepo with Frontend + API + Shared Database**
790
+
791
+ This is the most common multi-service scenario.
792
+
793
+ **Repository structure:**
794
+ ```
795
+ monorepo/
796
+ ├── apps/
797
+ │ ├── web/ # Next.js frontend
798
+ │ │ ├── package.json
799
+ │ │ └── src/
800
+ │ └── api/ # Express API
801
+ │ ├── package.json
802
+ │ └── src/
803
+ ├── packages/
804
+ │ └── shared/ # Shared code
805
+ │ └── package.json
806
+ ├── package.json # Root workspace config
807
+ └── pnpm-workspace.yaml # or package-lock.json, yarn.lock
808
+ ```
809
+
810
+ **app-spec.yaml:**
811
+ ```yaml
812
+ name: my-fullstack-app
813
+ region: nyc1
814
+
815
+ services:
816
+ # Frontend service
817
+ - name: web
818
+ github:
819
+ repo: owner/monorepo
820
+ branch: main
821
+ deploy_on_push: true
822
+ source_dir: /apps/web
823
+ build_command: "" # Auto-detect Next.js
824
+ run_command: "" # Auto-detect Next.js start
825
+ http_port: 8080
826
+ instance_count: 1
827
+ instance_size_slug: basic-xxs
828
+ routes:
829
+ - path: / # Frontend handles root and all non-API routes
830
+ envs:
831
+ - key: API_URL
832
+ value: ${api.PRIVATE_URL} # Internal URL to API service (fast, no public internet)
833
+ - key: DATABASE_URL
834
+ value: ${db.DATABASE_URL}
835
+ scope: RUN_AND_BUILD_TIME
836
+ - key: NODE_ENV
837
+ value: production
838
+
839
+ # API service
840
+ - name: api
841
+ github:
842
+ repo: owner/monorepo
843
+ branch: main
844
+ deploy_on_push: true
845
+ source_dir: /apps/api
846
+ build_command: "" # Auto-detect or specify if custom
847
+ run_command: "" # Auto-detect Express/Node
848
+ http_port: 8080
849
+ instance_count: 1
850
+ instance_size_slug: basic-xxs
851
+ routes:
852
+ - path: /api # API handles all /api/* routes
853
+ envs:
854
+ - key: DATABASE_URL
855
+ value: ${db.DATABASE_URL}
856
+ scope: RUN_AND_BUILD_TIME
857
+ - key: NODE_ENV
858
+ value: production
859
+
860
+ databases:
861
+ - name: db
862
+ engine: PG
863
+ version: "18"
864
+ production: false # Set to true for production tier with backups
865
+ ```
866
+
867
+ **Key Points:**
868
+ 1. Both services reference same repository, different `source_dir`
869
+ 2. Services can reference each other with `${service-name.PRIVATE_URL}` (internal communication, fast)
870
+ 3. Public routes are configured per service (`/` for web, `/api` for API)
871
+ 4. Database is shared via `${db.DATABASE_URL}` reference
872
+ 5. All services deploy together when code is pushed
873
+ 6. Buildpack auto-detects framework in each service's directory
874
+
875
+ **Monorepo Package Manager Detection:**
876
+ - If `pnpm-workspace.yaml` exists → buildpack uses pnpm
877
+ - If root `package.json` has "workspaces" field → buildpack uses npm/yarn workspaces
878
+ - Buildpack automatically installs dependencies for each service
879
+
880
+ ---
881
+
882
+ **Example 2: Adding Workers and Jobs for Background Tasks**
883
+
884
+ **Repository structure:**
885
+ ```
886
+ app/
887
+ ├── web/ # Frontend
888
+ ├── api/ # API
889
+ ├── worker/ # Background worker (continuous)
890
+ │ └── worker.js # Processes queue, runs continuously
891
+ └── jobs/
892
+ └── migrations/ # Database migrations (one-time)
893
+ └── migrate.js
894
+ ```
895
+
896
+ **app-spec.yaml additions:**
897
+ ```yaml
898
+ name: my-app-with-workers
899
+ region: nyc1
900
+
901
+ services:
902
+ # ... web and api services as above ...
903
+
904
+ workers:
905
+ # Background worker - runs continuously
906
+ - name: email-worker
907
+ github:
908
+ repo: owner/repo
909
+ branch: main
910
+ source_dir: /worker
911
+ build_command: ""
912
+ run_command: "node worker.js" # Continuous process
913
+ instance_count: 1
914
+ instance_size_slug: basic-xxs
915
+ envs:
916
+ - key: DATABASE_URL
917
+ value: ${db.DATABASE_URL}
918
+ - key: REDIS_URL
919
+ value: ${cache.DATABASE_URL}
920
+ - key: NODE_ENV
921
+ value: production
922
+
923
+ jobs:
924
+ # Pre-deploy job - runs before deployment
925
+ - name: db-migrate
926
+ kind: PRE_DEPLOY
927
+ github:
928
+ repo: owner/repo
929
+ branch: main
930
+ source_dir: /jobs/migrations
931
+ build_command: ""
932
+ run_command: "node migrate.js" # Runs once before deployment
933
+ instance_size_slug: basic-xxs
934
+ envs:
935
+ - key: DATABASE_URL
936
+ value: ${db.DATABASE_URL}
937
+
938
+ databases:
939
+ - name: db
940
+ engine: PG
941
+ version: "18"
942
+ - name: cache
943
+ engine: REDIS # ValKey (Redis fork)
944
+ version: "7"
945
+ ```
946
+
947
+ **Worker vs Job:**
948
+ - **Worker**: Continuous process (e.g., queue processor, scheduled task runner)
949
+ - **Job**: Runs once per deployment (e.g., database migrations, cache warming)
950
+ - **Job kinds**:
951
+ - `PRE_DEPLOY`: Runs before new code is deployed (migrations)
952
+ - `POST_DEPLOY`: Runs after deployment succeeds (cache warming)
953
+
954
+ ---
955
+
956
+ **Example 3: Separating Static Site from API Service**
957
+
958
+ Sometimes you want a separate static frontend (SPA) and API backend.
959
+
960
+ **app-spec.yaml:**
961
+ ```yaml
962
+ name: spa-with-api
963
+ region: nyc1
964
+
965
+ static_sites:
966
+ # Static React/Vue/Angular SPA
967
+ - name: web
968
+ github:
969
+ repo: owner/repo
970
+ branch: main
971
+ source_dir: /frontend
972
+ build_command: "npm run build" # Or leave empty for auto-detect
973
+ output_dir: dist # Or build, out, public
974
+ routes:
975
+ - path: /
976
+ envs:
977
+ - key: VITE_API_URL # Or REACT_APP_API_URL, NEXT_PUBLIC_API_URL
978
+ value: ${api.PUBLIC_URL} # Public URL to API
979
+
980
+ services:
981
+ # API service
982
+ - name: api
983
+ github:
984
+ repo: owner/repo
985
+ branch: main
986
+ source_dir: /backend
987
+ build_command: ""
988
+ run_command: ""
989
+ http_port: 8080
990
+ routes:
991
+ - path: /api
992
+ envs:
993
+ - key: DATABASE_URL
994
+ value: ${db.DATABASE_URL}
995
+
996
+ databases:
997
+ - name: db
998
+ engine: PG
999
+ version: "18"
1000
+ ```
1001
+
1002
+ **When to use this pattern:**
1003
+ - SPA that's 100% client-side rendered
1004
+ - Clear separation between frontend and backend
1005
+ - Frontend only needs static file hosting
1006
+
1007
+ ---
1008
+
1009
+ **When to Use Multiple Apps vs One App with Multiple Components:**
1010
+
1011
+ **Use ONE app with multiple components when:**
1012
+ - ✅ All services are in the same repository (monorepo)
1013
+ - ✅ Services share the same database
1014
+ - ✅ Services need to deploy together (atomic deployments)
1015
+ - ✅ Services communicate internally (low latency requirements)
1016
+ - ✅ Simpler management (one dashboard, one app spec)
1017
+
1018
+ **Use MULTIPLE separate apps when:**
1019
+ - ✅ Services are in different repositories
1020
+ - ✅ Services need to deploy independently
1021
+ - ✅ Services have different teams/ownership
1022
+ - ✅ Services need independent scaling and resource management
1023
+ - ✅ Services are truly separate products/systems
1024
+
1025
+ ---
1026
+
1027
+ **Deployment Behavior with Multiple Components:**
1028
+ - Git push triggers deployment of **ALL components** in the app
1029
+ - All components must build successfully before deployment
1030
+ - If **one component fails**, entire deployment fails (rollback to previous)
1031
+ - Components start simultaneously after successful build
1032
+ - Database migrations (PRE_DEPLOY jobs) run before services start
1033
+
1034
+ **Troubleshooting Multi-Component Deployments:**
1035
+
1036
+ If one component fails:
1037
+ 1. Check which component failed in logs: `doctl apps logs <app-id> --type build`
1038
+ 2. Fix the failing component's code or configuration
1039
+ 3. Push fix - all components rebuild
1040
+ 4. Consider deploying components in separate apps if you need independent deployments
1041
+
1042
+ **Internal Service Communication:**
1043
+ - Use `${service-name.PRIVATE_URL}` for fast internal communication (no public internet)
1044
+ - Example: Frontend calls `${api.PRIVATE_URL}/users` instead of public URL
1045
+ - Faster and more secure than public URLs
1046
+ - Private URLs are only accessible within the app's components
1047
+
1048
+ **Assistant Instructions:**
1049
+ - When detecting a monorepo, ask user: "I see this is a monorepo with multiple services. Would you like to deploy them as separate components in one app, or as a single service?"
1050
+ - Show the user which services you detected (by finding multiple package.json files)
1051
+ - Propose an app spec with multiple components
1052
+ - Explain that all services will deploy together
1053
+ - Confirm the routing strategy (which paths go to which services)
198
1054
 
199
1055
  #### 2.4 Feature Translation
200
1056
 
@@ -242,119 +1098,249 @@ Determine the appropriate App Platform component type based on the app's charact
242
1098
 
243
1099
  #### 2.5 Create App Platform App
244
1100
 
245
- **Using DigitalOcean MCP (Primary Method):**
1101
+ **Using doctl CLI (Primary Method):**
246
1102
 
247
- 1. **Use DigitalOcean MCP to create the app with configuration based on component type:**
1103
+ 1. **Create app spec YAML file** with configuration based on component type:
248
1104
 
249
- **IMPORTANT: Only proceed with app creation after completing validation in step 2.1**
1105
+ **IMPORTANT: Only proceed with app creation after completing validation in step 2.1 and local testing in Step 0**
250
1106
 
251
1107
  **For Static Sites:**
252
- ```
253
- - Repository: [GitHub/GitLab URL]
254
- - Branch: [same as Vercel]
255
- - Region: Choose closest to user's audience
256
- - Build Command: [Leave empty for buildpack auto-detection, or use custom command from vercel.json if present]
257
- - Output Directory: [Only specify if non-standard, e.g., "out" for Next.js static export]
258
- - Source Directory: [if monorepo, the path to the app, e.g., "apps/frontend"]
259
- - Environment Variables: [from .env.<environment> file pulled in Step 1.1]
260
- - Component Type: Static Site
261
- - Node Version: [from package.json engines field, if specified]
1108
+ ```yaml
1109
+ name: <app-name>
1110
+ region: <region> # e.g., nyc1, sfo1, ams3
1111
+ services:
1112
+ - name: web
1113
+ github:
1114
+ repo: <owner>/<repo-name>
1115
+ branch: main # or from Vercel if migrating
1116
+ deploy_on_push: true
1117
+ source_dir: / # or path for monorepo
1118
+ build_command: "" # empty for buildpack auto-detection
1119
+ output_dir: "" # only if non-standard
1120
+ instance_count: 1
1121
+ instance_size_slug: basic-xxs
1122
+ envs:
1123
+ # Add environment variables here
262
1124
  ```
263
1125
 
264
1126
  **For Web Services (Dynamic Sites):**
265
- ```
266
- - Repository: [GitHub/GitLab URL]
267
- - Branch: [same as Vercel]
268
- - Region: Choose closest to user's audience
269
- - Build Command: [Leave empty for buildpack auto-detection, or use custom command from vercel.json if present]
270
- - Run Command: [Leave empty for buildpack auto-detection, or use custom command from vercel.json if present]
271
- - Source Directory: [if monorepo, the path to the app, e.g., "apps/api"]
272
- - Environment Variables: [from .env.<environment> file pulled in Step 1.1]
273
- - Component Type: Web Service
274
- - HTTP Port: [Leave as default, buildpack will detect. App must listen on process.env.PORT]
275
- - Node Version: [from package.json engines field, if specified]
1127
+ ```yaml
1128
+ name: <app-name>
1129
+ region: <region> # e.g., nyc1, sfo1, ams3
1130
+ services:
1131
+ - name: web
1132
+ github:
1133
+ repo: <owner>/<repo-name>
1134
+ branch: main # or from Vercel if migrating
1135
+ deploy_on_push: true
1136
+ source_dir: / # or path for monorepo
1137
+ build_command: "" # empty for buildpack auto-detection
1138
+ run_command: "" # empty for buildpack auto-detection
1139
+ http_port: 8080
1140
+ instance_count: 1
1141
+ instance_size_slug: basic-xxs
1142
+ envs:
1143
+ - key: NODE_ENV
1144
+ value: production
1145
+ scope: RUN_AND_BUILD_TIME
1146
+ # Add other environment variables here
1147
+ databases:
1148
+ - name: db
1149
+ engine: PG
1150
+ version: "18"
1151
+ production: false
276
1152
  ```
277
1153
 
278
- 2. **Include the git commit hash** to ensure deployment matches Vercel's current state
1154
+ 2. **Save the app spec to local filesystem:**
1155
+ - Save as `app-spec.yaml` in project root or migration folder
1156
+ - This allows the user to manually create the app if needed
279
1157
 
280
- 3. **Save the app spec to local filesystem:**
281
- - Save the generated app spec as `./vercel-migration/<app-name>-migration/app-spec.yaml`
282
- - This allows the user to manually create the app if automatic deployment fails
283
-
284
- **Alternative using CLI:** Use `doctl apps create` with an app spec YAML/JSON file
1158
+ 3. **Create app using doctl CLI:**
1159
+ - Run: `doctl apps create --spec app-spec.yaml`
1160
+ - Capture app ID from output
1161
+ - Monitor deployment: `doctl apps get <app-id>`
285
1162
 
286
1163
  4. **Set up any required databases:**
287
1164
  - If app uses Vercel Postgres → Create Managed PostgreSQL
288
1165
  - If app uses Vercel KV → Create Managed ValKey (Redis fork)
289
1166
  - Update connection strings in environment variables
290
1167
 
1168
+ **Database Configuration Details:**
1169
+
1170
+ **Adding Managed Databases in app spec:**
1171
+
1172
+ ```yaml
1173
+ databases:
1174
+ # PostgreSQL database
1175
+ - name: db
1176
+ engine: PG
1177
+ version: "18" # Or "17", "16", "15", "14"
1178
+ production: false # false = dev tier ($15/mo), true = production tier ($25/mo+)
1179
+ cluster_name: my-db-cluster # optional - creates new cluster or references existing
1180
+
1181
+ # Redis/ValKey cache
1182
+ - name: cache
1183
+ engine: REDIS # ValKey (Redis fork, Redis 7.2 compatible)
1184
+ version: "7"
1185
+ production: false
1186
+ ```
1187
+
1188
+ **Referencing databases in services:**
1189
+
1190
+ ```yaml
1191
+ services:
1192
+ - name: web
1193
+ # ... other config ...
1194
+ envs:
1195
+ # Database URL is injected automatically
1196
+ - key: DATABASE_URL
1197
+ value: ${db.DATABASE_URL} # Format: postgresql://user:pass@host:port/dbname?sslmode=require
1198
+ scope: RUN_AND_BUILD_TIME # Available during build and runtime
1199
+
1200
+ # Redis URL
1201
+ - key: REDIS_URL
1202
+ value: ${cache.DATABASE_URL} # Format: redis://user:pass@host:port
1203
+ scope: RUN_TIME # Only available at runtime
1204
+ ```
1205
+
1206
+ **Connection string formats:**
1207
+ - **PostgreSQL**: `postgresql://username:password@host:port/database?sslmode=require`
1208
+ - **Redis/ValKey**: `redis://username:password@host:port`
1209
+ - SSL/TLS is enforced for all connections to managed databases and cannot be disabled
1210
+ - Credentials are automatically generated and rotated
1211
+
1212
+ **Database tiers:**
1213
+ - **Development** (`production: false`): $15/month, 1 GB RAM, 10 GB disk, 1 node, daily backups
1214
+ - **Production** (`production: true`): Starting at $25/month, 2 GB RAM, 25 GB disk, automatic failover, point-in-time recovery
1215
+
1216
+ **Using external database (not managed by App Platform):**
1217
+
1218
+ If you want to use an existing external database:
1219
+
1220
+ ```yaml
1221
+ services:
1222
+ - name: web
1223
+ envs:
1224
+ - key: DATABASE_URL
1225
+ value: "postgresql://external-host.com:5432/mydb?sslmode=require"
1226
+ type: SECRET # Mark as secret to encrypt in dashboard
1227
+ ```
1228
+
1229
+ **Database migrations:**
1230
+
1231
+ Use PRE_DEPLOY jobs to run migrations before deployment:
1232
+
1233
+ ```yaml
1234
+ jobs:
1235
+ - name: db-migrate
1236
+ kind: PRE_DEPLOY
1237
+ github:
1238
+ repo: owner/repo
1239
+ branch: main
1240
+ source_dir: /
1241
+ run_command: "npm run migrate" # or "pnpm migrate", "yarn migrate"
1242
+ instance_size_slug: basic-xxs
1243
+ envs:
1244
+ - key: DATABASE_URL
1245
+ value: ${db.DATABASE_URL}
1246
+ ```
1247
+
1248
+ Common migration commands:
1249
+ - Prisma: `npx prisma migrate deploy`
1250
+ - Drizzle: `npm run db:push` or `npm run db:migrate`
1251
+ - TypeORM: `npm run typeorm migration:run`
1252
+ - Knex: `npm run knex migrate:latest`
1253
+ - Sequelize: `npx sequelize-cli db:migrate`
1254
+
1255
+ **Important notes:**
1256
+ - Database creation can take 10-15 minutes on first deployment
1257
+ - Databases persist across deployments and app deletions (must manually delete)
1258
+ - Connection pooling is recommended (use connection pool library)
1259
+ - **Data migration** from Vercel Postgres is a separate manual process (not automated by this guide)
1260
+
1261
+ **Data migration strategy (manual process):**
1262
+ 1. Create new App Platform database
1263
+ 2. Use `pg_dump` to export from Vercel Postgres
1264
+ 3. Use `psql` or `pg_restore` to import to App Platform database
1265
+ 4. Test thoroughly before switching DNS
1266
+ 5. Keep Vercel database running during transition
1267
+ 6. Consider using database migration tools like `pg_dump`/`pg_restore`, or managed migration services
1268
+
291
1269
  #### 2.6 Configure Domains
292
1270
 
293
- **Using DigitalOcean MCP (Primary Method):**
1271
+ **Using doctl CLI (Primary Method):**
294
1272
 
295
1273
  1. **Add custom domains to the App Platform app:**
296
- - For each domain that was in Vercel, add it to the App Platform app
1274
+ - Run: `doctl apps create-domain <app-id> --domain <domain-name>`
1275
+ - For each domain that was in Vercel (if migrating), add it to App Platform
297
1276
  - App Platform will provide DNS configuration details
298
1277
  - Both apex domains (example.com) and subdomains (www.example.com) are supported
299
1278
  - App Platform will automatically provision SSL certificates
300
1279
 
301
- 2. **Provide DNS update instructions to the user:**
302
- - Display these instructions as post deployment instruction.
1280
+ 2. **Get DNS configuration:**
1281
+ - Get default ingress: `doctl apps get <app-id> --format DefaultIngress`
1282
+ - Get domain configuration: `doctl apps get-domain <app-id> <domain-name>`
1283
+
1284
+ 3. **Provide DNS update instructions to the user:**
1285
+ - Display these instructions as post deployment instruction
303
1286
  - List each domain that needs to be updated
304
1287
  - Ask if the user wants to manage domains through DigitalOcean or keep it self managed (outside of DigitalOcean)
305
- - If the user wants to Manage domains through DigitalOcean, then display the following message
306
-
1288
+ - If the user wants to manage domains through DigitalOcean, then display:
1289
+
307
1290
  ```md
308
1291
  ## Move DNS records to DigitalOcean
309
-
1292
+
310
1293
  Update your DNS provider with our nameservers.
311
-
1294
+
312
1295
  DigitalOcean Nameservers
313
1296
  - ns1.digitalocean.com
314
1297
  - ns2.digitalocean.com
315
1298
  - ns3.digitalocean.com
316
1299
  ```
317
- - If the user wants to keep it self managed
318
- - Get the default_ingress using `get_app` and replace the value in the following section, then display the following message
1300
+
1301
+ - If the user wants to keep it self managed:
1302
+ - Get the default_ingress using `doctl apps get <app-id> --format DefaultIngress`
1303
+ - Display:
1304
+
319
1305
  ```md
320
1306
  Add a new CNAME record using the provided alias to point your domain to your DigitalOcean app.
321
-
1307
+
322
1308
  ## CNAME alias
323
- $default_ingress
324
-
1309
+ <default_ingress>
1310
+
325
1311
  Check if CNAME flattening is supported for root domains. If your provider doesn't support this method, you can create an A record that points to your root domain.
326
-
1312
+
327
1313
  ## A Records
328
1314
  - 162.159.140.98
329
1315
  - 172.66.0.96
330
1316
  ```
331
- - Note: default ingress is only available after a successful deployment.
1317
+
1318
+ - Note: default ingress is only available after a successful deployment
332
1319
 
333
- 3. **Important notes for the user:**
1320
+ 4. **Important notes for the user:**
334
1321
  - DNS propagation can take up to 48 hours
335
1322
  - Wildcard domains (*.example.com) are also supported if needed
336
1323
 
337
- **Alternative using CLI:** Use `doctl apps update <app-id>` to add domains
1324
+ #### 2.8 Assisted Deployment Troubleshooting
338
1325
 
339
- #### 2.8 Automatic Deployment Troubleshooting
1326
+ **If deployment fails, follow this assisted troubleshooting process:**
340
1327
 
341
- **If deployment fails, follow this automatic recovery process:**
1328
+ The AI assistant will analyze errors and suggest fixes for you to review and approve. This is not fully automatic - you remain in control.
342
1329
 
343
1330
  1. **Check deployment status:**
344
- - Use DigitalOcean MCP to get the deployment status
1331
+ - Use `doctl apps get <app-id>` to get deployment status
345
1332
  - Status will be either: ACTIVE, DEPLOYED (success) or FAILED, ERROR (failure)
346
1333
 
347
1334
  2. **Fetch deployment logs immediately:**
348
- - Use DigitalOcean MCP to get build logs for the failed deployment
349
- - Use DigitalOcean MCP to get runtime logs if available
350
- - Use DigitalOcean REST API to get logs if MCP doesn't support retriving logs
351
- - Ask the user to copy and paste the build and deploy error logs if REST api is not available for use
1335
+ - Get build logs: `doctl apps logs <app-id> --type build`
1336
+ - Get runtime logs: `doctl apps logs <app-id> --type run`
1337
+ - Get deployment logs: `doctl apps get-deployment <app-id> <deployment-id>`
352
1338
  - Parse the error messages to identify the failure type
353
1339
 
354
- 3. **Analyze the error and attempt automatic fix:**
1340
+ 3. **Analyze the error and suggest fixes:**
355
1341
 
356
1342
  **For "command not found" or "script not found" errors:**
357
- - **Automatic fix - prefer buildpack auto-detection:**
1343
+ - **Suggested fix - prefer buildpack auto-detection:**
358
1344
  - **First attempt:** Leave build/run commands empty to let buildpack auto-detect
359
1345
  - This works for most standard frameworks (Next.js, React, Vue, etc.)
360
1346
  - If this fails, then try checking package.json for custom scripts:
@@ -364,14 +1350,14 @@ Determine the appropriate App Platform component type based on the app's charact
364
1350
  - Update the app with corrected configuration and redeploy
365
1351
 
366
1352
  **For "no start command" or run command errors:**
367
- - **Automatic fix - prefer buildpack auto-detection:**
1353
+ - **Suggested fix - prefer buildpack auto-detection:**
368
1354
  - **First attempt:** Leave run command empty to let buildpack auto-detect
369
1355
  - Buildpack will use framework defaults or package.json "start" script
370
1356
  - Only specify custom run command if buildpack auto-detection fails
371
1357
  - Update run command and redeploy
372
1358
 
373
1359
  **For "output directory not found" errors:**
374
- - **Automatic fix:**
1360
+ - **Suggested fix:**
375
1361
  - Check common output directories: `build`, `dist`, `out`, `public`, `.next`
376
1362
  - **Check .gitignore in migration folder** for build output patterns
377
1363
  - Look in build logs for "writing output to..." messages
@@ -379,20 +1365,20 @@ Determine the appropriate App Platform component type based on the app's charact
379
1365
 
380
1366
  **For "module not found" or dependency errors:**
381
1367
  - **Check migration folder for lockfile** (package-lock.json or yarn.lock)
382
- - **Automatic fix options:**
1368
+ - **Suggested fix options:**
383
1369
  - If lockfile is in a subdirectory, update source_dir
384
1370
  - If using private packages, check if registry auth env vars are needed
385
1371
  - Add NODE_ENV=production if missing
386
1372
 
387
1373
  **For port/health check failures (service starts but fails health check):**
388
1374
  - Fetch runtime logs to see what port the app is listening on
389
- - **Automatic fix:**
1375
+ - **Suggested fix:**
390
1376
  - Check if app is hardcoded to wrong port
391
1377
  - Ensure PORT environment variable is set
392
1378
  - Update HTTP port configuration if needed
393
1379
 
394
1380
  **For monorepo/source directory errors:**
395
- - **Automatic fix:**
1381
+ - **Suggested fix:**
396
1382
  - Check Vercel config for rootDirectory
397
1383
  - **Search migration folder** for package.json in subdirectories
398
1384
  - Look for workspace configuration files (lerna.json, nx.json, etc.)
@@ -400,14 +1386,15 @@ Determine the appropriate App Platform component type based on the app's charact
400
1386
  - Deploy the mono repo under 1 app, where each repository service is a `service component` or `static site component` depending on the repository service. Ask the user for confirmation.
401
1387
 
402
1388
  4. **Apply the fix and redeploy:**
403
- - Use DigitalOcean MCP to update the app configuration
404
- - Trigger a new deployment
1389
+ - Update app spec YAML with fixes
1390
+ - Update app using doctl: `doctl apps update <app-id> --spec app-spec.yaml`
1391
+ - Or update specific config: `doctl apps update <app-id> --env <key>=<value>`
405
1392
  - Wait for deployment to complete and check status again
406
1393
 
407
1394
  5. **Retry logic:**
408
- - If first automatic fix fails, fetch logs again and try alternative fix
409
- - Maximum 3 automatic retry attempts per app
410
- - After 3 failed attempts, report to user with detailed error and ask for manual intervention
1395
+ - If first suggested fix doesn't work, analyze logs again and try alternative approach
1396
+ - Maximum 3 assisted troubleshooting attempts per app
1397
+ - After 3 failed attempts, report to user with detailed error analysis and request manual intervention
411
1398
 
412
1399
  6. **Report fix applied:**
413
1400
  - Tell the user what error was found
@@ -418,19 +1405,19 @@ Determine the appropriate App Platform component type based on the app's charact
418
1405
 
419
1406
  After migrating the app:
420
1407
 
421
- 1. **Verify deployment succeeded** in App Platform (use DigitalOcean MCP to check status)
1408
+ 1. **Verify deployment succeeded** in App Platform (use `doctl apps get <app-id>` to check status)
422
1409
  - Wait for the deployment to complete (this may take several minutes)
423
1410
  - Check deployment status: should be "ACTIVE" or "DEPLOYED"
424
1411
 
425
- 2. **If deployment FAILED, trigger automatic troubleshooting:**
426
- - Follow the process in section 2.8 "Automatic Deployment Troubleshooting"
427
- - Fetch logs, analyze errors, apply fixes automatically
428
- - Retry up to 3 times with different fixes
1412
+ 2. **If deployment FAILED, begin assisted troubleshooting:**
1413
+ - Follow the process in section 2.8 "Assisted Deployment Troubleshooting"
1414
+ - Fetch logs, analyze errors, suggest fixes for user to review
1415
+ - Retry up to 3 times with different suggested approaches
429
1416
  - **Continue with validation after:**
430
1417
  - The app is successfully deployed, OR
431
- - 3 automatic fix attempts have failed and user intervention is needed
1418
+ - 3 troubleshooting attempts have been made and user intervention is needed
432
1419
 
433
- 3. **If automatic fixes fail after 3 attempts:**
1420
+ 3. **If suggested fixes don't resolve the issue after 3 attempts:**
434
1421
  - Present detailed error information to the user
435
1422
  - Show what fixes were attempted
436
1423
  - Ask user for manual configuration input:
@@ -451,6 +1438,200 @@ After migrating the app:
451
1438
  - If auto-fixed, show what was corrected
452
1439
  - If failed, show the errors and fixes that were attempted
453
1440
 
1441
+ 6. **Provide rollback plan:**
1442
+ - Inform user how to rollback if issues arise
1443
+ - See section 3.1 below for detailed rollback instructions
1444
+
1445
+ #### 3.1 Rollback and Recovery Plan
1446
+
1447
+ **Before updating DNS (if migrating from Vercel):**
1448
+
1449
+ 1. ✅ Test App Platform deployment thoroughly using the default `.ondigitalocean.app` URL
1450
+ 2. ✅ Verify all functionality works (API endpoints, database, authentication, etc.)
1451
+ 3. ✅ Keep Vercel app running during DNS propagation (24-48 hours)
1452
+ 4. ✅ Monitor App Platform logs and metrics for errors
1453
+ 5. ✅ Have rollback plan ready before updating DNS
1454
+
1455
+ ---
1456
+
1457
+ **Rollback Option A: DNS Rollback (if you've already updated DNS)**
1458
+
1459
+ If you've migrated domains but need to roll back to Vercel:
1460
+
1461
+ ```bash
1462
+ # 1. Identify which DNS records need to be changed back
1463
+ # For each domain, update DNS records:
1464
+
1465
+ # If using CNAME record:
1466
+ # Change: myapp.com -> CNAME -> my-app-abc123.ondigitalocean.app
1467
+ # Back to: myapp.com -> CNAME -> cname.vercel-dns.com
1468
+
1469
+ # If using A records:
1470
+ # Remove App Platform A records (162.159.140.98, 172.66.0.96)
1471
+ # Restore original Vercel A records (check your DNS provider's history)
1472
+ ```
1473
+
1474
+ **Steps:**
1475
+ 1. Log into your DNS provider (Cloudflare, Namecheap, etc.)
1476
+ 2. Restore DNS records to point back to Vercel
1477
+ 3. Wait for DNS propagation (can take up to 48 hours, but often faster)
1478
+ 4. Monitor traffic shifting back to Vercel
1479
+ 5. Keep App Platform app running until you're ready to delete it
1480
+
1481
+ **Timeline**: DNS propagation typically takes 15 minutes to 48 hours depending on TTL settings.
1482
+
1483
+ ---
1484
+
1485
+ **Rollback Option B: App Platform Deployment Rollback**
1486
+
1487
+ If App Platform is working but a recent deployment introduced bugs:
1488
+
1489
+ ```bash
1490
+ # 1. View deployment history
1491
+ doctl apps list-deployments <app-id>
1492
+
1493
+ # Output will show:
1494
+ # ID Status Created At
1495
+ # abc123 ACTIVE 2025-01-15 10:30:00
1496
+ # def456 ACTIVE 2025-01-14 08:15:00 <- previous working deployment
1497
+ # ghi789 ACTIVE 2025-01-13 14:20:00
1498
+
1499
+ # 2. Rollback to previous deployment
1500
+ doctl apps create-deployment <app-id> --deployment-id <previous-deployment-id>
1501
+
1502
+ # Example:
1503
+ # doctl apps create-deployment abc-123-app --deployment-id def456
1504
+ ```
1505
+
1506
+ **When to use this:**
1507
+ - Recent code push broke the app
1508
+ - Need to quickly return to last known good state
1509
+ - Issue is with application code, not infrastructure
1510
+
1511
+ **Limitations:**
1512
+ - Only rolls back application code, not infrastructure changes (database schema, env vars)
1513
+ - Can only rollback to deployments that are still available (typically last 10 deployments)
1514
+ - Database changes are NOT rolled back automatically - handle separately
1515
+
1516
+ ---
1517
+
1518
+ **Rollback Option C: Code Rollback via Git**
1519
+
1520
+ If you need to revert code changes:
1521
+
1522
+ ```bash
1523
+ # 1. Identify the problematic commit
1524
+ git log --oneline
1525
+
1526
+ # 2. Revert the commit (creates new commit that undoes changes)
1527
+ git revert <commit-hash>
1528
+
1529
+ # 3. Push to main branch
1530
+ git push origin main
1531
+
1532
+ # App Platform will automatically deploy the reverted code
1533
+ ```
1534
+
1535
+ **When to use this:**
1536
+ - Need to undo specific code changes
1537
+ - Want to maintain git history
1538
+ - Problem is in application code
1539
+
1540
+ **Alternative - Reset to previous commit** (more destructive):
1541
+ ```bash
1542
+ # WARNING: This rewrites history
1543
+ git reset --hard <previous-commit-hash>
1544
+ git push origin main --force
1545
+
1546
+ # App Platform will deploy the previous state
1547
+ ```
1548
+
1549
+ ⚠️ **Use `--force` with caution** - only do this if you understand the implications.
1550
+
1551
+ ---
1552
+
1553
+ **Rollback Option D: Full App Deletion and Vercel Restoration**
1554
+
1555
+ If App Platform isn't working and you need to fully abort the migration:
1556
+
1557
+ 1. **Do NOT delete Vercel app yet** - keep it running
1558
+ 2. Update DNS to point back to Vercel (see Option A above)
1559
+ 3. Wait for DNS propagation
1560
+ 4. Verify traffic is back on Vercel
1561
+ 5. Once confirmed stable, delete App Platform app:
1562
+ ```bash
1563
+ doctl apps delete <app-id>
1564
+ ```
1565
+ 6. Note: Databases must be deleted separately:
1566
+ ```bash
1567
+ doctl databases delete <db-id>
1568
+ ```
1569
+
1570
+ ---
1571
+
1572
+ **Database Rollback Considerations:**
1573
+
1574
+ ⚠️ **Database schemas and data are NOT automatically rolled back**
1575
+
1576
+ If you ran database migrations on App Platform:
1577
+
1578
+ **Option 1: Restore from backup**
1579
+ ```bash
1580
+ # List database backups
1581
+ doctl databases backups list <db-id>
1582
+
1583
+ # Restore from backup
1584
+ doctl databases restore <db-id> --backup-id <backup-id>
1585
+ ```
1586
+
1587
+ **Option 2: Run reverse migrations**
1588
+ - If using Prisma, Drizzle, TypeORM, etc., run down/reverse migrations
1589
+ - This requires having written reverse migration scripts
1590
+
1591
+ **Option 3: Manual database restoration**
1592
+ - If you have a pg_dump from before migration, restore it
1593
+ - This is why taking a backup before migration is critical
1594
+
1595
+ ---
1596
+
1597
+ **Monitoring During Rollback:**
1598
+
1599
+ While rolling back, monitor:
1600
+ - **DNS propagation**: Use `dig myapp.com` or online DNS checkers
1601
+ - **Traffic**: Check which servers are receiving traffic
1602
+ - **Error rates**: Monitor both Vercel and App Platform
1603
+ - **User impact**: Communicate with users if necessary
1604
+
1605
+ ---
1606
+
1607
+ **Best Practices to Minimize Rollback Risk:**
1608
+
1609
+ 1. ✅ **Test thoroughly** before updating DNS
1610
+ 2. ✅ **Use low TTL** on DNS records during migration (e.g., 300 seconds / 5 minutes)
1611
+ 3. ✅ **Backup database** before running migrations
1612
+ 4. ✅ **Deploy to App Platform dev environment first** (create a separate dev app)
1613
+ 5. ✅ **Keep Vercel running** for at least 48 hours after DNS update
1614
+ 6. ✅ **Monitor metrics** closely for first 24-48 hours
1615
+ 7. ✅ **Have team available** during DNS cutover window
1616
+ 8. ✅ **Communicate with users** about potential brief disruption
1617
+
1618
+ ---
1619
+
1620
+ **When to Rollback:**
1621
+
1622
+ Consider rolling back if:
1623
+ - ❌ Critical functionality is broken
1624
+ - ❌ Performance is significantly degraded
1625
+ - ❌ Database connection issues persist
1626
+ - ❌ Authentication/authorization fails
1627
+ - ❌ Third-party integrations break
1628
+ - ❌ Error rate exceeds acceptable threshold
1629
+
1630
+ Don't rollback for:
1631
+ - ✅ Minor UI issues (can be fixed with quick patch)
1632
+ - ✅ Non-critical features not working (can be fixed iteratively)
1633
+ - ✅ Expected differences in platform behavior (document for users)
1634
+
454
1635
  ### Step 4: Migration Summary
455
1636
 
456
1637
  After completing the migration, provide:
@@ -485,6 +1666,140 @@ After completing the migration, provide:
485
1666
  - Optimization suggestions
486
1667
  - Timeline: Remind user to keep Vercel running until DNS fully propagates
487
1668
 
1669
+ ## App Platform Strengths and When to Use It
1670
+
1671
+ While this guide focuses on migration considerations and limitations, it's important to understand App Platform's advantages:
1672
+
1673
+ **Built-in Managed Features:**
1674
+ - ✅ **Managed databases** with automatic backups, point-in-time recovery, and automatic failover (PostgreSQL, Redis/ValKey)
1675
+ - ✅ **Automatic SSL certificates** for all custom domains with auto-renewal
1676
+ - ✅ **Built-in CDN** for global content delivery with automatic edge caching
1677
+ - ✅ **Native cron jobs** and background workers for scheduled tasks
1678
+ - ✅ **One-click rollbacks** to previous deployments (last 10 deployments available)
1679
+ - ✅ **Automatic health checks** and restarts for failing services
1680
+ - ✅ **Zero-downtime deployments** with automatic traffic shifting
1681
+
1682
+ **Developer Experience:**
1683
+ - ✅ **Buildpack auto-detection** - minimal configuration required for standard frameworks
1684
+ - ✅ **Git-based deployments** - push to deploy, no complex CI/CD setup needed
1685
+ - ✅ **Preview URLs** for every deployment (`.ondigitalocean.app` subdomains)
1686
+ - ✅ **Integrated logs and metrics** - no external logging service needed
1687
+ - ✅ **Simple, transparent pricing** - no surprise bills, predictable costs
1688
+ - ✅ **Multi-component apps** - deploy frontend, API, workers in one app
1689
+ - ✅ **Internal service communication** - fast, secure service-to-service calls
1690
+
1691
+ **Infrastructure & Operations:**
1692
+ - ✅ **Managed infrastructure** - no Kubernetes knowledge required
1693
+ - ✅ **Automatic scaling** (horizontal scaling for web services)
1694
+ - ✅ **Resource monitoring** built into dashboard
1695
+ - ✅ **Security updates** handled automatically by buildpacks
1696
+ - ✅ **Compliance** - SOC 2, GDPR, HIPAA available on higher tiers
1697
+ - ✅ **Multiple regions** - deploy closer to your users (NYC, SF, AMS, SGP, BLR, etc.)
1698
+
1699
+ **When App Platform is a Great Fit:**
1700
+ - ✅ You want **managed infrastructure** without Kubernetes complexity
1701
+ - ✅ Your app uses **standard frameworks** (Next.js, Express, Django, Rails, Go, etc.)
1702
+ - ✅ You value **operational simplicity** over fine-grained control
1703
+ - ✅ You need **cost predictability** (flat monthly pricing per service)
1704
+ - ✅ You want **database management** handled for you
1705
+ - ✅ You're building **monorepo** apps with multiple services
1706
+ - ✅ You prefer **convention over configuration**
1707
+
1708
+ **When to Consider Alternatives:**
1709
+ - ⚠️ You need edge computing with sub-10ms global latency
1710
+ - ⚠️ You heavily rely on Vercel Edge Functions or middleware
1711
+ - ⚠️ You need ISR (Incremental Static Regeneration)
1712
+ - ⚠️ You require custom infrastructure or bare metal
1713
+ - ⚠️ You need highly customized caching strategies
1714
+ - ⚠️ You want automatic PR preview deployments (requires GitHub Actions setup)
1715
+
1716
+ ---
1717
+
1718
+ ## Expected Outcomes and Success Criteria
1719
+
1720
+ **This guide works well for:**
1721
+
1722
+ ✅ **Standard web applications:**
1723
+ - Next.js apps with API routes and database
1724
+ - React/Vue/Angular SPAs with backend APIs
1725
+ - Express/Fastify Node.js applications
1726
+ - Full-stack monorepo applications
1727
+ - Apps with straightforward build processes
1728
+ - Apps using standard framework conventions
1729
+
1730
+ ✅ **Migration scenarios:**
1731
+ - Simple to moderate complexity apps
1732
+ - Apps with manageable environment variables (< 50 vars)
1733
+ - Standard database usage (PostgreSQL, Redis)
1734
+ - Apps without heavy Vercel-specific features
1735
+ - Teams comfortable with some manual configuration
1736
+
1737
+ **This guide may require additional work for:**
1738
+
1739
+ ⚠️ **Complex architectures:**
1740
+ - Heavy monorepo setups with custom build orchestration
1741
+ - Apps with complex multi-stage builds
1742
+ - Apps with custom buildpacks or Docker requirements
1743
+ - Microservices with complex inter-service dependencies
1744
+ - Apps with extensive custom middleware
1745
+
1746
+ ⚠️ **Vercel-heavy applications:**
1747
+ - Apps heavily dependent on Edge Functions
1748
+ - Apps using Vercel middleware extensively
1749
+ - Apps relying on ISR (Incremental Static Regeneration)
1750
+ - Apps with complex Vercel-specific rewrites/redirects
1751
+ - Apps using Vercel's built-in image optimization heavily
1752
+
1753
+ ⚠️ **Special requirements:**
1754
+ - Real-time collaborative applications with WebSocket state management
1755
+ - Apps requiring GPU acceleration
1756
+ - Apps with proprietary build systems
1757
+ - Apps that need extensive custom caching logic
1758
+ - Apps requiring sub-10ms global edge latency
1759
+
1760
+ **This guide is NOT suitable for:**
1761
+
1762
+ ❌ **Non-standard infrastructure:**
1763
+ - Custom infrastructure requirements (bare metal, GPU, specific hardware)
1764
+ - Apps that can't use buildpacks (custom base images, etc.)
1765
+ - Apps requiring Windows servers
1766
+ - Apps with licensed software that can't run in containers
1767
+
1768
+ ❌ **Extreme edge cases:**
1769
+ - Real-time gaming backends with state synchronization
1770
+ - Video/audio processing requiring specialized hardware
1771
+ - Blockchain nodes or cryptocurrency mining
1772
+ - Applications requiring root access or kernel modules
1773
+
1774
+ **If your app falls into these categories**, consult DigitalOcean documentation or support for custom solutions, or consider using DigitalOcean Droplets/Kubernetes for more control.
1775
+
1776
+ ---
1777
+
1778
+ **Realistic Expectations:**
1779
+
1780
+ **What this guide will help you achieve:**
1781
+ - 🎯 Deploy your app to App Platform in 30-60 minutes (simple apps)
1782
+ - 🎯 Automated error detection and fix suggestions (up to 3 attempts)
1783
+ - 🎯 Working app spec YAML file you can modify
1784
+ - 🎯 Clear understanding of what needs manual work
1785
+ - 🎯 Rollback plan if things go wrong
1786
+
1787
+ **What requires human intervention:**
1788
+ - 👤 Understanding your app's architecture
1789
+ - 👤 Making trade-off decisions (cost, features, performance)
1790
+ - 👤 Implementing code changes for unsupported features
1791
+ - 👤 Testing and validating functionality
1792
+ - 👤 Database data migration (separate manual process)
1793
+ - 👤 Monitoring production performance
1794
+
1795
+ **Success metrics:**
1796
+ - ✅ App builds successfully on first or second attempt
1797
+ - ✅ All critical functionality works on App Platform
1798
+ - ✅ Performance is acceptable (within 10-20% of Vercel)
1799
+ - ✅ Database connections work reliably
1800
+ - ✅ Environment variables are correctly configured
1801
+ - ✅ You understand how to deploy updates
1802
+
488
1803
  ## Special Considerations
489
1804
 
490
1805
  ### Preview Deployments
@@ -492,17 +1807,27 @@ After completing the migration, provide:
492
1807
  - **Workaround:** Create a separate dev app with dev environment
493
1808
  - Recommend using GitHub Actions for preview deployments
494
1809
 
495
- ### MCP vs CLI Usage
496
- This migration uses a **hybrid approach** combining both MCP servers and CLI tools:
497
-
498
- **Vercel:**
499
- - **Vercel CLI (Required):** Environment variables retrieval, app inspection
1810
+ ### CLI Tools vs MCP Servers
1811
+
1812
+ **Primary Method: CLI Tools (Recommended)**
1813
+ - **doctl CLI:** Primary method for App Platform operations
1814
+ - Create apps: `doctl apps create --spec app-spec.yaml`
1815
+ - Manage deployments: `doctl apps get <app-id>`
1816
+ - Configure domains: `doctl apps create-domain <app-id> --domain <domain>`
1817
+ - View logs: `doctl apps logs <app-id> --type build|run`
1818
+ - Update apps: `doctl apps update <app-id> --spec app-spec.yaml`
1819
+ - **gh CLI:** For GitHub repository operations
1820
+ - Create repo: `gh repo create <name> --private --source=. --push`
1821
+ - Fork repo: `gh repo fork <owner>/<repo>`
1822
+ - View repo: `gh repo view`
1823
+ - **Vercel CLI (if migrating from Vercel):** For environment variables and app details
1824
+ - Pull env vars: `vercel env pull .env.production --environment=production`
1825
+ - Inspect app: `vercel inspect <app-name>`
1826
+
1827
+ **Alternative Method: MCP Servers (Optional)**
500
1828
  - **Vercel MCP server (Optional):** Project metadata where available
501
- - **Note:** The Vercel MCP server does NOT provide environment variables
502
-
503
- **DigitalOcean:**
504
- - **DigitalOcean MCP server (Primary):** App creation, deployment management, domain configuration
505
- - **Fallback:** `doctl` CLI or REST API if MCP is unavailable
1829
+ - **DigitalOcean MCP server (Optional):** App Platform operations
1830
+ - **Note:** CLI tools are preferred - users don't need MCP servers
506
1831
 
507
1832
  ### Database Migration
508
1833
  - Creating new databases is straightforward
@@ -618,34 +1943,64 @@ Throughout the migration:
618
1943
  - Migration folders will be created at `./vercel-migration/<app-name>-migration/` for each app
619
1944
  - App specs will be saved for each app as backup
620
1945
  - App Platform buildpack documentation will be referenced for best practices
621
- - **Explain automatic recovery** - let users know that if deployments fail, you will automatically analyze logs and attempt fixes
622
- - **Show your work** - when automatic fixes are applied, explain what error was found and how it was fixed
1946
+ - **Explain assisted troubleshooting** - let users know that if deployments fail, you will analyze logs and suggest fixes for them to review
1947
+ - **Show your work** - when fixes are suggested and applied, explain what error was found and what solution was proposed
623
1948
  - **Confirm** before making changes that could affect production
624
- - **Keep user informed** during automatic retry attempts (e.g., "Deployment failed, analyzing logs and attempting fix 1 of 3...")
1949
+ - **Keep user informed** during retry attempts (e.g., "Deployment failed, analyzing logs and suggesting fix 1 of 3...")
625
1950
 
626
1951
  ## Final Checklist
627
1952
 
628
- Before marking migration complete:
629
-
630
- - [ ] The app has been created in App Platform
631
- - [ ] Deployment is successful (either on first try or after automatic fixes)
632
- - [ ] Automatic troubleshooting was attempted if deployment failed
633
- - [ ] User has been informed of any automatic fixes that were applied
634
- - [ ] Environment variables have been transferred from the .env file pulled in Step 1.1
1953
+ Before marking deployment complete:
1954
+
1955
+ - [ ] Local testing completed (Step 0) - dependencies install, build succeeds
1956
+ - [ ] Repository is set up and accessible (Step 1)
1957
+ - [ ] Database is created (if needed) and connection string is available
1958
+ - [ ] Environment variables are collected and prepared
1959
+ - [ ] App spec YAML file is created and validated
1960
+ - [ ] The app has been created in App Platform using `doctl apps create`
1961
+ - [ ] Deployment is successful (either on first try or after assisted troubleshooting)
1962
+ - [ ] Assisted troubleshooting was attempted if deployment failed
1963
+ - [ ] User has been informed of any fixes that were suggested and applied
1964
+ - [ ] Environment variables have been configured in App Platform
635
1965
  - [ ] Build configurations match validated settings from repository inspection
636
- - [ ] App spec has been saved to `./vercel-migration/<app-name>-migration/app-spec.yaml`
637
- - [ ] Custom domains have been added to the App Platform app
638
- - [ ] User has received DNS update instructions for each domain
1966
+ - [ ] App spec has been saved to `app-spec.yaml` (or migration folder)
1967
+ - [ ] Custom domains have been added to the App Platform app (if applicable)
1968
+ - [ ] User has received DNS update instructions for each domain (if applicable)
639
1969
  - [ ] User understands to test before updating DNS
640
1970
  - [ ] User has been informed about unsupported features
641
1971
  - [ ] User has testing instructions
642
1972
  - [ ] User knows how to rollback if needed
643
- - [ ] User knows to keep Vercel running until DNS propagates
1973
+ - [ ] If migrating from Vercel: User knows to keep Vercel running until DNS propagates
644
1974
  - [ ] Summary includes the app's status (Success/Auto-Fixed/Failed) with details
645
1975
  - [ ] If successful: provide app name, URL (default ingress), and dashboard URL (`https://cloud.digitalocean.com/apps/$app_id`)
646
1976
  - [ ] If failed: tell the user to create a support ticket and link to DigitalOcean's documentation
647
- - [ ] Remind user they can repeat this process for additional apps they want to migrate
1977
+ - [ ] Remind user they can repeat this process for additional apps they want to deploy
1978
+
648
1979
  ---
649
1980
 
650
- **Remember:** This is a migration assistant role. Always prioritize user confirmation for critical decisions and be clear about what can and cannot be automatically migrated.
1981
+ ## Key Points from This Update
1982
+
1983
+ 1. **Multiple deployment scenarios supported:**
1984
+ - Migrating from existing Vercel deployment
1985
+ - Deploying source code directly (no Vercel required)
1986
+ - Deploying without repository access (create new repo or deploy from local)
1987
+
1988
+ 2. **CLI tools are primary method:**
1989
+ - `doctl` for App Platform operations
1990
+ - `gh` CLI for GitHub repository operations
1991
+ - `vercel` CLI only if migrating from Vercel
1992
+ - MCP servers are optional, not required
1993
+
1994
+ 3. **Local testing before deployment:**
1995
+ - Test build locally to catch issues early
1996
+ - Avoid waiting for deployment errors
1997
+ - Verify dependencies, build, and configuration
1998
+
1999
+ 4. **Goal is to get app working on App Platform:**
2000
+ - Doesn't require existing Vercel deployment
2001
+ - Focus on making source code work on App Platform
2002
+ - Support users who don't want to give repo access
2003
+
2004
+ ---
651
2005
 
2006
+ **Remember:** This is an AI-assisted deployment guide. Always prioritize user confirmation for critical decisions and be clear about what can and cannot be automated. The AI assistant provides suggestions and automates routine tasks, but the human user makes final decisions and validates results. The goal is to get the application working on App Platform through active collaboration, whether it's a migration from Vercel or a fresh deployment.