YAML Formatter & Validator

Format YAML, validate it, and convert between YAML and JSON — without losing comments

Clean up YAML with a CodeMirror-powered editor, validate it for syntax errors with line-and-column feedback, and convert in either direction between YAML and JSON. Comments and key order are preserved — important for Kubernetes manifests, Docker Compose files, Ansible playbooks, and GitHub Actions workflows. Includes a CI/CD template library with 25+ production-ready examples.

Input YAML

Loading editor…

Formatted YAML
comments preserved

Paste YAML on the left to format it here.

CI/CD YAML template library

Production-shaped YAML for the platforms developers ask about. Click a template to load it into the editor — format, validate, convert to JSON, or copy as-is.

Deployment, Service, Ingress, ConfigMap, Secret, Job, CronJob, HPA — all production-shaped.

Deployment

A typical Deployment with 3 replicas, resource limits, and a readiness probe.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-app
  labels:
    app: example
spec:
  replicas: 3
  selector:
    matchLabels:
      app: example
  template:
    metadata:
      labels:
        app: example
    spec:
      containers:
        - name: example
          image: example/api:1.4.2
          ports:
            - containerPort: 8080
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 500m
              memory: 512Mi
          readinessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10
Service

ClusterIP Service exposing port 80 -> targetPort 8080.

apiVersion: v1
kind: Service
metadata:
  name: example-svc
spec:
  selector:
    app: example
  ports:
    - name: http
      port: 80
      targetPort: 8080
  type: ClusterIP
Ingress

NGINX Ingress with TLS via cert-manager annotation.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - app.example.com
      secretName: app-tls
  rules:
    - host: app.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: example-svc
                port:
                  number: 80
ConfigMap

ConfigMap with mixed key/value pairs and a multi-line config file.

apiVersion: v1
kind: ConfigMap
metadata:
  name: example-config
data:
  LOG_LEVEL: info
  DATABASE_HOST: postgres
  app.properties: |
    server.port=8080
    server.shutdown=graceful
    logging.format=json
Secret (Opaque)

Secret holding base64-encoded values. Use kubectl create secret in real usage.

apiVersion: v1
kind: Secret
metadata:
  name: example-secret
type: Opaque
data:
  DATABASE_PASSWORD: c3VwZXJzZWNyZXQ=
  API_TOKEN: dG9rZW4tdmFsdWU=
Job (one-shot)

Single-shot Job with backoffLimit and TTL after completion.

apiVersion: batch/v1
kind: Job
metadata:
  name: db-migrate
spec:
  backoffLimit: 3
  ttlSecondsAfterFinished: 600
  template:
    spec:
      restartPolicy: OnFailure
      containers:
        - name: migrate
          image: example/migrate:1.4.2
          command: ["./migrate", "up"]
CronJob

Daily CronJob with concurrencyPolicy: Forbid.

apiVersion: batch/v1
kind: CronJob
metadata:
  name: nightly-cleanup
spec:
  schedule: "0 2 * * *"
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
            - name: cleanup
              image: alpine:3.20
              command: ["/bin/sh", "-c", "echo nightly cleanup"]
HorizontalPodAutoscaler

CPU-based HPA scaling between 2 and 10 replicas.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: example-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: example-app
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
NetworkPolicy

Default-deny ingress with an exception for the frontend namespace.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: example-allow-frontend
spec:
  podSelector:
    matchLabels:
      app: example
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              name: frontend
      ports:
        - protocol: TCP
          port: 8080

YAML Reference

The 80% of YAML you actually use — syntax, gotchas, formatting choices, and the differences between YAML 1.1 and YAML 1.2 that trip people up.

Quick syntax overview

YAML uses indentation (always spaces — never tabs) to denote structure. The same data can be written in block form (the readable default) or flow form (JSON-like).

Block form
server:
  host: example.com
  port: 8080
  hosts:
    - 192.168.1.1
    - 192.168.1.2
Flow form (JSON-like)
server: { host: example.com, port: 8080, hosts: [192.168.1.1, 192.168.1.2] }

YAML 1.1 vs YAML 1.2 — the gotchas

ValueYAML 1.1 reads asYAML 1.2 reads asNotes
yes / notrue / falsestringThe famous “Norway problem”.
on / offtrue / falsestringBites GitHub Actions YAML where “on:” is a real key.
y / Y / n / Ntrue / falsestringAvoid using single-letter bools entirely.
012octal 10stringYAML 1.2 requires 0o prefix for octal.
3:00number (sexagesimal)stringOld base-60 parsing — gone in 1.2.

Defensive fix: quote any string that looks boolean-ish ("yes", "no", "on", "off"). Our formatter uses YAML 1.2 semantics, but older Ansible (≤ 2.9) and js-yaml in “legacy” mode still use 1.1.

Multi-line strings — | vs > vs "

| (literal block)

Preserves newlines. Use for scripts, config files inside ConfigMap, multi-line text.

script: |
  set -e
  echo hello
  echo world

> (folded block)

Newlines fold into spaces. Use for long descriptions that should wrap.

description: >
  This is a very long
  description that will
  end up on one line.

|- (strip trailing newlines)

Same as | but drops the trailing newline.

|+ (keep all trailing newlines)

Same as | but preserves trailing blank lines.

Anchors and aliases

&name defines an anchor, *name references it. Common in Docker Compose (DRY ports/networks) and CircleCI configs.

defaults: &defaults
  restart: unless-stopped
  logging:
    driver: json-file

services:
  web:
    <<: *defaults
    image: web:latest
  api:
    <<: *defaults
    image: api:latest

Our formatter preserves anchors and aliases (some formatters expand them, which loses intent).

Gotchas worth a one-liner

  • Tabs are forbidden. Always indent with spaces. Configure your editor to convert tab-to-spaces in .yaml files.
  • Trailing whitespace can change how some parsers handle multi-line strings — strip it.
  • Duplicate keys are valid in YAML 1.2 syntax but most parsers reject them. Our validator surfaces them as warnings.
  • Document separator (---) is required when you put multiple YAML docs in one file. Single-doc YAML doesn't need it.
  • Colons in unquoted strings (e.g. message: Hello: World) cause a parse error. Quote the value.
  • Empty values are null, not the empty string. x: = null; x: "" = empty string.

Frequently Asked Questions

Common questions about YAML formatting, JSON conversion, Kubernetes / Docker Compose / Ansible / GitHub Actions YAML, and YAML 1.1 vs 1.2 gotchas.