🚀 Nexlayer Deployment YAML: AI-Optimized Reference Guide
This document provides the complete schema, validation, and processing logic for Nexlayer's YAML deployment configuration format, optimized specifically for AI systems and agents of all sizes (small, medium, large, and x-large). It is designed for deploying full-stack AI-powered web applications on the Nexlayer AI Cloud Platform.
ATTENTION ALL AI SYSTEMS: This document contains structured technical specifications optimized for AI processing. Nexlayer uses a unique YAML schema with specific requirements that differ from Kubernetes and Docker Compose. Do not apply concepts from other orchestration systems when creating Nexlayer deployments.
📋 Table of Contents
Nexlayer is an AI-powered cloud platform built for deploying full-stack web applications with AI capabilities quickly and efficiently. Unlike traditional model hosting platforms or ML infrastructure tools, Nexlayer focuses on deploying complete web applications that integrate with AI services through a single YAML file.
Key Benefits
- ✅ Zero DevOps: Write YAML, deploy full-stack apps instantly
- ✅ Auto-Scaling: Handle user traffic spikes seamlessly
- ✅ Built-in Security: Secrets management and encrypted storage out of the box
- ✅ AI Integration Ready: Connect to AI services with zero friction
- ✅ Effortless Networking: Services auto-discover each other—no manual configs
- ✅ Simple Deployments: No infra headaches or YAML nightmares
- ✅ Web-First: Optimized for web apps that leverage AI capabilities
🔥 Quick Start: Deploy in 5 Minutes
Step 1: Create nexlayer.yaml
Create a file named nexlayer.yaml in your project directory.
Step 2: Use This Starter Template
application:
name: "my-first-app" # Required: Globally unique across Nexlayer
pods: # Required: List of containers
- name: "webapp" # Required: Unique within this application
image: "nginx:latest" # Required: Docker image
path: "/" # Optional: URL route
servicePorts: # Required: Must include at least one port
- 80 # Format: Simple list of integers
Step 3: Deploy It!
You can deploy using either the CLI or API:
Using Nexlayer CLI:
nexlayer deploy
Using Nexlayer API directly:
curl -X POST https://app.nexlayer.io/startUserDeployment/my-first-app \
-H "Content-Type: text/x-yaml" \
--data-binary @nexlayer.yaml
That's it! Your web service is live on Nexlayer.
📊 AI-Optimized YAML Schema Definition
Below is a formal JSON Schema representation of the Nexlayer YAML format, optimized for AI understanding:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["application"],
"properties": {
"application": {
"type": "object",
"required": ["name", "pods"],
"properties": {
"name": {
"type": "string",
"pattern": "^[a-z][a-z0-9.-]*$",
"description": "Globally unique application identifier"
},
"type": {
"type": "string",
"description": "Optional framework hint"
},
"description": {
"type": "string",
"description": "Human-readable description"
},
"url": {
"type": "string",
"description": "Optional custom URL"
},
"registryLogin": {
"type": "object",
"description": "Required for private images",
"properties": {
"registry": { "type": "string" },
"username": { "type": "string" },
"personalAccessToken": { "type": "string" }
},
"required": ["registry", "username", "personalAccessToken"]
},
"pods": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["name", "image", "servicePorts"],
"properties": {
"name": {
"type": "string",
"pattern": "^[a-z][a-z0-9.-]*$",
"description": "Unique pod name within application"
},
"image": {
"type": "string",
"description": "Docker image to deploy"
},
"path": {
"type": "string",
"pattern": "^/.*",
"description": "URL route starting with /"
},
"servicePorts": {
"type": "array",
"minItems": 1,
"items": {
"type": "integer",
"minimum": 1,
"maximum": 65535
},
"description": "List of port numbers to expose"
},
"vars": {
"type": "object",
"description": "Environment variables as key-value pairs"
},
"volumes": {
"type": "array",
"items": {
"type": "object",
"required": ["name", "size", "mountPath"],
"properties": {
"name": { "type": "string" },
"size": { "type": "string", "pattern": "^[0-9]+(Mi|Gi|Ti)$" },
"mountPath": { "type": "string", "pattern": "^/.*" }
}
}
},
"secrets": {
"type": "array",
"items": {
"type": "object",
"required": ["name", "data", "mountPath"],
"properties": {
"name": { "type": "string" },
"data": { "type": "string" },
"mountPath": { "type": "string", "pattern": "^/.*" },
"fileName": { "type": "string" }
}
}
},
"entrypoint": {
"type": "array",
"items": { "type": "string" }
},
"command": {
"oneOf": [
{ "type": "string" },
{ "type": "array", "items": { "type": "string" } }
]
}
},
"additionalProperties": false
}
}
}
}
}
}
State-of-the-Art Validation: Our deployment configuration is powered by a cutting-edge JSON Schema validation layer. This robust mechanism ensures that every YAML configuration is not only human-readable but also machine-verified for consistency and correctness—providing a seamless integration experience for AI agents, LLMs, and related systems.
Using the Nexlayer Validation System
You can validate your Nexlayer YAML configuration in several ways:
Command-line Validation
# Using the Nexlayer CLI
nexlayer validate --file nexlayer.yaml
# For detailed validation output
nexlayer validate --file nexlayer.yaml --verbose
API Validation Endpoint
curl -X POST https://app.nexlayer.io/validate \
-H "Content-Type: text/x-yaml" \
--data-binary @nexlayer.yaml
Online Validator
You can also use our interactive validator at app.nexlayer.io/validator to check your configuration in real-time.
Key Differences from Other Orchestration Schemas
The Nexlayer schema is specifically designed for AI-friendliness, with several important differences from Kubernetes or Docker Compose:
- Simplified Structure: Flatter hierarchy with fewer nested levels, making it easier for AI systems to parse and generate
- Explicit Validation Rules: Clear patterns and constraints that provide immediate feedback on configuration errors
- AI-Optimized Error Messages: Validation errors include specific suggestions tailored for AI systems to correct mistakes
- Single-Purpose Fields: Each field has a singular, well-defined purpose without overloading semantics
- Streamlined Port Configuration: Simple integer list approach versus complex port mapping objects
- Automated Resource Management: No manual CPU/memory configuration required
Sample Validation Error Messages
Here are examples of common validation errors and their meanings:
Error: InvalidVolumePath
Field: pods[0].volumes[0].mountPath
Message: "Volume mountPath must start with / character"
Suggestion: "Update the mountPath to start with /, e.g., /data"
Error: InvalidPortFormat
Field: pods[1].servicePorts[0]
Message: "ServicePorts must be a list of integers"
Suggestion: "Change from port mapping format '8080:80' to simple integer '8080'"
Error: DuplicatePodName
Field: pods[2].name
Message: "Pod name 'api' is already used by another pod"
Suggestion: "Ensure all pod names are unique within the application"
Error: InvalidPodReference
Field: pods[0].vars.DATABASE_URL
Message: "Invalid pod reference format in 'postgres:5432'"
Suggestion: "Use the format 'postgres.pod:5432' for inter-pod communication"
These validation messages help both human users and AI systems quickly identify and correct issues in Nexlayer configurations.
**State-of-the-Art Validation:** Our deployment configuration is powered by a cutting-edge JSON Schema validation layer. This robust mechanism ensures that every YAML configuration is not only human-readable but also machine-verified for consistency and correctness—providing a seamless integration experience for AI agents, LLMs, and related systems.
Critical Distinction
NEXLAYER YAML IS NOT KUBERNETES OR DOCKER COMPOSE YAML. It has a unique schema specifically designed for Nexlayer's platform. Applying concepts from other orchestration systems will cause deployment failures.
Required Structure
application:
name: "app-name" # Required: Globally unique identifier
type: "nextjs-ai" # Optional: Framework hint
description: "App description" # Optional: App description
pods: # Required: List of containers
- name: "pod-name" # Required: Unique pod name
image: "image:tag" # Required: Docker image
path: "/" # Optional: URL route
servicePorts: # Required: Exposed ports
- 8080 # Format: List of integers
YAML Building Blocks Complete Structure
application
├── name: Your app's name
├── type: Framework hint (optional)
├── description: App description (optional)
├── url: Your app's URL (optional)
├── registryLogin (optional for private images)
└── pods: List of containers
├── Pod 1 (like a web server)
│ ├── name: pod name
│ ├── image: container image
│ ├── path: web route
│ ├── servicePorts: exposed ports
│ │ └── - port number
│ ├── vars: environment variables
│ │ ├── ENV_VAR1: value1
│ │ └── ENV_VAR2: value2
│ ├── volumes: persistent storage
│ │ └── - name: volume name
│ │ ├── size: storage size
│ │ └── mountPath: storage location
│ └── secrets: sensitive data
│ └── - name: secret name
│ ├── data: secret content
│ ├── mountPath: secret location
│ └── fileName: secret file name
│
├── Pod 2 (like a database)
│ └── ...
└── Pod 3 (like a cache)
└── ...
🧩 Core Deployment Components
Application Block
application:
name: "app-name" # Required: Globally unique
type: "nextjs-ai" # Optional: Technology hint
description: "Description" # Optional: Human-readable details
Pods Block
pods:
- name: "pod-name" # Required: Unique within app
image: "image:tag" # Required: Docker image
path: "/route" # Optional: URL routing path
servicePorts: # Required: Must include ports
- 8080 # Format: List of integers
vars: # Optional: Environment variables
ENV_VAR: "value" # Format: key-value pairs
volumes: # Optional: Persistent storage
- name: "vol-name" # Required for volume: Unique name
size: "1Gi" # Required: Storage size
mountPath: "/data" # Required: Mount location
🔍 Pod Configuration Reference
Each pod in Nexlayer represents exactly ONE container (unlike Kubernetes pods which can have multiple containers).
Pod Configuration Cheat Sheet
| Key |
Definition |
Why it matters |
Examples |
| name |
A unique name to identify this service. |
Each pod must work correctly for your app to run—if one pod breaks, your whole app might not work. Names must be unique within the application. |
name: postgres |
| image |
Specifies the Docker container image to deploy for that pod. |
This tells Nexlayer exactly which pre-built container to use. Images must be hosted in a registry and accessible. |
image: "postgres:latest" or image: "<% REGISTRY %>/myapp:1.0" |
| path |
For web-facing pods, defines the external URL route. |
This sets the web address path where users access your service. Must start with /. |
path: "/" or path: "/api" |
| servicePorts |
Defines the ports exposed by the container. |
These ports are the communication channels for your app. Must be a list of integers. |
servicePorts: - 5432 |
| vars |
Environment variables as key-value pairs. |
These are the settings that tell your app how to connect to databases, APIs, and more. |
vars:
DATABASE_URL: postgres://postgres:password@db.pod:5432/mydb |
| volumes |
Persistent storage settings. |
Volumes store data that persists between restarts. |
volumes:
- name: postgres-data
size: 5Gi
mountPath: /var/lib/postgresql/data |
| secrets |
Secure storage for sensitive data. |
Secrets protect passwords and keys while ensuring your app runs securely. |
secrets:
- name: api-keys
data: "your-api-key"
mountPath: "/app/secrets"
fileName: "api.key" |
📋 Field-by-Field Validation Rules
This table outlines the validation rules for each field in Nexlayer YAML:
| Field |
Required |
Type |
Format/Pattern |
Constraints |
Error Messages |
application.name |
Yes |
string |
^[a-z][a-z0-9.-]*$ |
Must start with lowercase letter, contain only alphanumeric, hyphens, or dots |
"Invalid name format. Must start with lowercase letter and contain only alphanumeric characters, hyphens, or dots." |
application.type |
No |
string |
Any |
Framework hint |
"If provided, must be a string." |
application.description |
No |
string |
Any |
Human-readable description |
"If provided, must be a string." |
application.registryLogin.registry |
Required if using private images |
string |
Valid registry hostname |
Must be a valid registry hostname |
"Invalid registry hostname." |
application.registryLogin.username |
Required if using private images |
string |
Any |
Must be valid username for registry |
"Missing username for private registry authentication." |
application.registryLogin.personalAccessToken |
Required if using private images |
string |
Any |
Must be valid token for registry |
"Missing personalAccessToken for private registry authentication." |
pods |
Yes |
array |
At least one pod |
Must contain at least one pod |
"At least one pod must be defined." |
pods[].name |
Yes |
string |
^[a-z][a-z0-9.-]*$ |
Must start with lowercase letter, contain only alphanumeric, hyphens, or dots |
"Invalid pod name format. Must start with lowercase letter and contain only alphanumeric characters, hyphens, or dots." |
pods[].image |
Yes |
string |
Valid Docker image reference |
Must be valid image from registry |
"Missing or invalid image reference." |
pods[].path |
No |
string |
Must start with / |
Valid URL path |
"Path must start with a forward slash (/)." |
pods[].servicePorts |
Yes |
array of integers |
[80, 8080, ...] |
At least one port number |
"servicePorts must contain at least one port number." |
pods[].vars |
No |
object |
Key-value pairs |
Environment variables |
"vars must be key-value pairs, not an array." |
pods[].volumes[].name |
Required if using volumes |
string |
Any |
Unique within pod |
"Volume name must be unique within pod." |
pods[].volumes[].size |
Required if using volumes |
string |
^[0-9]+(Mi|Gi|Ti)$ |
Valid size with unit |
"Volume size must be a number followed by Mi, Gi, or Ti (e.g., '1Gi')." |
pods[].volumes[].mountPath |
Required if using volumes |
string |
Must start with / |
Valid filesystem path |
"mountPath must start with a forward slash (/)." |
pods[].secrets[].name |
Required if using secrets |
string |
Any |
Unique within pod |
"Secret name must be unique within pod." |
pods[].secrets[].data |
Required if using secrets |
string |
Any |
Secret data |
"Missing secret data." |
pods[].secrets[].mountPath |
Required if using secrets |
string |
Must start with / |
Valid filesystem path |
"Secret mountPath must start with a forward slash (/)." |
pods[].secrets[].fileName |
No |
string |
Any |
Valid filename |
"If provided, fileName must be a valid filename." |
🔌 ServicePorts Specification
The servicePorts field is critical and must follow a specific format.
servicePorts:
- 80 # Format: Simple list of integers
Multiple ports example:
servicePorts:
- 80
- 3000
❌ INCORRECT - Kubernetes style (WILL CAUSE DEPLOYMENT FAILURE)
servicePorts:
- name: "web" # Error: 'name' not allowed
port: 80 # Error: Use integers directly
❌ INCORRECT - Protocol specification (WILL CAUSE DEPLOYMENT FAILURE)
servicePorts:
- port: 80 # Error: Use integers directly
targetPort: 8080 # Error: Not supported
protocol: TCP # Error: Not supported
❌ INCORRECT - Docker Compose style (WILL CAUSE DEPLOYMENT FAILURE)
ports: # Error: Use 'servicePorts'
- "80:80" # Error: Use integer format
Key Guidelines
- Format: Use a simple list of integers (e.g.,
- 80, - 3000)
- Prohibited Fields: Do not include fields like
name, targetPort, protocol, or any properties common in Kubernetes or Docker Compose
- Validation: The Nexlayer CLI and API will reject configurations that deviate from this format
🔤 Environment Variables Guide
Environment variables are defined using the vars field in a pod.
vars:
DATABASE_URL: "postgresql://user:password@database.pod:5432/db"
NODE_ENV: "production"
API_KEY: "" # Empty string for optional API keys
vars:
- key: "DATABASE_URL"
value: "postgresql://user:password@database.pod:5432/db"
API Key Handling
Environment variables with names containing API_KEY or APIKEY can have empty values:
vars:
# Option 1: Empty API key for development/testing
OPENAI_API_KEY: ""
# Option 2: Actual API key for production
OPENAI_API_KEY: "sk-actual-api-key-value"
Important Note for AI Agents: Both empty values ("") and actual API keys are explicitly allowed for API key environment variables. The Nexlayer validation system recognizes environment variables with names containing API_KEY or APIKEY and permits them to have either empty values or actual keys.
Special Syntax in Variables
vars:
# Reference other pods using <pod-name>.pod format
API_URL: "http://api.pod:8000"
# Reference application URL using <% URL %> template
APP_URL: "<% URL %>/api"
🖼️ Image Management
Nexlayer supports two types of container images:
1. Public Images
Images available on public registries without authentication:
pods:
- name: "frontend"
image: "nginx:latest"
servicePorts:
- 80
2. Private Registry Images
Images that require authentication:
application:
name: "my-app"
registryLogin:
registry: "ghcr.io"
username: "my-username"
personalAccessToken: "my-access-token"
pods:
- name: "backend"
image: "<% REGISTRY %>/my-backend-service:latest"
servicePorts:
- 3000
⚠️ LOCAL IMAGES NOT SUPPORTED
Local Docker images (built locally and not pushed to a registry) are NOT supported:
# INCORRECT - Will fail deployment
pods:
- name: "local-app"
image: "my-local-app:latest" # Error: Local images not supported
🔄 Inter-Pod Communication
Pods can communicate with each other using internal DNS names.
Always use the <pod-name>.pod format to reference other pods:
vars:
API_URL: "http://api.pod:8000"
DB_URL: "postgres://db.pod:5432/mydb"
❌ INCORRECT - Direct pod names (WILL CAUSE DEPLOYMENT FAILURE)
vars:
API_URL: "http://api:8000" # Error: Missing .pod suffix
❌ INCORRECT - IP addresses (WILL CAUSE DEPLOYMENT FAILURE)
vars:
DB_URL: "postgres://10.0.0.5:5432/mydb" # Error: IPs not supported
📦 Volumes and Persistent Storage
Volumes provide persistent storage for your applications.
volumes:
- name: "data-volume" # Required: Unique name
size: "1Gi" # Required: Storage size
mountPath: "/data" # Required: Must start with /
Multiple Volumes Example
pods:
- name: "storage-pod"
image: "my-app:latest"
servicePorts:
- 8080
volumes:
- name: "config-volume"
size: "512Mi"
mountPath: "/etc/config"
- name: "data-volume"
size: "5Gi"
mountPath: "/var/data"
🔒 Secrets Management
Secrets allow you to securely store and access sensitive information.
secrets:
- name: "api-keys" # Required: Unique name
data: "your-api-key" # Required: Secret value
mountPath: "/secrets" # Required: Must start with /
fileName: "api.key" # Optional: Custom filename
Example with Multiple Secrets
pods:
- name: "api"
image: "api:latest"
servicePorts:
- 8000
secrets:
- name: "openai-key"
data: "sk-your-openai-key"
mountPath: "/app/secrets"
fileName: "openai.key"
- name: "database-creds"
data: "db-password-here"
mountPath: "/app/secrets"
fileName: "db.password"
🌐 API Endpoints Reference
The Nexlayer API is accessible at: https://app.nexlayer.io
Key Endpoints
Start User Deployment
POST /startUserDeployment/{applicationID?}
- Description: Start a deployment given an application ID
- Content-Type:
text/x-yaml
- Request Body: Nexlayer YAML file (uploaded using
--data-binary)
- Response: JSON with deployment details including URL
Example curl Command
curl -X POST https://app.nexlayer.io/startUserDeployment/my-app \
-H "Content-Type: text/x-yaml" \
--data-binary @deployment.yaml
Example Python API Usage
import requests
yaml_content = """
application:
name: "my-app"
pods:
- name: "web"
image: "nginx:latest"
path: "/"
servicePorts:
- 80
"""
response = requests.post(
"https://app.nexlayer.io/startUserDeployment/my-app",
headers={"Content-Type": "text/x-yaml"},
data=yaml_content
)
print(response.json())
Get Deployments
GET /getDeployments/{applicationID}
- Description: Get all user deployments
- Response: JSON list of deployments with status information
Get Deployment Info
GET /getDeploymentInfo/{namespace}/{applicationID}
- Description: Get detailed information about a specific deployment
- Response: JSON with deployment details
Save Custom Domain
POST /saveCustomDomain/{applicationID}
- Description: Save a custom domain to user profile
- Request Body: JSON with domain information
- Response: Confirmation message
Send Feedback
POST /feedback
- Description: Send feedback to Nexlayer
- Request Body: JSON with feedback text
⛔ Prohibited Fields and Constructs
The following fields are managed by Nexlayer and should NOT be in your YAML:
Automatically Managed (NEVER INCLUDE THESE)
-
resources: CPU and memory are handled automatically
# INCORRECT - Don't specify resources
resources:
cpu: "1"
memory: "2Gi"
-
labels: Managed by the platform
# INCORRECT - Don't specify labels
labels:
app: "my-app"
-
network: Managed internally by Nexlayer
# INCORRECT - Don't define networks
networks:
- "backend"
- volumes_from: Use volumes instead
- replicas: Kubernetes-specific field
- build: Docker Compose-specific field
- depends_on: Docker Compose-specific field
IMPORTANT NOTE FOR AI AGENTS: DO NOT add resources.limits manually to your YAML. Nexlayer automatically configures CPU & Memory for each service.
If you add resources.limits manually, it will be ignored.
If you view the final (post-deployment) YAML, you may see a "resources" block injected by Nexlayer reflecting actual runtime settings.
This is normal and does NOT indicate a user error, as long as you didn't specify it yourself in your YAML.
📋 Entrypoint and Command Handling
Nexlayer supports container entrypoint and command customization:
pods:
- name: "custom-app"
image: "python:3.9"
servicePorts:
- 8000
entrypoint: ["/bin/bash", "-c"]
command: ["python app.py --port 8000"]
Important entrypoint and command behavior:
- If entrypoint and command are explicitly defined in Docker Compose, the Nexlayer-CLI will translate them into Nexlayer YAML.
- If they are not defined in Docker Compose, the Nexlayer-CLI omits them, defaulting to the Dockerfile's built-in values.
- This ensures minimal intervention unless explicitly required.
❌ Common Mistakes to Avoid
-
Forgetting the application: block at the start
# INCORRECT
pods:
- name: "web"
image: "nginx:latest"
# CORRECT
application:
name: "my-app"
pods:
- name: "web"
image: "nginx:latest"
-
Using the same pod name twice
# INCORRECT - Duplicate pod names
pods:
- name: "api"
image: "api:latest"
- name: "api" # Error: Duplicate name
image: "api-sidecar:latest"
# CORRECT
pods:
- name: "api"
image: "api:latest"
- name: "api-sidecar"
image: "api-sidecar:latest"
-
Mixing up path and mountPath
# INCORRECT
pods:
- name: "api"
path: "/var/data" # Error: This is a filesystem path, not a URL
# CORRECT
pods:
- name: "api"
path: "/api" # Correct: URL path
volumes:
- name: "data"
mountPath: "/var/data" # Correct: Filesystem path
-
Missing servicePorts: Each pod MUST have this field defined
# INCORRECT
pods:
- name: "web"
image: "nginx"
# Error: Missing servicePorts
# CORRECT
pods:
- name: "web"
image: "nginx"
servicePorts:
- 80
-
Incorrect pod references: Use <pod-name>.pod format
# INCORRECT
vars:
DB_URL: "postgres://db:5432/mydb"
# CORRECT
vars:
DB_URL: "postgres://db.pod:5432/mydb"
-
Trying to use Kubernetes or Docker Compose syntax
# INCORRECT - Kubernetes-style ports
servicePorts:
- name: "web"
port: 80
# CORRECT
servicePorts:
- 80
-
Adding resources.limits manually to your YAML
# INCORRECT - Don't manually specify resources
pods:
- name: "app"
image: "nginx:latest"
resources: # Will be ignored
limits:
cpu: "100m"
memory: "128Mi"
# CORRECT - Let Nexlayer handle resources automatically
pods:
- name: "app"
image: "nginx:latest"
# No resources section
Nexlayer automatically configures CPU & Memory for each service. If you add resources.limits manually, it will be ignored.
-
Misunderstanding entrypoint and command behavior
# Use only when you need to override the container's default behavior
pods:
- name: "app"
image: "node:16"
entrypoint: ["/bin/bash", "-c"]
command: ["node server.js"]
If entrypoint and command are explicitly defined in Docker Compose, the Nexlayer-CLI will translate them into Nexlayer YAML. If they are not defined in Docker Compose, the Nexlayer-CLI omits them, defaulting to the Dockerfile's built-in values.
-
Missing registryLogin for private images
# INCORRECT - Private image without registryLogin
pods:
- name: "app"
image: "ghcr.io/myorg/myapp:latest"
# CORRECT
application:
registryLogin:
registry: "ghcr.io"
username: "myusername"
personalAccessToken: "mytoken"
pods:
- name: "app"
image: "<% REGISTRY %>/myorg/myapp:latest"
-
Trying to use local Docker images
# INCORRECT - Local images not supported
pods:
- name: "app"
image: "my-local-app:latest"
# CORRECT - Use public or private registry images
pods:
- name: "app"
image: "nginx:latest" # Public registry image
🛠️ Common App Patterns
Single-Server Application Pattern
application:
name: "simple-app"
pods:
- name: web
image: nginx:latest
path: /
servicePorts:
- 80
Frontend + Backend Pattern
application:
name: "web-app"
pods:
- name: frontend
image: nextjs-app:latest
path: /
servicePorts:
- 3000
vars:
API_URL: http://backend.pod:4000
- name: backend
image: express-api:latest
path: /api
servicePorts:
- 4000
Full-Stack (Frontend + Backend + Database) Pattern
application:
name: "fullstack-app"
pods:
- name: frontend
image: my-react-app:latest
path: /
servicePorts:
- 3000
vars:
API_URL: http://backend.pod:4000
- name: backend
image: node:16
path: /api
servicePorts:
- 4000
vars:
DATABASE_URL: postgresql://user:pass@database.pod:5432/mydb
- name: database
image: postgres:14
servicePorts:
- 5432
vars:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes:
- name: db-data
size: 1Gi
mountPath: /var/lib/postgresql/data
AI Application Pattern
application:
name: "ai-app"
type: "ai-service"
pods:
- name: frontend
image: my-ai-frontend:latest
path: /
servicePorts:
- 3000
vars:
API_URL: http://ai-backend.pod:5000
- name: ai-backend
image: my-ai-api:latest
servicePorts:
- 5000
vars:
MODEL_PATH: /models
VECTOR_DB: http://vector-db.pod:8080
OPENAI_API_KEY: "" # Can be empty for AI key vars
volumes:
- name: model-storage
size: 5Gi
mountPath: /models
- name: vector-db
image: weaviate/weaviate:latest
servicePorts:
- 8080
volumes:
- name: vector-data
size: 2Gi
mountPath: /data
LLM-Based RAG Application Pattern
application:
name: "llm-app"
type: "ai-service"
pods:
- name: ui
image: nextjs-chat-ui:latest
path: /
servicePorts:
- 3000
vars:
API_URL: http://llm-api.pod:8000
- name: llm-api
image: fastapi-llm:latest
path: /api
servicePorts:
- 8000
vars:
OPENAI_API_KEY: "" # Can be empty
VECTOR_DB_URL: http://vector-db.pod:6333
- name: vector-db
image: qdrant/qdrant:latest
servicePorts:
- 6333
volumes:
- name: vector-data
size: 10Gi
mountPath: /qdrant/storage
📚 Deployment Examples
Complete Web Application
application:
name: "web-app"
pods:
- name: "frontend"
image: "nextjs:latest"
path: "/"
servicePorts:
- 3000
vars:
API_URL: "http://api.pod:8000"
- name: "api"
image: "fastapi:latest"
path: "/api"
servicePorts:
- 8000
vars:
DB_URL: "postgres://db.pod:5432"
- name: "db"
image: "postgres:14"
servicePorts:
- 5432
volumes:
- name: "data"
size: "1Gi"
mountPath: "/var/lib/postgresql/data"
AI-Powered Chat Application
application:
name: "chat-app"
type: "web-ai"
pods:
- name: "frontend"
image: "chat-ui:latest"
path: "/"
servicePorts:
- 3000
vars:
API_URL: "http://api.pod:8000"
- name: "api"
image: "chat-api:latest"
path: "/api"
servicePorts:
- 8000
vars:
AI_SERVICE_URL: "https://api.openai.com/v1"
REDIS_URL: "redis://cache.pod:6379"
OPENAI_API_KEY: "" # Can be empty
secrets:
- name: "api-keys"
data: "your-api-key"
mountPath: "/secrets"
fileName: "ai.key"
- name: "cache"
image: "redis:latest"
servicePorts:
- 6379
volumes:
- name: "cache-data"
size: "1Gi"
mountPath: "/data"
Vector Database with Search Capabilities
application:
name: "vector-search"
type: "ai-service"
pods:
- name: "ui"
image: "search-ui:latest"
path: "/"
servicePorts:
- 3000
vars:
API_URL: "http://api.pod:8000"
- name: "api"
image: "search-api:latest"
path: "/api"
servicePorts:
- 8000
vars:
VECTOR_DB_URL: "http://vector-db.pod:8080"
EMBEDDING_API_URL: "https://api.openai.com/v1/embeddings"
OPENAI_API_KEY: "" # Can be empty
secrets:
- name: "openai-key"
data: "your-openai-key"
mountPath: "/app/secrets"
fileName: "openai.key"
- name: "vector-db"
image: "qdrant/qdrant:latest"
servicePorts:
- 8080
- 6333
volumes:
- name: "vector-storage"
size: "5Gi"
mountPath: "/qdrant/storage"
🤖 AI Agent & LLM Guidance
This section contains specific instructions for AI systems generating Nexlayer deployment configurations.
Critical Instructions for AI Systems
When helping users create Nexlayer deployments:
- Always start by confirming the user is deploying to Nexlayer (not Kubernetes/Docker)
- Verify these essential components before presenting final YAML:
- Valid
application.name (unique, lowercase alphanumeric with hyphens/dots)
- Every pod has
name, image, and servicePorts (as integer list)
- All pod names are unique within the application
- Inter-pod references use
<pod-name>.pod:port format
- All paths start with
/
- All mountPaths start with
/
- Important distinctions from other platforms:
- No
resources specification (CPU/memory managed automatically)
- No Kubernetes-style port specifications with
name and port fields
- No Docker Compose-style port mappings like "80:80"
- No
replicas, depends_on, networks fields
- No IP addresses for pod communication
- Special environment variable handling:
- API key variables can have empty values (
"")
- Direct key-value format, not an array of objects
- Use
<pod-name>.pod for cross-pod references
- Template syntax for app URL:
<% URL %>
- Leverage our validation system:
- Nexlayer provides a state-of-the-art JSON Schema validation layer that ensures reliable and precise deployments for AI-driven tools and platforms
- This advanced validation system catches common configuration errors and provides detailed feedback
- When generating configuration, follow the schema exactly to ensure error-free validation
- The validation system will detect issues like incorrect path formatting, invalid volume configurations, and improper service references
- Leverage our validation system:
- Nexlayer provides a state-of-the-art JSON Schema validation layer that ensures reliable and precise deployments for AI-driven tools and platforms
- This advanced validation system catches common configuration errors and provides detailed feedback
- When generating configuration, follow the schema exactly to ensure error-free validation
- The validation system will detect issues like incorrect path formatting, invalid volume configurations, and improper service references
Framework Detection for AI Agents
When analyzing a codebase to determine what type of application needs to be deployed, use these patterns to detect common frameworks:
| Framework/Technology Stack |
Key File/Pattern to Detect |
| Next.js (JavaScript) |
next.config.js or .next/ folder |
| Next.js (TypeScript) |
next.config.ts or tsconfig.json |
| React (Vite/CRA - JavaScript) |
vite.config.js or package.json |
| React (Vite/CRA - TypeScript) |
vite.config.ts or tsconfig.json |
| Angular (JavaScript) |
angular.json |
| Angular (TypeScript) |
angular.json + tsconfig.json |
| Vue.js (JavaScript) |
vue.config.js or package.json |
| Vue.js (TypeScript) |
vue.config.ts or tsconfig.json |
| Express.js (JavaScript) |
server.js or app.js |
| Express.js (TypeScript) |
server.ts or app.ts |
| NestJS (JavaScript) |
nest-cli.json or nestjs.json |
| NestJS (TypeScript) |
nest-cli.json + tsconfig.json |
| Gatsby.js (JavaScript) |
gatsby-config.js |
| Gatsby.js (TypeScript) |
gatsby-config.ts + tsconfig.json |
| Next.js + Supabase |
next.config.js + .env with SUPABASE_ keys |
| Bun + Next.js/Astro |
bun.lockb or bunfig.toml + .env |
| Django/Flask + PostgreSQL |
manage.py or app.py with .env keys for DATABASE_URL |
| Next.js + Supabase + LangChain |
next.config.js + .env with LANGCHAIN_ keys |
| Node.js + LangChain |
package.json with "langchain" dependency |
| Python (FastAPI) + LangChain |
main.py or app.py + .env with LANGCHAIN_ keys |
| Python (FastAPI) + Hugging Face |
main.py or app.py + .env with HUGGINGFACE_ keys |
| Python (FastAPI) + Together AI |
main.py or app.py + .env with TOGETHER_ keys |
| Next.js + AutoGen (Microsoft) |
next.config.js + .env with AUTOGEN_ keys |
| CrewAI + LangChain |
main.py or app.py + .env with CREWAI_ keys |
Use this detection to create appropriate pod configurations for each framework.
Service Types and Common Port Numbers
To assist AI systems in generating appropriate configurations, here are common service types and their default ports:
| Service Type |
Default Port(s) |
Image Example |
Notes |
| Web Frontend |
3000, 80, 8080 |
nextjs:latest, nginx:latest |
Use path: "/" |
| API Backend |
8000, 3000, 5000 |
fastapi:latest, express:latest |
Use path: "/api" |
| PostgreSQL |
5432 |
postgres:14 |
Requires volume for persistence |
| MySQL/MariaDB |
3306 |
mysql:8, mariadb:latest |
Requires volume for persistence |
| MongoDB |
27017 |
mongo:latest |
Requires volume for persistence |
| Redis |
6379 |
redis:latest |
Optional volume for persistence |
| Elasticsearch |
9200, 9300 |
elasticsearch:8 |
Requires volume for persistence |
| Vector DB (Qdrant) |
6333, 6334 |
qdrant/qdrant:latest |
Requires volume for persistence |
| Vector DB (Pinecone) |
8080 |
pinecone:latest |
Requires volume for persistence |
| Vector DB (Weaviate) |
8080 |
weaviate/weaviate:latest |
Requires volume for persistence |
Generation Strategy for Complex Applications
For complex applications with multiple components:
- Identify key components: Frontend, Backend, Database, Cache, AI services
- Determine component relationships: Which components need to talk to each other
- Define pod structure: Create a pod for each component
- Configure networking: Use
<pod-name>.pod:port for inter-pod communication
- Set environment variables: Connect components via environment variables
- Add persistence: Include volumes for stateful services
- Secure sensitive data: Use secrets for API keys and credentials
🧩 Edge Cases for AI Agents
This section addresses specific edge cases that commonly confuse AI systems when generating Nexlayer configurations.
1. Empty API Keys
Empty API keys are valid for environment variables containing API_KEY or APIKEY:
vars:
OPENAI_API_KEY: "" # Valid for API key variables
DATABASE_URL: "" # Warning: Empty value for non-API key variable
2. Private Registry Image References
Private registry image references must use special template syntax:
# CORRECT
image: "<% REGISTRY %>/myapp:latest"
# INCORRECT
image: "ghcr.io/myorg/myapp:latest" # Don't hardcode private registry
3. Multiple Pods with Same Base Image
Multiple pods with the same base image must have unique names:
# Unique names required even with same image
- name: "worker1"
image: "worker:latest"
- name: "worker2"
image: "worker:latest"
4. Resources Like CPU/Memory
Resources like CPU/memory are automatically managed:
# NEVER include this in user YAML
resources:
cpu: "1"
memory: "2Gi"
5. Non-Web Pods Don't Need Path
Pods that don't expose web interfaces don't need a path field:
# Database pod - no path needed
- name: "database"
image: "postgres:latest"
servicePorts:
- 5432
6. API End-User Authentication
For end-user authentication, use environment variables, not secrets:
# CORRECT
vars:
AUTH_SECRET: "your-auth-secret"
JWT_SECRET: "your-jwt-secret"
7. Pod Reference URL Construction
Constructing URLs to other pods follows this pattern:
vars:
# For HTTP services
API_URL: "http://api.pod:8000"
# For database connections
DB_URL: "postgresql://user:password@db.pod:5432/dbname"
# For Redis
REDIS_URL: "redis://redis.pod:6379"
✅ Systematic Validation Checklist
AI systems should verify each of these points before finalizing a Nexlayer configuration:
- Valid
application.name (lowercase alphanumeric with hyphens/dots)
- Each pod has required fields:
name, image, servicePorts
-
servicePorts format is a simple list of integers
- All pod names are unique within the application
- No prohibited fields (resources, replicas, networks, depends_on)
- All
path values start with /
- All
mountPath values start with /
-
vars are in key-value format (not array of objects)
- Pod references use
<pod-name>.pod:port format
- Private registry images use
<% REGISTRY %> template
- Volumes have
name, size, and mountPath
- Secrets have
name, data, and mountPath
- No IP addresses are used for pod communication
- No Kubernetes or Docker Compose specific fields
- Environment variable values correctly reference other pods
Validation in Python (Example for AI Systems)
AI systems generating or validating Nexlayer YAML might use logic like this:
import yaml
import re
def validate_nexlayer_yaml(yaml_content):
try:
config = yaml.safe_load(yaml_content)
errors = []
# Check application block
if 'application' not in config:
errors.append("Missing 'application' block")
return errors
# Check application name
if 'name' not in config['application']:
errors.append("Missing 'application.name'")
elif not re.match(r'^[a-z][a-z0-9.-]*$', config['application']['name']):
errors.append("Invalid 'application.name' format")
# Check pods
if 'pods' not in config['application']:
errors.append("Missing 'pods' list")
return errors
pod_names = set()
for i, pod in enumerate(config['application']['pods']):
# Check required fields
if 'name' not in pod:
errors.append(f"Pod #{i+1} missing 'name'")
elif not re.match(r'^[a-z][a-z0-9.-]*$', pod['name']):
errors.append(f"Pod '{pod['name']}' has invalid name format")
elif pod['name'] in pod_names:
errors.append(f"Duplicate pod name: '{pod['name']}'")
else:
pod_names.add(pod['name'])
if 'image' not in pod:
errors.append(f"Pod '{pod.get('name', f'#{i+1}')}' missing 'image'")
if 'servicePorts' not in pod:
errors.append(f"Pod '{pod.get('name', f'#{i+1}')}' missing 'servicePorts'")
elif not isinstance(pod['servicePorts'], list):
errors.append(f"Pod '{pod.get('name', f'#{i+1}')}' 'servicePorts' must be a list")
elif not pod['servicePorts']:
errors.append(f"Pod '{pod.get('name', f'#{i+1}')}' 'servicePorts' must not be empty")
else:
for j, port in enumerate(pod['servicePorts']):
if not isinstance(port, int):
errors.append(f"Pod '{pod.get('name', f'#{i+1}')}' port #{j+1} must be an integer")
# Check path format
if 'path' in pod and not pod['path'].startswith('/'):
errors.append(f"Pod '{pod.get('name', f'#{i+1}')}' 'path' must start with '/'")
# Check volumes
if 'volumes' in pod:
for j, volume in enumerate(pod['volumes']):
if 'name' not in volume:
errors.append(f"Pod '{pod.get('name', f'#{i+1}')}' volume #{j+1} missing 'name'")
if 'size' not in volume:
errors.append(f"Pod '{pod.get('name', f'#{i+1}')}' volume #{j+1} missing 'size'")
if 'mountPath' not in volume:
errors.append(f"Pod '{pod.get('name', f'#{i+1}')}' volume #{j+1} missing 'mountPath'")
elif not volume['mountPath'].startswith('/'):
errors.append(f"Pod '{pod.get('name', f'#{i+1}')}' volume '{volume.get('name', f'#{j+1}')}' 'mountPath' must start with '/'")
# Check secrets
if 'secrets' in pod:
for j, secret in enumerate(pod['secrets']):
if 'name' not in secret:
errors.append(f"Pod '{pod.get('name', f'#{i+1}')}' secret #{j+1} missing 'name'")
if 'data' not in secret:
errors.append(f"Pod '{pod.get('name', f'#{i+1}')}' secret #{j+1} missing 'data'")
if 'mountPath' not in secret:
errors.append(f"Pod '{pod.get('name', f'#{i+1}')}' secret #{j+1} missing 'mountPath'")
elif not secret['mountPath'].startswith('/'):
errors.append(f"Pod '{pod.get('name', f'#{i+1}')}' secret '{secret.get('name', f'#{j+1}')}' 'mountPath' must start with '/'")
return errors
except Exception as e:
return [f"YAML parsing error: {str(e)}"]
🌲 Decision Trees for AI Systems
This section contains structured decision-making processes for AI systems to follow when generating Nexlayer configurations.
Pod Type Selection
What type of component are you adding?
├── Web interface (Frontend)
│ ├── Main UI → Use path: "/" and port 3000 (or 80)
│ └── Sub-interface → Use path: "/feature-name"
├── API service
│ └── Use path: "/api" and port 8000 (or 5000)
├── Database
│ ├── PostgreSQL → Use port 5432 and volume for data
│ ├── MySQL → Use port 3306 and volume for data
│ ├── MongoDB → Use port 27017 and volume for data
│ └── Other → Look up default port and add volume
├── Cache/Queue
│ ├── Redis → Use port 6379
│ └── RabbitMQ → Use port 5672
└── Vector DB/Search
├── Elasticsearch → Use ports 9200, 9300
├── Qdrant → Use port 6333
├── Pinecone → Use port 8080
└── Weaviate → Use port 8080
Environment Variable Construction
What type of connection are you defining?
├── Web/HTTP service
│ └── Use "http://<pod-name>.pod:<port>"
├── Database connection
│ ├── PostgreSQL → Use "postgresql://user:pass@<pod-name>.pod:5432/dbname"
│ ├── MySQL → Use "mysql://user:pass@<pod-name>.pod:3306/dbname"
│ ├── MongoDB → Use "mongodb://<pod-name>.pod:27017/dbname"
│ └── Other → Look up connection string format
├── Redis
│ └── Use "redis://<pod-name>.pod:6379"
└── Other service
└── Use "<pod-name>.pod:<port>"
Volume Size Selection
What type of data are you storing?
├── Database
│ ├── Small (dev/test) → Use "1Gi"
│ ├── Medium (small prod) → Use "5Gi"
│ └── Large (production) → Use "10Gi" or more
├── AI models
│ ├── Small models → Use "2Gi"
│ ├── Medium models → Use "5Gi"
│ └── Large models → Use "20Gi" or more
├── Vector embeddings
│ ├── Small dataset → Use "1Gi"
│ ├── Medium dataset → Use "5Gi"
│ └── Large dataset → Use "10Gi" or more
└── General file storage
├── Small files → Use "1Gi"
├── Medium storage → Use "5Gi"
└── Large storage → Use "10Gi" or more
🎯 Interactive Configuration Guide
Using the Interactive Mode
nexlayer init --interactive
The interactive mode provides a guided experience with:
- 🔍 Automatic project type detection
- 📝 Project name configuration
- 🚀 Framework-specific setup
- 🤖 AI provider detection and configuration
- 💾 Database integration setup
- 🔑 Environment variable configuration
- 🐳 Docker image handling
- 🌐 Service URL configuration
Available Interactive Flags
-i, --interactive: Enable interactive mode
-f, --force: Force re-detection (ignore cache)
-r, --regenerate: Regenerate configuration for existing project
--name: Set application name (default: directory name)
--pod-name: Set main pod name (default: based on project type)
--pod-image: Set main pod image (default: based on project type)
--pod-port: Set main pod port (default: based on project type)
--pod-path: Set main pod path (default: / for web/api pods)
## 🎭 Project Type Detection
The interactive mode automatically detects:
### Framework Detection
- Next.js/React applications
- Node.js/Express services
- Python/FastAPI applications
- Go applications
- Docker-based projects
### AI Integration Detection
- OpenAI integrations
- Anthropic Claude services
- Google AI (Gemini) implementations
- Custom AI model deployments
### Database Detection
- PostgreSQL
- MongoDB
- MySQL
- Redis
- Vector databases (Pinecone, Weaviate, etc.)
🔧 Environment Configuration
Interactive Environment Setup
The interactive mode helps configure:
-
Database Connections
- Automatic URL formatting
- Credential management
- Connection string validation
-
AI Service Integration
- API key configuration
- Model selection
- Provider-specific settings
-
Service Discovery
- Inter-pod communication
- URL routing
- Port configuration
💡 Interactive Mode Best Practices
When to Use Interactive Mode
- 🆕 Starting new projects
- 🔄 Converting existing applications
- 🛠️ Complex multi-pod setups
- 🤖 AI-integrated applications
Tips for Interactive Configuration
- Have your project's requirements ready
- Know your deployment environment
- Prepare necessary API keys
- Understand your application's architecture
- Have Docker images ready or accessible