# josevelazcoh/erdalchemy architecture

> Architecture diagram of the GitHub repository josevelazcoh/erdalchemy, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-23). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/josevelazcoh/erdalchemy
- Repository: https://github.com/josevelazcoh/erdalchemy

## Overview

1. **Purpose and top-level flow**
   This repository is a self-contained ERD generator for SQLAlchemy 2.0 models. The main pipeline is: take a `DeclarativeBase`, introspect tables and foreign keys, build an internal schema graph, lay it out, route edges, and export the result as interactive HTML or static image formats.

2. **Primary entry points**
   There are two user-facing entry points:
   - the Python API exposed from `sqlalchemy_erd` via `generate_erd(...)`
   - the CLI in `src/sqlalchemy_erd/cli.py`, which loads a target base class from a module path like `myapp.models:Base`
   Both paths converge into the same core generation pipeline.

3. **Schema introspection boundary**
   `introspect.py` is the boundary between SQLAlchemy models and the renderer. It reads mapped tables, columns, schemas, and foreign-key relationships from the provided declarative base and turns them into the repository’s internal graph representation. This is where multi-schema support and table/column filtering are applied.

4. **Internal model and serialization**
   `serialization.py` appears to define the portable data shape used across the rest of the pipeline. That matters because the layout and rendering subsystems should not depend directly on SQLAlchemy objects; they consume a normalized schema graph instead.

5. **Layout subsystem**
   The layout layer is split into selectable strategies:
   - `layered.py` for the default hierarchical FK-driven layout
   - `force.py` for force-directed placement
   - `star.py` for hub-and-spoke or disconnected schemas
   - `layout_select.py` chooses the strategy
   - `layout.py` provides shared layout primitives/data structures
   This is the main architectural decision point for how tables are positioned on the canvas.

6. **Edge routing subsystem**
   `edge_routing.py` handles orthogonal routing of foreign-key edges so connectors avoid cutting through table cards. This is separate from node placement, which is important for diagram readability: layout decides where tables sit, routing decides how relationships are drawn between them.

7. **Rendering and export**
   Rendering is split from layout:
   - `renderer.py` / `render.py` are the core rendering layer
   - `html_renderer.py` generates the interactive browser-based output
   - `export.py` manages output formats such as HTML, SVG, PNG, and PDF
   The README indicates PNG/PDF need an optional dependency, so static image export is an add-on boundary rather than a hard runtime dependency.

8. **Theming and presentation**
   `theme.py` controls visual styling, including built-in themes and per-table color overrides. This is the presentation layer that sits on top of the structural diagram, allowing the same schema graph to be rendered with different visual identities.

9. **Interactive HTML as a first-class output**
   The flagship output is the interactive HTML diagram: draggable cards, hover highlighting, and routed connectors. That makes the browser output the most feature-rich artifact, while SVG/PNG/PDF are simpler export targets derived from the same underlying diagram model.

10. **Filtering and scale management**
   The repo supports regex-based include/exclude filtering for tables and columns, which is an important scaling mechanism for large schemas. This likely happens before layout so the graph size is reduced early and all downstream steps work on a smaller subgraph.

11. **Examples as architecture references**
   The `examples/` directory is not just demos; it demonstrates the major schema shapes the system is designed to handle:
   - simple blog/ecommerce chains
   - N:N association tables
   - 1:1 and 1:N relationships
   - multi-schema cross-schema foreign keys
   - larger showcase graphs
   These examples show the intended input diversity and validate the layout strategies.

12. **Repo constraints and runtime boundary**
   The project emphasizes “zero dependencies beyond SQLAlchemy” for core use, with optional extras for richer exports. That constraint strongly shapes the architecture: introspection, layout, routing, and HTML generation are all implemented inside the package rather than delegated to heavier external graphing libraries.

Main entry points: [`tests`](https://github.com/josevelazcoh/erdalchemy/tree/main/tests) (Behavior tests), [`src/sqlalchemy_erd/layout_select.py`](https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/layout_select.py) (Strategy picker), [`src/sqlalchemy_erd/renderer.py`](https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/renderer.py) (Renderer), [`src/sqlalchemy_erd/__init__.py`](https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/__init__.py) (Public API)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_src["Source package"]
  node_api["Public API<br/>entrypoint<br/>[__init__.py]"]
  node_cli["CLI<br/>entrypoint<br/>[cli.py]"]
  node_introspect["Introspection<br/>schema scan<br/>[introspect.py]"]
  node_serialization["Schema model<br/>data model<br/>[serialization.py]"]
  node_layout_select["Strategy picker<br/>layout dispatch<br/>[layout_select.py]"]
  node_layout["Layout core<br/>layout primitives<br/>[layout.py]"]
  node_layered["Layered layout<br/>layout strategy<br/>[layered.py]"]
  node_force["Force layout<br/>layout strategy<br/>[force.py]"]
  node_star["Star layout<br/>layout strategy<br/>[star.py]"]
  node_edge_routing["Edge routing<br/>connector routing<br/>[edge_routing.py]"]
  node_render["Render core<br/>render pipeline<br/>[render.py]"]
  node_renderer["Renderer<br/>presentation layer<br/>[renderer.py]"]
  node_html_renderer["HTML output<br/>interactive export<br/>[html_renderer.py]"]
  node_export["Export<br/>[export.py]"]
  node_theme["Theme<br/>styling<br/>[theme.py]"]
end

subgraph group_examples["Examples"]
  node_blog_example["Blog demo<br/>example schema<br/>[demo.py]"]
  node_multi_schema_example["Multi-schema demo<br/>example schema<br/>[multi_schema.py]"]
  node_showcase_example["Showcase demo<br/>example schema<br/>[showcase.py]"]
end

subgraph group_tests["Tests"]
  node_test_suite["Behavior tests<br/>test coverage"]
end

node_api -->|"generate ERD"| node_introspect
node_cli -->|"invoke"| node_api
node_introspect -->|"normalize"| node_serialization
node_serialization -->|"dispatch"| node_layout_select
node_layout_select -->|"default"| node_layered
node_layout_select -->|"alternative"| node_force
node_layout_select -->|"alternative"| node_star
node_layered -->|"uses"| node_layout
node_force -->|"uses"| node_layout
node_star -->|"uses"| node_layout
node_layout -->|"prepare edges"| node_edge_routing
node_edge_routing -->|"routed diagram"| node_render
node_render -->|"compose"| node_renderer
node_renderer -->|"style"| node_theme
node_renderer -->|"interactive output"| node_html_renderer
node_renderer -->|"static formats"| node_export
node_blog_example -->|"demonstrates"| node_api
node_multi_schema_example -->|"demonstrates"| node_api
node_showcase_example -->|"demonstrates"| node_api
node_test_suite -->|"covers"| node_introspect
node_test_suite -->|"covers"| node_layout_select
node_test_suite -->|"covers"| node_edge_routing
node_test_suite -->|"covers"| node_renderer
node_test_suite -->|"covers"| node_export

click node_api "https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/__init__.py"
click node_cli "https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/cli.py"
click node_introspect "https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/introspect.py"
click node_serialization "https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/serialization.py"
click node_layout_select "https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/layout_select.py"
click node_layout "https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/layout.py"
click node_layered "https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/layered.py"
click node_force "https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/force.py"
click node_star "https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/star.py"
click node_edge_routing "https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/edge_routing.py"
click node_render "https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/render.py"
click node_renderer "https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/renderer.py"
click node_html_renderer "https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/html_renderer.py"
click node_export "https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/export.py"
click node_theme "https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/theme.py"
click node_blog_example "https://github.com/josevelazcoh/erdalchemy/blob/main/examples/blog/demo.py"
click node_multi_schema_example "https://github.com/josevelazcoh/erdalchemy/blob/main/examples/multi_schema/multi_schema.py"
click node_showcase_example "https://github.com/josevelazcoh/erdalchemy/blob/main/examples/showcase/showcase.py"
click node_test_suite "https://github.com/josevelazcoh/erdalchemy/tree/main/tests"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_api,node_cli,node_introspect,node_serialization,node_layout_select,node_layout,node_layered,node_force,node_star,node_edge_routing,node_render,node_renderer,node_html_renderer,node_export,node_theme toneBlue
class node_blog_example,node_multi_schema_example,node_showcase_example toneAmber
class node_test_suite toneMint
```

## Components

### Source package

Core ERD generation pipeline

- [Public API](https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/__init__.py): entrypoint · Exports generate_erd and package-level entry for Python users · `src/sqlalchemy_erd/__init__.py`
- [CLI](https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/cli.py): entrypoint · Command-line entry that loads a DeclarativeBase from a module path · `src/sqlalchemy_erd/cli.py`
- [Introspection](https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/introspect.py): schema scan · Reads SQLAlchemy metadata, tables, schemas, and foreign keys into the internal model · `src/sqlalchemy_erd/introspect.py`
- [Schema model](https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/serialization.py): data model · Normalized portable representation shared by layout and rendering · `src/sqlalchemy_erd/serialization.py`
- [Strategy picker](https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/layout_select.py): layout dispatch · Chooses the layout algorithm for the current schema shape · `src/sqlalchemy_erd/layout_select.py`
- [Layout core](https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/layout.py): layout primitives · Shared layout data structures and helpers · `src/sqlalchemy_erd/layout.py`
- [Layered layout](https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/layered.py): layout strategy · Default hierarchical FK-driven positioning · `src/sqlalchemy_erd/layered.py`
- [Force layout](https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/force.py): layout strategy · Force-directed placement for denser schemas · `src/sqlalchemy_erd/force.py`
- [Star layout](https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/star.py): layout strategy · Hub-and-spoke layout for disconnected or centered schemas · `src/sqlalchemy_erd/star.py`
- [Edge routing](https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/edge_routing.py): connector routing · Routes foreign-key connectors around table cards · `src/sqlalchemy_erd/edge_routing.py`
- [Render core](https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/render.py): render pipeline · Transforms the laid-out schema into drawable diagram elements · `src/sqlalchemy_erd/render.py`
- [Renderer](https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/renderer.py): presentation layer · Main rendering orchestration and view composition · `src/sqlalchemy_erd/renderer.py`
- [HTML output](https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/html_renderer.py): interactive export · Generates the interactive browser-based ERD artifact · `src/sqlalchemy_erd/html_renderer.py`
- [Export](https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/export.py): format export · Writes HTML and optional static image outputs · `src/sqlalchemy_erd/export.py`
- [Theme](https://github.com/josevelazcoh/erdalchemy/blob/main/src/sqlalchemy_erd/theme.py): styling · Controls visual styling and per-table color overrides · `src/sqlalchemy_erd/theme.py`

### Examples

Usage and schema shape references

- [Blog demo](https://github.com/josevelazcoh/erdalchemy/blob/main/examples/blog/demo.py): example schema · Simple relationship example used to demonstrate the generator · `examples/blog/demo.py`
- [Multi-schema demo](https://github.com/josevelazcoh/erdalchemy/blob/main/examples/multi_schema/multi_schema.py): example schema · Shows cross-schema foreign keys and schema grouping · `examples/multi_schema/multi_schema.py`
- [Showcase demo](https://github.com/josevelazcoh/erdalchemy/blob/main/examples/showcase/showcase.py): example schema · Larger reference schema for layout and rendering behavior · `examples/showcase/showcase.py`

### Tests

Behavior coverage for the main subsystems

- [Behavior tests](https://github.com/josevelazcoh/erdalchemy/tree/main/tests): test coverage · Exercises introspection, layout, rendering, export, CLI, and theming · `tests`

## Connections

- Public API → Introspection: generate ERD · Python API enters the schema scanning pipeline
- CLI → Public API: invoke · CLI resolves the target base class then calls the public API
- Introspection → Schema model: normalize · Converts SQLAlchemy metadata into the internal schema model
- Schema model → Strategy picker: dispatch · Hands the normalized schema to layout selection
- Strategy picker → Layered layout: default · Uses the hierarchical FK-driven strategy when appropriate
- Strategy picker → Force layout: alternative · Selects force-directed placement for dense graphs
- Strategy picker → Star layout: alternative · Selects hub-and-spoke placement for centered or sparse graphs
- Layered layout → Layout core: uses · Builds on shared layout primitives
- Force layout → Layout core: uses · Builds on shared layout primitives
- Star layout → Layout core: uses · Builds on shared layout primitives
- Layout core → Edge routing: prepare edges · Provides node geometry for connector routing
- Edge routing → Render core: routed diagram · Feeds routed connectors into renderable elements
- Render core → Renderer: compose · Renderer assembles the final diagram representation
- Renderer → Theme: style · Applies theme and table-level presentation overrides
- Renderer → HTML output: interactive output · Produces the browser-based HTML artifact
- Renderer → Export: static formats · Exports SVG, PNG, and PDF variants
- Blog demo → Public API: demonstrates · Example exercises the public generation flow
- Multi-schema demo → Public API: demonstrates · Example exercises multi-schema introspection and filtering
- Showcase demo → Public API: demonstrates · Example showcases larger schema and layout behavior
- Behavior tests → Introspection: covers · Tests schema scanning and filtering behavior
- Behavior tests → Strategy picker: covers · Tests strategy selection and layout behavior
- Behavior tests → Edge routing: covers · Tests connector routing behavior
- Behavior tests → Renderer: covers · Tests diagram rendering and presentation behavior
- Behavior tests → Export: covers · Tests export formats and output handling
