-
Notifications
You must be signed in to change notification settings - Fork 850
feat: add vercel deployment guide #7131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughAdds a new MDX guide demonstrating a programmatic Vercel + Prisma Postgres deployment workflow (CONFIG, six-step TypeScript API sequence, retry/error helpers, and deployApp orchestrator) and updates Changes
Sequence Diagram(s)sequenceDiagram
participant Dev as Developer script
participant VercelAPI as Vercel REST API
participant PrismaStore as Prisma Postgres (store)
participant VercelProject as Vercel Project / Deployment
rect rgba(0,128,96,0.08)
note right of Dev: deployApp() orchestrator (high-level)
end
Dev->>VercelAPI: POST /v10/projects (createProject)
VercelAPI-->>Dev: projectId
Dev->>VercelAPI: POST /v1/integrations/billing/authorization (createPrismaAuthorization)
VercelAPI-->>Dev: authorizationId
Dev->>VercelAPI: POST /v1/storage/stores/integration (createPrismaDatabase)
VercelAPI-->>PrismaStore: provision DB
VercelAPI-->>Dev: storeId, connectionString
Dev->>VercelAPI: POST /v1/integrations/installations/{configId}/products/{PRISMA_PRODUCT_ID}/resources/{storeId}/connections (connectDatabaseToProject)
VercelAPI-->>Dev: connection confirmation
Dev->>VercelAPI: POST /v13/deployments (deployApplication)
VercelAPI-->>VercelProject: build & deploy
VercelAPI-->>Dev: deploymentUrl
Dev->>VercelAPI: POST /v9/projects/{projectId}/transfer-request (createProjectTransfer)
VercelAPI-->>Dev: transferCode / claimUrl
note right of Dev: deployApp() returns consolidated result (projectId, url, transfer info)
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal). Please share your feedback with us on this Discord post. Comment |
Dangerous URL checkNo absolute URLs to prisma.io/docs found. |
Redirect checkThis PR probably requires the following redirects to be added to static/_redirects:
|
Images automagically compressed by Calibre's image-actions ✨ Compression reduced images by 87.7%, saving 274.7 KB.
|
Deploying docs with
|
Latest commit: |
5649dc5
|
Status: | ✅ Deploy successful! |
Preview URL: | https://0fa3e06d.docs-51g.pages.dev |
Branch Preview URL: | https://dc-5025-vercel-guide.docs-51g.pages.dev |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (7)
content/800-guides/380-vercel-app-deployment.mdx (6)
137-158
: Use the shared error/ retry helpers in all API calls.
createProject
(and later functions) don’t usehandleApiErrors
/apiCallWithRetry
, so failures will be silent and inconsistent with the guide’s best practices.- const response = await fetch( + const response = await apiCallWithRetry( `${CONFIG.VERCEL_API_URL}/v10/projects?teamId=${CONFIG.TEAM_ID}`, { method: "POST", headers: { Authorization: `Bearer ${CONFIG.ACCESS_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ name: projectName }), } ); - const project = await response.json(); + await handleApiErrors(response, "Create project"); + const project = await response.json();
369-405
:fileSha
is undefined; make it a parameter and wire in error/retry.The orchestration example won’t run as-is. Accept
fileSha
(or upload first) and consistently use your helpers.-async function deployApp() { +async function deployApp(fileSha: string) { console.log("🚀 Starting instant deployment..."); @@ - const deployment = await deployApplication(project.name, fileSha); + const deployment = await deployApplication(project.name, fileSha); @@ return { projectId: project.id, deploymentUrl: `https://${deployment.url}`, claimCode: transfer.code, claimUrl: transfer.claimUrl, }; }
447-466
: Surface parsed JSON where possible and include response snippet in errors.Parsing only
text()
loses structure. Prefer JSON where applicable and include truncated payload for diagnostics.- const errorData = await response.text(); + const raw = await response.text(); + let errorData: unknown = raw; + try { errorData = JSON.parse(raw); } catch {} @@ - throw new Error(`${operation} failed: ${response.status} - ${errorData}`); + throw new Error(`${operation} failed: ${response.status} - ${typeof errorData === "string" ? errorData.slice(0, 500) : JSON.stringify(errorData).slice(0, 500)}`);
475-492
: Respect Retry-After, add jitter, and support timeouts.This improves resilience under rate limits and network stalls.
-async function apiCallWithRetry(url: string, options: RequestInit, maxRetries = 3) { +async function apiCallWithRetry(url: string, options: RequestInit, maxRetries = 3, timeoutMs = 15000) { for (let attempt = 1; attempt <= maxRetries; attempt++) { try { - const response = await fetch(url, options); + const ac = new AbortController(); + const t = setTimeout(() => ac.abort(), timeoutMs); + const response = await fetch(url, { ...options, signal: ac.signal }); + clearTimeout(t); if (response.status === 429) { - const waitTime = Math.pow(2, attempt) * 1000; // Exponential backoff - await new Promise(resolve => setTimeout(resolve, waitTime)); + const ra = response.headers.get("retry-after"); + const base = ra ? Number(ra) * 1000 : Math.pow(2, attempt) * 1000; + const jitter = Math.floor(Math.random() * 250); + await new Promise(resolve => setTimeout(resolve, base + jitter)); continue; } return response; } catch (error) { if (attempt === maxRetries) throw error; } } }
499-506
: Add an explicit note to avoid logging or storing secrets (tokens and database URLs).Strengthen the guidance given the examples return sensitive values earlier.
- **Store tokens securely**: Never expose API tokens in client-side code + - **Never log or store secrets**: Avoid printing ACCESS_TOKEN, connection strings (DATABASE_URL), or other credentials to logs or analytics
121-129
: Avoid hard-coding product IDs — use Vercel's 'prisma' slug and VERCEL_TOKEN
- Replace PRISMA_PRODUCT_ID = "iap_yVdbiKqs5fLkYDAB" with the Marketplace slug "prisma" (use integrationProductIdOrSlug = "prisma").
- Rename ACCESS_TOKEN → VERCEL_TOKEN and store it as a Sensitive env var; optionally namespace other vars as VERCEL_TEAM_ID and VERCEL_INTEGRATION_CONFIG_ID.
File: content/800-guides/380-vercel-app-deployment.mdx lines 121-129.
sidebars.ts (1)
549-559
: Prefertype: "doc"
for internal pages over rawhref
for consistency and broken-link checks.Using
doc
ids enables Docusaurus validation and versioning. Keephref
only for external links.Example:
-{ - type: "link", - label: "Integrating the Vercel AI SDK in a Next.js application", - href: "/guides/ai-sdk-nextjs", -}, +{ + type: "doc", + id: "guides/ai-sdk-nextjs", + label: "Integrating the Vercel AI SDK in a Next.js application", +},Also applies to: 572-582, 595-600
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
static/img/guides/vercel_app_deployments.png
is excluded by!**/*.png
📒 Files selected for processing (2)
content/800-guides/380-vercel-app-deployment.mdx
(1 hunks)sidebars.ts
(4 hunks)
🔇 Additional comments (5)
sidebars.ts (2)
604-606
: LGTM on formatting tweaks.Trailing commas/comments here are harmless and match existing style.
453-454
: Ensure sidebar entry id matches MDX doc id/slugsidebars.ts references "guides/vercel-app-deployment" (sidebars.ts:453) but content/800-guides/380-vercel-app-deployment.mdx frontmatter has no
id
orslug
. Addslug: /guides/vercel-app-deployment
orid: guides/vercel-app-deployment
to the MDX frontmatter, or update the sidebar entry to the doc's actual id.content/800-guides/380-vercel-app-deployment.mdx (3)
33-33
: Validate external links and follow redirects.File: content/800-guides/380-vercel-app-deployment.mdx Lines: 33-33
[Try the demo](https://pris.ly/vercel_app_deployment_demo?utm_source=docs).
HEAD check results:
- https://pris.ly/vercel_app_deployment_demo?utm_source=docs — HTTP/2 302 (redirect)
- https://vercel.com/docs/deployments/claim-deployments — HTTP/2 200
- https://vercel.com/docs/rest-api — HTTP/2 302 (redirect)
- https://www.better-auth.com/ — HTTP/2 200
Action: follow the 302 redirects (e.g., curl -IL) and confirm the final URLs and any fragment anchors resolve to 200 and the intended content; update links/anchors or replace with final destination URLs if they will 404 at publish time.
Also applies to: 362-363, 407-407, 556-561
332-355
: Add API error handling; TTL is 24h — don't rely on returnUrl for expired/invalid codes.File: content/800-guides/380-vercel-app-deployment.mdx (lines 332-355)
- Replace the raw fetch with apiCallWithRetry and call handleApiErrors on the response; handle non-2xx results (show a user-facing error/fallback) instead of assuming the claim flow will redirect.
- Vercel docs: the POST returns a transfer
code
valid for 24 hours and the claim URL acceptsreturnUrl
; behavior for invalid/expired codes is not documented (the accept endpoint surfaces 4xx/422 errors), so explicitly handle these error cases in code. (vercel.com)
170-200
:metadata
should be an object, not a JSON string.Vercel's integrations/marketplace examples and responses use metadata as a JSON object; keep it as an object unless this exact endpoint explicitly requires a string. (vercel.com)
- metadata: JSON.stringify({ region: "iad1" }), + metadata: { region: "iad1" },
--- | ||
title: 'Instant app deployment with Vercel and Prisma Postgres' | ||
metaTitle: 'Instant app deployment with Vercel and Prisma Postgres' | ||
description: 'Learn how to programmatically deploy applications with Vercel and Prisma Postgres using the instant deployment API' | ||
sidebar_label: 'Vercel app deployment' | ||
image: '/img/guides/vercel_app_deployments.png' | ||
community_section: true | ||
--- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add a stable slug/id so the sidebar link resolves.
The sidebar references guides/vercel-app-deployment
, but this file lacks a matching slug
or id
. Add a slug to avoid 404s and decouple from the numeric path.
---
title: 'Instant app deployment with Vercel and Prisma Postgres'
metaTitle: 'Instant app deployment with Vercel and Prisma Postgres'
description: 'Learn how to programmatically deploy applications with Vercel and Prisma Postgres using the instant deployment API'
sidebar_label: 'Vercel app deployment'
image: '/img/guides/vercel_app_deployments.png'
community_section: true
+slug: /guides/vercel-app-deployment
---
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
--- | |
title: 'Instant app deployment with Vercel and Prisma Postgres' | |
metaTitle: 'Instant app deployment with Vercel and Prisma Postgres' | |
description: 'Learn how to programmatically deploy applications with Vercel and Prisma Postgres using the instant deployment API' | |
sidebar_label: 'Vercel app deployment' | |
image: '/img/guides/vercel_app_deployments.png' | |
community_section: true | |
--- | |
--- | |
title: 'Instant app deployment with Vercel and Prisma Postgres' | |
metaTitle: 'Instant app deployment with Vercel and Prisma Postgres' | |
description: 'Learn how to programmatically deploy applications with Vercel and Prisma Postgres using the instant deployment API' | |
sidebar_label: 'Vercel app deployment' | |
image: '/img/guides/vercel_app_deployments.png' | |
community_section: true | |
slug: /guides/vercel-app-deployment | |
--- |
🤖 Prompt for AI Agents
In content/800-guides/380-vercel-app-deployment.mdx around lines 1 to 8, the
file frontmatter is missing a stable slug/id so the sidebar link to
guides/vercel-app-deployment can 404; add a slug (and optionally an id) to the
YAML frontmatter such as slug: 'guides/vercel-app-deployment' (or id:
'guides/vercel-app-deployment') to decouple the URL from the numeric path and
ensure the sidebar link resolves.
async function createPrismaDatabase( | ||
projectName: string, | ||
authId: string, | ||
configId: string | ||
): Promise<{ id: string; connectionString?: string }> { | ||
const response = await fetch( | ||
`${CONFIG.VERCEL_API_URL}/v1/storage/stores/integration?teamId=${CONFIG.TEAM_ID}`, | ||
{ | ||
method: "POST", | ||
headers: { | ||
Authorization: `Bearer ${CONFIG.ACCESS_TOKEN}`, | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ | ||
metadata: { region: "iad1" }, | ||
billingPlanId: "pro", | ||
name: `postgres-${projectName}`, | ||
integrationConfigurationId: configId, | ||
integrationProductIdOrSlug: CONFIG.PRISMA_PRODUCT_ID, | ||
authorizationId: authId, | ||
source: "marketplace", | ||
}), | ||
} | ||
); | ||
|
||
const storageData = await response.json(); | ||
|
||
return { | ||
id: storageData.store.id, | ||
connectionString: storageData.store.connectionString, | ||
}; | ||
} | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not surface raw connection strings in return values/logs.
connectionString
is sensitive. Avoid returning or logging it in examples; rely on the connection injected into env vars after linking.
-): Promise<{ id: string; connectionString?: string }> {
+): Promise<{ id: string }> {
const response = await fetch(
`${CONFIG.VERCEL_API_URL}/v1/storage/stores/integration?teamId=${CONFIG.TEAM_ID}`,
{
method: "POST",
headers: {
Authorization: `Bearer ${CONFIG.ACCESS_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
metadata: { region: "iad1" },
billingPlanId: "pro",
name: `postgres-${projectName}`,
integrationConfigurationId: configId,
- integrationProductIdOrSlug: CONFIG.PRISMA_PRODUCT_ID,
+ integrationProductIdOrSlug: CONFIG.PRISMA_PRODUCT_ID,
authorizationId: authId,
source: "marketplace",
}),
}
);
const storageData = await response.json();
return {
- id: storageData.store.id,
- connectionString: storageData.store.connectionString,
+ id: storageData.store.id,
};
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
async function createPrismaDatabase( | |
projectName: string, | |
authId: string, | |
configId: string | |
): Promise<{ id: string; connectionString?: string }> { | |
const response = await fetch( | |
`${CONFIG.VERCEL_API_URL}/v1/storage/stores/integration?teamId=${CONFIG.TEAM_ID}`, | |
{ | |
method: "POST", | |
headers: { | |
Authorization: `Bearer ${CONFIG.ACCESS_TOKEN}`, | |
"Content-Type": "application/json", | |
}, | |
body: JSON.stringify({ | |
metadata: { region: "iad1" }, | |
billingPlanId: "pro", | |
name: `postgres-${projectName}`, | |
integrationConfigurationId: configId, | |
integrationProductIdOrSlug: CONFIG.PRISMA_PRODUCT_ID, | |
authorizationId: authId, | |
source: "marketplace", | |
}), | |
} | |
); | |
const storageData = await response.json(); | |
return { | |
id: storageData.store.id, | |
connectionString: storageData.store.connectionString, | |
}; | |
} | |
``` | |
async function createPrismaDatabase( | |
projectName: string, | |
authId: string, | |
configId: string | |
): Promise<{ id: string }> { | |
const response = await fetch( | |
`${CONFIG.VERCEL_API_URL}/v1/storage/stores/integration?teamId=${CONFIG.TEAM_ID}`, | |
{ | |
method: "POST", | |
headers: { | |
Authorization: `Bearer ${CONFIG.ACCESS_TOKEN}`, | |
"Content-Type": "application/json", | |
}, | |
body: JSON.stringify({ | |
metadata: { region: "iad1" }, | |
billingPlanId: "pro", | |
name: `postgres-${projectName}`, | |
integrationConfigurationId: configId, | |
integrationProductIdOrSlug: CONFIG.PRISMA_PRODUCT_ID, | |
authorizationId: authId, | |
source: "marketplace", | |
}), | |
} | |
); | |
const storageData = await response.json(); | |
return { | |
id: storageData.store.id, | |
}; | |
} |
🤖 Prompt for AI Agents
In content/800-guides/380-vercel-app-deployment.mdx around lines 214 to 246, the
function currently returns storageData.store.connectionString which exposes a
sensitive DB connection string; remove the connectionString from the returned
object (return only the store id), do not log or surface the raw connection
string anywhere in examples, and rely on the connection being injected into env
vars after linking; optionally validate storageData.store exists and throw a
safe error message if missing but never include the connection string in return
values or logs.
async function connectDatabaseToProject( | ||
projectId: string, | ||
storeId: string, | ||
configId: string | ||
): Promise<void> { | ||
await fetch( | ||
`${CONFIG.VERCEL_API_URL}/v1/integrations/installations/${configId}/products/${CONFIG.PRISMA_PRODUCT_ID}/resources/${storeId}/connections?teamId=${CONFIG.TEAM_ID}`, | ||
{ | ||
method: "POST", | ||
headers: { | ||
Authorization: `Bearer ${CONFIG.ACCESS_TOKEN}`, | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ projectId }), | ||
} | ||
); | ||
|
||
console.log("✅ Database connected to project"); | ||
} | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify the “connect resource to project” endpoint path and params.
The path uses installations/{configId}/products/{PRISMA_PRODUCT_ID}/resources/{storeId}/connections
. Confirm the expected installations
vs configurations
, required IDs, and query/body fields.
🌐 Web query:
What is the correct Vercel endpoint to connect an Integration resource (Prisma Postgres store) to a Project, and which IDs are required (installation/configuration, product, resource, project)?
💡 Result:
Endpoint:
- POST /v1/integrations/installations/{integrationConfigurationId}/resources/{resourceId}/connections. [1]
Required IDs/fields:
- integrationConfigurationId — the installation / integration configuration ID (path). [1]
- resourceId — the provider resource ID (path). [1][2]
- projectId — the Vercel project ID (JSON body, required). [1]
Optional/query:
- teamId or slug — to act on behalf of a team (query parameters). [1]
Notes:
- productId is returned in the resource metadata but is not required to call this endpoint. [2]
Sources:
[1] Vercel REST API — Connect integration resource to project (POST).
[2] Vercel REST API — Get Integration Resource (resource fields).
Fix endpoint path — remove /products/{productId} and call Vercel’s connect-resource endpoint.
Use POST /v1/integrations/installations/{integrationConfigurationId}/resources/{resourceId}/connections. Path params: integrationConfigurationId (configId) and resourceId (storeId). Request body must include { projectId } (already present). Optional: ?teamId or ?slug. productId is not required and should be removed from the URL.
File: content/800-guides/380-vercel-app-deployment.mdx — lines 260–279.
🤖 Prompt for AI Agents
In content/800-guides/380-vercel-app-deployment.mdx around lines 260 to 279, the
request URL incorrectly includes /products/{productId}; change the endpoint to
POST
/v1/integrations/installations/{integrationConfigurationId}/resources/{resourceId}/connections
by removing the /products/{productId} segment and using configId as
integrationConfigurationId and storeId as resourceId in the path, keep the JSON
body { projectId } as-is and retain optional query params like ?teamId or ?slug
if needed.
async function deployApplication( | ||
projectName: string, | ||
fileSha: string | ||
): Promise<{ id: string; url: string }> { | ||
const response = await fetch( | ||
`${CONFIG.VERCEL_API_URL}/v13/deployments?teamId=${CONFIG.TEAM_ID}`, | ||
{ | ||
method: "POST", | ||
headers: { | ||
Authorization: `Bearer ${CONFIG.ACCESS_TOKEN}`, | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ | ||
files: [{ file: ".vercel/source.tgz", sha: fileSha }], | ||
name: `deployment-${Date.now()}`, | ||
projectSettings: { framework: "nextjs" }, | ||
project: projectName, | ||
}), | ||
} | ||
); | ||
|
||
const deploymentData = await response.json(); | ||
|
||
return { | ||
id: deploymentData.id, | ||
url: deploymentData.alias?.[0] || deploymentData.url, | ||
}; | ||
} | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Deployment flow misses file upload and ‘target’; verify project
field semantics.
- You reference
fileSha
without showing how to upload and compute it. - For production URLs, set
target: "production"
. - Confirm whether
project
expects project ID or name in v13.
body: JSON.stringify({
files: [{ file: ".vercel/source.tgz", sha: fileSha }],
- name: `deployment-${Date.now()}`,
+ name: `deployment-${Date.now()}`,
projectSettings: { framework: "nextjs" },
- project: projectName,
+ project: projectName, // use projectId if required
+ target: "production",
}),
🌐 Web query:
For POST /v13/deployments:
1) How to upload files and compute `sha` for `.vercel/source.tgz`?
2) Is `project` a project ID or name?
3) Is `target: "production"` required for production URLs?
💡 Result:
Short answers:
- Upload + compute sha:
- Compute a SHA1 of the file contents (the API expects the file SHA1). On Unix you can use shasum, e.g. shasum -a 1 (Vercel guide shows using shasum and then sending that value as the x-vercel-digest header). Then POST the raw file to the upload endpoint with header x-vercel-digest (and proper Content-Length). See Vercel guide and the Upload Deployment Files docs. [1][2]
- project field:
- Vercel accepts either a project ID or project name for the project endpoints (there are endpoints like GET /v9/projects/{idOrName} that accept id OR name). Use the project ID when you need an unambiguous identifier. [3]
- target: "production":
- target is optional. If omitted the deployment is a preview deployment; to assign production aliases / mark it as a production deployment you should set target: "production". So include target: "production" when you want production URLs / alias promotion. [4][2]
Sources:
[1] Vercel guide — “How do I generate an SHA for uploading a file to the Vercel API?”.
[2] Vercel REST API — Upload Deployment Files (POST /v2/files) (x-vercel-digest / Content-Length).
[3] Vercel REST API — Find a project by id or name (GET /v9/projects/{idOrName}).
[4] Vercel POST /v13/deployments docs / integration reference (target: optional — use "production" to assign aliases).
Implement file upload (SHA1) + set target="production"; prefer project ID
- Compute SHA1 for .vercel/source.tgz (e.g., shasum -a 1 .vercel/source.tgz) and upload the raw file to Vercel's upload endpoint (POST /v2/files) with header x-vercel-digest: and correct Content-Length; use that SHA as files[].sha in the v13 deployment request.
- Add target: "production" to get production aliases / mark the deployment as production.
- Use project ID (preferred) rather than name for unambiguous behavior — v13 accepts either, but ID is safer.
Location: content/800-guides/380-vercel-app-deployment.mdx — deployApplication (lines 290-318).
body: JSON.stringify({
files: [{ file: ".vercel/source.tgz", sha: fileSha }],
- name: `deployment-${Date.now()}`,
+ name: `deployment-${Date.now()}`,
projectSettings: { framework: "nextjs" },
- project: projectName,
+ project: projectName, // use projectId if required
+ target: "production",
}),
- `POST /v13/deployments` - Deploy application code | ||
- `POST /v9/projects/{id}/transfer-request` - Generate claim code for user transfer | ||
|
||
## Required API keys and environment variables |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ankur-arch do you need a Prisma token also?
Co-authored-by: Petra Donka <[email protected]>
Summary by CodeRabbit