Skip to main content

Deployment Requirements

Clue2App automatically detects and builds your applications. This guide covers the requirements for successful deployments.

Supported Languages

Clue2App automatically detects and builds applications written in:

LanguageFrameworks
PythonFastAPI, Flask, Django, etc.
Node.jsExpress, Next.js, React, Vue, etc.
JavaSpring Boot, Quarkus, etc.
GoStandard library, Gin, Echo, etc.
.NET CoreASP.NET, Blazor, etc.

Project Structure

Detection Files

Clue2App needs specific files at the repository root to detect your application:

LanguageRequired File
Pythonrequirements.txt, pyproject.toml, or setup.py
Node.jspackage.json
Javapom.xml or build.gradle
Gogo.mod
.NET*.csproj or *.fsproj

Monorepo / Subdirectory Projects

If your code is in a subdirectory (e.g., backend/), create wrapper files at the root:

Python Example

my-repo/
├── requirements.txt # Points to backend
├── Procfile # Runs from backend
├── backend/
│ ├── requirements.txt # Actual dependencies
│ └── app/
│ └── main.py
└── frontend/
└── ...

Root requirements.txt:

-r backend/requirements.txt

Root Procfile:

web: cd backend && uvicorn app.main:app --host 0.0.0.0 --port 8000

Node.js Example

my-repo/
├── package.json # Wrapper
├── Procfile # Runs from backend
├── backend/
│ ├── package.json
│ └── src/
└── frontend/
└── ...

Root package.json:

{
"name": "app-wrapper",
"scripts": {
"start": "cd backend && npm start"
}
}

Procfile

A Procfile specifies how to run your application. It's optional for simple projects but recommended for:

  • Monorepo projects
  • Custom startup commands
  • Specific runtime configurations

Format:

web: <command to start your app>

Examples:

# Python FastAPI
web: uvicorn app.main:app --host 0.0.0.0 --port 8000

# Python Flask
web: gunicorn app:app --bind 0.0.0.0:8000

# Node.js
web: node server.js

# Java
web: java -jar target/app.jar

Static Sites & SPAs (React, Vue, Vite)

Frontend apps built with Vite, Create React App, Vue CLI, etc. produce static files in a dist/ or build/ folder. These need a simple HTTP server at runtime.

Important: node_modules is not available at runtime

The Paketo buildpack prunes node_modules after the build step. Packages like serve, http-server, or anything in node_modules/.bin/ will not be available when the container starts. npx is also not on the PATH.

Solution: Create a server.js at the repo root using only Node.js built-in modules:

const { createServer } = require("http");
const { readFileSync, existsSync } = require("fs");
const { join, extname } = require("path");

const PORT = process.env.PORT || 8080;
const DIST = join(__dirname, "dist");

const MIME = {
".html": "text/html",
".js": "application/javascript",
".css": "text/css",
".json": "application/json",
".png": "image/png",
".jpg": "image/jpeg",
".svg": "image/svg+xml",
".ico": "image/x-icon",
".woff": "font/woff",
".woff2": "font/woff2",
};

createServer((req, res) => {
let filePath = join(DIST, req.url.split("?")[0]);

// SPA fallback — serve index.html for non-file routes
if (!existsSync(filePath) || filePath === DIST + "/") {
filePath = join(DIST, "index.html");
}

try {
const data = readFileSync(filePath);
const ext = extname(filePath);
res.writeHead(200, { "Content-Type": MIME[ext] || "application/octet-stream" });
res.end(data);
} catch {
res.writeHead(404);
res.end("Not Found");
}
}).listen(PORT, () => console.log(`Serving on port ${PORT}`));

The buildpack auto-detects server.js (and server.cjs, server.mjs) — no Procfile needed.

ESM projects

If your package.json has "type": "module", Node.js treats .js files as ESM and require() won't work. Name the file server.cjs instead to force CommonJS mode.

Build script

Make sure your package.json has a build script (e.g., "build": "vite build") so the buildpack generates the dist/ folder during the build step.

Port Configuration

Your application must listen on the PORT environment variable (defaults to 8080):

Python:

import os
port = int(os.environ.get("PORT", 8080))

Node.js:

const port = process.env.PORT || 8080;

Java:

int port = Integer.parseInt(System.getenv().getOrDefault("PORT", "8080"));

Environment Variables

Set environment variables via:

  • Console: App Settings → Environment Variables
  • CLI: c2a env set <app> KEY=value

Common variables:

VariablePurpose
DATABASE_URLDatabase connection string
SECRET_KEYApplication secret
NODE_ENVNode.js environment
LOG_LEVELLogging verbosity

Troubleshooting

Build fails with "detection error"

Cause: Required files not found at repository root.

Solution:

  1. Ensure detection files (requirements.txt, package.json, etc.) are at the repo root
  2. For subdirectory projects, create wrapper files as shown above

Build succeeds but app crashes

Cause: Missing configuration or incorrect startup command.

Solution:

  1. Check app logs: c2a logs show <app-name>
  2. Verify Procfile command is correct
  3. Ensure all required environment variables are set

Build succeeds but app crashes with "command not found"

Cause: The Procfile or start script references npx, serve, or another binary from node_modules. The Paketo buildpack prunes node_modules after building, so these are not available at runtime.

Solution:

  1. Don't use npx or node_modules/.bin/* in your Procfile
  2. For static sites, create a server.js using only Node.js built-in modules (see Static Sites & SPAs above)
  3. If you need a package at runtime, ensure your app entry point (e.g., server.js) uses require() — the buildpack keeps modules that are imported by the detected entry point

App not accessible

Cause: App not listening on correct port.

Solution:

  1. Ensure your app reads the PORT environment variable
  2. Default to port 8080 if PORT is not set
  3. Bind to 0.0.0.0, not localhost

Best Practices

  1. Keep dependencies minimal - Faster builds, smaller images
  2. Use a Procfile - Explicit is better than implicit
  3. Set PORT dynamically - Don't hardcode ports
  4. Use environment variables - Never commit secrets
  5. Test locally first - Ensure your app runs before deploying