diff --git a/src/components/codehike/annotations/index.tsx b/src/components/codehike/annotations/index.tsx
index 4c82561..72b52f6 100644
--- a/src/components/codehike/annotations/index.tsx
+++ b/src/components/codehike/annotations/index.tsx
@@ -20,7 +20,6 @@ export {
tokenTransitions,
SmoothPre,
} from "@/components/codehike/annotations/token-transitions";
-export { wordWrap } from "@/components/codehike/annotations/word-wrap";
export { link } from "@/components/codehike/annotations/link";
export { mark } from "@/components/codehike/annotations/mark";
export { foldinline } from "@/components/codehike/annotations/fold-inline";
diff --git a/src/components/codehike/annotations/word-wrap.tsx b/src/components/codehike/annotations/word-wrap.tsx
deleted file mode 100644
index e8586c6..0000000
--- a/src/components/codehike/annotations/word-wrap.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * Copyright 2025 GoodRx, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* eslint-disable react/prop-types */
-import {
- AnnotationHandler,
- InnerLine,
- InnerPre,
- InnerToken,
- CustomPreProps,
-} from "codehike/code";
-
-export const wordWrap: AnnotationHandler = {
- name: "word-wrap",
- Pre: (props: CustomPreProps) => (
-
- ),
- Line: (props) => (
-
- ),
- Token: (props) => ,
-};
diff --git a/src/components/codehike/code.tsx b/src/components/codehike/code.tsx
index 488d2f3..7ee2ad3 100644
--- a/src/components/codehike/code.tsx
+++ b/src/components/codehike/code.tsx
@@ -21,7 +21,6 @@ import dynamic from "next/dynamic";
import { Pre, type CustomPreProps } from "codehike/code";
import {
callout,
- wordWrap,
className,
tabs,
mark,
@@ -42,7 +41,6 @@ export const CodeHikeSSR = ({
codeblock,
handlers = [
callout,
- wordWrap,
className,
tabs,
mark,
diff --git a/src/components/codehike/index.tsx b/src/components/codehike/index.tsx
index e978745..7470425 100644
--- a/src/components/codehike/index.tsx
+++ b/src/components/codehike/index.tsx
@@ -24,7 +24,6 @@ export {
MAX_TRANSITION_DURATION,
} from "@/components/codehike/constants";
export {
- wordWrap,
tokenTransitions,
SmoothPre,
callout,
diff --git a/src/components/codehike/scrollycoding.tsx b/src/components/codehike/scrollycoding.tsx
index fee7d12..b648f44 100644
--- a/src/components/codehike/scrollycoding.tsx
+++ b/src/components/codehike/scrollycoding.tsx
@@ -24,7 +24,6 @@ import { Block, HighlightedCodeBlock, parseProps } from "codehike/blocks";
import { HighlightedCode, Pre } from "codehike/code";
import {
callout,
- wordWrap,
className,
tabs,
mark,
@@ -79,7 +78,6 @@ function Code({ codeblock }: { codeblock: HighlightedCode }) {
code={codeblock}
handlers={[
callout,
- wordWrap,
className,
tabs,
mark,
diff --git a/src/components/codehike/slideshow.tsx b/src/components/codehike/slideshow.tsx
index 6652dae..4b54c40 100644
--- a/src/components/codehike/slideshow.tsx
+++ b/src/components/codehike/slideshow.tsx
@@ -20,7 +20,6 @@ import React, { useState, useEffect } from "react";
import { Pre, HighlightedCode, highlight, RawCode } from "codehike/code";
import {
callout,
- wordWrap,
className,
tabs,
mark,
@@ -92,7 +91,6 @@ function Code({ codeblock }: { codeblock: RawCode | HighlightedCode }) {
code={highlightedCode}
handlers={[
callout,
- wordWrap,
className,
tabs,
mark,
diff --git a/src/components/codehike/spotlight.tsx b/src/components/codehike/spotlight.tsx
index a092c96..7885145 100644
--- a/src/components/codehike/spotlight.tsx
+++ b/src/components/codehike/spotlight.tsx
@@ -25,7 +25,6 @@ import {
} from "codehike/utils/selection";
import {
callout,
- wordWrap,
className,
tabs,
mark,
@@ -114,7 +113,6 @@ function Code({ codeblock }: { codeblock: RawCode | HighlightedCode }) {
code={highlightedCode}
handlers={[
callout,
- wordWrap,
className,
tabs,
mark,
diff --git a/src/components/codehike/token-transition-toggle.tsx b/src/components/codehike/token-transition-toggle.tsx
index 0e79694..8f648c3 100644
--- a/src/components/codehike/token-transition-toggle.tsx
+++ b/src/components/codehike/token-transition-toggle.tsx
@@ -18,7 +18,7 @@
import { useState, useEffect } from "react";
import { Pre, highlight, HighlightedCode } from "codehike/code";
-import { tokenTransitions, wordWrap } from "@/components/codehike/annotations";
+import { tokenTransitions } from "@/components/codehike/annotations";
import dynamic from "next/dynamic";
import Loader from "@/components/loader";
import {
@@ -56,7 +56,7 @@ function TokenTransitionToggleClient({
diff --git a/src/components/index.tsx b/src/components/index.tsx
index 042ac32..bc6a276 100644
--- a/src/components/index.tsx
+++ b/src/components/index.tsx
@@ -36,7 +36,6 @@ export {
Scrollycoding,
THEMES,
MAX_TRANSITION_DURATION,
- wordWrap,
tokenTransitions,
SmoothPre,
callout,
diff --git a/src/pages/docs/_meta.ts b/src/pages/docs/_meta.ts
index 5ea09a1..12ff43a 100644
--- a/src/pages/docs/_meta.ts
+++ b/src/pages/docs/_meta.ts
@@ -27,6 +27,9 @@ export default {
"getting-started": {
"title": "Getting Started"
},
+ "schema": {
+ "title": "Schema Reference"
+ },
"--": {
"type": "separator"
},
diff --git a/src/pages/docs/schema/_meta.ts b/src/pages/docs/schema/_meta.ts
new file mode 100644
index 0000000..602298d
--- /dev/null
+++ b/src/pages/docs/schema/_meta.ts
@@ -0,0 +1,48 @@
+/**
+ * Copyright 2026 GoodRx, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export default {
+ "overview": {
+ "title": "Schema Overview"
+ },
+ "environment": {
+ "title": "Environment Configuration"
+ },
+ "webhooks": {
+ "title": "Webhooks Configuration"
+ },
+ "---": {
+ "type": "separator"
+ },
+ "github": {
+ "title": "GitHub Service"
+ },
+ "docker": {
+ "title": "Docker Service"
+ },
+ "helm": {
+ "title": "Helm Service"
+ },
+ "codefresh": {
+ "title": "Codefresh Service"
+ },
+ "aurora-restore": {
+ "title": "Aurora Restore Service"
+ },
+ "configuration": {
+ "title": "Configuration Service"
+ }
+};
\ No newline at end of file
diff --git a/src/pages/docs/schema/aurora-restore.mdx b/src/pages/docs/schema/aurora-restore.mdx
new file mode 100644
index 0000000..f1335a3
--- /dev/null
+++ b/src/pages/docs/schema/aurora-restore.mdx
@@ -0,0 +1,98 @@
+---
+title: Aurora Restore Service
+description: Restore AWS Aurora database snapshots for ephemeral environments
+tags:
+ - schema
+ - aurora
+ - database
+ - aws
+ - restore
+---
+
+import { Callout } from "nextra/components";
+
+The `auroraRestore` service type restores AWS Aurora database snapshots for use in ephemeral environments. This allows you to test against production-like data.
+
+
+ This documentation is still in progress and will be updated shortly with the
+ latest information.
+
+
+## Required Fields
+
+| Field | Type | Description |
+| ----------- | ------ | -------------------------------------------- |
+| `command` | string | Command to execute for the restore operation |
+| `arguments` | string | Arguments passed to the command |
+
+```yaml filename="lifecycle.yaml"
+services:
+ - name: "database-restore"
+ auroraRestore:
+ command: "/restore/run.sh" # Required
+ arguments: "--snapshot-id latest" # Required
+```
+
+## How It Works
+
+1. When the environment is deployed, Lifecycle executes the configured command with arguments
+2. The command typically triggers an Aurora snapshot restore process
+3. Once complete, the restored database is available for other services
+
+
+ The `auroraRestore` service type is a specialized service that runs a command
+ to initiate database restoration. The actual restore logic is implemented in
+ your command/script.
+
+
+## Example
+
+```yaml filename="lifecycle.yaml"
+environment:
+ defaultServices:
+ - name: "api"
+ - name: "aurora-db"
+
+services:
+ - name: "api"
+ github:
+ repository: "myorg/api"
+ branchName: "main"
+ docker:
+ defaultTag: "main"
+ app:
+ dockerfilePath: "Dockerfile"
+ env:
+ DATABASE_URL: "{{aurora-db_internalHostname}}:5432"
+ ports:
+ - 3000
+
+ - name: "aurora-db"
+ auroraRestore:
+ command: "/scripts/restore-aurora.sh"
+ arguments: "--cluster my-cluster --snapshot production-backup"
+```
+
+## Use Cases
+
+- **Production data testing** - Test features against realistic production data
+- **Database migrations** - Validate migrations against production schema
+- **Performance testing** - Benchmark against production-scale data
+- **Bug reproduction** - Reproduce issues with production data state
+
+
+ When restoring from production snapshots, ensure sensitive data is properly
+ anonymized or that access is appropriately restricted.
+
+
+## Implementation Notes
+
+The restore command is executed as part of the environment deployment process. Your script should:
+
+1. Handle authentication with AWS
+2. Initiate the snapshot restore
+3. Wait for the restore to complete
+4. Configure network access to the restored instance
+5. Return the connection information
+
+The restored database endpoint can then be referenced by other services using template variables.
diff --git a/src/pages/docs/schema/codefresh.mdx b/src/pages/docs/schema/codefresh.mdx
new file mode 100644
index 0000000..707e9c1
--- /dev/null
+++ b/src/pages/docs/schema/codefresh.mdx
@@ -0,0 +1,120 @@
+---
+title: Codefresh Service
+description: Trigger external Codefresh pipelines for deployment and destruction
+tags:
+ - schema
+ - codefresh
+ - pipeline
+ - ci-cd
+---
+
+import { Callout } from "nextra/components";
+
+The `codefresh` service type delegates deployment to external Codefresh pipelines. This is useful when you have existing CI/CD pipelines that handle complex build and deployment logic.
+
+## Example
+
+```yaml filename="lifecycle.yaml"
+services:
+ - name: "api"
+ codefresh:
+ repository: "myorg/api" # Required - GitHub repo in owner/repo format
+ branchName: "main" # Required - branch to build from
+ env: # Environment variables passed to pipelines
+ ENVIRONMENT: "ephemeral"
+ DATABASE_URL: "postgres://{{database_internalHostname}}:5432/app"
+ CACHE_URL: "redis://{{cache_internalHostname}}:6379"
+ LOG_LEVEL: "info"
+ deploy: # Required - deployment pipeline configuration
+ pipelineId: "64598362453cc650c0c9cd4d" # Codefresh pipeline ID for deployment
+ trigger: "lifecycle-deploy" # Pipeline trigger name
+ destroy: # Required - destruction pipeline configuration
+ pipelineId: "74283905723ff650c0d9ab7e" # Codefresh pipeline ID for destruction
+ trigger: "lifecycle-destroy" # Pipeline trigger name
+```
+
+## Required Fields
+
+| Field | Type | Description |
+| -------------------- | ------ | ---------------------------------------- |
+| `repository` | string | GitHub repository in `owner/repo` format |
+| `branchName` | string | Branch to build from |
+| `deploy.pipelineId` | string | Codefresh pipeline ID for deployment |
+| `deploy.trigger` | string | Pipeline trigger name for deployment |
+| `destroy.pipelineId` | string | Codefresh pipeline ID for destruction |
+| `destroy.trigger` | string | Pipeline trigger name for destruction |
+
+## Optional Fields
+
+| Field | Type | Description |
+| ----- | ------ | ----------------------------------------- |
+| `env` | object | Environment variables passed to pipelines |
+
+## Pipeline Configuration
+
+### deploy
+
+Configure the pipeline triggered when deploying the service.
+
+```yaml
+codefresh:
+ deploy:
+ pipelineId: "64598362453cc650c0c9cd4d"
+ trigger: "deploy"
+```
+
+### destroy
+
+Configure the pipeline triggered when tearing down the environment.
+
+```yaml
+codefresh:
+ destroy:
+ pipelineId: "74283905723ff650c0d9ab7e"
+ trigger: "destroy"
+```
+
+## Environment Variables
+
+Pass environment variables to both deploy and destroy pipelines:
+
+```yaml
+codefresh:
+ repository: "myorg/api"
+ branchName: "main"
+ env:
+ ENVIRONMENT: "ephemeral"
+ SERVICE_NAME: "api"
+ DATABASE_URL: "{{database_internalHostname}}:5432"
+```
+
+
+ Environment variables defined in `env` are passed to both deploy and destroy
+ pipelines. Use template variables to reference other services.
+
+
+## How It Works
+
+1. When an environment is deployed, Lifecycle triggers the `deploy` pipeline with the configured environment variables.
+2. The pipeline receives context about the deployment including branch, namespace, and service information.
+3. When the environment is torn down, Lifecycle triggers the `destroy` pipeline to clean up resources.
+
+## Use Cases
+
+- **Complex build processes** - When builds require multi-stage pipelines or custom tooling
+- **External dependencies** - When deployment requires interaction with external systems
+- **Existing CI/CD** - When you have established Codefresh pipelines you want to reuse
+- **Custom deployment logic** - When standard Kubernetes deployment isn't sufficient
+
+
+ Codefresh pipelines run asynchronously. Lifecycle tracks pipeline status but
+ the actual deployment logic is managed by Codefresh.
+
+
+## Finding Pipeline IDs
+
+To find your Codefresh pipeline ID:
+
+1. Open your pipeline in Codefresh
+2. The pipeline ID is in the URL: `https://g.codefresh.io/pipelines/edit/new/.../
`
+3. Or use the Codefresh CLI: `codefresh get pipelines`
diff --git a/src/pages/docs/schema/configuration.mdx b/src/pages/docs/schema/configuration.mdx
new file mode 100644
index 0000000..cb93227
--- /dev/null
+++ b/src/pages/docs/schema/configuration.mdx
@@ -0,0 +1,136 @@
+---
+title: Configuration Service
+description: Deploy configuration-only services for feature flags and shared configuration
+tags:
+ - schema
+ - configuration
+ - feature-flags
+ - config
+---
+
+import { Callout } from "nextra/components";
+
+The `configuration` service type creates a configuration-only service that doesn't deploy any containers. It's useful for managing feature flags, shared configuration, or service metadata that other services can reference.
+
+
+ This documentation is still in progress and will be updated shortly with the
+ latest information.
+
+
+## Required Fields
+
+| Field | Type | Description |
+| ------------ | ------ | ------------------------------------ |
+| `defaultTag` | string | Configuration version tag |
+| `branchName` | string | Branch name for configuration source |
+
+```yaml filename="lifecycle.yaml"
+services:
+ - name: "config"
+ configuration:
+ defaultTag: "v1.0.0" # Required
+ branchName: "main" # Required
+```
+
+## How It Works
+
+A configuration service:
+
+1. Does not deploy any containers or pods
+2. Registers a service entry in Lifecycle for reference by other services
+3. Provides a way to version and track configuration changes
+4. Can be referenced by other services using template variables
+
+## Example
+
+```yaml filename="lifecycle.yaml"
+environment:
+ defaultServices:
+ - name: "api"
+ - name: "feature-flags"
+
+services:
+ - name: "api"
+ github:
+ repository: "myorg/api"
+ branchName: "main"
+ docker:
+ defaultTag: "main"
+ app:
+ dockerfilePath: "Dockerfile"
+ env:
+ CONFIG_VERSION: "{{feature-flags_branchName}}"
+ ports:
+ - 3000
+
+ - name: "feature-flags"
+ configuration:
+ defaultTag: "v2.1.0"
+ branchName: "main"
+```
+
+## Use Cases
+
+### Feature Flags
+
+Track feature flag configuration versions:
+
+```yaml
+services:
+ - name: "feature-flags"
+ configuration:
+ defaultTag: "2024.01.15"
+ branchName: "main"
+```
+
+### Shared Configuration
+
+Reference shared configuration across services:
+
+```yaml
+services:
+ - name: "shared-config"
+ configuration:
+ defaultTag: "v1.0.0"
+ branchName: "production"
+
+ - name: "api"
+ github:
+ repository: "myorg/api"
+ branchName: "main"
+ docker:
+ defaultTag: "main"
+ app:
+ dockerfilePath: "Dockerfile"
+ env:
+ CONFIG_BRANCH: "{{shared-config_branchName}}"
+
+ - name: "worker"
+ github:
+ repository: "myorg/worker"
+ branchName: "main"
+ docker:
+ defaultTag: "main"
+ app:
+ dockerfilePath: "Dockerfile"
+ env:
+ CONFIG_BRANCH: "{{shared-config_branchName}}"
+```
+
+### Environment Metadata
+
+Track environment-specific metadata:
+
+```yaml
+services:
+ - name: "env-metadata"
+ configuration:
+ defaultTag: "ephemeral"
+ branchName: "{{PR_BRANCH}}"
+```
+
+
+ Configuration services are lightweight entries in Lifecycle's service
+ registry. They don't consume cluster resources but allow other services to
+ reference configuration state.
+
diff --git a/src/pages/docs/schema/docker.mdx b/src/pages/docs/schema/docker.mdx
new file mode 100644
index 0000000..b113aea
--- /dev/null
+++ b/src/pages/docs/schema/docker.mdx
@@ -0,0 +1,263 @@
+---
+title: Docker Service
+description: Deploy pre-built Docker images like databases, caches, and other infrastructure components
+tags:
+ - schema
+ - docker
+ - database
+ - redis
+ - postgres
+---
+
+import { Callout } from "nextra/components";
+import { Tabs } from "nextra/components";
+
+The `docker` service type deploys pre-built Docker images without building from source. This is ideal for databases, caches, message queues, and other infrastructure components.
+
+## Examples
+
+
+
+
+PostgreSQL database (internal only):
+
+```yaml filename="lifecycle.yaml"
+services:
+ - name: "database"
+ docker:
+ dockerImage: "postgres" # Required - Docker image name
+ defaultTag: "15-alpine" # Required - image tag
+ ports:
+ - 5432
+ env:
+ POSTGRES_USER: "app"
+ POSTGRES_PASSWORD: "secret"
+ POSTGRES_DB: "myapp"
+ deployment:
+ public: false # No ingress - internal only
+```
+
+Reference from other services:
+
+```yaml
+env:
+ DATABASE_URL: "postgres://app:secret@{{database_internalHostname}}:5432/myapp"
+```
+
+
+
+
+Redis cache:
+
+```yaml filename="lifecycle.yaml"
+services:
+ - name: "cache"
+ docker:
+ dockerImage: "redis"
+ defaultTag: "7-alpine"
+ command: "redis-server" # Override entrypoint
+ arguments: "--appendonly%%SPLIT%%yes" # Use %%SPLIT%% for spaces
+ ports:
+ - 6379
+ deployment:
+ public: false
+ resource: # Custom memory allocation
+ memory:
+ request: "128Mi"
+ limit: "256Mi"
+```
+
+Reference from other services:
+
+```yaml
+env:
+ REDIS_URL: "redis://{{cache_internalHostname}}:6379"
+```
+
+
+
+
+MySQL with persistent storage:
+
+```yaml filename="lifecycle.yaml"
+services:
+ - name: "mysql"
+ docker:
+ dockerImage: "mysql"
+ defaultTag: "8.0"
+ ports:
+ - 3306
+ env:
+ MYSQL_ROOT_PASSWORD: "rootpassword"
+ MYSQL_DATABASE: "myapp"
+ MYSQL_USER: "app"
+ MYSQL_PASSWORD: "apppassword"
+ deployment:
+ public: false
+ resource:
+ cpu:
+ request: "100m"
+ memory:
+ request: "512Mi"
+ limit: "1Gi"
+ readiness: # Health check
+ tcpSocketPort: 3306
+ initialDelaySeconds: 30
+ serviceDisks: # Persistent volume
+ - name: "mysql-data"
+ mountPath: "/var/lib/mysql"
+ storageSize: "10Gi"
+ accessModes: "ReadWriteOnce"
+```
+
+
+
+
+Complete configuration with all options:
+
+```yaml filename="lifecycle.yaml"
+services:
+ - name: "database"
+ docker:
+ dockerImage: "postgres" # Required - Docker image name
+ defaultTag: "15-alpine" # Required - image tag
+ command: "docker-entrypoint.sh" # Optional - override entrypoint
+ arguments: "postgres%%SPLIT%%-c%%SPLIT%%max_connections=200" # Use %%SPLIT%% for spaces
+ ports:
+ - 5432
+ env:
+ POSTGRES_USER: "app"
+ POSTGRES_PASSWORD: "secret"
+ POSTGRES_DB: "myapp"
+ PGDATA: "/var/lib/postgresql/data/pgdata"
+ deployment:
+ public: false # false = internal only, no ingress
+ capacityType: "on-demand" # Options: spot, on-demand
+ resource: # Custom CPU/memory requests and limits
+ cpu:
+ request: "250m"
+ limit: "1000m"
+ memory:
+ request: "512Mi"
+ limit: "2Gi"
+ readiness: # Health check - tcpSocketPort or httpGet
+ tcpSocketPort: 5432
+ initialDelaySeconds: 15 # Delay before first check
+ periodSeconds: 10 # Check interval
+ failureThreshold: 5 # Failures before unhealthy
+ serviceDisks: # Persistent volume mounts
+ - name: "postgres-data" # Required - volume name
+ mountPath: "/var/lib/postgresql/data" # Required - path in container
+ storageSize: "20Gi" # Required - storage size
+ accessModes: "ReadWriteOnce" # Optional - ReadWriteOnce or ReadWriteMany
+```
+
+
+
+
+
+## Fields Reference
+
+### Required Fields
+
+| Field | Type | Description |
+| ------------- | ------ | --------------------------------------------- |
+| `dockerImage` | string | Docker image name (e.g., `postgres`, `redis`) |
+| `defaultTag` | string | Image tag (e.g., `15-alpine`, `7-alpine`) |
+
+### Optional Fields
+
+| Field | Type | Description |
+| ------------ | ------ | ----------------------------------------------------------- |
+| `command` | string | Override container entrypoint |
+| `arguments` | string | Arguments passed to the command. Use `%%SPLIT%%` for spaces |
+| `env` | object | Environment variables |
+| `ports` | array | Exposed container ports |
+| `deployment` | object | Deployment configuration (see below) |
+
+## Deployment Options
+
+The `deployment` section configures how the service is deployed to Kubernetes. All fields are optional.
+
+See [GitHub Service - Deployment Options](/docs/schema/github#deployment-options) for detailed documentation of each field.
+
+| Field | Description |
+| -------------- | ------------------------------------------------------------------------- |
+| `public` | `true` = creates ingress, `false` = internal only |
+| `capacityType` | Node type: `spot` or `on-demand` |
+| `resource` | CPU and memory requests/limits |
+| `readiness` | Health check using `httpGet` or `tcpSocketPort` |
+| `hostnames` | Custom hostname config (auto-constructed from `global_config` if omitted) |
+| `network` | IP whitelist, port mapping, gRPC support |
+| `serviceDisks` | Persistent volume mounts |
+
+
+ For databases and caches, you typically want `public: false` to keep them
+ internal to the cluster.
+
+
+## Common Images
+
+### Databases
+
+```yaml
+# PostgreSQL
+docker:
+ dockerImage: "postgres"
+ defaultTag: "15-alpine"
+ ports:
+ - 5432
+ env:
+ POSTGRES_USER: "user"
+ POSTGRES_PASSWORD: "pass"
+ POSTGRES_DB: "db"
+
+# MySQL
+docker:
+ dockerImage: "mysql"
+ defaultTag: "8.0"
+ ports:
+ - 3306
+ env:
+ MYSQL_ROOT_PASSWORD: "root"
+ MYSQL_DATABASE: "db"
+
+# MongoDB
+docker:
+ dockerImage: "mongo"
+ defaultTag: "7.0"
+ ports:
+ - 27017
+ env:
+ MONGO_INITDB_ROOT_USERNAME: "admin"
+ MONGO_INITDB_ROOT_PASSWORD: "pass"
+```
+
+### Caches & Queues
+
+```yaml
+# Redis
+docker:
+ dockerImage: "redis"
+ defaultTag: "7-alpine"
+ ports:
+ - 6379
+
+# Memcached
+docker:
+ dockerImage: "memcached"
+ defaultTag: "1.6-alpine"
+ ports:
+ - 11211
+
+# RabbitMQ
+docker:
+ dockerImage: "rabbitmq"
+ defaultTag: "3.12-management-alpine"
+ ports:
+ - 5672
+ - 15672
+ env:
+ RABBITMQ_DEFAULT_USER: "guest"
+ RABBITMQ_DEFAULT_PASS: "guest"
+```
diff --git a/src/pages/docs/schema/environment.mdx b/src/pages/docs/schema/environment.mdx
new file mode 100644
index 0000000..4d6a7c9
--- /dev/null
+++ b/src/pages/docs/schema/environment.mdx
@@ -0,0 +1,204 @@
+---
+title: Environment Configuration
+description: Configure deployment behavior, service grouping, and automation for ephemeral environments
+tags:
+ - schema
+ - environment
+ - configuration
+ - services
+---
+
+import { Callout } from "nextra/components";
+import { Tabs } from "nextra/components";
+
+The `environment` section controls how Lifecycle deploys and manages your ephemeral environments. It defines which services are deployed by default, which are optional, and how automation (webhooks) should behave.
+
+## Fields Reference
+
+| Field | Type | Required | Description |
+| ------------------------ | ------- | -------- | ---------------------------------------- |
+| `autoDeploy` | boolean | No | Automatically deploy on PR updates |
+| `defaultServices` | array | Yes | Services deployed with every environment |
+| `optionalServices` | array | No | Services available on-demand |
+| `webhooks` | array | No | Automation triggers on state changes |
+| `enabledFeatures` | array | No | Feature flags for the environment |
+| `githubDeployments` | boolean | No | Create GitHub deployment records |
+| `useGithubStatusComment` | boolean | No | Post status comments on PRs |
+
+## defaultServices
+
+Services listed in `defaultServices` are deployed automatically when an environment is created. At least one default service is required.
+
+```yaml filename="lifecycle.yaml"
+environment:
+ defaultServices:
+ - name: "api" # Required - service name (must match a service definition)
+ - name: "frontend"
+ - name: "database"
+```
+
+### Service Reference Fields
+
+Each entry in `defaultServices` can include optional fields to override the service configuration:
+
+| Field | Type | Description |
+| ------------ | ------ | ------------------------------------------------------------- |
+| `name` | string | **Required.** Name matching a service in the `services` array |
+| `repository` | string | Override the repository for this service |
+| `branch` | string | Override the branch for this service |
+| `serviceId` | number | Internal service ID reference |
+
+```yaml filename="lifecycle.yaml"
+environment:
+ defaultServices:
+ - name: "api"
+ repository: "myorg/api" # Optional - override repository
+ branch: "develop" # Optional - override branch
+```
+
+## optionalServices
+
+Services listed in `optionalServices` are not deployed by default but can be added to an environment on-demand through the Lifecycle UI or API.
+
+```yaml filename="lifecycle.yaml"
+environment:
+ defaultServices:
+ - name: "api"
+ optionalServices:
+ - name: "cache"
+ repository: "myorg/services"
+ branch: "main"
+ - name: "worker"
+ repository: "myorg/services"
+ branch: "main"
+```
+
+
+ Optional services are useful for components that aren't always needed, like
+ background workers, caching layers, or additional databases for specific
+ testing scenarios.
+
+
+## autoDeploy
+
+When `autoDeploy` is enabled, Lifecycle automatically triggers a deployment whenever the PR is updated (new commits pushed).
+
+```yaml filename="lifecycle.yaml"
+environment:
+ autoDeploy: true # Default: false
+ defaultServices:
+ - name: "api"
+```
+
+
+ With `autoDeploy: true`, environments are created automatically on every
+ commit to the PR branch without requiring manual label addition.
+
+
+## webhooks
+
+Webhooks allow you to trigger external actions when the environment reaches certain states. See the [Webhooks](/docs/schema/webhooks) page for detailed configuration.
+
+```yaml filename="lifecycle.yaml"
+environment:
+ defaultServices:
+ - name: "api"
+ webhooks:
+ - name: "Run E2E Tests"
+ state: deployed
+ type: docker
+ docker:
+ image: "myorg/e2e-tests:latest"
+ env:
+ TEST_URL: "https://{{api_publicUrl}}"
+```
+
+## Examples
+
+
+
+
+The minimal configuration requires only `defaultServices`:
+
+```yaml filename="lifecycle.yaml"
+environment:
+ defaultServices:
+ - name: "api"
+```
+
+
+
+
+Configuration with both default and optional services:
+
+```yaml filename="lifecycle.yaml"
+environment:
+ autoDeploy: true
+ defaultServices:
+ - name: "api"
+ - name: "frontend"
+ - name: "database"
+ optionalServices:
+ - name: "cache"
+ repository: "myorg/infrastructure"
+ branch: "main"
+ - name: "worker"
+ repository: "myorg/api"
+ branch: "main"
+ - name: "monitoring"
+ repository: "myorg/tools"
+ branch: "main"
+```
+
+
+
+
+Complete configuration with all options:
+
+```yaml filename="lifecycle.yaml"
+environment:
+ autoDeploy: true
+ githubDeployments: true
+ useGithubStatusComment: true
+
+ defaultServices:
+ - name: "api"
+ - name: "frontend"
+ - name: "database"
+
+ optionalServices:
+ - name: "cache"
+ repository: "myorg/infrastructure"
+ branch: "main"
+ - name: "worker"
+
+ webhooks:
+ # Run tests after deployment
+ - name: "Integration Tests"
+ state: deployed
+ type: docker
+ docker:
+ image: "myorg/integration-tests:latest"
+ timeout: 1800
+ env:
+ API_URL: "https://{{api_publicUrl}}"
+ FRONTEND_URL: "https://{{frontend_publicUrl}}"
+
+ # Notify on errors
+ - name: "Slack Alert"
+ state: error
+ type: command
+ command:
+ image: "alpine:latest"
+ script: |
+ apk add --no-cache curl
+ curl -X POST "$SLACK_WEBHOOK" \
+ -H "Content-Type: application/json" \
+ -d '{"text":"Deployment failed for PR"}'
+ env:
+ SLACK_WEBHOOK: "https://hooks.slack.com/services/XXX/YYY/ZZZ"
+```
+
+
+
+
diff --git a/src/pages/docs/schema/github.mdx b/src/pages/docs/schema/github.mdx
new file mode 100644
index 0000000..f74eced
--- /dev/null
+++ b/src/pages/docs/schema/github.mdx
@@ -0,0 +1,282 @@
+---
+title: GitHub Service
+description: Build and deploy services from GitHub repositories with Docker
+tags:
+ - schema
+ - github
+ - docker
+ - deployment
+ - build
+---
+
+import { Callout } from "nextra/components";
+import { Tabs } from "nextra/components";
+
+The `github` service type builds and deploys applications from a GitHub repository using a Dockerfile. This is the most common service type for application code that needs to be built from source.
+
+## Examples
+
+
+
+
+Minimal configuration with only required fields:
+
+```yaml filename="lifecycle.yaml"
+services:
+ - name: "api"
+ github:
+ repository: "myorg/api" # Required - GitHub repo in owner/repo format
+ branchName: "main" # Required - default branch to build
+ docker: # Required - Docker build configuration
+ defaultTag: "main" # Required - image tag, typically matches branch
+ app: # Required - main application container
+ dockerfilePath: "Dockerfile" # Required - path to Dockerfile
+ ports:
+ - 3000
+```
+
+
+
+
+Configuration with deployment options:
+
+```yaml filename="lifecycle.yaml"
+services:
+ - name: "api"
+ github:
+ repository: "myorg/api"
+ branchName: "main"
+ docker:
+ defaultTag: "main"
+ builder:
+ engine: "buildkit" # Options: buildkit (default), codefresh, kaniko
+ app:
+ dockerfilePath: "Dockerfile"
+ env:
+ NODE_ENV: "production"
+ LOG_LEVEL: "info"
+ ports:
+ - 3000
+ deployment:
+ public: true # Creates ingress for external access
+ resource: # Custom CPU/memory allocation
+ cpu:
+ request: "100m"
+ limit: "500m"
+ memory:
+ request: "256Mi"
+ limit: "512Mi"
+ readiness: # Health check configuration
+ httpGet:
+ path: "/health"
+ port: 3000
+ initialDelaySeconds: 10
+ periodSeconds: 5
+```
+
+
+
+
+Complete configuration with all options:
+
+```yaml filename="lifecycle.yaml"
+services:
+ - name: "api"
+ github:
+ repository: "myorg/api"
+ branchName: "main"
+ docker:
+ defaultTag: "main"
+ builder:
+ engine: "buildkit" # Options: buildkit (default), codefresh, kaniko
+ # Init container - runs before main application (optional)
+ init:
+ dockerfilePath: "docker/migrate.dockerfile"
+ command: "/bin/sh"
+ arguments: "-c%%SPLIT%%npm run db:migrate" # Use %%SPLIT%% for spaces in arguments
+ env:
+ DATABASE_URL: "postgres://{{database_internalHostname}}:5432/app"
+ # Main application container (required)
+ app:
+ dockerfilePath: "Dockerfile"
+ command: "node" # Optional - override entrypoint
+ arguments: "dist/main.js" # Optional - arguments to command
+ env:
+ NODE_ENV: "production"
+ DATABASE_URL: "postgres://{{database_internalHostname}}:5432/app"
+ REDIS_URL: "redis://{{cache_internalHostname}}:6379"
+ ports:
+ - 3000
+ - 9090
+ deployment:
+ public: true # true = creates ingress, false = internal only
+ capacityType: "spot" # Options: spot, on-demand
+ resource: # Custom CPU/memory requests and limits
+ cpu:
+ request: "100m"
+ limit: "1000m"
+ memory:
+ request: "256Mi"
+ limit: "1Gi"
+ readiness: # Health check - httpGet or tcpSocketPort
+ httpGet:
+ path: "/health"
+ port: 3000
+ initialDelaySeconds: 15 # Delay before first check
+ periodSeconds: 10 # Check interval
+ timeoutSeconds: 5 # Check timeout
+ failureThreshold: 3 # Failures before unhealthy
+ hostnames: # Optional - auto-constructed from global_config if omitted
+ host: "api.example.com"
+ defaultPublicUrl: "api.myapp.example.com"
+ network: # Optional - advanced routing
+ ipWhitelist:
+ - "10.0.0.0/8"
+ pathPortMapping: # Map URL paths to container ports
+ "/api": 3000
+ "/metrics": 9090
+ grpc: # gRPC support
+ enable: true
+ host: "grpc.api.example.com"
+ serviceDisks: # Optional - persistent volume mounts
+ - name: "uploads" # Required - volume name
+ mountPath: "/app/uploads" # Required - path in container
+ storageSize: "5Gi" # Required - storage size
+ accessModes: "ReadWriteOnce" # Optional - ReadWriteOnce or ReadWriteMany
+```
+
+
+
+
+
+## Docker Configuration
+
+The `docker` section defines how the application is built and run.
+
+### docker.defaultTag
+
+The default Docker image tag, typically matching the branch name.
+
+### docker.builder
+
+Configuration for the Docker build process. The `engine` field specifies which build engine to use:
+
+- `buildkit` - BuildKit engine (default)
+- `codefresh` - Codefresh build engine
+- `kaniko` - Kaniko build engine
+
+### docker.app (Required)
+
+Configuration for the main application container:
+
+- `dockerfilePath` - **Required.** Path to Dockerfile relative to repo root
+- `command` - Override container entrypoint
+- `arguments` - Arguments passed to the command. Use `%%SPLIT%%` as a delimiter for spaces (e.g., `-c%%SPLIT%%npm run start`)
+- `env` - Environment variables
+- `ports` - Exposed container ports
+
+### docker.init (Optional)
+
+Configuration for an init container that runs before the main application. Uses the same fields as `docker.app`.
+
+## Deployment Options
+
+The `deployment` section configures how the service is deployed to Kubernetes. All fields are optional.
+
+### public
+
+Controls whether the service is exposed via ingress for external access.
+
+- `true` - Creates an ingress, service gets a public URL
+- `false` - Internal only, accessible only within the cluster
+
+### capacityType
+
+Specifies the node capacity type for scheduling:
+
+- `spot` - Use spot/preemptible instances (cost-effective)
+- `on-demand` - Use on-demand instances (more reliable)
+
+### resource
+
+CPU and memory requests and limits for the container:
+
+| Field | Description |
+| ---------------- | ----------------------------------------- |
+| `cpu.request` | Minimum CPU guaranteed (e.g., `100m`) |
+| `cpu.limit` | Maximum CPU allowed (e.g., `1000m`) |
+| `memory.request` | Minimum memory guaranteed (e.g., `256Mi`) |
+| `memory.limit` | Maximum memory allowed (e.g., `1Gi`) |
+
+### readiness
+
+Health check configuration to determine when the service is ready to receive traffic.
+
+**HTTP health check:**
+
+| Field | Description |
+| -------------- | ------------------------------------ |
+| `httpGet.path` | HTTP endpoint path (e.g., `/health`) |
+| `httpGet.port` | Port to check |
+
+**TCP health check:**
+
+| Field | Description |
+| --------------- | ------------------------------ |
+| `tcpSocketPort` | TCP port to check connectivity |
+
+**Common fields:**
+
+| Field | Description |
+| --------------------- | ------------------------------------ |
+| `initialDelaySeconds` | Delay before first check |
+| `periodSeconds` | Interval between checks |
+| `timeoutSeconds` | Timeout for each check |
+| `successThreshold` | Consecutive successes to be healthy |
+| `failureThreshold` | Consecutive failures to be unhealthy |
+
+### hostnames
+
+Custom hostname configuration. If omitted, hostnames are auto-constructed from `global_config` values.
+
+| Field | Description |
+| ------------------------- | ------------------------------- |
+| `host` | Custom hostname suffix |
+| `defaultInternalHostname` | Internal Kubernetes hostname |
+| `defaultPublicUrl` | Default public URL |
+| `acmARN` | AWS ACM certificate ARN for TLS |
+
+### network
+
+Advanced network configuration:
+
+| Field | Description |
+| ----------------- | ------------------------------------------ |
+| `ipWhitelist` | Array of allowed IP ranges (CIDR notation) |
+| `pathPortMapping` | Map URL paths to container ports |
+| `hostPortMapping` | Map hostnames to container ports |
+| `grpc.enable` | Enable gRPC support |
+| `grpc.host` | gRPC hostname |
+
+### serviceDisks
+
+Persistent volume mounts for stateful data:
+
+| Field | Required | Description |
+| ------------- | -------- | ---------------------------------- |
+| `name` | Yes | Volume name |
+| `mountPath` | Yes | Path inside the container |
+| `storageSize` | Yes | Storage size (e.g., `10Gi`) |
+| `accessModes` | No | `ReadWriteOnce` or `ReadWriteMany` |
+| `medium` | No | Storage medium |
+
+## Template Variables
+
+Reference other services in your configuration using template variables. See the [Template Variables](/docs/features/template-variables) guide for the complete list.
+
+```yaml
+env:
+ DATABASE_URL: "postgres://{{database_internalHostname}}:5432/app"
+ CACHE_URL: "redis://{{cache_internalHostname}}:6379"
+ FRONTEND_URL: "https://{{frontend_publicUrl}}"
+```
diff --git a/src/pages/docs/schema/helm.mdx b/src/pages/docs/schema/helm.mdx
new file mode 100644
index 0000000..fa3e824
--- /dev/null
+++ b/src/pages/docs/schema/helm.mdx
@@ -0,0 +1,289 @@
+---
+title: Helm Service
+description: Deploy services using Helm charts - local, OCI, or public repositories
+tags:
+ - schema
+ - helm
+ - kubernetes
+ - charts
+---
+
+import { Callout } from "nextra/components";
+import { Tabs } from "nextra/components";
+
+The `helm` service type deploys applications using Helm charts. It supports local charts, OCI registries, and public Helm repositories. You can optionally include a Docker build step for custom images.
+
+
+ For advanced Helm deployment features like native Helm and environment
+ variable mapping, see the [Native Helm
+ Deployment](/docs/features/native-helm-deployment) guide.
+
+
+## Examples
+
+
+
+
+Local chart with Docker build:
+
+```yaml filename="lifecycle.yaml"
+services:
+ - name: "web-app"
+ helm:
+ repository: "myorg/web-app" # Required for builds - GitHub repo
+ branchName: "main" # Required for builds - branch
+ chart:
+ name: "./charts/web-app" # Local chart path (relative to repo root)
+ valueFiles:
+ - "./helm/values.yaml"
+ docker:
+ defaultTag: "main" # Required - image tag
+ app: # Required - main application container
+ dockerfilePath: "Dockerfile" # Required - path to Dockerfile
+ ports:
+ - 3000
+```
+
+
+
+
+OCI registry chart with Docker build:
+
+```yaml filename="lifecycle.yaml"
+services:
+ - name: "api"
+ helm:
+ repository: "myorg/api" # Required for builds - GitHub repo
+ branchName: "main" # Required for builds - branch
+ chart:
+ name: "oci://registry.example.com/charts/api" # OCI registry URL
+ version: "1.2.0" # Chart version
+ values:
+ - "replicaCount=2"
+ - "labels.app=api"
+ docker:
+ defaultTag: "main"
+ builder:
+ engine: "buildkit" # Options: buildkit (default), codefresh, kaniko
+ app:
+ dockerfilePath: "Dockerfile"
+ command: "node" # Optional - override entrypoint
+ arguments: "dist/main.js" # Optional - arguments to command
+ env:
+ NODE_ENV: "production"
+ ports:
+ - 8080
+```
+
+
+ For Helm template variables that should be resolved at deployment time, use triple braces `{{{variable}}}` to prevent Helm from processing them prematurely.
+
+
+
+
+Public Bitnami chart (no Docker build):
+
+```yaml filename="lifecycle.yaml"
+services:
+ - name: "jenkins"
+ helm:
+ chart:
+ name: "jenkins" # Public chart name
+ repoUrl: "https://charts.bitnami.com/bitnami" # Helm repository URL
+ version: "13.6.8" # Chart version
+ values:
+ - "service.type=ClusterIP"
+ - "ingress.enabled=true"
+ - "ingress.hostname={{jenkins_publicUrl}}"
+ - "ingress.ingressClassName=nginx"
+```
+
+Other popular Bitnami charts:
+
+```yaml
+# PostgreSQL
+chart:
+ name: "postgresql"
+ repoUrl: "https://charts.bitnami.com/bitnami"
+ version: "12.9.0"
+ values:
+ - "auth.username=myuser"
+ - "auth.database=mydb"
+
+# Redis
+chart:
+ name: "redis"
+ repoUrl: "https://charts.bitnami.com/bitnami"
+ version: "18.4.0"
+ values:
+ - "architecture=standalone"
+```
+
+
+
+
+Complete configuration with all options:
+
+```yaml filename="lifecycle.yaml"
+services:
+ - name: "api-gateway"
+ helm:
+ deploymentMethod: "native" # Use native Helm deployment
+ version: "3.14.0" # Helm CLI version
+ args: "--wait --timeout 10m" # Additional Helm args
+
+ repository: "myorg/api-services" # Required for builds - GitHub repo
+ branchName: "main" # Required for builds - branch
+
+ chart:
+ name: "./charts/microservices" # Local chart path
+ values: # Inline Helm values (key=value format)
+ - "replicaCount=2"
+ - "service.type=LoadBalancer"
+ - "ingress.enabled=true"
+ - "labels.environment=preview"
+ valueFiles: # Value file paths (relative to repo root)
+ - "deploy/helm/base-values.yaml"
+ - "deploy/helm/api-gateway-values.yaml"
+
+ # Environment variable mapping for native Helm
+ envMapping:
+ app:
+ format: "array" # Options: array, map
+ path: "containers.api.env"
+
+ docker:
+ defaultTag: "main"
+ builder:
+ engine: "buildkit" # Options: buildkit (default), codefresh, kaniko
+ # Init container - runs before main application (optional)
+ init:
+ dockerfilePath: "docker/migrate.dockerfile"
+ command: "/bin/sh"
+ arguments: "-c%%SPLIT%%npm run migrate" # Use %%SPLIT%% for spaces
+ # Main application container (required)
+ app:
+ dockerfilePath: "docker/api.dockerfile"
+ command: "node" # Optional - override entrypoint
+ arguments: "dist/main.js" # Optional - arguments to command
+ env:
+ NODE_ENV: "production"
+ BACKEND_URL: "{{backend_internalHostname}}:3000"
+ ports:
+ - 8080
+ - 9090
+```
+
+
+
+
+
+## Chart Configuration
+
+The `chart` section is required and defines which Helm chart to deploy.
+
+
+ Commonly used charts can be configured in the `global_config` table to reuse
+ chart configuration across multiple services.
+
+
+### chart.name (Required)
+
+The chart name can be one of:
+
+| Value | Description |
+| ------------------------ | ----------------------------------- |
+| `"./"` or `"../"` prefix | Relative path to local chart |
+| `"oci://..."` | OCI registry chart URL |
+| Chart name | Public chart name from a repository |
+
+### chart.repoUrl
+
+URL of the Helm repository (required for public charts).
+
+### chart.version
+
+Specific chart version to deploy.
+
+### chart.values
+
+Array of Helm values in `key=value` format.
+
+### chart.valueFiles
+
+Array of value file paths relative to the repository root.
+
+## Docker Configuration
+
+The optional `docker` section defines how to build a custom image. This uses the same configuration as the [GitHub service docker section](/docs/schema/github#docker-configuration).
+
+### docker.defaultTag
+
+The default Docker image tag, typically matching the branch name.
+
+### docker.builder
+
+Configuration for the Docker build process. The `engine` field specifies which build engine to use:
+
+- `buildkit` - BuildKit engine (default)
+- `codefresh` - Codefresh build engine
+- `kaniko` - Kaniko build engine
+
+### docker.app (Required when using docker)
+
+Configuration for the main application container:
+
+- `dockerfilePath` - **Required.** Path to Dockerfile relative to repo root
+- `command` - Override container entrypoint
+- `arguments` - Arguments passed to the command. Use `%%SPLIT%%` as a delimiter for spaces (e.g., `-c%%SPLIT%%npm run start`)
+- `env` - Environment variables
+- `ports` - Exposed container ports
+
+### docker.init (Optional)
+
+Configuration for an init container that runs before the main application. Uses the same fields as `docker.app`.
+
+## Complete Fields Reference
+
+| Field | Type | Required | Description |
+| ------------------ | ------ | ---------- | ------------------------- |
+| `chart.name` | string | **Yes** | Chart name or path |
+| `chart.repoUrl` | string | For public | Helm repository URL |
+| `chart.version` | string | No | Chart version |
+| `chart.values` | array | No | Inline Helm values |
+| `chart.valueFiles` | array | No | Value file paths |
+| `repository` | string | For builds | GitHub repository |
+| `branchName` | string | For builds | Branch to build from |
+| `docker` | object | No | Docker build config |
+| `args` | string | No | Additional Helm arguments |
+| `version` | string | No | Helm CLI version |
+| `deploymentMethod` | string | No | `"native"` or `"ci"` |
+
+## Templated Variables
+
+Use templated variables in chart values to reference dynamic deployment values. See the [Template Variables](/docs/features/template-variables) guide for the complete list.
+
+
+ Use triple braces `{{{variable}}}` for Lifecycle template variables. This prevents Helm from trying to process them as Helm template functions.
+
+
+## Native Helm Deployment
+
+For more control over Helm deployments, enable native Helm:
+
+```yaml filename="lifecycle.yaml"
+services:
+ - name: "api"
+ helm:
+ deploymentMethod: "native" # Enable native Helm
+ # ... rest of config
+```
+
+Native Helm provides:
+
+- Direct Kubernetes job execution
+- Real-time deployment logs
+- Better handling of concurrent deployments
+- Full Helm argument control
+
+See the [Native Helm Deployment](/docs/features/native-helm-deployment) guide for details.
diff --git a/src/pages/docs/schema/overview.mdx b/src/pages/docs/schema/overview.mdx
new file mode 100644
index 0000000..0b917b3
--- /dev/null
+++ b/src/pages/docs/schema/overview.mdx
@@ -0,0 +1,167 @@
+---
+title: Schema Overview
+description: Introduction to the lifecycle.yaml configuration file and its structure
+tags:
+ - schema
+ - configuration
+ - lifecycle.yaml
+---
+
+import { Callout } from "nextra/components";
+
+The `lifecycle.yaml` file is the core configuration file that defines how Lifecycle manages your ephemeral environments. Place this file at the root of your repository.
+
+## File Structure
+
+A `lifecycle.yaml` file has three main sections:
+
+```yaml filename="lifecycle.yaml"
+version: "1.0.0" # Schema version
+
+environment: # Environment-level configuration
+ autoDeploy: true
+ defaultServices:
+ - name: "my-service"
+ # optionalServices, webhooks, etc.
+
+services: # Service definitions
+ - name: "my-service"
+ github: # Service type configuration
+ # ...
+```
+
+| Section | Description |
+| ------------- | ------------------------------------------------------------ |
+| `version` | Schema version (currently `"1.0.0"`) |
+| `environment` | Controls deployment behavior, service grouping, and webhooks |
+| `services` | Array of service definitions with their configurations |
+
+## Service Types
+
+Each service in the `services` array must have exactly one service type configured. Choose based on your deployment needs:
+
+| Service Type | Use Case |
+| ------------------------------------------------ | ----------------------------------------------------------------- |
+| [**github**](/docs/schema/github) | Build and deploy from a GitHub repository with Dockerfile |
+| [**docker**](/docs/schema/docker) | Deploy pre-built Docker images (databases, caches, etc.) |
+| [**helm**](/docs/schema/helm) | Deploy using Helm charts (local or remote) |
+| [**codefresh**](/docs/schema/codefresh) | Trigger external Codefresh pipelines for deployment |
+| [**auroraRestore**](/docs/schema/aurora-restore) | Restore AWS Aurora database snapshots |
+| [**configuration**](/docs/schema/configuration) | Deploy configuration-only services (feature flags, shared config) |
+
+## Choosing a Service Type
+
+```
+Do you need to build from source?
+├─ Yes → Do you need custom Helm charts?
+│ ├─ Yes → helm (with docker section)
+│ └─ No → github
+└─ No → Is it a pre-built image?
+ ├─ Yes → docker
+ └─ No → Do you need Helm charts?
+ ├─ Yes → helm (without docker section)
+ └─ No → Is it a CI/CD pipeline?
+ ├─ Yes → codefresh
+ └─ No → configuration or auroraRestore
+```
+
+## Minimal Example
+
+Here's the simplest valid `lifecycle.yaml` for a single service:
+
+```yaml filename="lifecycle.yaml"
+version: "1.0.0"
+
+environment:
+ defaultServices:
+ - name: "api"
+
+services:
+ - name: "api"
+ github:
+ repository: "myorg/api"
+ branchName: "main"
+ docker:
+ defaultTag: "main"
+ app:
+ dockerfilePath: "Dockerfile"
+ ports:
+ - 3000
+```
+
+## Complete Example
+
+A more complete example with multiple service types:
+
+```yaml filename="lifecycle.yaml"
+version: "1.0.0"
+
+environment:
+ autoDeploy: true
+ defaultServices:
+ - name: "api"
+ - name: "database"
+ optionalServices:
+ - name: "cache"
+ repository: "myorg/services"
+ branch: "main"
+ webhooks:
+ - name: "E2E Tests"
+ state: deployed
+ type: docker
+ docker:
+ image: "myorg/e2e-tests:latest"
+ env:
+ TEST_URL: "https://{{api_publicUrl}}"
+
+services:
+ # Build from GitHub repository
+ - name: "api"
+ github:
+ repository: "myorg/api"
+ branchName: "main"
+ docker:
+ defaultTag: "main"
+ app:
+ dockerfilePath: "Dockerfile"
+ ports:
+ - 3000
+ deployment:
+ public: true
+
+ # Pre-built Docker image
+ - name: "database"
+ docker:
+ dockerImage: "postgres"
+ defaultTag: "15-alpine"
+ ports:
+ - 5432
+ env:
+ POSTGRES_USER: "app"
+ POSTGRES_PASSWORD: "secret"
+ POSTGRES_DB: "myapp"
+ deployment:
+ public: false
+
+ # Pre-built Docker image (optional)
+ - name: "cache"
+ docker:
+ dockerImage: "redis"
+ defaultTag: "7-alpine"
+ ports:
+ - 6379
+```
+
+## Template Variables
+
+Throughout your configuration, you can use template variables like `{{api_publicUrl}}` or `{{database_internalHostname}}` to reference dynamic values from other services.
+
+See the [Template Variables](/docs/features/template-variables) guide for the complete list of available variables and usage examples.
+
+## Next Steps
+
+- [Environment Configuration](/docs/schema/environment) - Configure deployment behavior and service grouping
+- [Webhooks](/docs/schema/webhooks) - Automate actions on deployment events
+- [GitHub Service](/docs/schema/github) - Build and deploy from source
+- [Docker Service](/docs/schema/docker) - Deploy pre-built images
+- [Helm Service](/docs/schema/helm) - Deploy with Helm charts
diff --git a/src/pages/docs/schema/webhooks.mdx b/src/pages/docs/schema/webhooks.mdx
new file mode 100644
index 0000000..12420bb
--- /dev/null
+++ b/src/pages/docs/schema/webhooks.mdx
@@ -0,0 +1,121 @@
+---
+title: Webhooks Configuration
+description: Schema reference for configuring webhooks to automate actions on deployment events
+tags:
+ - schema
+ - webhooks
+ - automation
+ - codefresh
+ - docker
+---
+
+import { Callout } from "nextra/components";
+
+Webhooks allow you to trigger automated actions when an environment reaches certain states. They are configured under `environment.webhooks` in your `lifecycle.yaml`.
+
+
+ For detailed use cases, examples, and execution behavior, see the
+ [Webhooks](/docs/features/webhooks) guide.
+
+
+## Common Fields
+
+All webhook types share these common fields:
+
+| Field | Type | Required | Description |
+| ------------- | ------ | -------- | -------------------------------------------------- |
+| `name` | string | No | Human-readable name for the webhook |
+| `description` | string | No | Description of what the webhook does |
+| `state` | string | **Yes** | Trigger state: `deployed`, `error`, or `torn_down` |
+| `type` | string | **Yes** | Webhook type: `codefresh`, `docker`, or `command` |
+| `env` | object | **Yes** | Environment variables passed to the webhook |
+
+## Trigger States
+
+| State | Description |
+| ----------- | ---------------------------------------------- |
+| `deployed` | All services successfully deployed and running |
+| `error` | Build or deployment failed |
+| `torn_down` | Environment has been destroyed |
+
+## Webhook Types
+
+### codefresh
+
+Triggers an existing Codefresh pipeline.
+
+| Field | Type | Required | Description |
+| ------------ | ------ | -------- | --------------------- |
+| `pipelineId` | string | Yes | Codefresh pipeline ID |
+| `trigger` | string | No | Pipeline trigger name |
+
+```yaml filename="lifecycle.yaml"
+environment:
+ webhooks:
+ - name: "Run E2E Tests"
+ state: deployed
+ type: codefresh
+ pipelineId: "64598362453cc650c0c9cd4d"
+ trigger: "tests"
+ env:
+ BRANCH: "{{api_branchName}}"
+```
+
+### docker
+
+Runs a Docker image as a Kubernetes job.
+
+| Field | Type | Required | Description |
+| ---------------- | ------ | -------- | --------------------------------------------- |
+| `docker.image` | string | **Yes** | Docker image to execute |
+| `docker.command` | array | No | Override entrypoint command |
+| `docker.args` | array | No | Arguments to pass to the command |
+| `docker.timeout` | number | No | Max execution time in seconds (default: 1800) |
+
+```yaml filename="lifecycle.yaml"
+environment:
+ webhooks:
+ - name: "Integration Tests"
+ state: deployed
+ type: docker
+ docker:
+ image: "myorg/integration-tests:latest"
+ command: ["npm", "run", "test"]
+ timeout: 3600
+ env:
+ API_URL: "https://{{api_publicUrl}}"
+```
+
+### command
+
+Runs a shell script in a specified Docker image.
+
+| Field | Type | Required | Description |
+| ----------------- | ------ | -------- | --------------------------------------------- |
+| `command.image` | string | **Yes** | Docker image to run the script in |
+| `command.script` | string | **Yes** | Shell script to execute |
+| `command.timeout` | number | No | Max execution time in seconds (default: 1800) |
+
+```yaml filename="lifecycle.yaml"
+environment:
+ webhooks:
+ - name: "Slack Notification"
+ state: deployed
+ type: command
+ command:
+ image: "alpine:latest"
+ script: |
+ apk add --no-cache curl
+ curl -X POST "$SLACK_WEBHOOK" \
+ -H "Content-Type: application/json" \
+ -d '{"text":"Deployed to $URL"}'
+ env:
+ SLACK_WEBHOOK: "https://hooks.slack.com/services/XXX"
+ URL: "https://{{api_publicUrl}}"
+```
+
+## Template Variables
+
+You can use template variables like `{{api_publicUrl}}` in the `env` section to reference dynamic values from your services.
+
+See the [Template Variables](/docs/features/template-variables) guide for the complete list of available variables.