# pmcrawler/anvil architecture

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

- Interactive diagram: https://gitdiagram.com/pmcrawler/anvil
- Repository: https://github.com/pmcrawler/anvil

## Overview

1. This is an Anvil full-stack Python app, so the architecture splits cleanly into browser-side UI in `client_code/` and backend business logic in `server_code/`. Anvil handles the client/server bridge, so client forms can call server modules directly without a separate API layer.

2. The app shell is centered around `Frame` and `StartupModule.py`. `Frame` is likely the shared layout/navigation container, while `StartupModule.py` is the app entry/bootstrap point that decides which top-level form to show on launch.

3. The main product surface is an event-management subsystem under `client_code/Events/`. It includes:
   - `EventList` for browsing collections
   - `EventView` and `EventDetails`/`EventDetails2` for detailed inspection
   - `EventForm` for creating/editing events
   - `AIResponse` for showing AI-generated output tied to an event workflow
   - card/item templates used by repeated-list UI components

4. The task subsystem under `client_code/Tasks/` mirrors the event side with `TaskList` and `TaskForm`. This suggests the app supports at least two domain objects with similar CRUD-style interactions, but they are kept in separate UI modules rather than one shared generic screen.

5. On the backend, `EventsModule.py` and `TasksModule.py` are the main service boundaries. These modules likely own domain operations such as loading, saving, updating, and validating event/task records, and they are the canonical place where client forms fetch or persist data.

6. `models.py` is the shared domain layer for server-side data structures, while `sample_events.py` appears to provide fixture/demo content for local development or seeded examples. This indicates the server has an explicit data model instead of embedding record shapes in the UI.

7. The event workflow has an AI augmentation path. `event_ai.py` and `prompts.py` indicate backend prompt construction and model interaction, and the `AIResponse` client form is the presentation point for that generated text. So the AI feature sits behind the server boundary, not in the browser.

8. `ui_builder.py` and `ui_config.py` inside `client_code/Events/` suggest the event UI is at least partly assembled/configured dynamically rather than being purely static forms. That points to a reusable UI-generation layer for event screens, cards, or form variants.

9. The UI is componentized using Anvil form templates: nearly every screen has a `form_template.yaml`, and some list views have nested item/card templates. That means repeated rendering is handled by template components, especially for list views and cards, rather than hand-built DOM logic.

10. The theme layer is separated from app logic in `theme/`. `theme.css`, `theme2.css`, `card_sample.css`, and the theme parameter/template files provide shared styling and visual system configuration across the forms. This is the repo’s main presentation boundary.

11. The overall data flow is: user action in a client form → client-side form logic and templates → server module call for domain work → optional AI processing for events → returned data rendered back into list/detail/forms. The two main business domains, Events and Tasks, are isolated but share the same app shell and theme system.

12. For an architecture diagram, the key boxes are: Anvil client UI shell, Events UI subsystem, Tasks UI subsystem, server domain modules, AI integration, and shared theme/assets. The important arrows are client-to-server calls for CRUD and AI responses, with the server layer owning authoritative business logic and data shaping.

Main entry points: [`client_code/Events`](https://github.com/pmcrawler/anvil/tree/master/client_code/Events) (Events UI), [`server_code/EventsModule.py`](https://github.com/pmcrawler/anvil/blob/master/server_code/EventsModule.py) (EventsModule), [`client_code/Frame`](https://github.com/pmcrawler/anvil/tree/master/client_code/Frame) (Frame), [`client_code/Tasks`](https://github.com/pmcrawler/anvil/tree/master/client_code/Tasks) (Tasks UI)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_client["Client UI"]
  node_startup["Startup<br/>bootstrap module<br/>[StartupModule.py]"]
  node_frame["Frame<br/>app shell"]
  node_form1["Form1<br/>landing form"]
  node_events_ui["Events UI<br/>feature bundle"]
  node_event_list["EventList<br/>event browser"]
  node_event_view["EventView<br/>event detail"]
  node_event_form["EventForm<br/>event editor"]
  node_event_details["EventDetails<br/>event details"]
  node_ai_response["AIResponse<br/>ai output view"]
  node_tasks_ui["Tasks UI<br/>feature bundle"]
  node_task_list["TaskList<br/>task browser"]
  node_task_form["TaskForm<br/>task editor"]
end

subgraph group_server["Server Logic"]
  node_events_module["EventsModule<br/>domain service<br/>[EventsModule.py]"]
  node_tasks_module["TasksModule<br/>domain service<br/>[TasksModule.py]"]
  node_ai_engine["AI Engine<br/>prompt pipeline<br/>[event_ai.py]"]
  node_models[("Models<br/>shared domain model<br/>[models.py]")]
end

subgraph group_theme["Theme"]
  node_theme_assets["Theme Assets<br/>styling system"]
end

node_startup -->|"launches"| node_frame
node_startup -->|"opens"| node_form1
node_frame -->|"hosts"| node_events_ui
node_frame -->|"hosts"| node_tasks_ui
node_events_ui -->|"navigates"| node_event_list
node_events_ui -->|"navigates"| node_event_view
node_events_ui -->|"navigates"| node_event_form
node_events_ui -->|"navigates"| node_event_details
node_events_ui -->|"renders"| node_ai_response
node_event_list -->|"calls"| node_events_module
node_event_view -->|"calls"| node_events_module
node_event_form -->|"calls"| node_events_module
node_event_details -->|"calls"| node_events_module
node_ai_response -->|"shows output"| node_ai_engine
node_events_module -->|"uses"| node_models
node_tasks_ui -->|"navigates"| node_task_list
node_tasks_ui -->|"navigates"| node_task_form
node_task_list -->|"calls"| node_tasks_module
node_task_form -->|"calls"| node_tasks_module
node_tasks_module -->|"uses"| node_models
node_events_ui -->|"styles"| node_theme_assets
node_tasks_ui -->|"styles"| node_theme_assets
node_frame -->|"styles"| node_theme_assets

click node_startup "https://github.com/pmcrawler/anvil/blob/master/client_code/StartupModule.py"
click node_frame "https://github.com/pmcrawler/anvil/tree/master/client_code/Frame"
click node_form1 "https://github.com/pmcrawler/anvil/tree/master/client_code/Form1"
click node_events_ui "https://github.com/pmcrawler/anvil/tree/master/client_code/Events"
click node_event_list "https://github.com/pmcrawler/anvil/tree/master/client_code/Events/EventList"
click node_event_view "https://github.com/pmcrawler/anvil/tree/master/client_code/Events/EventView"
click node_event_form "https://github.com/pmcrawler/anvil/tree/master/client_code/Events/EventForm"
click node_event_details "https://github.com/pmcrawler/anvil/tree/master/client_code/Events/EventDetails"
click node_ai_response "https://github.com/pmcrawler/anvil/tree/master/client_code/Events/AIResponse"
click node_tasks_ui "https://github.com/pmcrawler/anvil/tree/master/client_code/Tasks"
click node_task_list "https://github.com/pmcrawler/anvil/tree/master/client_code/Tasks/TaskList"
click node_task_form "https://github.com/pmcrawler/anvil/tree/master/client_code/Tasks/TaskForm"
click node_events_module "https://github.com/pmcrawler/anvil/blob/master/server_code/EventsModule.py"
click node_tasks_module "https://github.com/pmcrawler/anvil/blob/master/server_code/TasksModule.py"
click node_ai_engine "https://github.com/pmcrawler/anvil/blob/master/server_code/event_ai.py"
click node_models "https://github.com/pmcrawler/anvil/blob/master/server_code/models.py"
click node_theme_assets "https://github.com/pmcrawler/anvil/tree/master/theme"

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_startup,node_frame,node_form1,node_events_ui,node_event_list,node_event_view,node_event_form,node_event_details,node_ai_response,node_tasks_ui,node_task_list,node_task_form toneBlue
class node_events_module,node_tasks_module,node_ai_engine,node_models toneAmber
class node_theme_assets toneMint
```

## Components

### Client UI

Browser-side forms, shells, and reusable templates.

- [Startup](https://github.com/pmcrawler/anvil/blob/master/client_code/StartupModule.py): bootstrap module · App entry point that selects the initial form. · `client_code/StartupModule.py`
- [Frame](https://github.com/pmcrawler/anvil/tree/master/client_code/Frame): app shell · Shared layout and navigation container used by forms. · `client_code/Frame`
- [Form1](https://github.com/pmcrawler/anvil/tree/master/client_code/Form1): landing form · Top-level form present in the client tree. · `client_code/Form1`
- [Events UI](https://github.com/pmcrawler/anvil/tree/master/client_code/Events): feature bundle · Client-side event management surface and reusable event templates. · `client_code/Events`
- [EventList](https://github.com/pmcrawler/anvil/tree/master/client_code/Events/EventList): event browser · List view for browsing events and opening records. · `client_code/Events/EventList`
- [EventView](https://github.com/pmcrawler/anvil/tree/master/client_code/Events/EventView): event detail · Event inspection view with nested item templates. · `client_code/Events/EventView`
- [EventForm](https://github.com/pmcrawler/anvil/tree/master/client_code/Events/EventForm): event editor · Create and edit event records. · `client_code/Events/EventForm`
- [EventDetails](https://github.com/pmcrawler/anvil/tree/master/client_code/Events/EventDetails): event details · Detailed event presentation screen. · `client_code/Events/EventDetails`
- [AIResponse](https://github.com/pmcrawler/anvil/tree/master/client_code/Events/AIResponse): ai output view · Client view for displaying AI-generated event text. · `client_code/Events/AIResponse`
- [Tasks UI](https://github.com/pmcrawler/anvil/tree/master/client_code/Tasks): feature bundle · Client-side task management surface. · `client_code/Tasks`
- [TaskList](https://github.com/pmcrawler/anvil/tree/master/client_code/Tasks/TaskList): task browser · Task list view with repeated item template rendering. · `client_code/Tasks/TaskList`
- [TaskForm](https://github.com/pmcrawler/anvil/tree/master/client_code/Tasks/TaskForm): task editor · Create and edit task records. · `client_code/Tasks/TaskForm`

### Server Logic

Backend domain modules, models, and AI prompt flow.

- [EventsModule](https://github.com/pmcrawler/anvil/blob/master/server_code/EventsModule.py): domain service · Backend boundary for event load/save/update operations. · `server_code/EventsModule.py`
- [TasksModule](https://github.com/pmcrawler/anvil/blob/master/server_code/TasksModule.py): domain service · Backend boundary for task load/save/update operations. · `server_code/TasksModule.py`
- [AI Engine](https://github.com/pmcrawler/anvil/blob/master/server_code/event_ai.py): prompt pipeline · Server-side event AI flow combining prompt construction and model calls. · `server_code/event_ai.py`
- [Models](https://github.com/pmcrawler/anvil/blob/master/server_code/models.py): shared domain model · Server-side shared data structures for the application. · `server_code/models.py`

### Theme

Shared visual styling and theme configuration.

- [Theme Assets](https://github.com/pmcrawler/anvil/tree/master/theme): styling system · Shared CSS and theme parameters/templates used across forms. · `theme`

## Connections

- Startup → Frame: launches · Startup chooses the shell or first visible form.
- Startup → Form1: opens · Initial app flow may route to the default form.
- Frame → Events UI: hosts · Shared shell contains the main events experience.
- Frame → Tasks UI: hosts · Shared shell contains the main tasks experience.
- Events UI → EventList: navigates · Event area centers on browsing collections.
- Events UI → EventView: navigates · Event area opens detailed inspection views.
- Events UI → EventForm: navigates · Event area provides create/edit flows.
- Events UI → EventDetails: navigates · Event area includes detailed record display.
- Events UI → AIResponse: renders · AI-generated output is shown in the event workflow.
- EventList → EventsModule: calls · List views fetch event collections from the backend.
- EventView → EventsModule: calls · Detail views request event data and actions.
- EventForm → EventsModule: calls · Editor persists and validates event changes.
- EventDetails → EventsModule: calls · Details screens retrieve authoritative event records.
- AIResponse → AI Engine: shows output · AI view displays server-generated event text.
- EventsModule → Models: uses · Event service works through shared domain models.
- Tasks UI → TaskList: navigates · Task area centers on browsing task collections.
- Tasks UI → TaskForm: navigates · Task area provides task create/edit flow.
- TaskList → TasksModule: calls · Task list fetches task collections from backend services.
- TaskForm → TasksModule: calls · Task editor persists task changes through backend service.
- TasksModule → Models: uses · Task service works through shared domain models.
- Events UI → Theme Assets: styles · Event screens inherit shared presentation rules.
- Tasks UI → Theme Assets: styles · Task screens inherit shared presentation rules.
- Frame → Theme Assets: styles · Shell layout is themed with shared assets.
