Skip to content

Commit 8863bee

Browse files
feat(cli): add Render and Vercel deployment targets (#507)
* feat(cli): add --deployment render flag with GitHub handoff Add Render as a deployment provider for both React and Solid frameworks. - Creates render.yaml for one-click deploy via Render's GitHub integration - Uses Nitro server preset (render-com) for SSR, server functions, and static assets - Matches existing Railway pattern for GitHub-first deployments - Updates deployment provider documentation Part of TanStack/Render Gold partnership (Sep 2026 launch). * feat(cli): harden Render and add Vercel deployment * fix(create): type generated worker manifests * fix(create): harden partner deployment metadata --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
1 parent f537073 commit 8863bee

29 files changed

Lines changed: 492 additions & 27 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'@tanstack/cli': minor
3+
'@tanstack/create': minor
4+
---
5+
6+
Add Gold partner deployment targets for Render and Vercel to React and Solid
7+
scaffolds. Render generates package-manager-aware Blueprint commands, while
8+
Vercel generates explicit framework detection and Nitro Build Output API
9+
support.

packages/cli/skills/choose-ecosystem-integrations/references/deployment-targets.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Map deployment intent to one supported target and include it in scaffold command
77
- `cloudflare`
88
- `netlify`
99
- `railway`
10+
- `render`
11+
- `vercel`
1012
- `nitro`
1113

1214
## Selection pattern

packages/cli/skills/create-app-scaffold/references/deployment-providers.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ Targets `@tanstack/cli` v0.61.0.
77
- `cloudflare`
88
- `netlify`
99
- `railway`
10+
- `render`
11+
- `vercel`
1012
- `nitro`
1113

1214
## Usage
1315

1416
```bash
1517
npx @tanstack/cli create app --deployment cloudflare -y
1618
npx @tanstack/cli create app --deployment netlify -y
19+
npx @tanstack/cli create app --deployment vercel -y
1720
```
1821

1922
Deployment providers are exclusive; choose one per scaffold.

packages/cli/tests/partner-placement.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ describe('partner placement', () => {
6060
addOn('netlify', { id: 'netlify', tier: 'gold' }),
6161
addOn('cloudflare', { id: 'cloudflare', tier: 'gold' }),
6262
addOn('railway', { id: 'railway', tier: 'gold' }),
63+
addOn('render', { id: 'render', tier: 'gold' }),
64+
addOn('vercel', { id: 'vercel', tier: 'gold' }),
6365
],
6466
'deployment',
6567
'test',
@@ -71,6 +73,6 @@ describe('partner placement', () => {
7173
.slice(1)
7274
.map((item) => item.id)
7375
.sort(),
74-
).toEqual(['netlify', 'railway'])
76+
).toEqual(['netlify', 'railway', 'render', 'vercel'])
7577
})
7678
})

packages/create/scripts/generate-manifest.mjs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,9 @@ function writeWorkerManifest(manifest) {
472472

473473
writeGeneratedModule(
474474
join(workerOutputDir, 'catalog.ts'),
475-
`export const manifestCatalog = ${JSON.stringify(
475+
`import type { ManifestCatalog } from '../../manifest-types.js'
476+
477+
export const manifestCatalog: ManifestCatalog = ${JSON.stringify(
476478
{
477479
frameworks: manifest.map(stripFrameworkForCatalog),
478480
},
@@ -491,16 +493,18 @@ function writeWorkerManifest(manifest) {
491493

492494
writeGeneratedModule(
493495
join(workerOutputDir, 'frameworks', `${frameworkSegment}.ts`),
494-
`${createTemplateRendererSource(
495-
createTemplateRenderersForFrameworkBase(framework),
496-
)}\n\nexport const framework = ${JSON.stringify(
496+
`import type { WorkerFrameworkManifestModule } from '../../../manifest-types.js'
497+
498+
${createTemplateRendererSource(
499+
createTemplateRenderersForFrameworkBase(framework),
500+
)}\n\nexport const framework = ${JSON.stringify(
497501
{
498502
id: framework.id,
499503
base: framework.base,
500504
},
501505
null,
502506
2,
503-
)}\n`,
507+
)} satisfies WorkerFrameworkManifestModule['framework']\n`,
504508
)
505509

506510
for (const addOn of framework.addOns) {
@@ -516,9 +520,11 @@ function writeWorkerManifest(manifest) {
516520
'add-ons',
517521
`${addOnSegment}.ts`,
518522
),
519-
`${createTemplateRendererSource(
520-
createTemplateRenderersForAddOn(addOn),
521-
)}\n\nexport const addOn = ${JSON.stringify(addOn, null, 2)}\n`,
523+
`import type { AddOnCompiled } from '../../../../../types.js'
524+
525+
${createTemplateRendererSource(
526+
createTemplateRenderersForAddOn(addOn),
527+
)}\n\nexport const addOn = ${JSON.stringify(addOn, null, 2)} satisfies AddOnCompiled\n`,
522528
)
523529
}
524530
}

packages/create/src/create-app.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
intentCommand,
99
packageManagerInstall,
1010
translateExecuteCommand,
11+
validatePackageManagerSupport,
1112
} from './package-manager.js'
1213
import { createPackageJSON } from './package-json.js'
1314
import { resolvePackageJSONLatest } from './npm-resolver.js'
@@ -475,6 +476,7 @@ Please read the README.md file for information on ${readmeDescription}${errorSta
475476
}
476477

477478
export async function createApp(environment: Environment, options: Options) {
479+
validatePackageManagerSupport(options.packageManager, options.chosenAddOns)
478480
const effectiveOptions = stripExamplesFromOptions(options)
479481

480482
environment.startRun()

packages/create/src/edge-create-app.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
intentCommand,
1313
packageManagerInstall,
1414
translateExecuteCommand,
15+
validatePackageManagerSupport,
1516
} from './package-manager.js'
1617

1718
import type { Environment, FileBundleHandler, Options } from './types.js'
@@ -591,6 +592,7 @@ Please read the README.md file for information on ${readmeDescription}${errorSta
591592
}
592593

593594
export async function createApp(environment: Environment, options: Options) {
595+
validatePackageManagerSupport(options.packageManager, options.chosenAddOns)
594596
const effectiveOptions = stripExamplesFromOptions(options)
595597

596598
environment.startRun()

packages/create/src/frameworks/react/add-ons/sentry/package.json

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"scripts": {
3+
"build": "<%= addOnEnabled.vercel ? 'vite build' : 'vite build && cp instrument.server.mjs .output/server' %>",
4+
"dev": "<%= addOnEnabled.vercel ? 'dotenv -e .env.local -- vite dev --port 3000' : 'dotenv -e .env.local -- sh -c \"NODE_OPTIONS=\'--import ./instrument.server.mjs\' vite dev --port 3000\"' %>",
5+
"start": "<%= addOnEnabled.vercel ? 'node .output/server/index.mjs' : 'node --import ./.output/server/instrument.server.mjs .output/server/index.mjs' %>"
6+
},
7+
"dependencies": {
8+
"@sentry/tanstackstart-react": "^10.67.0",
9+
"dotenv-cli": "^11.0.0"
10+
},
11+
"pnpm": {
12+
"onlyBuiltDependencies": [
13+
"@sentry/cli"
14+
]
15+
}
16+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
## Deploy to Render
2+
3+
This project includes a Render Blueprint:
4+
5+
1. Push this repo to GitHub, GitLab, or Bitbucket
6+
2. In Render, choose **New > Blueprint** and connect this repo
7+
3. Render reads `render.yaml` and creates the web service
8+
4. In the Render Dashboard, add any secrets from `.env.example` under **Environment**
9+
5. Deploy
10+
11+
The Nitro server handles SSR, server functions, API routes, and static assets.
12+
Render provides `PORT` automatically; Nitro reads it at runtime.
13+
14+
Need a database? Add one from the Render Dashboard, then connect it via
15+
environment variables. See https://render.com/docs/databases for options.

0 commit comments

Comments
 (0)