# Gitea TUI (fjtui) System Architecture This document provides a comprehensive overview of the Gitea/Forgejo TUI Dashboard's system architecture, component layout, and user flows. It uses **Mermaid.js** diagrams to detail the application structure and page lifecycle transitions. --- ## 1. High-Level Architecture The Gitea TUI client is a modular CLI application written in TypeScript and Node.js. It operates as a local state machine that communicates with a Gitea or Forgejo instance REST API over HTTPS. ```mermaid graph TD subgraph Client ["Gitea TUI Application Context"] EP["index.ts (CLI Entry Point)"] ConfigManager["config.ts (Configuration Manager)"] TuiEngine["tui.ts (TuiEngine Controller)"] APILayer["api.ts (API Service Layer)"] Types["types.ts (State & Entity Types)"] end subgraph External ["External Resources"] LocalConfig["Local Config (./fjtui.json)"] GlobalConfig["Global Config (~/.config/fjtui/fjtui.json)"] GiteaAPI["Gitea/Forgejo Instance REST API"] end subgraph IO ["Terminal User Interface"] Stdin["stdin (Raw Keypress Listeners)"] Stdout["stdout (Chalk Styled Rendering)"] end %% Key Relationships EP -->|Reads Config / Parses Args| ConfigManager EP -->|Direct Connect Check| APILayer EP -->|Initializes & Starts| TuiEngine ConfigManager <-->|Read / Write| LocalConfig ConfigManager <-->|Read / Write| GlobalConfig TuiEngine -->|Subscribes to Events| Stdin TuiEngine -->|Paints Screens| Stdout TuiEngine -->|Fetches & Mutates Data| APILayer TuiEngine -->|Saves Config| ConfigManager APILayer -->|HTTP / REST Requests (Axios)| GiteaAPI TuiEngine -.->|Operates on AppState| Types ``` --- ## 2. Screen & Page Transition Flow The terminal application operates as a single-page terminal application (SPTA) with a central screen router state. Below is the transition flow (state machine) representing how keypress actions route the user between screens. ```mermaid stateDiagram-v2 [*] --> Launch : Run gitea-tui (Bootstrap or Direct Connect) Launch --> Setup : No config / finished or skipped Launch --> List : Config exists / direct connect (finished or skipped) state Setup { [*] --> EnteringCredentials EnteringCredentials --> Validating : Enter/Submit Form Validating --> EnteringCredentials : Connection Error } Setup --> RepoPicker : Validated & Repositories Loaded state RepoPicker { [*] --> BrowsingRepos BrowsingRepos --> BrowsingRepos : Filter / Search } RepoPicker --> Setup : Escape (Go Back) RepoPicker --> List : Select Repo (Enter) & Load Issues state List { [*] --> DisplayingIssues DisplayingIssues --> DisplayingIssues : Toggle Filters / Sort / Paginate / Search } List --> Setup : Change Connection ('o' key) List --> CreateIssue : Create Issue ('c' key) List --> Details : View Issue Details (Enter) state CreateIssue { [*] --> FillingIssueForm FillingIssueForm --> SavingIssue : Ctrl+S (Submit) SavingIssue --> DisplayingIssues : Success (List reloads) SavingIssue --> FillingIssueForm : Failure (Shows error) } CreateIssue --> List : Escape (Cancel) state Details { [*] --> ViewingDetails ViewingDetails --> ViewingDetails : Scroll description & comments } Details --> List : Escape / Backspace / Q (Go Back) Details --> Setup : Change Connection ('o' key) Details --> AddComment : Add Comment ('c' key) Details --> EditIssue : Edit Issue ('e' key) Details --> AddTime : Add Tracked Time ('t' key) Details --> SetAssignees : Set Assignees ('a' key) Details --> ConfirmStateChange : Toggle Issue State ('x' key) state AddComment { [*] --> EnteringComment EnteringComment --> SubmittingComment : Ctrl+S (Submit) SubmittingComment --> ViewingDetails : Success (Comments reload) SubmittingComment --> EnteringComment : Failure (Shows error) } AddComment --> Details : Escape (Cancel) state EditIssue { [*] --> EditingIssueForm EditingIssueForm --> SubmittingEdit : Ctrl+S (Submit) SubmittingEdit --> ViewingDetails : Success (Details reload) SubmittingEdit --> EditingIssueForm : Failure (Shows error) } EditIssue --> Details : Escape (Cancel) state AddTime { [*] --> EnteringTime EnteringTime --> SubmittingTime : Ctrl+S (Submit) SubmittingTime --> ViewingDetails : Success (Time reloads) SubmittingTime --> EnteringTime : Failure (Shows error) } AddTime --> Details : Escape (Cancel) state SetAssignees { [*] --> EnteringAssignees EnteringAssignees --> SubmittingAssignees : Enter (Submit) SubmittingAssignees --> ViewingDetails : Success (Assignees reload) SubmittingAssignees --> EnteringAssignees : Failure (Shows error) } SetAssignees --> Details : Escape (Cancel) state ConfirmStateChange { [*] --> AwaitingConfirmation AwaitingConfirmation --> Details : No / Escape (Cancel) AwaitingConfirmation --> AnimatingChange : Yes ('y' key) state AnimatingChange { [*] --> AnimatingClose : If Closing (Gravestones) [*] --> AnimatingReopen : If Reopening (Zombies) AnimatingClose --> ExecutingStateChangeAPI : Finish Frames (1.5s) AnimatingReopen --> ExecutingStateChangeAPI : Finish Frames (1.8s) } ExecutingStateChangeAPI --> ViewingDetails : Done & Reloaded } ``` --- ## 3. Data Interaction & Rerender Lifecycle When the user interacts with the interface, keyboard events are processed by the active screen key handler, state variables are updated, API calls are made if necessary, and a full screen redraw is triggered on the terminal buffer. The following sequence diagram details the lifecyle of adding a comment to an issue: ```mermaid sequenceDiagram autonumber actor User as User Terminal participant TUI as TuiEngine (tui.ts) participant API as API Layer (api.ts) participant Gitea as Gitea REST API User->>TUI: Keypress (e.g. 'c' on Details screen) TUI->>TUI: Update screen state to 'add-comment' TUI->>TUI: Render text input area (addCommentForm) TUI-->>User: Display empty comment field User->>TUI: Type comment text + Ctrl+S TUI->>TUI: Set state.loading = true & render spinner TUI->>API: createIssueComment(config, issueNumber, commentBody) API->>Gitea: POST /repos/{owner}/{repo}/issues/{index}/comments Gitea-->>API: 201 Created (Comment entity JSON) API-->>TUI: Comment Object TUI->>TUI: Set screen state to 'details' TUI->>TUI: Trigger loadComments(issue) (Async) TUI->>API: fetchIssueComments(config, issueNumber) API->>Gitea: GET /repos/{owner}/{repo}/issues/{index}/comments Gitea-->>API: 200 OK (Comments list JSON) API-->>TUI: Comment[] Array TUI->>TUI: Set state.loading = false TUI->>TUI: Render details screen + updated comments TUI-->>User: Display issue details and new comment ``` --- ## 4. Module Directories & Code Structure The project code is organized into a clean multi-file architecture located under [src](file:///wsl.localhost/Ubuntu/home/builder/Workspaces/fjtui/src): 1. **[index.ts](file:///wsl.localhost/Ubuntu/home/builder/Workspaces/fjtui/src/index.ts)**: - Sets up Command-line parsing with the `commander` package. - Automatically bootstraps the configuration and constructs the default `AppState`. - Checks CLI credentials. If valid, validates them directly, bypassing the setup page and going straight to the issue dashboard. - Instantiates the `TuiEngine` and starts the app loop. 2. **[tui.ts](file:///wsl.localhost/Ubuntu/home/builder/Workspaces/fjtui/src/tui.ts)**: - Contains the core `TuiEngine` class which manages key listeners on `process.stdin` (in raw mode). - Manages loading spinners and UI animations (Gravestones for closed issues and Zombies for reopened issues). - Performs terminal buffer manipulation (e.g. entering alternate screen buffer `\x1B[?1049h`, hiding cursor `\x1B[?25l`). - Delegates the rendering of specific screens using modular helper functions (e.g., `renderSetupScreen`, `renderListScreen`, `renderDetailsScreen`). 3. **[api.ts](file:///wsl.localhost/Ubuntu/home/builder/Workspaces/fjtui/src/api.ts)**: - Hosts the REST API layer built on top of `axios`. - Interacts with Forgejo/Gitea endpoints such as `/repos`, `/issues`, `/comments`, and `/times`. - Handles network errors and formats them into user-friendly diagnostic messages. 4. **[config.ts](file:///wsl.localhost/Ubuntu/home/builder/Workspaces/fjtui/src/config.ts)**: - Manages persistence of credentials. - Reads configuration locally from `fjtui.json` and globally from `~/.config/fjtui/fjtui.json`. Local configurations take priority. - Writes updated credentials back to the user's home configuration safely. 5. **[types.ts](file:///wsl.localhost/Ubuntu/home/builder/Workspaces/fjtui/src/types.ts)**: - Declares the TypeScript contracts and interfaces representing the application state (`AppState`), target forms (`SetupForm`, `CreateIssueForm`, etc.), and returned entities (`User`, `Issue`, `Label`, `Comment`, `RepoItem`). 6. **ASCII Art Assets**: - [ascii-art.txt](file:///wsl.localhost/Ubuntu/home/builder/Workspaces/fjtui/ascii-art.txt): ASCII art loaded at startup to perform the color-shifting launch animation.