This document provides a technical overview of the DocForge application's architecture, components, and key systems.
- Framework: Electron for cross-platform desktop application development.
- UI Library: React for building the user interface.
- Language: TypeScript for type safety and improved developer experience.
- Editor Core: Monaco Editor for a rich, consistent editing experience.
- Database: SQLite via the better-sqlite3 library for robust, local data storage.
- Bundler: esbuild for fast and efficient bundling of the application's source code.
- Styling: Tailwind CSS for a utility-first CSS framework.
- Packaging: electron-builder for creating distributable application packages.
- Diagram Rendering: PlantUML via either the public plantuml.com service or a PlantUML jar bundled with the application (
assets/plantuml/plantuml.jar). Offline rendering invokes the jar through the system Java Runtime Environment, so diagrams render without any network connectivity.
doc-forge/
├── assets/ # Static assets like the application icon.
├── components/ # Reusable React components.
│ ├── iconsets/ # SVG icon components for different libraries.
│ └── ...
├── contexts/ # React context providers for global state.
├── electron/ # Source code for the Electron main process.
│ ├── database.ts # Manages the SQLite database connection and migrations.
│ ├── schema.ts # Contains the embedded SQL schema string.
│ ├── main.ts # Main process entry point.
│ └── preload.ts # Preload script for secure IPC.
├── hooks/ # Custom React hooks for business logic.
├── services/ # Modules for data access and external systems.
│ ├── preview/ # Renderer plugins for the preview system.
│ └── ...
├── release/ # Output directory for packaged application.
├── dist/ # Output directory for bundled code.
├── index.html # The main HTML file for the renderer process.
├── index.tsx # The entry point for the React application.
├── package.json # Project metadata and dependencies.
└── ...
The main process is responsible for managing the application lifecycle, database, and native OS interactions.
- Window Management: It creates the frameless
BrowserWindowwhich contains the React UI. - Database Management (
database.ts): This service is the single owner of the SQLite database file. It usesbetter-sqlite3to open the connection, run schema migrations on startup, and execute queries. All database access must go through this service. - IPC (Inter-Process Communication): It sets up IPC handlers to listen for events from the renderer process. The UI communicates with the database exclusively through these channels. Key handlers include:
db:query,db:run: Generic handlers to execute SQL against the database.db:duplicate-nodes: A handler to perform a deep, transactional copy of selected nodes.db:migrate-from-json: A special handler for the one-time migration of data from old JSON files.- Window Controls: Handlers for
window:minimize,window:maximize, etc. - Application Integrations:
app:open-executable-folderresolves the on-disk location of the running binary and opens it via the host OS shell so support teams can quickly reach the installation directory.
- Security: The
preload.tsscript uses Electron'scontextBridgeto securely expose specific IPC functions to the renderer process under thewindow.electronAPIobject, maintaining context isolation.
The renderer process is responsible for the entire user interface.
- Component Tree: The application is built as a tree of React components, starting from
index.tsx. - UI State: Most UI state is managed within components using React hooks (
useState,useMemo). - Business & Data Logic: Logic for managing the application's data is encapsulated in custom hooks (e.g.,
useNodes,useTemplates,useSettings). These hooks interact with therepository.tsservice to communicate with the backend.
- React Hooks & Context: Global state (like theme and logs) is shared via React Context.
- SQLite Database: The single source of truth for all persistent data (documents, folders, templates, settings, versions) is the
docforge.dbSQLite file. Data is fetched into React state on load and updated in the database via the repository service.
This is the core data persistence layer, replacing the old JSON file system.
electron/database.ts(Main Process): Manages the physical database file and connection usingbetter-sqlite3. It handles schema creation and versioning by executing SQL scripts embedded directly within the application's source code (electron/schema.ts). This removes the need for external.sqlfiles and simplifies packaging.services/repository.ts(Renderer Process): The data access layer for the UI. It acts as an abstraction over the IPC communication. It contains all the application's SQL queries and provides clear, async methods (e.g.,getNodeTree(),updateDocumentContent(),deleteDocVersions(),duplicateNodes()) for the React hooks to use. It does not access the database directly.- Schema: The database uses a highly normalized schema with tables for
nodes(hierarchy),documents,content_store(for content-addressable storage and deduplication), anddoc_versions. - One-Time Migration: The repository contains logic to detect if it's the first run with the new database. If old JSON files are found, it reads them and sends the data to the main process to be migrated into the SQLite database in a single, safe transaction.
This system provides a consistent and extensible editing experience for all document types. It is built on a decoupled, modular architecture.
CodeEditor.tsx: A React component that wraps and configures the Monaco Editor instance. It's responsible for managing the editor's content, theme, and language for syntax highlighting based on props.PreviewPane.tsx: This component is responsible for displaying the rendered output of a document. It debounces content updates for performance and uses thePreviewServiceto get the correct output.services/previewService.ts: This service acts as a registry for all available renderer "plugins." It exposes a method,getRendererForLanguage(), which finds and returns the appropriate renderer for a given language ID (e.g., 'markdown').- Renderer Plugins (
services/preview/): Each file format with a preview is supported by a dedicated renderer class that implements theIRendererinterface. This makes the system highly extensible: to support a new format, one only needs to create a new renderer class and add it to thepreviewServiceregistry. The bundled plugins cover Markdown (with Mermaid + PlantUML support), standalone PlantUML documents, HTML, PDFs, common image formats, and a plaintext fallback renderer.- Both the Markdown renderer and the standalone PlantUML renderer share the
PlantUMLDiagramcomponent, which routes diagrams through either the remote plantuml.com server or the offline Java-based IPC bridge depending on the active setting.
- Both the Markdown renderer and the standalone PlantUML renderer share the
The export service centralizes all logic for saving documents to disk.
- Extension Inference: It inspects the document's type, Monaco language hint, and any embedded MIME metadata to choose the best file extension. Titles are sanitized and de-duplicated so the suggested filename is always valid.
- Payload Preparation: Text documents are serialized with UTF-8 defaults, while PDFs and images are decoded from data URLs or base64 strings into
Uint8Arraybuffers before saving. - Renderer Integration: Renderer components call
handleSaveNodeToFile()which delegates to the export service. In Electron builds the payload is sent over IPC toelectron/main.ts, which opens a native save dialog and streams the bytes. Browser builds fall back to programmatically triggering a download with the correct MIME type. - Cancellation Handling: If a user dismisses the save dialog, the service returns a
canceledresult that callers treat as a no-op so logs and notifications stay quiet.
DocForge treats shell and PowerShell automation as first-class workflows that span the renderer and main processes.
- Renderer orchestration (
components/ScriptExecutionPanel.tsx): Presents the UI for configuring per-document environment variables, working directory, and interpreter overrides. It merges those overrides with the defaults loaded from the settings context before dispatching a run. - IPC bridge (
services/scriptService.ts): Normalizes renderer requests intoscriptRun,scriptGetNodeSettings, and related IPC calls. In preview builds it can swap to the mock bridge exposed bypreview/createScriptPreviewBridge.tsso web previews behave consistently. - Main-process runner (
electron/scriptRunner.ts): Persists run metadata, writes temporary script files, and spawns the resolved executable. Test mode leveragesscriptArgs.tsto compute syntax-only flags (for example, Bash-n, or a PowerShellScriptBlockparser) and gracefully fails when an interpreter cannot support syntax checks. Streams from stdout/stderr are recorded toscript_execution_logsand broadcast back to the renderer. - Defaults management: Global defaults live in the
settingstable (shellDefaults,powershellDefaults) and are edited throughSettingsView.tsx. When a run starts, the runner merges these defaults with per-document overrides so teams can set organization-wide variables while allowing individual scripts to customize their environment safely.
This module handles all communication with the external Large Language Model. It is largely unchanged by the database migration.
- It constructs the appropriate API request body based on the configured API type (Ollama or OpenAI-compatible).
- It includes robust error handling to manage connection failures or non-OK responses from the provider.
- Clipboard imports invoke
llmService.generateTitle()when a provider is online, allowing the renderer to assign meaningful titles to new documents automatically.
App.tsx: The root component that orchestrates the entire application. It initializes the repository, triggers the data migration if needed, manages the main layout, and uses the data hooks (useNodes,useSettings, etc.).Sidebar.tsx: Manages the display of thenodestree (documents and folders) and templates. It handles search/filtering, drag-and-drop, and keyboard navigation.DocumentEditor.tsx: The primary user-facing editor component. It serves as a layout controller, managing the view mode (editor, preview, split-screen) and containing both theCodeEditor(Monaco) andPreviewPanecomponents. It orchestrates the flow of data between the editor and the preview.SettingsView.tsx: Manages all application settings, which are now read from and saved to thesettingstable in the database.DocumentHistoryView.tsx: This view now fetches version history for a document directly from the database, providing a reliable timeline of changes.
Electron Builder manages the packaging and publishing workflow for DocForge. The most relevant npm scripts are:
npm run build— Bundles the renderer and preload scripts, prepares assets indist/, and generates platform icon binaries from the source SVG.npm run package— Produces distributable builds without uploading them.npm run publish— Builds the application and publishes artifacts using Electron Builder's configured GitHub target.
- Run
npm version <new-version> --no-git-tag-versionto bump the version in bothpackage.jsonandpackage-lock.jsonwithout creating a Git tag. - Update
VERSION_LOG.mdwith a new section that captures the highlights of the release—the automated workflow copies the top entry into the GitHub release body—and record detailed notes underdocs/releases/<version>.mdfor long-form context. - Review and update the Markdown documentation (README, manuals, release notes) so the written guidance reflects the final state of the build.
- Sync the Markdown files under
docs/with the copies at the project root. - Commit and push the changes so the release tag points at the finished documentation.
- Create and push a matching version tag (for example,
git tag v0.8.0followed bygit push origin v0.8.0) to trigger the automated release pipeline. - Monitor the "Release" workflow run and verify the published GitHub release lists the correct notes and includes the installers for every supported platform before announcing availability.
- Tag pushes that match
v*trigger theReleaseGitHub Actions workflow. - An initial job extracts the latest section from
VERSION_LOG.mdand creates the GitHub release with those notes. - A platform matrix rebuilds DocForge via the existing packaging scripts (
npm run package:*) for macOS, Windows (x64/ia32), and Linux (x64/arm64/armv7l). - Each job uploads its generated installers (and accompanying update manifests) to the release using the GitHub CLI.
npm run publishremains available for manual distribution, but the automated workflow is the canonical path for tagged releases.
- The canonical icon artwork lives at
assets/icon.svg. Duringnpm run build(and thus duringnpm run package/npm run publish), thescripts/prepare-icons.mjsscript validates the SVG and, if valid, generates the requiredicon.icns,icon.ico, andicon.pngfiles in theassets/directory usingicon-gen. - If the SVG is missing or invalid, the script logs a warning and leaves the existing binary icon assets untouched so packaging can proceed with the previous icons.
- To regenerate icons without running a full build, execute
npm run prepare:icons.
DocForge integrates GitHub Spec Kit to manage feature planning artifacts alongside the codebase.
- CLI tooling: Install the Specify CLI with
uv tool install specify-cli --from git+https://github.com/github/spec-kit.gitand runspecify checkto validate prerequisites. - Project scripts: Helper scripts live under
.specify/scripts/for creating feature folders, updating agent context, and enforcing executable permissions. - Spec storage: Feature specifications, plans, and task lists reside in numbered folders under
specs/. Seespecs/README.mdfor the canonical workflow. - Agent prompts: Slash-command prompt files for AI assistants are stored in
.github/prompts/, enabling/speckit.*commands inside supported tools. - Governance: The living constitution at
.specify/memory/constitution.mddefines development principles, quality gates, and review expectations for the project.