Skip to main content

The strongly.manifest.yaml File

The manifest file provides declarative configuration for building and deploying your application. It must be placed in your project root alongside the Dockerfile.

Basic Structure​

# strongly.manifest.yaml (place in project root)
version: "1.0"
type: nodejs # react, nodejs, flask, rshiny, mcp_server, static, fullstack, custom
name: my-app
description: Brief description of your application
author: Your Name or Organization
homepage: https://github.com/yourorg/my-app
license: MIT
icon: "https://example.com/icon.png"
tags:
- api
- backend

ports:
- port: 3000
name: http
expose: true
target_port: 3000 # Optional: if different from port

env:
- name: NODE_ENV
value: "production"
required: true

- name: DATABASE_URL
value: "" # User must provide
required: true
secret: true # Stored encrypted
description: PostgreSQL connection string
inject_as: env # How to inject: 'env' (default), 'file', 'config'

runtime:
command: ["node", "server.js"]
working_dir: /app
health_check_path: /health
readiness_check_path: /ready # Defaults to health_check_path if not set
startup_timeout: 60 # Startup timeout in seconds

health_check:
path: /health
initial_delay: 15
period: 30

Application Types​

The type field determines default configuration and runtime behavior:

TypeDefault PortUse CaseSpecial Features
react3000React/Vue SPA with client-side routingStatic build serving, SPA fallback
nodejs3000Node.js APIs, Express, NestJSStandard Node.js runtime
flask5000Python Flask/FastAPI applicationsPython WSGI/ASGI support
rshiny3838R Shiny interactive dashboardsR Shiny server runtime
static80Static HTML/CSS/JS sitesNginx static file serving
fullstack3000, 8000Monorepo with frontend + backendMultiple port exposure
mcp_server8080MCP protocol tool serversMCP-specific configurations
custom8080Any other application typeNo special defaults

Configuration Sections​

Ports​

Define which ports your application listens on:

ports:
- port: 3000
name: http
expose: true # Reachable from outside the app
target_port: 3000 # Optional: target port if different from port
- port: 8080
name: metrics
expose: false # Internal only

Fields:

  • port: Port number
  • name: Friendly name for the port (default: "http")
  • expose: Whether to expose externally (default: true)
  • target_port: Target port if different from port (optional)
The port your app listens on

Your app listens on the port you declare (the first one with expose: true, or the first port), and the platform routes to it, so the app and its Dockerfile run on their own port unchanged. The platform also sets the PORT environment variable to that port. App containers run as a non-root user and may still listen on a port below 1024 (for example 80).

Environment Variables​

Define runtime configuration with proper metadata:

env:
# Regular environment variable
- name: API_URL
value: "https://api.example.com"
required: false
description: Backend API endpoint
inject_as: env # How to inject: 'env' (default), 'file', 'config'

# Secret (passwords, API keys, tokens)
- name: API_KEY
value: "" # Must be provided by user
required: true
secret: true # Stored encrypted
description: Third-party API key

# Build-time variable
- name: REACT_APP_VERSION
value: "1.0.0"
buildtime: true # Passed as Docker build arg
description: App version

Fields:

  • name: Variable name (uppercase with underscores)
  • value: Default value (can be empty for required vars)
  • required: Whether variable must have a value (default: false)
  • secret: Store the value encrypted, and keep it out of the built image and client-side config (default: false)
  • buildtime: Pass to Docker build as ARG (default: false)
  • description: User-friendly description
  • inject_as: How to inject the variable - env (default), file, or config
Secrets Management

Variables marked as secret: true are stored encrypted at rest. Use this for passwords, API keys, and tokens.

React/Static App Configuration​

For React and static applications, configure nginx serving:

type: react
static:
root: /app/build
index: index.html
spa: true # Fallback to index.html for client-side routing
config_file: /app/build/config.js
config_placeholder: __APP_CONFIG__

build:
args:
NODE_ENV: production
output_dir: /app/build

Static Fields:

  • root: Directory containing built static files
  • index: Index file name (default: index.html)
  • spa: Enable SPA routing fallback (default: true for react)
  • config_file: Runtime config injection file path
  • config_placeholder: Placeholder to replace with config

Health Checks​

Your app must expose a health endpoint, which the platform calls to tell whether the app is running and ready for requests:

health_check:
path: /health
port: 3000
initial_delay: 10 # Seconds before first check
period: 30 # Check every 30 seconds
timeout: 3
failure_threshold: 3

Implementation Example (Express.js):

app.get('/health', (req, res) => {
res.status(200).json({ status: 'ok' });
});

Implementation Example (Flask):

@app.route('/health')
def health():
return {'status': 'ok'}, 200
Required Endpoint

Health checks are mandatory. If your app doesn't respond to health checks, the platform keeps restarting it.

Runtime Configuration​

Customize the container runtime:

runtime:
command: ["node", "dist/server.js"]
working_dir: /app
health_check_path: /health
readiness_check_path: /ready # Defaults to health_check_path
startup_timeout: 60 # Startup timeout in seconds (default: 60)
user: appuser # User to run as (if not set in Dockerfile)

Fields:

  • command: Override container CMD (string or array format)
  • working_dir: Working directory (default: /app)
  • health_check_path: Health check endpoint path (default: /health)
  • readiness_check_path: Readiness check path (defaults to health_check_path)
  • startup_timeout: Startup timeout in seconds (default: 60)
  • user: User to run as (optional)

Resource Requirements​

An app's size is chosen when you deploy it, not in the manifest: pick an environment, or Custom Configuration and type the CPU and memory (and optionally disk and GPU). The app runs at exactly that size. A resources block in the manifest does not set the size.

Proxy Configuration​

Configure how requests reach your app through the platform's proxy:

proxy:
websocket: true # Enable WebSocket support
timeout: 30 # Request timeout in seconds (default: 30)
preserve_host: false # Preserve original host header
rewrite_paths: # Path rewriting rules
"/api": "/api/v1"
headers: # Additional headers to add
X-App-Version: "1.0.0"

Fields:

  • websocket: Enable WebSocket proxying (default: false)
  • timeout: Proxy timeout in seconds (default: 30)
  • preserve_host: Preserve original host header (default: false)
  • rewrite_paths: Path rewriting rules (optional)
  • headers: Additional headers to add (optional)

MCP Configuration​

For MCP server applications (type: mcp_server):

mcp:
protocol_version: "1.0"
transport: http # 'http', 'stdio', 'sse'
capabilities:
- tools
- prompts
- resources
authentication_required: true
tools:
- name: example_tool
description: An example tool
parameters:
type: object
properties:
input:
type: string
required: [input]
prompts:
- name: analyze_data
description: Analyzes data
arguments:
- name: data_source
required: true
resources:
- uri: "mcp://data/*"
name: "Data Resource"
description: "Access to data resources"

Complete Examples​

Node.js API​

version: "1.0"
type: nodejs
name: user-api
description: REST API for user management
author: Acme Corp
tags: [nodejs, api, backend]

ports:
- port: 3000
name: http
expose: true

env:
- name: NODE_ENV
value: "production"
required: true

- name: DATABASE_URL
value: ""
required: true
secret: true
description: PostgreSQL connection string

- name: JWT_SECRET
value: ""
required: true
secret: true
description: Secret for JWT signing

runtime:
command: ["node", "dist/server.js"]
working_dir: /app
health_check_path: /health

health_check:
path: /health
initial_delay: 15
period: 30

proxy:
websocket: true
timeout: 30

React SPA​

version: "1.0"
type: react
name: admin-dashboard
description: Admin dashboard SPA
author: Acme Corp
tags: [react, frontend]

ports:
- port: 3000
name: http
expose: true

static:
root: /app/build
index: index.html
spa: true
config_file: /app/build/config.js
config_placeholder: __APP_CONFIG__

build:
args:
NODE_ENV: production
REACT_APP_VERSION: "1.0.0"
output_dir: /app/build

env:
- name: REACT_APP_API_URL
value: "https://api.acme.com"
buildtime: true
description: Backend API endpoint

health_check:
path: /
initial_delay: 5
period: 30

Flask API​

version: "1.0"
type: flask
name: ml-api
description: Machine learning inference API
author: Data Team
tags: [python, flask, ml]

ports:
- port: 5000
name: http
expose: true

env:
- name: FLASK_ENV
value: "production"
required: true

- name: MODEL_PATH
value: "/app/models/model.pkl"
description: Path to ML model file

- name: REDIS_URL
value: ""
required: true
secret: true
description: Redis cache connection string

runtime:
command: ["sh", "-c", "gunicorn -w 4 -b 0.0.0.0:${PORT:-5000} app:app"]
working_dir: /app
health_check_path: /health

health_check:
path: /health
port: 5000
initial_delay: 20
period: 30
timeout: 5

R Shiny Dashboard​

version: "1.0"
type: rshiny
name: analytics-dashboard
description: Interactive R Shiny analytics dashboard
author: Data Team
tags: [rshiny, analytics, dashboard]

ports:
- port: 3838
name: http
expose: true

env:
- name: SHINY_LOG_LEVEL
value: "INFO"
description: Shiny log level

runtime:
working_dir: /app
health_check_path: /health

health_check:
path: /
initial_delay: 15
period: 30

MCP Server​

version: "1.0"
type: mcp_server
name: my-mcp-server
description: MCP server providing custom tools
author: Your Organization
homepage: https://github.com/yourorg/mcp-server
license: MIT
tags: [mcp, tools]

ports:
- port: 8080
name: http
expose: true

env:
- name: LOG_LEVEL
value: "info"
description: Logging level

runtime:
command: ["python", "server.py"]
working_dir: /app
health_check_path: /health
startup_timeout: 60

health_check:
path: /health
initial_delay: 10
period: 30

mcp:
protocol_version: "1.0"
transport: http
capabilities: [tools, prompts, resources]
authentication_required: true
tools:
- name: example_tool
description: An example tool that processes data
parameters:
type: object
properties:
input:
type: string
description: Input data to process
required: [input]

Validation​

The platform validates your manifest during deployment. Common errors:

  • Missing required field: type is the only required field (version defaults to "1.0")
  • Invalid type: Must be one of the 8 supported types (react, nodejs, static, fullstack, flask, rshiny, mcp_server, custom)
  • Wrong field types: Fields must match their expected types (e.g., port must be an integer, env must be a list)

Next Steps​