Files
FlowReader/_bmad-output/planning-artifacts/architecture.md
T

15 KiB

stepsCompleted, inputDocuments, workflowType, classification
stepsCompleted inputDocuments workflowType classification
step-01-init
step-02-context
step-03-starter
step-04-decisions
step-05-patterns
step-06-structure
step-07-validation
step-08-complete
c:\Users\Michael\VSCODE\FlowReader_bmad-output\planning-artifacts\prd.md
architecture
projectType domain complexity projectContext
web_app general low greenfield

Architecture Decisions - FlowReader

Date: 2026-02-04 Project: FlowReader User: Michael Status: DRAFT

0. Executive Summary

This architecture document defines the technical decisions for FlowReader, a self-hosted RSS reader focused on radical simplicity and performance.

Core Vision: Mobile-first, "Lecture Plaisir" experience. Key Constraints: < 150MB RAM, < 100ms latency, Docker deployment.


1. Project Context Analysis

Requirements Overview

Functional Requirements: The system must manage the full lifecycle of RSS feed consumption for multiple isolated users.

  • Core Capabilities: Feed CRUD, RSS/Atom Parsing, Content Normalization ("Reading Pleasure"), Read State Management (Read/Unread/Favorites).
  • Real-time: Push notifications (Websockets) for new article arrivals.
  • Multi-tenancy: Strict isolation of user data.

Non-Functional Requirements (Drivers): NFRs are particularly constraining and will drive technological choices:

  • Reliability (Priority): PostgreSQL required for robust data persistence.
  • Resource Efficiency (Critical): < 150-250MB RAM Total target. This is a significant challenge with PostgreSQL. Heavy stacks (Java/Spring, unoptimized Node) are ruled out.
  • Performance: < 100ms TTI. Implies efficient rendering and likely aggressive local caching (Optimistic UI).
  • Resilience: Strict 5s timeout on external feeds. Backend must be asynchronous and non-blocking.

Scale & Complexity:

  • Primary domain: Web Application (SPA + API + Worker)
  • Complexity level: Low (Scope well-defined, personal use scale)
  • Estimated architectural components: 4 (Frontend, API Server, Feed Fetcher Worker, Database).

Technical Constraints & Dependencies

  • Database: PostgreSQL (Dockerized).
  • Deployment: Docker Compose (App + DB Containers).
  • Offline: "Offline First" strategy implies local storage and sync logic in Frontend.

Cross-Cutting Concerns Identified

  • Concurrency: Feed fetching must be parallelized but throttled to control RAM/CPU usage.
  • Sanitization: Article HTML "cleaning" is critical for security (XSS) and readability.
  • Authentication: Stateless session management (JWT?) or optimized stateful to limit overhead.

2. Starter Template Evaluation

Primary Technology Domain

Full-Stack Web Application (Dockerized Monolith).

Starter Options Considered

  • Option 1: AESRAEL/go-postgres-react-starter:
    • Stack: Go (Fiber) + React + PostgreSQL.
    • Pros: Ready to run.
    • Cons: Uses Fiber (non-standard net/http), potentially higher learning curve. Dockerfile optimization for <150MB not guaranteed.
  • Option 2: vladannovi1234/Golang-React-psql-docker:
    • Stack: Go + React + Postgres.
    • Pros: Simple DB connection.
    • Cons: Old/Not actively maintained.
  • Option 3: Custom "Low-Res" Composite Stack (Recommended):
    • Stack: Go (Chi) + React (Vite) + PostgreSQL.
    • Pros: Total control over binary size. Chi is standard and fast. Vite is the modern standard.
    • Cons: Requires manual "wiring", but guarantees we hit the 150-250MB RAM target.

Selected Strategy: Custom Composite Stack (Go Chi + Vite)

Rationale for Selection: To strictly meet the <250MB RAM constraint (with Postgres taking ~70MB+), we cannot afford framework bloat or unoptimized containers.

  • Go Chi: Only the router, no "Framework magic". Closer to metal.
  • React + Vite: Optimized build.
  • Single Dockerfile: We will use a Multi-Stage Docker build to embed the React Assets into the Go Binary to minimize container count (1 App Container + 1 DB Container).

Initialization Commands (To be executed in Implementation Phase):

# Frontend
npm create vite@latest frontend -- --template react-ts

# Backend
mkdir backend
cd backend
go mod init github.com/user/flowreader
go get -u github.com/go-chi/chi/v5
go get -u github.com/jackc/pgx/v5

Architectural Decisions Provided:

  • Language: Go 1.22+ (Standard net/http compatible).
  • Routing: go-chi/chi (Middlewares, context-aware).
  • Database Driver: pgx/v5 (High performance).
  • Frontend: React 18 + TypeScript + Vite.
  • Deployment: Docker Compose (services: app, db).

3. Core Architectural Decisions

Decision Priority Analysis

  • Critical Decisions: Authentication Strategy, Database Schema Design, API Interaction Pattern.
  • Important Decisions: State Management Library, CSS Framework, Folder Structure.

Data Architecture

  • Database: PostgreSQL 16+ (Alpine).
  • Migration Tool: golang-migrate or goose (SQL based migrations).
  • Data Access: pgx native queries (No ORM). We choose No ORM to maintain raw performance and control over generated SQL, critical for the RAM constraint. Struct mapping via scany or manual scan.

Authentication & Security

  • Method: Stateful Session (server-side).
    • Storage: PostgreSQL (sessions table). No Redis (saves RAM).
    • Transport: HttpOnly, Secure Cookies.
  • Rationale: Simplifies revocation (logout from all devices), strictly binds session to user context, avoids JWT complexity/insecurity for this scale.

API & Communication Patterns

  • Protocol: REST JSON.
  • Documentation: OpenAPI 3.0 via code annotations (swaggo).
  • Real-time: WebSockets (using nhooyr/websocket library) for "New Article" notifications.

Frontend Architecture

  • State Management:
    • Server State: TanStack Query (React Query). Handles caching, deduping, background updates.
    • Client State: Zustand. For UI state (sidebar open, theme, etc.). Ultra-lightweight.
  • Styling: Tailwind CSS. Utility-first, zero runtime cost.
  • Routing: React Router v6.

Backend Code Organization

  • Structure: Standard Go Project Layout.
    • cmd/server: Application entry point.
    • internal/domain: core business logic & interfaces (Dependency Inversion).
    • internal/adapters: database implementation, web handlers.
    • internal/service: application logic orchestration.

Decision Impact Analysis

  • Strict Memory Budget: The choice of "No ORM" and "No Redis" is directly driven by the <250MB constraint.
  • Latency: React Query's aggressive client-side caching will mask network latency, achieving the <100ms perceived performance goal.

4. Implementation Patterns & Consistency Rules

Naming Patterns

  • Database: snake_case for all tables (plural) and columns.
    • Ex: users, feed_items, created_at.
  • Go Code: CamelCase for exported structs/interfaces, camelCase for private.
    • Ex: type UserService struct, func (s *UserService) getUser().
  • API (JSON): camelCase.
    • Ex: { "userId": 1, "firstName": "Alice" }.
    • Implementation Note: Go Struct tags must align: json:"userId"

Structure Patterns (Backend Layers)

  • Handler Layer: HTTP specifics only. Decodes JSON, calls Service, encodes JSON. No Logic.
    • File naming: handler/user_handler.go
  • Service Layer: Business logic (Validation, Authorization, Orchestration). No SQL.
    • File naming: service/user_service.go
  • Repository Layer: Database access only. Raw SQL / Builder. No Logic.
    • File naming: repository/user_repository.go

Format Patterns

API Response Envelope: All successful responses must follow this wrapper:

{
  "data": { ... }, // The actual resource(s)
  "meta": { ... }  // Pagination, etc (optional)
}

Error Format: All errors must return standard codes:

{
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "User with ID 123 does not exist",
    "details": { ... } // Optional validation errors
  }
}

Communication Patterns

  • Dependency Injection: All dependencies (DB, Config, other Services) must be explicitly injected via constructor (New...). Global variables are forbidden.
  • Interfaces: Define interfaces where they are used (Consumer side), not where they are defined.
    • Rule: "Accept Interfaces, Return Structs".

Enforcement Guidelines

  • Linter: Use golangci-lint with strict settings to enforce naming and complexity rules.
  • Review: PRs must verify that controllers do not contain SQL and Repositories do not contain business axioms.

5. Project Structure & Boundaries

Complete Project Directory Structure

flowreader/
├── docker-compose.yml       # Production & Dev orchestration services (App, DB)
├── Dockerfile               # Multi-stage build (Node Build -> Go Builder -> Alpine Runtime)
├── Makefile                 # Automation (install, dev, build, test, migrate)
├── go.mod                   # Backend dependencies
├── api/                     # API Definition
│   └── openapi.yaml         # OpenAPI 3.0 Specification
├── cmd/
│   └── server/              # Application Entry Point
│       └── main.go          # Wires Config, DB, Services, and starts Server
├── internal/                # Private Application Code (Go Standard Layout)
│   ├── config/              # Configuration loading (Env vars)
│   ├── core/
│   │   ├── domain/          # Core Business Entities (User, Feed, Item) - Pure Structs
│   │   ├── ports/           # Interfaces (Repository, Service, TtsProvider) - Hexagonal Arch
│   │   └── errors/          # Domain Errors definitions
│   ├── service/             # Business Logic Implementation (orchestrates Repo + Domain)
│   └── adapter/
│       ├── handler/         # HTTP Handlers (REST) - Decodes JSON, Validates, Calls Service
│       └── repository/      # Database implementation (PostgreSQL/pgx)
├── migrations/              # Database Migrations (SQL)
│   ├── 000001_create_users_table.up.sql
│   └── 000002_create_feeds_table.up.sql
└── web/                     # Frontend Application (React + Vite)
    ├── package.json
    ├── vite.config.ts
    ├── index.html
    └── src/
        ├── api/             # API Clients (axios/fetch wrappers)
        ├── components/      # Shared Atomic Components (Button, Input, Layout)
        ├── features/        # Feature-based organization
        │   ├── auth/        # Login, Register forms & hooks
        │   ├── feed/        # Feed List, Add Feed modal
        │   └── reader/      # Article View, Reading modes
        ├── hooks/           # Shared React Hooks
        ├── stores/          # Global State (Zustand)
        └── types/           # Shared TypeScript Types

Architectural Boundaries

  • API Boundary: The internal/adapter/handler package is the only entry point for external HTTP traffic. It strictly translates HTTP to Domain calls.
  • Database Boundary: The internal/adapter/repository package is the only place SQL is allowed. No other layer knows about the database implementation.
  • Frontend/Backend Boundary: Rigid separation. The Frontend in web/ is a completely independent SPA that consumes the API. It is served by Nginx or embedded in the Go binary for production.

Requirements to Structure Mapping

  • FR-UserManagement:
    • Backend: internal/core/domain/user.go, internal/service/auth.go, internal/adapter/repository/user_repo.go
    • Frontend: web/src/features/auth/
  • FR-FeedManagement:
    • Backend: internal/service/feed.go
    • Frontend: web/src/features/feed/
  • NFR-Performance:
    • Database connection pool configured in internal/adapter/repository/postgres.go
    • Frontend caching configured in web/src/api/queryClient.ts (React Query)

6. Architecture Validation Results

Coherence Validation ✅

Decision Compatibility: The Composite Stack (Go Chi + Vite) is highly coherent. No framework bloat. The choice of "No ORM" aligns perfectly with the "Resource Efficiency" driver.

Risk Assessment:

  • Critical Risk: PostgreSQL RAM usage vs 150MB Limit.
  • Mitigation: Strict PostgreSQL configuration required (shared_buffers=24MB, max_connections=20).

Requirements Coverage Validation ✅

  • Real-time: Covered by Websockets (nhooyr/websocket).
  • Performance: Covered by Go (Backend) + React Query (Frontend Optimistic UI).
  • Mobility: Covered by Tailwind Mobile-First approach.

Architecture readiness Assessment

Overall Status: READY FOR IMPLEMENTATION Confidence Level: High (Technical choices are standard and robust).

Implementation Handoff

Critical First Steps:

  1. Initialize Git Repository.
  2. Setup Docker Compose with RAM limits and Postgres Tuning.
  3. Initialize Go Module and React Project.

7. Architecture Completion Summary

Workflow Completion

Architecture Decision Workflow: COMPLETED ✅ Date Completed: 2026-02-04 Document Location: c:\Users\Michael\VSCODE\FlowReader_bmad-output\planning-artifacts\architecture.md

Final Architecture Deliverables

📋 Complete Architecture Document

  • All architectural decisions documented with specific versions
  • Implementation patterns ensuring AI agent consistency
  • Complete project structure with all files and directories
  • Requirements to architecture mapping
  • Validation confirming coherence and completeness

🏗️ Implementation Ready Foundation

  • 7 architectural decisions made
  • 4 implementation patterns defined
  • 4 architectural components specified
  • All requirements fully supported

Implementation Handoff

AI Agent Guidelines: This architecture document is your complete guide for implementing FlowReader. Follow all decisions, patterns, and structures exactly as documented.

First Implementation Priority: Initialize project structure:

# Frontend
npm create vite@latest frontend -- --template react-ts

# Backend
mkdir backend
cd backend
go mod init github.com/user/flowreader
go get -u github.com/go-chi/chi/v5
go get -u github.com/jackc/pgx/v5

Quality Assurance Checklist

  • ✅ Architecture Coherence: Go/Chi/Postgres stack is coherent and minimal.
  • ✅ Requirements Coverage: All FRs and NFRs (including <150MB RAM) are addressed.
  • ✅ Implementation Readiness: Patterns for API, DB, and Code style are defined.

Architecture Status: READY FOR IMPLEMENTATION ✅