Skip to Content

Deploy Next.js

Deploy a Next.js application to Espace-Tech Cloud.

Prerequisites

  • Next.js 13+ (App Router or Pages Router)
  • Node.js 18+
  • Espace-Tech CLI installed

1. Initialize

cd my-nextjs-app espacetech init

Auto-detected espacetech.json:

{ "name": "my-nextjs-app", "framework": "nextjs", "build_command": "npm run build", "start_command": "npm start", "port": 3000 }

2. Configure for Standalone Output

For optimal performance, enable standalone output in next.config.ts:

next.config.ts
import type { NextConfig } from "next"; const nextConfig: NextConfig = { output: "standalone", }; export default nextConfig;

This creates a minimal production build without unnecessary node_modules.

3. Deploy

espacetech deploy

Your app will be live at my-nextjs-app.app.espace-tech.com.

Environment Variables

Set environment variables before or after deploy:

espacetech env set DATABASE_URL=postgres://... NEXT_PUBLIC_API_URL=https://api.example.com

Variables prefixed with NEXT_PUBLIC_ are embedded at build time. Set them before deploying.

Using the SDK

Install the Espace-Tech SDK for storage, auth, and database access:

npm install github:bz-reda/Espace-Tech-Cloud-SDK
lib/espace.ts
import { EspaceTech } from "@espace-tech/sdk"; export const espace = new EspaceTech({ apiToken: process.env.ESPACE_TECH_TOKEN!, });

Storage (Server Components / API Routes)

app/api/upload/route.ts
import { espace } from "@/lib/espace"; export async function POST(req: Request) { const formData = await req.formData(); const file = formData.get("file") as File; await espace.storage.upload("bucket-id", `uploads/${file.name}`, file); return Response.json({ success: true }); }

Auth (Middleware)

app/api/protected/route.ts
import { espace } from "@/lib/espace"; export async function GET(req: Request) { const token = req.headers.get("authorization")?.replace("Bearer ", ""); if (!token) return Response.json({ error: "Unauthorized" }, { status: 401 }); const user = await espace.auth.verifyToken("auth-app-id", token); if (!user.valid) return Response.json({ error: "Invalid token" }, { status: 401 }); return Response.json({ user }); }

Database

import { espace } from "@/lib/espace"; import { Pool } from "pg"; const conn = await espace.database.getConnection("db-id"); const pool = new Pool({ connectionString: conn.url });

Serving Images with Presigned URLs

next.config.ts
const nextConfig: NextConfig = { output: "standalone", images: { remotePatterns: [ { protocol: "https", hostname: "s3.espace-tech.com" }, ], }, };
app/api/images/route.ts
import { espace } from "@/lib/espace"; export async function GET() { const result = await espace.storage.listObjects("bucket-id", { prefix: "images/" }); const images = await Promise.all( result.objects .filter((obj) => !obj.is_folder) .map(async (obj) => ({ key: obj.key, url: (await espace.storage.getDownloadUrl("bucket-id", obj.key)).url, })) ); return Response.json({ images }); // Use directly: <Image src={image.url} /> }

Custom Domain

espacetech domains add my-app.com

Add an A record pointing my-app.com to 65.109.68.181. SSL is automatic.