Next.js 15 application with i18n (ru/kk/en), deployed as a Node.js standalone bundle to Plesk via GitHub Actions + FTPS.
bun devCreate .env.local in the project root with the values below (see Environment Variables).
output: "standalone" is set in next.config.ts. bun run build produces a self-contained standalone bundle:
.next/standalone/ ← server.js + minimal node_modules (default entry point)
.next/static/ ← client JS/CSS (copied in by CI)
public/ ← static assets (copied in by CI)
Start the raw standalone bundle locally:
node .next/standalone/server.jsWorkflow: .github/workflows/deploy-plesk.yml
Trigger: push to dev
Flow:
- Install dependencies (
bun install --frozen-lockfile) - Lint
- Build —
NEXT_PUBLIC_*secrets are injected here and baked into the client bundle - Copy
.next/static/andpublic/into.next/standalone/ - Copy
server.js→app.js(Plesk startup file) - Upload
.next/standalone/as a versioned artifact (14-day retention) - Deploy
.next/standalone/via FTPS to/httpdocs/on Plesk
- In Plesk panel → Node.js, create an application:
- Application root:
/httpdocs - Startup file:
app.js - Node.js version: 20+
- Application root:
- Set runtime environment variables in Plesk:
NODE_ENV=productionPORT=3000TELEGRAM_BOT_TOKENTELEGRAM_CHAT_ID
- After first deploy, restart the Node.js app manually. Subsequent deploys restart automatically via Passenger.
Set as GitHub Actions secrets (or Variables — these values are public):
| Variable | Description |
|---|---|
NEXT_PUBLIC_PHONE_MAIN |
Phone number in E.164 format, e.g. +77755020555 |
NEXT_PUBLIC_PHONE_DISPLAY |
Formatted display phone, e.g. +7 (775) 502-05-55 |
NEXT_PUBLIC_WHATSAPP_BASE |
Full WhatsApp link with pre-filled message |
NEXT_PUBLIC_INSTAGRAM_URL |
Instagram profile URL |
NEXT_PUBLIC_EMAIL |
Contact email address |
NEXT_PUBLIC_MAP_IFRAME_SRC |
Yandex Maps embed src attribute |
| Variable | Description |
|---|---|
TELEGRAM_BOT_TOKEN |
Bot token from @BotFather |
TELEGRAM_CHAT_ID |
Target chat/group ID (obtain via @userinfobot) |
| Secret | Description |
|---|---|
FTP_SERVER |
Plesk hostname, e.g. pkz33.hoster.kz |
FTP_PORT |
FTPS port (typically 21 for explicit mode) |
FTP_USERNAME |
Plesk FTP account username |
FTP_PASSWORD |
Plesk FTP account password |