Skip to content

Views

Views are how you actually look at your architecture. Think of them as different camera angles on the same movie set — your models are the actors, and views are how you frame the shot. A landscape view is the sweeping helicopter shot showing everything. A component view is the intimate close-up on a single character’s face. Without views, you’ve got a bunch of models sitting in a database that nobody can see. With views, you’ve got architecture diagrams that actually tell a story.

View Types

buildzr supports all major C4 model view types:

  • System Landscape View: Shows all systems and people across your entire organization
  • System Context View: Focuses on a single system and what it depends on or talks to
  • Container View: Zooms into a system to show its applications, databases, and services
  • Component View: Drills into a container to reveal its internal code structure
  • Deployment View: Maps containers to actual infrastructure (servers, clusters, cloud resources)

System Landscape View

The SystemLandscapeView is your 30,000-foot view — it shows every software system and every person in your organization’s ecosystem. This is the view you show to executives who want to see “everything” without actually wanting to understand anything. It answers the question: “What systems do we even have?”

# norun
SystemLandscapeView(
    key='landscape',
    description='Enterprise System Landscape',
    auto_layout='tb'
)

Example

from buildzr.dsl import Workspace, Person, SoftwareSystem, SystemLandscapeView, Group

with Workspace('w') as w:
    with Group("Users"):
        customer = Person('Customer')

    with Group("Internal"):
        web = SoftwareSystem('Web App')
        api = SoftwareSystem('API')

    with Group("External"):
        payment = SoftwareSystem('Payment Gateway')

    customer >> "Uses" >> web
    web >> "Calls" >> api
    api >> "Processes payments via" >> payment

    SystemLandscapeView(
        key='landscape',
        description='System Landscape',
        auto_layout='lr'
    )

    w.to_json('workspace.json')

System Context View

Zoom in one level, and you’ve got the SystemContextView. This shows a single software system surrounded by everything it talks to — users, external systems, databases, or external APIs (including free or third-party services).

# norun
SystemContextView(
    software_system_selector=my_system,
    key='context',
    description='System Context for My System',
    auto_layout='tb'
)

Example

from buildzr.dsl import Workspace, Person, SoftwareSystem, SystemContextView

with Workspace('w') as w:
    user = Person('User')
    system = SoftwareSystem('My System')
    email = SoftwareSystem('Email System', tags=['external'])
    database = SoftwareSystem('Legacy Database', tags=['external'])

    user >> "Uses" >> system
    system >> "Sends emails via" >> email
    system >> "Reads data from" >> database

    SystemContextView(
        software_system_selector=system,
        key='system-context',
        description='My System Context',
        auto_layout='tb'
    )

    w.to_json('workspace.json')

Container View

Open up that system and peer inside! The ContainerView shows you all the applications, databases, microservices, and other runtime components that make up a software system. This is where you start seeing the actual architecture — web apps talking to APIs, APIs talking to databases, message queues doing their queuey thing.

# norun
ContainerView(
    software_system_selector=my_system,
    key='containers',
    description='Container View',
    auto_layout='tb'
)

Example

from buildzr.dsl import (
    Workspace,
    Person,
    SoftwareSystem,
    Container,
    ContainerView,
)

with Workspace('w') as w:
    user = Person('User')
    system = SoftwareSystem('Web Application')

    with system:
        web = Container('Web App', technology='React')
        api = Container('API', technology='FastAPI')
        db = Container('Database', technology='PostgreSQL')

    user >> "Uses" >> web
    web >> ("Calls", "REST/HTTPS") >> api
    api >> ("Reads/Writes", "SQL") >> db

    ContainerView(
        software_system_selector=system,
        key='containers',
        description='Web Application Containers',
        auto_layout='tb'
    )

    w.to_json('workspace.json')

Component View

The ComponentView shows the most granular level of detail in the C4 model. It reveals the internal structure of a single container — the controllers, services, repositories, and other architectural layers that live inside. This is the view developers care about most, because it shows where the code lives and how it’s organized.

# norun
ComponentView(
    container_selector=my_container,
    key='components',
    description='Component View',
    auto_layout='tb'
)

Example

from buildzr.dsl import (
    Workspace,
    SoftwareSystem,
    Container,
    Component,
    ComponentView,
)

with Workspace('w') as w:
    system = SoftwareSystem('System')

    with system:
        api = Container('API')

        with api:
            controller = Component('REST Controller')
            service = Component('Business Service')
            repository = Component('Data Repository')

        database = Container('Database')

    controller >> "Uses" >> service
    service >> "Uses" >> repository
    repository >> ("Queries", "SQL") >> database

    ComponentView(
        container_selector=api,
        key='api-components',
        description='API Components',
        auto_layout='tb'
    )

    w.to_json('workspace.json')

Deployment View

Time to get physical! The DeploymentView shows where your containers actually run — which cloud provider, which region, which servers, which Docker containers on which Kubernetes clusters in which data centers. For this reason, DeploymentNodes can be nested indefinitely. This is the bridge between your beautiful logical architecture and the messy reality of infrastructure. DevOps engineers live here.

# norun
DeploymentView(
    software_system_selector=my_system,
    environment='Production',
    key='deployment',
    description='Production Deployment',
    auto_layout='tb'
)

Example

from buildzr.dsl import (
    Workspace,
    SoftwareSystem,
    Container,
    DeploymentEnvironment,
    DeploymentNode,
    ContainerInstance,
    DeploymentView,
)

with Workspace('w') as w:
    system = SoftwareSystem('Web App')

    with system:
        api = Container('API', technology='Python')
        db = Container('Database', technology='PostgreSQL')

    with DeploymentEnvironment('Production') as prod:
        with DeploymentNode('AWS', technology='Cloud'):
            with DeploymentNode('ECS Cluster', technology='Docker'):
                api_instance = ContainerInstance(api)

            with DeploymentNode('RDS', technology='Managed Service'):
                db_instance = ContainerInstance(db)

    DeploymentView(
        software_system_selector=system,
        environment=prod,
        key='prod-deployment',
        description='Production Deployment',
        auto_layout='tb'
    )

    w.to_json('workspace.json')

Auto Layout

Views without layout are just random boxes scattered across a canvas like a toddler’s finger painting. The auto_layout parameter tells buildzr how to arrange elements so humans can actually understand them. You’ve got four directions to choose from:

  • 'tb' - Top to bottom (default) - Classic hierarchy style
  • 'bt' - Bottom to top - For when you want to be contrarian
  • 'lr' - Left to right - Great for process flows and timelines
  • 'rl' - Right to left - For RTL languages or just mixing things up
# norun
SystemContextView(
    software_system_selector=system,
    key='context-horizontal',
    auto_layout='lr'  # Left to right
)

Choosing the Right Direction

Use 'tb' for hierarchical relationships (user → app → database). Use 'lr' for sequential processes (request → auth → process → response). Use 'bt' if you’re feeling rebellious. Use 'rl' if… well, probably just stick with the first two. Or if you speak Arabic.

Including/Excluding Elements

Sometimes your view has too much clutter. Maybe there’s an internal admin system that’s technically part of the architecture but would just confuse the audience. Or maybe you only want to highlight specific critical components. That’s where including and excluding elements comes in — it’s like Photoshopping your ex out of vacation photos, but for architecture diagrams.

Exclude Specific Elements

Remove the stuff you don’t want anyone to see (for now):

# norun
SystemContextView(
    software_system_selector=system,
    key='context',
    exclude_elements=[internal_admin, test_system]  # Pretend these don't exist
)

Include Specific Elements

Or flip it around — to include additional containers that otherwise have not have been included in the view:

# norun
# critical_container is not part of system, but we want to include it in the
# view too!
ContainerView(
    software_system_selector=system,
    key='containers',
    include_elements=[critical_container]
)

View Best Practices

Create Multiple Views

You need more than one view. Different people need different levels of detail. Your CEO doesn’t want to see your repository pattern implementation, and your backend developer doesn’t care about the landscape view. Create views for your audience:

# High-level for executives who ask "what does it do?"
SystemLandscapeView(key='landscape')

# Mid-level for architects who ask "how does it work?"
SystemContextView(software_system_selector=system, key='context')

# Detailed for developers who ask "where's the bug?"
ContainerView(software_system_selector=system, key='containers')
ComponentView(container_selector=api, key='components')

Use Descriptive Keys and Descriptions

Future you (or worse, someone else) will thank you for clear, descriptive names. Don’t be cryptic:

# Good - clear and informative
SystemContextView(
    software_system_selector=payment_system,
    key='payment-system-context',
    description='Payment System and External Dependencies'
)

# Bad - might as well be lorem ipsum
SystemContextView(
    software_system_selector=payment_system,
    key='view1',
    description='System View'
)

Choose Appropriate Layouts

Match your layout direction to your diagram’s natural flow:

# norun
# Hierarchical flow - use top-to-bottom
ContainerView(
    software_system_selector=system,
    key='containers',
    auto_layout='tb'  # User at top, database at bottom
)

# Process flow - use left-to-right
SystemContextView(
    software_system_selector=system,
    key='context',
    auto_layout='lr'  # Request flows left to right, like reading
)

Complete Example

Let’s bring it all together with a full example that creates multiple views of an e-commerce system. Notice how we define the models once, then create different views for different audiences.

Enable implied_relationships

The example below uses implied relationships. Otherwise, the SystemLandscapeView won’t show any relationships between the SoftwareSystems and the Person!

from buildzr.dsl import (
    Workspace,
    Person,
    SoftwareSystem,
    Container,
    Component,
    Group,
    SystemLandscapeView,
    SystemContextView,
    ContainerView,
    ComponentView,
)

with Workspace('multi-view-example', implied_relationships=True) as w:
    # Model
    with Group("Users"):
        customer = Person('Customer')

    with Group("E-Commerce"):
        ecommerce = SoftwareSystem('E-Commerce Platform')

        with ecommerce:
            web = Container('Web App', technology='React')
            api = Container('API', technology='Node.js')

            with api:
                order_ctrl = Component('Order Controller')
                order_svc = Component('Order Service')
                order_repo = Component('Order Repository')

            db = Container('Database', technology='MongoDB')

    with Group("External"):
        payment = SoftwareSystem('Payment Gateway')

    # Relationships
    customer >> "Browses and purchases" >> web
    web >> ("Calls", "REST") >> api
    api >> ("Stores", "MongoDB") >> db
    order_ctrl >> "Uses" >> order_svc
    order_svc >> "Uses" >> order_repo
    order_repo >> "Queries" >> db
    api >> ("Processes payments", "REST") >> payment

    # Multiple views for different audiences
    SystemLandscapeView(
        key='landscape',
        description='All Systems'
    )

    SystemContextView(
        software_system_selector=ecommerce,
        key='ecommerce-context',
        description='E-Commerce System Context',
        auto_layout='tb'
    )

    ContainerView(
        software_system_selector=ecommerce,
        key='ecommerce-containers',
        description='E-Commerce Containers',
        auto_layout='tb'
    )

    ComponentView(
        container_selector=api,
        key='api-components',
        description='API Components',
        auto_layout='lr'
    )

    w.to_json('workspace.json')

Next Steps