# bytepute/website architecture

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

- Interactive diagram: https://gitdiagram.com/bytepute/website
- Repository: https://github.com/bytepute/website

## Overview

1. **Project shape**
   - This is a **Next.js App Router** application built as a small content management site for articles, with a **public reading surface** and an **admin editing surface**.
   - The repo is organized around route segments in `app/`, shared UI in `components/`, and database/domain logic in `lib/` plus Prisma schema/migrations.

2. **Route topology**
   - Public routes:
     - `app/page.tsx` — landing page
     - `app/articles/page.tsx` — article index
     - `app/articles/[slug]/page.tsx` — article detail page
   - Admin routes:
     - `app/admin/page.tsx` — admin entry/dashboard
     - `app/admin/articles/new/page.tsx` — create article
     - `app/admin/articles/[id]/edit/page.tsx` — edit article
   - This is a route-driven architecture rather than a separate frontend/backend split.

3. **Content domain**
   - The central domain model is **Article**.
   - The article lifecycle is: list → read → create → edit.
   - The naming (`slug` for public detail pages, `id` for admin edit pages) suggests a clear boundary between **public URL identity** and **internal database identity**.

4. **Data access layer**
   - `lib/articles.ts` is the main domain/data access module for article operations.
   - `lib/prisma.ts` centralizes the Prisma client, so database access is funneled through a single ORM boundary.
   - `prisma/schema.prisma` and the migration files define the persistence model and its evolution, making the database a first-class part of the architecture.

5. **Admin mutation flow**
   - `app/admin/actions.ts` indicates the admin side uses **server actions** for mutations rather than a separate REST API.
   - The likely flow is: admin form submits → server action runs on the server → Prisma writes to the database → updated article data is revalidated/rendered.
   - This keeps write operations close to the route that owns them and avoids an extra API layer.

6. **Public read flow**
   - Public article pages are read-only consumers of the article domain.
   - `components/articles-list.tsx`, `components/article-detail.tsx`, and `components/article-content.tsx` separate the list/detail rendering concerns from the route files.
   - The public side is therefore “route composes data + presentation components,” with data coming from the shared article layer.

7. **Admin UI boundary**
   - `components/admin-gate.tsx` and `proxy.ts` are the main protection mechanisms around admin routes.
   - `lib/auth.ts` likely contains auth/session checks, while the gate component controls rendering access inside the UI and the proxy enforces route-level protection.
   - This creates a distinct boundary between anonymous public browsing and privileged content management.

8. **Forms and editing UX**
   - `components/article-form.tsx` and `components/edit-article-panel.tsx` are the main edit/create interfaces.
   - These components are reused by the new/edit admin pages, so the form logic is shared and the route files stay thin.
   - The admin UI is therefore centered on a reusable form/editor component rather than page-specific form implementations.

9. **Shared presentation system**
   - The app uses a component library based on **shadcn/ui** with primitives in `components/ui/` (`button`, `input`, `label`, `textarea`).
   - `components/site-header.tsx`, `components/loading-fallbacks.tsx`, and `components/theme-provider.tsx` support cross-cutting app presentation concerns.
   - `app/layout.tsx` and `app/globals.css` provide the global shell and styling foundation for both public and admin areas.

10. **Runtime and persistence boundaries**
   - The application runs as a **single Next.js server/client app**; there is no separate backend service or standalone API project in the tree.
   - Persistence is handled through **Prisma + a relational database**, with migrations in `prisma/migrations/`.
   - That means the major boundaries are:
     - browser UI
     - Next.js route/server-action layer
     - auth/protection layer
     - Prisma-backed data layer
     - database

11. **What to show in an architecture diagram**
   - A good diagram should show:
     - Public routes feeding shared article display components
     - Admin routes feeding form/editor components
     - Admin requests passing through auth/protection before mutations
     - Server actions and `lib/articles`/`lib/prisma` as the bridge to the database
     - Prisma schema/migrations as the persistence contract
   - The key architectural idea is a **single Next.js application with strong separation between public read paths and protected admin write paths**.

Main entry points: [`app/layout.tsx`](https://github.com/bytepute/website/blob/main/app/layout.tsx) (App shell), [`lib/articles.ts`](https://github.com/bytepute/website/blob/main/lib/articles.ts) (Articles domain), [`components/article-form.tsx`](https://github.com/bytepute/website/blob/main/components/article-form.tsx) (Article form), [`proxy.ts`](https://github.com/bytepute/website/blob/main/proxy.ts) (Route proxy)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_public["Public surface"]
  node_articles_page["Article index<br/>public route<br/>[page.tsx]"]
  node_article_detail_page["Article detail<br/>public route<br/>[page.tsx]"]
  node_home_page["Landing page<br/>public route<br/>[page.tsx]"]
  node_articles_list["Articles list<br/>list component<br/>[articles-list.tsx]"]
  node_article_detail["Article detail view<br/>detail component<br/>[article-detail.tsx]"]
  node_article_content["Article content<br/>content renderer"]
end

subgraph group_admin["Admin surface"]
  node_admin_dashboard["Admin dashboard<br/>admin route<br/>[page.tsx]"]
  node_admin_new["New article<br/>admin route<br/>[page.tsx]"]
  node_admin_edit["Edit article<br/>admin route<br/>[page.tsx]"]
  node_admin_actions["Admin actions<br/>server actions<br/>[actions.ts]"]
  node_article_form["Article form<br/>form component<br/>[article-form.tsx]"]
  node_edit_panel["Edit panel<br/>editor panel"]
end

subgraph group_shared["Shared UI"]
  node_app_layout["App shell<br/>[layout.tsx]"]
  node_app_globals["Global styles<br/>css base<br/>[globals.css]"]
  node_site_header["Site header<br/>chrome<br/>[site-header.tsx]"]
  node_theme_provider["Theme provider<br/>client provider<br/>[theme-provider.tsx]"]
  node_loading_fallbacks["Loading states<br/>ui states"]
  node_ui_button["Button<br/>ui primitive<br/>[button.tsx]"]
  node_ui_input["Input<br/>ui primitive<br/>[input.tsx]"]
  node_ui_label["Label<br/>ui primitive<br/>[label.tsx]"]
  node_ui_textarea["Textarea<br/>ui primitive<br/>[textarea.tsx]"]
end

subgraph group_data["Domain data"]
  node_articles_lib["Articles domain<br/>domain service<br/>[articles.ts]"]
  node_prisma_client[("Prisma client<br/>orm client<br/>[prisma.ts]")]
end

subgraph group_persistence["Persistence"]
  node_schema["Schema<br/>[schema.prisma]"]
  node_migrations["Migrations"]
end

subgraph group_security["Access control"]
  node_admin_gate["Admin gate<br/>ui guard<br/>[admin-gate.tsx]"]
  node_proxy["Route proxy<br/>edge guard<br/>[proxy.ts]"]
  node_auth["Auth<br/>[auth.ts]"]
end

node_home_page -->|"composes"| node_site_header
node_home_page -->|"reads"| node_articles_lib
node_articles_page -->|"renders"| node_articles_list
node_articles_page -->|"reads"| node_articles_lib
node_article_detail_page -->|"renders"| node_article_detail
node_article_detail_page -->|"reads"| node_articles_lib
node_article_detail -->|"includes"| node_article_content
node_article_detail_page -->|"composes"| node_site_header
node_admin_dashboard -->|"guards"| node_admin_gate
node_admin_dashboard -->|"reads"| node_articles_lib
node_admin_new -->|"guards"| node_admin_gate
node_admin_new -->|"renders"| node_edit_panel
node_admin_edit -->|"guards"| node_admin_gate
node_admin_edit -->|"renders"| node_edit_panel
node_edit_panel -->|"contains"| node_article_form
node_article_form -->|"uses"| node_ui_input
node_article_form -->|"uses"| node_ui_textarea
node_article_form -->|"uses"| node_ui_label
node_article_form -->|"uses"| node_ui_button
node_admin_actions -->|"mutates"| node_articles_lib
node_articles_lib -->|"queries"| node_prisma_client
node_prisma_client -->|"maps to"| node_schema
node_schema -->|"evolves via"| node_migrations
node_proxy -->|"enforces"| node_auth
node_admin_gate -->|"checks"| node_auth
node_app_layout -->|"wraps"| node_theme_provider
node_app_layout -->|"includes"| node_site_header
node_app_layout -->|"uses"| node_loading_fallbacks
node_app_layout -->|"loads"| node_app_globals
node_app_layout -->|"hosts"| node_home_page
node_app_layout -->|"hosts"| node_articles_page
node_app_layout -->|"hosts"| node_article_detail_page
node_app_layout -->|"hosts"| node_admin_dashboard
node_app_layout -->|"hosts"| node_admin_new
node_app_layout -->|"hosts"| node_admin_edit
node_proxy -->|"protects"| node_admin_dashboard
node_proxy -->|"protects"| node_admin_new
node_proxy -->|"protects"| node_admin_edit

click node_app_layout "https://github.com/bytepute/website/blob/main/app/layout.tsx"
click node_app_globals "https://github.com/bytepute/website/blob/main/app/globals.css"
click node_site_header "https://github.com/bytepute/website/blob/main/components/site-header.tsx"
click node_theme_provider "https://github.com/bytepute/website/blob/main/components/theme-provider.tsx"
click node_loading_fallbacks "https://github.com/bytepute/website/blob/main/components/loading-fallbacks.tsx"
click node_articles_page "https://github.com/bytepute/website/blob/main/app/articles/page.tsx"
click node_article_detail_page "https://github.com/bytepute/website/blob/main/app/articles/[slug]/page.tsx"
click node_home_page "https://github.com/bytepute/website/blob/main/app/page.tsx"
click node_articles_list "https://github.com/bytepute/website/blob/main/components/articles-list.tsx"
click node_article_detail "https://github.com/bytepute/website/blob/main/components/article-detail.tsx"
click node_article_content "https://github.com/bytepute/website/blob/main/components/article-content.tsx"
click node_admin_dashboard "https://github.com/bytepute/website/blob/main/app/admin/page.tsx"
click node_admin_new "https://github.com/bytepute/website/blob/main/app/admin/articles/new/page.tsx"
click node_admin_edit "https://github.com/bytepute/website/blob/main/app/admin/articles/[id]/edit/page.tsx"
click node_admin_actions "https://github.com/bytepute/website/blob/main/app/admin/actions.ts"
click node_article_form "https://github.com/bytepute/website/blob/main/components/article-form.tsx"
click node_edit_panel "https://github.com/bytepute/website/blob/main/components/edit-article-panel.tsx"
click node_admin_gate "https://github.com/bytepute/website/blob/main/components/admin-gate.tsx"
click node_proxy "https://github.com/bytepute/website/blob/main/proxy.ts"
click node_auth "https://github.com/bytepute/website/blob/main/lib/auth.ts"
click node_articles_lib "https://github.com/bytepute/website/blob/main/lib/articles.ts"
click node_prisma_client "https://github.com/bytepute/website/blob/main/lib/prisma.ts"
click node_schema "https://github.com/bytepute/website/blob/main/prisma/schema.prisma"
click node_migrations "https://github.com/bytepute/website/blob/main/prisma/migrations/migration_lock.toml"
click node_ui_button "https://github.com/bytepute/website/blob/main/components/ui/button.tsx"
click node_ui_input "https://github.com/bytepute/website/blob/main/components/ui/input.tsx"
click node_ui_label "https://github.com/bytepute/website/blob/main/components/ui/label.tsx"
click node_ui_textarea "https://github.com/bytepute/website/blob/main/components/ui/textarea.tsx"

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_articles_page,node_article_detail_page,node_home_page,node_articles_list,node_article_detail,node_article_content toneBlue
class node_admin_dashboard,node_admin_new,node_admin_edit,node_admin_actions,node_article_form,node_edit_panel toneAmber
class node_app_layout,node_app_globals,node_site_header,node_theme_provider,node_loading_fallbacks,node_ui_button,node_ui_input,node_ui_label,node_ui_textarea toneMint
class node_articles_lib,node_prisma_client toneRose
class node_schema,node_migrations toneIndigo
class node_admin_gate,node_proxy,node_auth toneTeal
```

## Components

### Public surface

Anonymous reading routes and article display

- [Article index](https://github.com/bytepute/website/blob/main/app/articles/page.tsx): public route · Lists published articles · `app/articles/page.tsx`
- [Article detail](https://github.com/bytepute/website/blob/main/app/articles/[slug]/page.tsx): public route · Renders a single article by slug · `app/articles/[slug]/page.tsx`
- [Landing page](https://github.com/bytepute/website/blob/main/app/page.tsx): public route · Front page entry point · `app/page.tsx`
- [Articles list](https://github.com/bytepute/website/blob/main/components/articles-list.tsx): list component · Shared article index presentation · `components/articles-list.tsx`
- [Article detail view](https://github.com/bytepute/website/blob/main/components/article-detail.tsx): detail component · Article page presentation wrapper · `components/article-detail.tsx`
- [Article content](https://github.com/bytepute/website/blob/main/components/article-content.tsx): content renderer · Article body rendering component · `components/article-content.tsx`

### Admin surface

Protected editing routes and write flows

- [Admin dashboard](https://github.com/bytepute/website/blob/main/app/admin/page.tsx): admin route · Admin entry and overview · `app/admin/page.tsx`
- [New article](https://github.com/bytepute/website/blob/main/app/admin/articles/new/page.tsx): admin route · Create article page · `app/admin/articles/new/page.tsx`
- [Edit article](https://github.com/bytepute/website/blob/main/app/admin/articles/[id]/edit/page.tsx): admin route · Edit article page · `app/admin/articles/[id]/edit/page.tsx`
- [Admin actions](https://github.com/bytepute/website/blob/main/app/admin/actions.ts): server actions · Server-side mutation entry points · `app/admin/actions.ts`
- [Article form](https://github.com/bytepute/website/blob/main/components/article-form.tsx): form component · Shared create/edit form · `components/article-form.tsx`
- [Edit panel](https://github.com/bytepute/website/blob/main/components/edit-article-panel.tsx): editor panel · Admin editing UI wrapper · `components/edit-article-panel.tsx`

### Shared UI

Cross-cutting layout and reusable presentation components

- [App shell](https://github.com/bytepute/website/blob/main/app/layout.tsx): next app shell · Global app layout and providers · `app/layout.tsx`
- [Global styles](https://github.com/bytepute/website/blob/main/app/globals.css): css base · Application-wide styling foundation · `app/globals.css`
- [Site header](https://github.com/bytepute/website/blob/main/components/site-header.tsx): chrome · Shared top-level navigation and branding · `components/site-header.tsx`
- [Theme provider](https://github.com/bytepute/website/blob/main/components/theme-provider.tsx): client provider · App-wide theme and client UI context · `components/theme-provider.tsx`
- [Loading states](https://github.com/bytepute/website/blob/main/components/loading-fallbacks.tsx): ui states · Shared loading and fallback UI · `components/loading-fallbacks.tsx`
- [Button](https://github.com/bytepute/website/blob/main/components/ui/button.tsx): ui primitive · Shared button primitive · `components/ui/button.tsx`
- [Input](https://github.com/bytepute/website/blob/main/components/ui/input.tsx): ui primitive · Shared input primitive · `components/ui/input.tsx`
- [Label](https://github.com/bytepute/website/blob/main/components/ui/label.tsx): ui primitive · Shared label primitive · `components/ui/label.tsx`
- [Textarea](https://github.com/bytepute/website/blob/main/components/ui/textarea.tsx): ui primitive · Shared textarea primitive · `components/ui/textarea.tsx`

### Domain data

Article logic, auth, and ORM boundary

- [Articles domain](https://github.com/bytepute/website/blob/main/lib/articles.ts): domain service · Article queries and mutations · `lib/articles.ts`
- [Prisma client](https://github.com/bytepute/website/blob/main/lib/prisma.ts): orm client · Centralized database client · `lib/prisma.ts`

### Persistence

Schema and migration contract

- [Schema](https://github.com/bytepute/website/blob/main/prisma/schema.prisma): db schema · Prisma data model definition · `prisma/schema.prisma`
- [Migrations](https://github.com/bytepute/website/blob/main/prisma/migrations/migration_lock.toml): db migrations · Database evolution history · `prisma/migrations/migration_lock.toml`

### Access control

Route and UI protection for admin access

- [Admin gate](https://github.com/bytepute/website/blob/main/components/admin-gate.tsx): ui guard · UI-level access gate for admin pages · `components/admin-gate.tsx`
- [Route proxy](https://github.com/bytepute/website/blob/main/proxy.ts): edge guard · Route-level admin protection · `proxy.ts`
- [Auth](https://github.com/bytepute/website/blob/main/lib/auth.ts): session auth · Authentication and authorization checks · `lib/auth.ts`

## Connections

- Landing page → Site header: composes · Uses shared site chrome
- Landing page → Articles domain: reads · Fetches article data for landing content
- Article index → Articles list: renders · Delegates index presentation
- Article index → Articles domain: reads · Loads published articles
- Article detail → Article detail view: renders · Delegates single-article presentation
- Article detail → Articles domain: reads · Loads article by slug
- Article detail view → Article content: includes · Uses body rendering component
- Article detail → Site header: composes · Shares global navigation
- Admin dashboard → Admin gate: guards · Blocks unauthorized access in UI
- Admin dashboard → Articles domain: reads · Shows managed content state
- New article → Admin gate: guards · Requires admin access
- New article → Edit panel: renders · Uses shared editor wrapper
- Edit article → Admin gate: guards · Requires admin access
- Edit article → Edit panel: renders · Uses shared editor wrapper
- Edit panel → Article form: contains · Wraps the reusable form
- Article form → Input: uses · Text input primitive
- Article form → Textarea: uses · Body editing primitive
- Article form → Label: uses · Field labeling primitive
- Article form → Button: uses · Submit action primitive
- Admin actions → Articles domain: mutates · Routes writes through domain layer
- Articles domain → Prisma client: queries · Uses centralized ORM client
- Prisma client → Schema: maps to · Backed by Prisma schema
- Schema → Migrations: evolves via · Schema changes are captured in migrations
- Route proxy → Auth: enforces · Checks route access before admin entry
- Admin gate → Auth: checks · Uses auth state for UI gating
- App shell → Theme provider: wraps · Provides client theme context
- App shell → Site header: includes · Shared shell chrome
- App shell → Loading states: uses · Provides app-level fallback UI
- App shell → Global styles: loads · Imports global stylesheet
- App shell → Landing page: hosts · Root route within global shell
- App shell → Article index: hosts · Public route within global shell
- App shell → Article detail: hosts · Public route within global shell
- App shell → Admin dashboard: hosts · Admin route within global shell
- App shell → New article: hosts · Admin route within global shell
- App shell → Edit article: hosts · Admin route within global shell
- Route proxy → Admin dashboard: protects · Blocks unprivileged route entry
- Route proxy → New article: protects · Blocks unprivileged route entry
- Route proxy → Edit article: protects · Blocks unprivileged route entry
