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.