Workspace Dependency Graph

Arrows point from the importer to the thing it imports. shared/ is leaf code: everything points into it, nothing points out of it. That direction is enforced mechanically by tools/lint/check-shared-boundaries.ts (see ADR 0006).

graph LR
    subgraph Consumers["Consumer packages"]
        FE["frontend/<br/>(Angular 21)"]
        FN["functions/<br/>(Cloud Functions)"]
        TB["tools/build<br/>(content pipeline)"]
        BS["tools/blog-scheduler<br/>(CLI, standalone)"]
    end

    subgraph Shared["shared/ — leaf code"]
        SM["@jjk/models"]
        SC["@jjk/constants"]
        SU["@jjk/utils<br/>(no current consumers)"]
        SS["@jjk/services<br/>(empty barrel)"]
    end

    FE --> SM
    FE --> SC
    FE -.-> SU
    FN --> SC
    TB --> SM

    classDef idle fill:#f4f4f4,stroke:#999,color:#666,stroke-dasharray: 4 2
    class SU,SS,BS idle

Current package responsibilities

Package Role Imports from shared/
frontend/ Angular 21 blog app, admin dashboards, prerendered at build time @jjk/models, @jjk/constants
functions/ Firebase Cloud Functions — callable handlers, Firestore triggers, third-party integrations @jjk/constants
tools/build Markdown → JSON content pipeline (Shiki, Mermaid, route manifest, search index) @jjk/models
tools/blog-scheduler Mon/Thu publication slot CLI none

What the graph enforces

  • Direction. shared/ is a dependency sink. No arrow flows out of the shared/ subgraph. Attempting to add one — a shared/ file importing @app/*, or a relative path that escapes shared/, or a bare frontend/functions/tools specifier — fails npm run build via the boundary check.
  • Independence. tools/blog-scheduler is a standalone CLI with no shared-code dependencies. It can be extracted to its own repo without touching anything else.
  • Runtime vs. build-time. This graph shows TypeScript import dependencies only. tools/build also produces frontend/src/assets/generated/** as a build artifact consumed by the prerendered frontend — that relationship is captured in the content pipeline diagram, not here.

What this graph does not show

  • functions/ is not an npm workspace member (it has its own node_modules and deploys independently). It resolves @jjk/constants via a local tsconfig.json paths map.
  • Third-party dependencies (Firebase SDKs, Angular, Shiki, Mermaid, Sentry, Resend, LinkedIn API) are omitted for readability. They are consumed by the Consumer packages, never by shared/ except for pure types.