Back to catalog

yaml-driven-architecture

Apply YAML-driven architecture-as-code patterns for system definition, configuration management, and automated generation. Use when designing configuration schemas, building code generators, or implementing declarative architecture definitions.

  • Category: discovered
  • Tags: github, community
  • Version: 1.0.0
  • Author: walid
  • Downloads: 0
  • Updated: 2025-11-22

Download the latest version (v1.0.0) from this page.

SKILL.md

---
name: yaml-driven-architecture
description: Apply YAML-driven architecture-as-code patterns for system definition, configuration management, and automated generation. Use when designing configuration schemas, building code generators, or implementing declarative architecture definitions.
---

# YAML-Driven Architecture Patterns

Apply these patterns when building systems that transform declarative YAML specifications into architecture artifacts.

## Core Pipeline

```
YAML → Validation → Model → Transform → Output
```

**Stages**:
1. **Parse**: YAML files to data structures
2. **Validate**: Schema compliance (Pydantic/JSON Schema)
3. **Model**: Type-safe internal representation
4. **Transform**: Apply business logic/templates
5. **Generate**: Code, docs, diagrams, configs

## YAML Design Principles

### Hierarchy and Nesting
```yaml
system:                    # Top level
  modules:                 # Second level
    - components:          # Third level
        - functions:       # Fourth level (max depth)
```

**Rules**:
- Maximum 4 levels deep (readability limit)
- Use references for deeper structures
- Group related items at same level

### Convention Over Configuration
```yaml
# Minimal required config
name: payment-service

# Conventions provide defaults:
# - language: inferred from tooling.yaml
# - directory: ./src/{name}/
# - tests: ./tests/{name}/
```

### Type Detection Patterns
Use filename conventions for automatic type detection:
```
system*.yaml      → SystemContext
module*.yaml      → ModuleView
component*.yaml   → ComponentView
contracts*.yaml   → ContractsView
tooling.yaml      → ProjectTooling
```

## Schema Definition

### Pydantic Models
```python
class Component(BaseModel):
    """Strict validation with forbidden extras"""
    id: str
    name: str
    module_id: str
    description: str

    class Config:
        extra = "forbid"  # Catch typos
        validate_assignment = True
```

### Field Validation
```yaml
component:
  id: order-processor      # kebab-case, no spaces
  type: service            # enum: [service, library, database]
  ports:
    - protocol: HTTP       # enum: [HTTP, gRPC, AMQP]
      format: JSON         # enum: [JSON, XML, protobuf]
```

## Generation Patterns

### Template-Based Generation
```python
# Functional pipeline
def generate_module(module: ModuleView, tooling: ProjectTooling) -> str:
    """Pure function: model → output"""
    template = load_template("module.h.j2")
    return template.render(
        module=module,
        config=tooling
    )
```

### Multi-Output Generation
```yaml
# Single source → multiple outputs
module:
  id: physics
  outputs:
    - template: module.h.j2
      path: src/physics/module.h
    - template: module.md.j2
      path: docs/physics.md
    - template: module.test.j2
      path: tests/physics_test.cpp
```

## Relationship Management

### ID-Based References
```yaml
# Use IDs for relationships, not inline definitions
modules:
  - id: payment
    depends_on: [auth, database]  # References by ID

  - id: auth
    provides: [authenticate, authorize]

  - id: database
    type: external
```

### Bidirectional Validation
```python
def validate_relationships(system: SystemModel):
    """Ensure all references exist"""
    for module in system.modules:
        for dep in module.depends_on:
            if not system.has_module(dep):
                raise ValueError(f"Unknown dependency: {dep}")
```

## Configuration Patterns

### Environment Layering
```yaml
# base.yaml
database:
  type: postgresql
  pool_size: 10

# dev.yaml (overrides)
database:
  host: localhost
  pool_size: 2

# prod.yaml (overrides)
database:
  host: db.production.internal
  pool_size: 50
```

### Feature Flags
```yaml
features:
  experimental:
    enabled: false
    components: []

  stable:
    enabled: true
    components: [auth, payment, shipping]
```

## Error Handling

### Validation Errors
```yaml
# Provide context in errors
❌ Error: Invalid field 'component.typ'
✅ Error at component-auth.yaml:15:
   Unknown field 'typ'. Did you mean 'type'?
   Valid fields: [id, name, type, description]
```

### Schema Evolution
```yaml
# Version your schemas
version: 2.0
compatibility: backwards  # or: breaking, forward

# Migration path
migrate:
  from: 1.0
  changes:
    - rename: container → module
    - remove: deprecated_field
    - add: new_field (default: null)
```

## Best Practices

### DO:
- **Validate early**: Catch errors at YAML level
- **Use anchors**: For repeated configurations
- **Provide defaults**: Minimize required fields
- **Version schemas**: Track breaking changes
- **Generate schemas**: From code models
- **Support includes**: For modular configs

### DON'T:
- **Mix concerns**: Separate config from code
- **Use complex logic**: YAML isn't a programming language
- **Nest deeply**: Flatten or use references
- **Ignore errors**: Fail fast with clear messages
- **Hardcode paths**: Use relative or configured paths

## Example Architecture Pipeline

```yaml
# .archctl/system.yaml
system:
  name: order-management
  modules: [orders, inventory, shipping]

# .archctl/modules.yaml
modules:
  - id: orders
    components: [api, service, repository]
    depends_on: [inventory]

# .archctl/tooling.yaml
tooling:
  language: python
  directories:
    source: src
    tests: tests
    docs: docs
```

**Generation command**:
```bash
archctl generate  # Reads .archctl/*.yaml → generates all outputs
```

**Output structure**:
```
src/
  orders/
    module.py      # Generated module interface
    __init__.py    # Generated exports
docs/
  orders.md        # Generated documentation
tests/
  test_orders.py   # Generated test stubs
```

## Quality Checklist

- [ ] Schema validates all inputs
- [ ] Errors provide helpful context
- [ ] Generation is deterministic
- [ ] Templates are maintainable
- [ ] Relationships are validated
- [ ] Conventions reduce boilerplate
- [ ] File organization is clear
- [ ] Pipeline stages are pure functions

**Remember**: YAML is for configuration, not computation. Keep logic in the generators, use YAML for declarative specification.