# blampe/rreading-glasses architecture

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

- Interactive diagram: https://gitdiagram.com/blampe/rreading-glasses
- Repository: https://github.com/blampe/rreading-glasses

## Overview

rreading-glasses is a self-hostable metadata API compatible with Readarr-style clients, with separate G——R—— and Hardcover-backed servers. The principal workflow is a client request to search or retrieve book/author metadata, through HTTP handlers and a controller, to an upstream provider and back as cached metadata; recommendations are another documented capability. The README also highlights new releases and large-author coverage. The entrypoint wiring and selected handler, controller, and provider excerpts support the main links; unsampled storage and route details are not expanded into inferred flows.

Main entry points: [`cmd/rghc/main.go`](https://github.com/blampe/rreading-glasses/blob/main/cmd/rghc/main.go) (Hardcover server), [`cmd/rggr/main.go`](https://github.com/blampe/rreading-glasses/blob/main/cmd/rggr/main.go) (G——R—— server), [`internal/controller.go`](https://github.com/blampe/rreading-glasses/blob/main/internal/controller.go) (Metadata controller), [`internal/handler.go`](https://github.com/blampe/rreading-glasses/blob/main/internal/handler.go) (HTTP routes)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_entry["Server entrypoints"]
  node_gr_server["G——R—— server<br/>[main.go]"]
  node_hc_server["Hardcover server<br/>[main.go]"]
end

subgraph group_api["Metadata API"]
  node_http["HTTP routes<br/>[handler.go]"]
  node_controller["Metadata controller<br/>[controller.go]"]
end

subgraph group_providers["Metadata providers"]
  node_gr_getter["G——R—— getter<br/>[gr.go]"]
  node_hc_getter["Hardcover getter<br/>[hardcover.go]"]
  node_gr_gql["G——R—— GraphQL<br/>[generated.go]"]
  node_hc_gql["Hardcover GraphQL<br/>[generated.go]"]
  node_graphql_client["GraphQL transport<br/>[graphql.go]"]
  node_transport["HTTP transport<br/>[transport.go]"]
end

subgraph group_state["Cache and operations"]
  node_cache[("Metadata cache<br/>[cache.go]")]
  node_cloudflare[("Cloudflare cache<br/>[cloudflare.go]")]
  node_persist["Persistence layer<br/>[persist.go]"]
  node_postgres[("Postgres store<br/>[postgres.go]")]
  node_metrics["Metrics<br/>[metrics.go]"]
end

node_client(("Readarr client"))
node_gr_service(("G——R—— service"))
node_hc_service(("Hardcover service"))

node_client -->|"requests metadata"| node_gr_server
node_client -->|"requests metadata"| node_hc_server
node_gr_server -->|"registers routes"| node_http
node_hc_server -->|"registers routes"| node_http
node_http -->|"calls"| node_controller
node_controller -.->|"fetches metadata"| node_gr_getter
node_controller -.->|"fetches metadata"| node_hc_getter
node_gr_server -->|"configures provider"| node_gr_getter
node_hc_server -->|"configures provider"| node_hc_getter
node_gr_getter -.->|"queries"| node_gr_gql
node_hc_getter -.->|"queries"| node_hc_gql
node_gr_getter -.->|"fetches metadata"| node_gr_service
node_hc_getter -.->|"fetches metadata"| node_hc_service
node_gr_server -->|"creates client"| node_graphql_client
node_hc_server -->|"creates client"| node_graphql_client
node_hc_server -->|"configures authorization"| node_transport
node_gr_server -->|"configures cache"| node_cache
node_hc_server -->|"configures cache"| node_cache
node_gr_server -->|"creates controller"| node_controller
node_hc_server -->|"creates controller"| node_controller
node_controller -->|"reads and writes"| node_cache
node_controller -->|"persists refresh state"| node_persist
node_persist -.->|"stores metadata"| node_postgres
node_gr_server -.->|"configures optionally"| node_cloudflare
node_hc_server -.->|"configures optionally"| node_cloudflare
node_http -->|"instruments routes"| node_metrics

click node_gr_server "https://github.com/blampe/rreading-glasses/blob/main/cmd/rggr/main.go"
click node_hc_server "https://github.com/blampe/rreading-glasses/blob/main/cmd/rghc/main.go"
click node_http "https://github.com/blampe/rreading-glasses/blob/main/internal/handler.go"
click node_controller "https://github.com/blampe/rreading-glasses/blob/main/internal/controller.go"
click node_gr_getter "https://github.com/blampe/rreading-glasses/blob/main/internal/gr.go"
click node_hc_getter "https://github.com/blampe/rreading-glasses/blob/main/internal/hardcover.go"
click node_gr_gql "https://github.com/blampe/rreading-glasses/blob/main/gr/generated.go"
click node_hc_gql "https://github.com/blampe/rreading-glasses/blob/main/hardcover/generated.go"
click node_cache "https://github.com/blampe/rreading-glasses/blob/main/internal/cache.go"
click node_cloudflare "https://github.com/blampe/rreading-glasses/blob/main/internal/cloudflare.go"
click node_persist "https://github.com/blampe/rreading-glasses/blob/main/internal/persist.go"
click node_postgres "https://github.com/blampe/rreading-glasses/blob/main/internal/postgres.go"
click node_metrics "https://github.com/blampe/rreading-glasses/blob/main/internal/metrics.go"
click node_graphql_client "https://github.com/blampe/rreading-glasses/blob/main/internal/graphql.go"
click node_transport "https://github.com/blampe/rreading-glasses/blob/main/internal/transport.go"

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_gr_server,node_hc_server,node_client toneBlue
class node_http,node_controller toneAmber
class node_gr_getter,node_hc_getter,node_gr_gql,node_hc_gql,node_graphql_client,node_transport toneMint
class node_cache,node_cloudflare,node_persist,node_postgres,node_metrics toneRose
class node_gr_service,node_hc_service toneIndigo
```

## Components

### Server entrypoints

- [G——R—— server](https://github.com/blampe/rreading-glasses/blob/main/cmd/rggr/main.go): `cmd/rggr/main.go`
- [Hardcover server](https://github.com/blampe/rreading-glasses/blob/main/cmd/rghc/main.go): `cmd/rghc/main.go`

### Metadata API

- [HTTP routes](https://github.com/blampe/rreading-glasses/blob/main/internal/handler.go): `internal/handler.go`
- [Metadata controller](https://github.com/blampe/rreading-glasses/blob/main/internal/controller.go): `internal/controller.go`

### Metadata providers

- [G——R—— getter](https://github.com/blampe/rreading-glasses/blob/main/internal/gr.go): `internal/gr.go`
- [Hardcover getter](https://github.com/blampe/rreading-glasses/blob/main/internal/hardcover.go): `internal/hardcover.go`
- [G——R—— GraphQL](https://github.com/blampe/rreading-glasses/blob/main/gr/generated.go): `gr/generated.go`
- [Hardcover GraphQL](https://github.com/blampe/rreading-glasses/blob/main/hardcover/generated.go): `hardcover/generated.go`
- [GraphQL transport](https://github.com/blampe/rreading-glasses/blob/main/internal/graphql.go): `internal/graphql.go`
- [HTTP transport](https://github.com/blampe/rreading-glasses/blob/main/internal/transport.go): `internal/transport.go`

### Cache and operations

- [Metadata cache](https://github.com/blampe/rreading-glasses/blob/main/internal/cache.go): `internal/cache.go`
- [Cloudflare cache](https://github.com/blampe/rreading-glasses/blob/main/internal/cloudflare.go): `internal/cloudflare.go`
- [Persistence layer](https://github.com/blampe/rreading-glasses/blob/main/internal/persist.go): `internal/persist.go`
- [Postgres store](https://github.com/blampe/rreading-glasses/blob/main/internal/postgres.go): `internal/postgres.go`
- [Metrics](https://github.com/blampe/rreading-glasses/blob/main/internal/metrics.go): `internal/metrics.go`

### Other components

- **Readarr client**
- **G——R—— service**
- **Hardcover service**

## Connections

- Readarr client → G——R—— server: requests metadata (evidence: `README.md`)
- Readarr client → Hardcover server: requests metadata (evidence: `README.md`)
- G——R—— server → HTTP routes: registers routes (evidence: `cmd/rggr/main.go`)
- Hardcover server → HTTP routes: registers routes (evidence: `cmd/rghc/main.go`)
- HTTP routes → Metadata controller: calls (evidence: `internal/handler.go`)
- Metadata controller → G——R—— getter: fetches metadata
- Metadata controller → Hardcover getter: fetches metadata
- G——R—— server → G——R—— getter: configures provider (evidence: `cmd/rggr/main.go`)
- Hardcover server → Hardcover getter: configures provider (evidence: `cmd/rghc/main.go`)
- G——R—— getter → G——R—— GraphQL: queries
- Hardcover getter → Hardcover GraphQL: queries
- G——R—— getter → G——R—— service: fetches metadata
- Hardcover getter → Hardcover service: fetches metadata
- G——R—— server → GraphQL transport: creates client (evidence: `cmd/rggr/main.go`)
- Hardcover server → GraphQL transport: creates client (evidence: `cmd/rghc/main.go`)
- Hardcover server → HTTP transport: configures authorization (evidence: `cmd/rghc/main.go`)
- G——R—— server → Metadata cache: configures cache (evidence: `cmd/rggr/main.go`)
- Hardcover server → Metadata cache: configures cache (evidence: `cmd/rghc/main.go`)
- G——R—— server → Metadata controller: creates controller (evidence: `cmd/rggr/main.go`)
- Hardcover server → Metadata controller: creates controller (evidence: `cmd/rghc/main.go`)
- Metadata controller → Metadata cache: reads and writes (evidence: `internal/controller.go`)
- Metadata controller → Persistence layer: persists refresh state (evidence: `internal/controller.go`)
- Persistence layer → Postgres store: stores metadata
- G——R—— server → Cloudflare cache: configures optionally (evidence: `cmd/rggr/main.go`)
- Hardcover server → Cloudflare cache: configures optionally (evidence: `cmd/rghc/main.go`)
- HTTP routes → Metrics: instruments routes (evidence: `internal/handler.go`)
