You have a Next.js project running fine locally, and you want to put it online for others to use.
Vercel? Unreliable access from China. Buy your own server? Then you're stuck with Nginx, PM2, SSL and the whole ops rigmarole.
There's actually another path — Tencent Cloud CloudBase's HTTP cloud functions. No server management, no Docker; push the code and it runs. SSR and API Routes are supported, and binding a domain gives you a production environment.
This post walks you from create-next-app to a live, accessible site. The whole thing takes about 15 minutes.
Before you start, prepare these
- Node.js 18+ (20 recommended)
- A Tencent Cloud account, with CloudBase cloud development enabled
- Your CloudBase environment ID (visible on the console home page)
If you haven't installed the CloudBase CLI, you'll need it later for CI/CD:
npm install -g @cloudbase/cli
One more thing — if you use AI editors like Cursor, VS Code or Claude Code, install CloudBase MCP. The deploy step can then be done right in the editor, no console switching.
Step 1: create the Next.js project
Skip this if you already have a project.
npx create-next-app@latest my-cloudbase-app
Options are up to you, but make sure it uses the App Router (the default).
Enter the project directory and run it to confirm everything works:
cd my-cloudbase-app
npm run dev
Open http://localhost:3000 in a browser — seeing the Next.js welcome page is enough.
Step 2: edit next.config.js
This step is key. CloudBase HTTP cloud functions need Next.js to output standalone-mode artifacts, so it can run independently of node_modules.
Open next.config.mjs (or next.config.js, depending on your project) and change it to:
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone',
images: {
unoptimized: true,
},
compress: true,
poweredByHeader: false,
}
export default nextConfig
Why each:
output: 'standalone'— generates an independently runnable build, not dependent on the fullnode_modules. This is the prerequisite for deploying to a cloud function.images.unoptimized: true— the cloud function environment has no Sharp for image optimization; leaving it on causes build errors or runtime problems.compress: true— enables gzip, reducing transfer size.poweredByHeader: false— removes theX-Powered-Byheader; no need to expose it.
Step 3: write the scf_bootstrap startup file
An HTTP cloud function needs a file called scf_bootstrap (no extension), placed in the project root. It tells the cloud function how to start your app.
Create it in the project root:
touch scf_bootstrap
chmod +x scf_bootstrap
Contents:
#!/bin/bash
# CloudBase HTTP cloud functions listen on port 9000
export PORT=9000
export NODE_ENV=production
# start in standalone mode
node .next/standalone/server.js
A few notes:
- The port must be 9000 — a hard requirement of CloudBase HTTP cloud functions; change it and it won't run.
- The startup command is
node .next/standalone/server.js, because withoutput: 'standalone', the build artifacts live in.next/standalone/. This minimizes package size and cold-start time. The official docs example usesnpm start(i.e.next start), which also runs but needs the fullnode_modules, making it much larger. - Windows users, take special note: this file must use LF line endings (Unix format), not CRLF. In VS Code, switch it at the bottom-right. Wrong line endings cause an
exec format errorafter deploy — many people get stuck here. Addscf_bootstrap binaryto.gitattributesto prevent Git from auto-converting line endings.
Step 4: build the project
npm run build
After building, check that .next/standalone/ exists and contains server.js.
You also need to copy the static assets over (standalone mode doesn't include them automatically):
cp -r public .next/standalone/public
cp -r .next/static .next/standalone/.next/static
Your project structure now looks roughly like:
my-cloudbase-app/
├── .next/
│ └── standalone/
│ ├── server.js ← entry
│ ├── public/ ← just copied
│ ├── .next/static/ ← just copied
│ └── ...
├── scf_bootstrap ← startup script
├── next.config.mjs
├── package.json
└── ...
Step 5: deploy to CloudBase
Two ways — pick whichever suits you.
Method one: CloudBase MCP (recommended, for AI editor users)
If your editor has CloudBase MCP installed, you can deploy right in the editor. MCP creates the HTTP cloud function, uploads the code and configures the access route, all in one go.
In the AI editor, have the assistant do something like:
"Create an HTTP cloud function called nextjs-app, runtime Node.js 18.15, and deploy the current project to it"
What MCP does behind the scenes:
- Calls
createFunctionto create the HTTP cloud function (type: "HTTP",runtime: "Nodejs18.15") - Uploads the project code (
functionRootPathpoints to the parent of the function directory) - Calls
createFunctionHTTPAccessto configure the HTTP access route
After a successful deploy, you get a default access URL:
https://{your-env-id}.{region}.app.tcloudbase.com/nextjs-app
Method two: CloudBase CLI
# login (first time only)
tcb login
# create the HTTP cloud function and deploy
tcb fn deploy nextjs-app --path . --override
# create the HTTP access route
tcb service create -f nextjs-app -p /nextjs-app
After deploy, you can access it via the default domain too.
Verify
Open that URL — see your Next.js page? If so, congrats, the core part is done.
If you hit a 502 or a blank page, check:
- Is the port in
scf_bootstrapset to 9000 - Are
scf_bootstrap's line endings LF - Is the
.next/standalone/directory complete (hasserver.js,public/,.next/static/)
Step 6: bind a custom domain
The default app.tcloudbase.com domain works, but production needs your own domain.
Prerequisites:
- The domain has completed ICP filing (mandatory in mainland China)
- You have an SSL certificate for the domain (Tencent Cloud can issue one for free)
Flow:
- Go to the CloudBase console → HTTP access service
- Click "Add custom domain"
- Enter the domain, select the SSL certificate
- Create a "domain-associated resource", select your HTTP cloud function
nextjs-app, set the trigger path to/ - In your domain's DNS management backend, add a CNAME record pointing to the CNAME value the console gives you
Wait for DNS to take effect (usually minutes), then visit your domain to see the app.
With the CLI, you can also do:
# add a custom domain (need the cert ID first)
tcb domains add your-domain.com --certid <cert-id> -e <env-id>
# configure the route
tcb routes set your-domain.com / --target nextjs-app --type function
Step 7: environment variables
Next.js has two kinds of environment variables:
NEXT_PUBLIC_*— injected at build time, accessible on the client- others — server-only (like database connection strings, API keys)
Set server env vars in the CloudBase console:
- Enter your cloud function → Function config → Environment variables
- Add key-value pairs, e.g.
DATABASE_URL=mysql://...
With MCP too:
"Add an environment variable DATABASE_URL to the nextjs-app cloud function, value mysql://..."
With CLI:
tcb fn config update nextjs-app --envVariables '{"DATABASE_URL":"mysql://..."}'
One pitfall: updating env vars via MCP or API overwrites old values. If the function already has other variables, query first and merge, or you'll lose them.
As for NEXT_PUBLIC_* variables — they're decided at build time, not set in cloud function env vars. Export them before the build command, or write them in .env.production.
Step 8: CI/CD automation
Manual deploy after every change is tiring. Automate with GitHub Actions.
Create .github/workflows/deploy.yml in the project root:
name: Deploy to CloudBase
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Copy static assets
run: |
cp -r public .next/standalone/public
cp -r .next/static .next/standalone/.next/static
- name: Install CloudBase CLI
run: npm install -g @cloudbase/cli
- name: Login to CloudBase
run: tcb login --apiKeyId ${{ secrets.TCB_SECRET_ID }} --apiKey ${{ secrets.TCB_SECRET_KEY }}
- name: Deploy
run: |
tcb fn deploy nextjs-app --path . --override -e ${{ secrets.TCB_ENV_ID }}
Add three variables in your GitHub repo's Settings → Secrets:
TCB_SECRET_ID— Tencent Cloud API SecretIdTCB_SECRET_KEY— Tencent Cloud API SecretKeyTCB_ENV_ID— CloudBase environment ID
Now every push to main auto-builds and deploys.
Pitfall notes
Summing up the common pitfalls:
scf_bootstrap line endings
Files created on Windows default to CRLF, causing exec format error after deploy. Fix: switch to LF in VS Code's bottom-right, or run dos2unix scf_bootstrap.
Runtime can't be changed A cloud function's Node.js runtime (e.g. 18.15) can't be changed after creation. To upgrade to 20.19 you must delete and recreate. Decide the version upfront.
Image optimization must be off
Without images.unoptimized: true, Next.js tries to use Sharp for image optimization — a binary dependency the cloud function environment lacks, causing an immediate error.
Env var overwriting As above, updating env vars via API does a full overwrite. If your function has other variables, query them first and merge.
Cold start The first request, or when the function hasn't been called for a while, incurs cold-start latency. Next.js projects are large, so cold start can be a few seconds. If that's sensitive for your scenario, consider a scheduled trigger to keep it warm.
The dev experience with CloudBase MCP/Skills
A final note on AI-assisted development.
If you use an MCP-capable AI editor (Cursor, Claude Code, VS Code + Cline, etc.), install CloudBase MCP to connect your CloudBase environment.
Once installed, the AI assistant can directly:
- Create and deploy cloud functions
- View function logs and config
- Manage environment variables
- Configure domains and routes
Combined with CloudBase Skills (install: npx skills add tencentcloudbase/cloudbase-skills), AI also understands CloudBase best practices — like when to use an HTTP cloud function vs Cloud Run — without you digging through docs.
Simply put: MCP handles "what it can do" (permissions and connections), Skills handle "how it should be done" (norms and intuition). Together, the dev experience is noticeably smoother.
Summary
Recap the flow:
create-next-appto create the projectnext.config.jswithoutput: 'standalone'- Write
scf_bootstrap, listen on port 9000 npm run build+ copy static assets- Deploy to a CloudBase HTTP cloud function via MCP or CLI
- Bind a custom domain
- Configure env vars
- GitHub Actions for CI/CD
HTTP cloud functions beat Cloud Run (containers) on startup speed, config lightness and cost. For most Next.js projects, this path is enough.
If you got it running, or got stuck somewhere, drop a comment.
Reference links:

