Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/render-vercel-deployments.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@tanstack/cli': minor
'@tanstack/create': minor
---

Add Gold partner deployment targets for Render and Vercel to React and Solid
scaffolds. Render generates package-manager-aware Blueprint commands, while
Vercel generates explicit framework detection and Nitro Build Output API
support.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Map deployment intent to one supported target and include it in scaffold command
- `cloudflare`
- `netlify`
- `railway`
- `render`
- `vercel`
- `nitro`

## Selection pattern
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ Targets `@tanstack/cli` v0.61.0.
- `cloudflare`
- `netlify`
- `railway`
- `render`
- `vercel`
- `nitro`

## Usage

```bash
npx @tanstack/cli create app --deployment cloudflare -y
npx @tanstack/cli create app --deployment netlify -y
npx @tanstack/cli create app --deployment vercel -y

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't render also be added here @tannerlinsley

```

Deployment providers are exclusive; choose one per scaffold.
4 changes: 3 additions & 1 deletion packages/cli/tests/partner-placement.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ describe('partner placement', () => {
addOn('netlify', { id: 'netlify', tier: 'gold' }),
addOn('cloudflare', { id: 'cloudflare', tier: 'gold' }),
addOn('railway', { id: 'railway', tier: 'gold' }),
addOn('render', { id: 'render', tier: 'gold' }),
addOn('vercel', { id: 'vercel', tier: 'gold' }),
],
'deployment',
'test',
Expand All @@ -71,6 +73,6 @@ describe('partner placement', () => {
.slice(1)
.map((item) => item.id)
.sort(),
).toEqual(['netlify', 'railway'])
).toEqual(['netlify', 'railway', 'render', 'vercel'])
})
})
22 changes: 14 additions & 8 deletions packages/create/scripts/generate-manifest.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,9 @@ function writeWorkerManifest(manifest) {

writeGeneratedModule(
join(workerOutputDir, 'catalog.ts'),
`export const manifestCatalog = ${JSON.stringify(
`import type { ManifestCatalog } from '../../manifest-types.js'

export const manifestCatalog: ManifestCatalog = ${JSON.stringify(
{
frameworks: manifest.map(stripFrameworkForCatalog),
},
Expand All @@ -491,16 +493,18 @@ function writeWorkerManifest(manifest) {

writeGeneratedModule(
join(workerOutputDir, 'frameworks', `${frameworkSegment}.ts`),
`${createTemplateRendererSource(
createTemplateRenderersForFrameworkBase(framework),
)}\n\nexport const framework = ${JSON.stringify(
`import type { WorkerFrameworkManifestModule } from '../../../manifest-types.js'

${createTemplateRendererSource(
createTemplateRenderersForFrameworkBase(framework),
)}\n\nexport const framework = ${JSON.stringify(
{
id: framework.id,
base: framework.base,
},
null,
2,
)}\n`,
)} satisfies WorkerFrameworkManifestModule['framework']\n`,
)

for (const addOn of framework.addOns) {
Expand All @@ -516,9 +520,11 @@ function writeWorkerManifest(manifest) {
'add-ons',
`${addOnSegment}.ts`,
),
`${createTemplateRendererSource(
createTemplateRenderersForAddOn(addOn),
)}\n\nexport const addOn = ${JSON.stringify(addOn, null, 2)}\n`,
`import type { AddOnCompiled } from '../../../../../types.js'

${createTemplateRendererSource(
createTemplateRenderersForAddOn(addOn),
)}\n\nexport const addOn = ${JSON.stringify(addOn, null, 2)} satisfies AddOnCompiled\n`,
)
}
}
Expand Down
2 changes: 2 additions & 0 deletions packages/create/src/create-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
intentCommand,
packageManagerInstall,
translateExecuteCommand,
validatePackageManagerSupport,
} from './package-manager.js'
import { createPackageJSON } from './package-json.js'
import { resolvePackageJSONLatest } from './npm-resolver.js'
Expand Down Expand Up @@ -475,6 +476,7 @@ Please read the README.md file for information on ${readmeDescription}${errorSta
}

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

environment.startRun()
Expand Down
2 changes: 2 additions & 0 deletions packages/create/src/edge-create-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
intentCommand,
packageManagerInstall,
translateExecuteCommand,
validatePackageManagerSupport,
} from './package-manager.js'

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

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

environment.startRun()
Expand Down
16 changes: 0 additions & 16 deletions packages/create/src/frameworks/react/add-ons/sentry/package.json

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"scripts": {
"build": "<%= addOnEnabled.vercel ? 'vite build' : 'vite build && cp instrument.server.mjs .output/server' %>",
"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\"' %>",
"start": "<%= addOnEnabled.vercel ? 'node .output/server/index.mjs' : 'node --import ./.output/server/instrument.server.mjs .output/server/index.mjs' %>"
},
"dependencies": {
"@sentry/tanstackstart-react": "^10.67.0",
"dotenv-cli": "^11.0.0"
},
"pnpm": {
"onlyBuiltDependencies": [
"@sentry/cli"
]
}
}
15 changes: 15 additions & 0 deletions packages/create/src/frameworks/react/hosts/render/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## Deploy to Render

This project includes a Render Blueprint:

1. Push this repo to GitHub, GitLab, or Bitbucket
2. In Render, choose **New > Blueprint** and connect this repo
3. Render reads `render.yaml` and creates the web service
4. In the Render Dashboard, add any secrets from `.env.example` under **Environment**
5. Deploy

The Nitro server handles SSR, server functions, API routes, and static assets.
Render provides `PORT` automatically; Nitro reads it at runtime.

Need a database? Add one from the Render Dashboard, then connect it via
environment variables. See https://render.com/docs/databases for options.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
services:
- type: web
runtime: node
name: tanstack-start-app
buildCommand: <%= packageManager %> install && <%= getPackageManagerRunScript('build') %>
Comment thread
tannerlinsley marked this conversation as resolved.
startCommand: <%= getPackageManagerRunScript('start') %>
envVars:
<% if (packageManager === 'bun') { -%>
- key: BUN_VERSION
value: '1.3.14'
<% } -%>
- key: NITRO_PRESET
value: render-com
- key: HOST
value: 0.0.0.0
21 changes: 21 additions & 0 deletions packages/create/src/frameworks/react/hosts/render/info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "Render",
"description": "Deploy to Render (full-stack cloud platform with GitHub integration).",
"link": "https://render.com/",
"phase": "add-on",
"modes": ["file-router"],
"type": "deployment",
"supportedPackageManagers": ["npm", "yarn", "pnpm", "bun"],
"category": "deploy",
"exclusive": ["deploy"],
"color": "#46E3B7",
"priority": 150,
"partner": { "id": "render", "tier": "gold" },
"integrations": [
{
"type": "vite-plugin",
"import": "import { nitro } from 'nitro/vite'",
"code": "nitro({ rollupConfig: { external: [/^@sentry\\//] } })"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"scripts": {
"start": "<%= addOnEnabled.sentry ? 'node --import ./.output/server/instrument.server.mjs .output/server/index.mjs' : 'node .output/server/index.mjs' %>"
},
"dependencies": {
"nitro": "3.0.260610-beta"
}
}
13 changes: 13 additions & 0 deletions packages/create/src/frameworks/react/hosts/vercel/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Deploy to Vercel

1. Push this repo to GitHub, GitLab, or Bitbucket
2. In Vercel, choose **Add New > Project** and import the repo
3. Keep the detected TanStack Start framework settings
4. Add production values from `.env.example` under **Settings > Environment Variables**
5. Deploy

Vercel runs the build script and deploys Nitro's output as Vercel Functions and
static assets. The included `vercel.json` makes framework detection explicit.

Variables prefixed with `VITE_` are included in the browser bundle. Keep secrets
unprefixed so they remain server-only.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<% if (!addOnEnabled.sentry) { ignoreFile(); return; } -%>
import '../instrument.server.mjs'
import { wrapFetchWithSentry } from '@sentry/tanstackstart-react'
import handler, { createServerEntry } from '@tanstack/react-start/server-entry'

export default createServerEntry(
wrapFetchWithSentry({
fetch(request: Request) {
return handler.fetch(request)
},
}),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"framework": "tanstack-start"
}
21 changes: 21 additions & 0 deletions packages/create/src/frameworks/react/hosts/vercel/info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "Vercel",
"description": "Deploy to Vercel (Functions, static assets, and Git previews).",
"link": "https://vercel.com/docs/frameworks/full-stack/tanstack-start",
"phase": "add-on",
"modes": ["file-router"],
"type": "deployment",
"supportedPackageManagers": ["npm", "yarn", "pnpm", "bun"],
"category": "deploy",
"exclusive": ["deploy"],
"color": "#000000",
"priority": 140,
"partner": { "id": "vercel", "tier": "gold" },
"integrations": [
{
"type": "vite-plugin",
"import": "import { nitro } from 'nitro/vite'",
"code": "nitro()"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"dependencies": {
"nitro": "3.0.260610-beta"
}
}
15 changes: 15 additions & 0 deletions packages/create/src/frameworks/solid/hosts/render/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## Deploy to Render

This project includes a Render Blueprint:

1. Push this repo to GitHub, GitLab, or Bitbucket
2. In Render, choose **New > Blueprint** and connect this repo
3. Render reads `render.yaml` and creates the web service
4. In the Render Dashboard, add any secrets from `.env.example` under **Environment**
5. Deploy

The Nitro server handles SSR, server functions, API routes, and static assets.
Render provides `PORT` automatically; Nitro reads it at runtime.

Need a database? Add one from the Render Dashboard, then connect it via
environment variables. See https://render.com/docs/databases for options.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
services:
- type: web
runtime: node
name: tanstack-start-app
buildCommand: <%= packageManager %> install && <%= getPackageManagerRunScript('build') %>
startCommand: <%= getPackageManagerRunScript('start') %>
envVars:
<% if (packageManager === 'bun') { -%>
- key: BUN_VERSION
value: '1.3.14'
<% } -%>
- key: NITRO_PRESET
value: render-com
- key: HOST
value: 0.0.0.0
21 changes: 21 additions & 0 deletions packages/create/src/frameworks/solid/hosts/render/info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "Render",
"description": "Deploy to Render (full-stack cloud platform with GitHub integration).",
"link": "https://render.com/",
"phase": "add-on",
"modes": ["file-router"],
"type": "deployment",
"supportedPackageManagers": ["npm", "yarn", "pnpm", "bun"],
"category": "deploy",
"exclusive": ["deploy"],
"color": "#46E3B7",
"priority": 150,
"partner": { "id": "render", "tier": "gold" },
"integrations": [
{
"type": "vite-plugin",
"import": "import { nitro } from 'nitro/vite'",
"code": "nitro()"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"scripts": {
"start": "node .output/server/index.mjs"
},
"dependencies": {
"nitro": "3.0.260610-beta"
}
}
13 changes: 13 additions & 0 deletions packages/create/src/frameworks/solid/hosts/vercel/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Deploy to Vercel

1. Push this repo to GitHub, GitLab, or Bitbucket
2. In Vercel, choose **Add New > Project** and import the repo
3. Keep the detected TanStack Start framework settings
4. Add production values from `.env.example` under **Settings > Environment Variables**
5. Deploy

Vercel runs the build script and deploys Nitro's output as Vercel Functions and
static assets. The included `vercel.json` makes framework detection explicit.

Variables prefixed with `VITE_` are included in the browser bundle. Keep secrets
unprefixed so they remain server-only.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"framework": "tanstack-start"
}
21 changes: 21 additions & 0 deletions packages/create/src/frameworks/solid/hosts/vercel/info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "Vercel",
"description": "Deploy to Vercel (Functions, static assets, and Git previews).",
"link": "https://vercel.com/docs/frameworks/full-stack/tanstack-start",
"phase": "add-on",
"modes": ["file-router"],
"type": "deployment",
"supportedPackageManagers": ["npm", "yarn", "pnpm", "bun"],
"category": "deploy",
"exclusive": ["deploy"],
"color": "#000000",
"priority": 140,
"partner": { "id": "vercel", "tier": "gold" },
"integrations": [
{
"type": "vite-plugin",
"import": "import { nitro } from 'nitro/vite'",
"code": "nitro()"
}
]
}
Loading
Loading