# him7797/ainews architecture

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

- Interactive diagram: https://gitdiagram.com/him7797/ainews
- Repository: https://github.com/him7797/ainews

## Overview

1. **Overall shape**
   - This repository is a **two-part product**: an **Expo mobile client** at the root `src/` tree and a separate **TypeScript server** under `server/`.
   - The product intent is an **RSS/news aggregation app** with onboarding and authenticated feed access, supported by a backend that fetches, parses, sanitizes, caches, and serves content.

2. **Mobile client boundary**
   - The root app is an **Expo Router** application using file-based navigation in `src/app/`.
   - The main screens are:
     - `auth/sign-in` for authentication
     - `onboarding/` for first-run setup
     - `index.tsx` for the primary landing/home experience
   - `_layout.tsx` defines the navigation shell that wraps these routes.

3. **Client-side domain modules**
   - `src/services/authService.ts` and `src/services/feedService.ts` are the main client-to-server integration points.
   - `src/lib/storage.ts` handles local persistence, likely for tokens, onboarding state, or user preferences.
   - `src/lib/notifications.ts` indicates the client also owns local notification behavior.
   - UI composition is split into reusable components such as `OnboardingCarousel` and `TopicPill`, which suggests onboarding is interactive and preference-driven.

4. **Client data flow**
   - The client likely follows this sequence: **sign-in → persist session locally → onboarding topic selection → fetch personalized feed data**.
   - Local storage and notification helpers sit on the edge of that flow, keeping state on-device while the feed service talks to the backend.

5. **Server boundary and entrypoint**
   - `server/src/index.ts` is the runtime entrypoint for the backend API.
   - `server/src/router.ts` centralizes request routing, while `server/src/middleware/requireAuth.ts` enforces protected endpoints.
   - `server/src/config.ts` is the configuration boundary, and `server/src/db.ts` is the database access layer.

6. **Feed ingestion and processing pipeline**
   - The backend separates feed handling into distinct stages:
     - `fetcher.ts` retrieves remote content
     - `parser.ts` converts raw feed content into structured data
     - `sanitizer.ts` removes unsafe or unwanted content
     - `aggregator.ts` combines or deduplicates items into API-ready results
     - `cache.ts` stores frequently used results for faster responses
   - This is the core server-side data flow and is the most important pipeline to capture in an architecture diagram.

7. **Authentication and persistence**
   - The server has its own auth layer in `server/src/auth.ts`, backed by the database.
   - Migrations in `server/migrations/001_create_users.sql` show a relational schema with at least a `users` table.
   - The presence of `requireAuth` indicates authenticated API routes are a first-class boundary, not an afterthought.

8. **Database and operational scripts**
   - `server/scripts/migrate.ts` and the SQL migrations imply schema evolution is managed separately from runtime request handling.
   - The backend therefore has a clear split between **application code** and **database lifecycle management**.

9. **Testing layers**
   - The server has both **unit tests** and **integration tests** under `server/tests/`, with API coverage in `integration/api.test.ts`.
   - The client has at least one unit test under `tests/unit/test_storage.ts`.
   - Server testing uses **Vitest**, while the root project also includes **Jest** and ESLint config, showing multiple quality gates across app and server boundaries.

10. **Build, CI, and repository workflow**
   - GitHub Actions in `.github/workflows/ci.yml` and Husky pre-push hooks enforce validation before merge.
   - The `.specify/` and `specs/` directories are not runtime subsystems; they are the project’s **specification and task-planning layer**, documenting features like onboarding, CI checks, and RSS aggregation.
   - This means the repo has a strong separation between **product behavior definitions** and **implementation/runtime code**.

11. **What to draw in a diagram**
   - The cleanest architecture diagram would show:
     - the **Expo mobile app** on the left
     - the **TypeScript API server** in the middle
     - **remote RSS/content sources** on the right feeding the server
     - a **database** and **cache** behind the server
     - local client **storage/notifications** as device-side concerns
   - The key runtime flows are **authentication**, **onboarding/preferences**, and **feed retrieval/aggregation**.

Main entry points: [`server/src/router.ts`](https://github.com/him7797/ainews/blob/main/server/src/router.ts) (Router), [`server/src/fetcher.ts`](https://github.com/him7797/ainews/blob/main/server/src/fetcher.ts) (Fetcher), [`src/app/_layout.tsx`](https://github.com/him7797/ainews/blob/main/src/app/_layout.tsx) (App shell), [`src/app/onboarding/index.tsx`](https://github.com/him7797/ainews/blob/main/src/app/onboarding/index.tsx) (Onboarding)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_mobile["Expo app"]
  node_mobile_shell["App shell<br/>expo-router<br/>[_layout.tsx]"]
  node_mobile_signin["Sign in<br/>screen<br/>[sign-in.tsx]"]
  node_mobile_onboarding["Onboarding<br/>screen<br/>[index.tsx]"]
  node_mobile_topics["Topics<br/>screen<br/>[topics.tsx]"]
  node_mobile_home["Home<br/>screen<br/>[index.tsx]"]
  node_auth_service["Auth service<br/>client auth<br/>[authService.ts]"]
  node_feed_service["Feed service<br/>client api<br/>[feedService.ts]"]
  node_storage[("Storage<br/>local persistence<br/>[storage.ts]")]
  node_notifications["Notifications<br/>[notifications.ts]"]
  node_onboarding_carousel["Carousel<br/>ui component"]
  node_topic_pill["Topic pill<br/>ui component<br/>[TopicPill.tsx]"]
  node_client_device(("Device<br/>client runtime"))
end

subgraph group_server["API server"]
  node_server_entry["API entry<br/>server runtime<br/>[index.ts]"]
  node_router["Router<br/>api routing<br/>[router.ts]"]
  node_require_auth["Auth guard<br/>middleware<br/>[requireAuth.ts]"]
  node_server_auth["Auth<br/>[auth.ts]"]
  node_config["Config<br/>[config.ts]"]
  node_db[("Database<br/>persistence<br/>[db.ts]")]
  node_fetcher["Fetcher<br/>ingestion<br/>[fetcher.ts]"]
  node_parser["Parser<br/>processing<br/>[parser.ts]"]
  node_sanitizer["Sanitizer<br/>processing<br/>[sanitizer.ts]"]
  node_aggregator["Aggregator<br/>aggregation<br/>[aggregator.ts]"]
  node_cache[("Cache<br/>[cache.ts]")]
  node_url_lib["URL helper<br/>[url.ts]"]
  node_server_api(("API server<br/>service boundary"))
end

subgraph group_specs["Specs"]
  node_spec_onboarding["Onboarding spec<br/>specification<br/>[spec.md]"]
  node_spec_rss["RSS spec<br/>specification<br/>[spec.md]"]
end

subgraph group_ops["Automation"]
  node_ci_workflow["CI workflow<br/>automation<br/>[ci.yml]"]
  node_prepush["Pre-push<br/>git hook<br/>[pre-push]"]
end

node_remote_sources(("RSS sources<br/>external source"))

node_mobile_shell -->|"routes"| node_mobile_signin
node_mobile_shell -->|"routes"| node_mobile_onboarding
node_mobile_shell -->|"routes"| node_mobile_home
node_mobile_onboarding -->|"uses"| node_onboarding_carousel
node_mobile_topics -->|"uses"| node_topic_pill
node_mobile_signin -->|"calls"| node_auth_service
node_mobile_home -->|"calls"| node_feed_service
node_auth_service -->|"requests"| node_server_api
node_feed_service -->|"requests"| node_server_api
node_auth_service -->|"persists"| node_storage
node_mobile_onboarding -->|"persists"| node_storage
node_mobile_home -->|"triggers"| node_notifications
node_server_entry -->|"loads"| node_router
node_router -->|"guards"| node_require_auth
node_router -->|"delegates"| node_server_auth
node_server_auth -->|"reads/writes"| node_db
node_require_auth -->|"verifies"| node_db
node_router -->|"orchestrates"| node_fetcher
node_fetcher -->|"retrieves"| node_remote_sources
node_fetcher -->|"passes"| node_parser
node_parser -->|"passes"| node_sanitizer
node_sanitizer -->|"feeds"| node_aggregator
node_aggregator -->|"stores"| node_cache
node_aggregator -->|"reads/writes"| node_db
node_fetcher -->|"uses"| node_url_lib
node_client_device -->|"contains"| node_storage
node_client_device -->|"contains"| node_notifications
node_spec_onboarding -.->|"describes"| node_mobile_onboarding
node_spec_rss -.->|"describes"| node_feed_service
node_ci_workflow -.->|"validates"| node_server_entry
node_ci_workflow -.->|"validates"| node_mobile_shell
node_prepush -.->|"mirrors"| node_ci_workflow

click node_mobile_shell "https://github.com/him7797/ainews/blob/main/src/app/_layout.tsx"
click node_mobile_signin "https://github.com/him7797/ainews/blob/main/src/app/auth/sign-in.tsx"
click node_mobile_onboarding "https://github.com/him7797/ainews/blob/main/src/app/onboarding/index.tsx"
click node_mobile_topics "https://github.com/him7797/ainews/blob/main/src/app/onboarding/topics.tsx"
click node_mobile_home "https://github.com/him7797/ainews/blob/main/src/app/index.tsx"
click node_auth_service "https://github.com/him7797/ainews/blob/main/src/services/authService.ts"
click node_feed_service "https://github.com/him7797/ainews/blob/main/src/services/feedService.ts"
click node_storage "https://github.com/him7797/ainews/blob/main/src/lib/storage.ts"
click node_notifications "https://github.com/him7797/ainews/blob/main/src/lib/notifications.ts"
click node_onboarding_carousel "https://github.com/him7797/ainews/blob/main/src/components/OnboardingCarousel.tsx"
click node_topic_pill "https://github.com/him7797/ainews/blob/main/src/components/TopicPill.tsx"
click node_server_entry "https://github.com/him7797/ainews/blob/main/server/src/index.ts"
click node_router "https://github.com/him7797/ainews/blob/main/server/src/router.ts"
click node_require_auth "https://github.com/him7797/ainews/blob/main/server/src/middleware/requireAuth.ts"
click node_server_auth "https://github.com/him7797/ainews/blob/main/server/src/auth.ts"
click node_config "https://github.com/him7797/ainews/blob/main/server/src/config.ts"
click node_db "https://github.com/him7797/ainews/blob/main/server/src/db.ts"
click node_fetcher "https://github.com/him7797/ainews/blob/main/server/src/fetcher.ts"
click node_parser "https://github.com/him7797/ainews/blob/main/server/src/parser.ts"
click node_sanitizer "https://github.com/him7797/ainews/blob/main/server/src/sanitizer.ts"
click node_aggregator "https://github.com/him7797/ainews/blob/main/server/src/aggregator.ts"
click node_cache "https://github.com/him7797/ainews/blob/main/server/src/cache.ts"
click node_url_lib "https://github.com/him7797/ainews/blob/main/server/src/lib/url.ts"
click node_spec_onboarding "https://github.com/him7797/ainews/blob/main/specs/001-onboarding-flow/spec.md"
click node_spec_rss "https://github.com/him7797/ainews/blob/main/specs/003-rss-news-aggregator/spec.md"
click node_ci_workflow "https://github.com/him7797/ainews/blob/main/.github/workflows/ci.yml"
click node_prepush "https://github.com/him7797/ainews/blob/main/.husky/pre-push"

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_mobile_shell,node_mobile_signin,node_mobile_onboarding,node_mobile_topics,node_mobile_home,node_auth_service,node_feed_service,node_storage,node_notifications,node_onboarding_carousel,node_topic_pill,node_client_device toneBlue
class node_server_entry,node_router,node_require_auth,node_server_auth,node_config,node_db,node_fetcher,node_parser,node_sanitizer,node_aggregator,node_cache,node_url_lib,node_server_api toneAmber
class node_spec_onboarding,node_spec_rss toneMint
class node_ci_workflow,node_prepush toneRose
class node_remote_sources toneNeutral
```

## Components

### Expo app

Mobile client and on-device behavior

- [App shell](https://github.com/him7797/ainews/blob/main/src/app/_layout.tsx): expo-router · Navigation shell and route composition · `src/app/_layout.tsx`
- [Sign in](https://github.com/him7797/ainews/blob/main/src/app/auth/sign-in.tsx): screen · Authentication screen · `src/app/auth/sign-in.tsx`
- [Onboarding](https://github.com/him7797/ainews/blob/main/src/app/onboarding/index.tsx): screen · First-run setup flow · `src/app/onboarding/index.tsx`
- [Topics](https://github.com/him7797/ainews/blob/main/src/app/onboarding/topics.tsx): screen · Topic selection step · `src/app/onboarding/topics.tsx`
- [Home](https://github.com/him7797/ainews/blob/main/src/app/index.tsx): screen · Primary feed landing screen · `src/app/index.tsx`
- [Auth service](https://github.com/him7797/ainews/blob/main/src/services/authService.ts): client auth · Client authentication and session handling · `src/services/authService.ts`
- [Feed service](https://github.com/him7797/ainews/blob/main/src/services/feedService.ts): client api · Client feed retrieval from backend · `src/services/feedService.ts`
- [Storage](https://github.com/him7797/ainews/blob/main/src/lib/storage.ts): local persistence · On-device persistence for session and preferences · `src/lib/storage.ts`
- [Notifications](https://github.com/him7797/ainews/blob/main/src/lib/notifications.ts): device notifications · Local notification behavior on device · `src/lib/notifications.ts`
- [Carousel](https://github.com/him7797/ainews/blob/main/src/components/OnboardingCarousel.tsx): ui component · Interactive onboarding UI · `src/components/OnboardingCarousel.tsx`
- [Topic pill](https://github.com/him7797/ainews/blob/main/src/components/TopicPill.tsx): ui component · Topic selection control · `src/components/TopicPill.tsx`
- **Device**: client runtime · Mobile runtime boundary

### API server

TypeScript backend and data pipeline

- [API entry](https://github.com/him7797/ainews/blob/main/server/src/index.ts): server runtime · Backend process entrypoint · `server/src/index.ts`
- [Router](https://github.com/him7797/ainews/blob/main/server/src/router.ts): api routing · Central request routing · `server/src/router.ts`
- [Auth guard](https://github.com/him7797/ainews/blob/main/server/src/middleware/requireAuth.ts): middleware · Protected route enforcement · `server/src/middleware/requireAuth.ts`
- [Auth](https://github.com/him7797/ainews/blob/main/server/src/auth.ts): server auth · Backend authentication logic · `server/src/auth.ts`
- [Config](https://github.com/him7797/ainews/blob/main/server/src/config.ts): configuration · Runtime configuration boundary · `server/src/config.ts`
- [Database](https://github.com/him7797/ainews/blob/main/server/src/db.ts): persistence · Relational data store · `server/src/db.ts`
- [Fetcher](https://github.com/him7797/ainews/blob/main/server/src/fetcher.ts): ingestion · Retrieves remote feed content · `server/src/fetcher.ts`
- [Parser](https://github.com/him7797/ainews/blob/main/server/src/parser.ts): processing · Converts raw feeds into structured items · `server/src/parser.ts`
- [Sanitizer](https://github.com/him7797/ainews/blob/main/server/src/sanitizer.ts): processing · Removes unsafe or unwanted content · `server/src/sanitizer.ts`
- [Aggregator](https://github.com/him7797/ainews/blob/main/server/src/aggregator.ts): aggregation · Combines and deduplicates feed items · `server/src/aggregator.ts`
- [Cache](https://github.com/him7797/ainews/blob/main/server/src/cache.ts): cache · Stores frequently used results · `server/src/cache.ts`
- [URL helper](https://github.com/him7797/ainews/blob/main/server/src/lib/url.ts): utility · Server-side URL handling helper · `server/src/lib/url.ts`
- **API server**: service boundary · Backend request/response boundary

### Specs

Specification and planning artifacts

- [Onboarding spec](https://github.com/him7797/ainews/blob/main/specs/001-onboarding-flow/spec.md): specification · Feature specification and tasks · `specs/001-onboarding-flow/spec.md`
- [RSS spec](https://github.com/him7797/ainews/blob/main/specs/003-rss-news-aggregator/spec.md): specification · RSS/news aggregator specification · `specs/003-rss-news-aggregator/spec.md`

### Automation

CI and repository workflow

- [CI workflow](https://github.com/him7797/ainews/blob/main/.github/workflows/ci.yml): automation · GitHub Actions validation pipeline · `.github/workflows/ci.yml`
- [Pre-push](https://github.com/him7797/ainews/blob/main/.husky/pre-push): git hook · Local validation hook before push · `.husky/pre-push`

### Other components

- **RSS sources**: external source · Remote RSS and content providers

## Connections

- App shell → Sign in: routes · Navigation shell exposes sign-in route
- App shell → Onboarding: routes · Navigation shell exposes onboarding flow
- App shell → Home: routes · Navigation shell exposes home screen
- Onboarding → Carousel: uses · Onboarding screen composes carousel UI
- Topics → Topic pill: uses · Topic selection uses pill component
- Sign in → Auth service: calls · Sign-in screen authenticates through client service
- Home → Feed service: calls · Home screen loads feed data through service
- Auth service → API server: requests · Client auth requests go to backend
- Feed service → API server: requests · Client feed requests go to backend
- Auth service → Storage: persists · Session data is stored on device
- Onboarding → Storage: persists · Onboarding state and preferences are stored locally
- Home → Notifications: triggers · Feed experience can drive local notifications
- API entry → Router: loads · Runtime starts request router
- Router → Auth guard: guards · Protected endpoints use auth middleware
- Router → Auth: delegates · Authentication routes delegate to auth layer
- Auth → Database: reads/writes · Auth state is backed by the database
- Auth guard → Database: verifies · Auth checks consult persisted user data
- Router → Fetcher: orchestrates · Feed endpoints trigger ingestion pipeline
- Fetcher → RSS sources: retrieves · Fetcher pulls remote RSS/content
- Fetcher → Parser: passes · Raw content is parsed into structured items
- Parser → Sanitizer: passes · Parsed items are cleaned before exposure
- Sanitizer → Aggregator: feeds · Sanitized items are combined and deduplicated
- Aggregator → Cache: stores · Aggregated results are cached
- Aggregator → Database: reads/writes · Aggregated data can be persisted or hydrated
- Fetcher → URL helper: uses · Fetcher relies on URL helper for remote requests
- Device → Storage: contains · Local persistence lives on the device
- Device → Notifications: contains · Notifications are device-side behavior
- Onboarding spec → Onboarding: describes · Specification documents onboarding behavior
- RSS spec → Feed service: describes · Specification documents feed retrieval behavior
- CI workflow → API entry: validates · CI covers backend build and tests
- CI workflow → App shell: validates · CI covers client build and tests
- Pre-push → CI workflow: mirrors · Local hook mirrors repository validation
