Developer guide

This part of the manual is for people who want to change Marginalia itself, write an extension for it, or just understand how it works inside. If you only want to install and use Marginalia, see the User guide.

Marginalia is a single Java web application. The browser UI is written in Java with Vaadin Flow, the services are plain Spring beans wired in XML, the data lives in one SQLite file accessed through Hibernate, and extensions are OSGi bundles that hook into the UI at runtime. The same WAR runs on a server (Docker, Jetty) and inside the desktop app.

Technology

Area Used
Language, build Java 25, Maven 3.9
User interface Vaadin Flow 25 (server-side Java components, Lumo theme, server push over WebSocket)
Application framework Spring 7 (XML configuration, no Spring Boot), AspectJ compile-time weaving for @Configurable and @Transactional
Persistence Hibernate 7 (JPA), SQLite (sqlite-jdbc, WAL mode), Flyway migrations
LLM access openai-java against any OpenAI-compatible API, JTokkit and server tokenizers for token counts, victools and networknt json-schema-validator for structured answers
Templates Handlebars.java with SillyTavern-compatible macros
Extensions Apache Felix (OSGi), ByteBuddy agent for bytecode instrumentation of @Extendable classes
Server Any Jakarta EE 11 servlet container (Servlet 6.1) - Jetty 12 in Docker and in the desktop app
Tests JUnit 6, AssertJ, Spring Test, a fake OpenAI-compatible server
Manual Retype (sources in manual/, generated site in docs/)

Repository at a glance

Marginalia/
├── marginalia/            the application (Maven project, WAR packaging)
│   ├── src/main/java      application code (com.github.enerccio.marginalia)
│   ├── src/main/resources Spring XML, Flyway migrations, logging
│   ├── src/main/webapp    configuration.properties, persistence.xml
│   ├── src/main/frontend  CSS and JS used by the Vaadin frontend
│   ├── src/desktop        desktop launcher (tray icon, starts Jetty) and launch scripts
│   ├── src/test           tests
│   └── plugins/           the nineteen bundled extensions, each a separate Maven project
├── manual/                this manual (Retype sources); manual/user is also packed into the WAR for the help assistant
├── docs/                  generated manual, served by GitHub Pages
├── Dockerfile, docker-compose.yml
└── .github/workflows/     CI (desktop builds and releases)

Project structure describes the packages and files in detail.

Getting started

  1. Building from source - requirements, building the WAR, running Marginalia from your IDE or a local Jetty, running the tests, building the plugins.

  2. Architecture - how the pieces fit together: startup, Spring wiring, the UI, services and data, generation, extensions.

  3. Then read the page about the area you want to change.

The shortest path from a fresh clone to a running instance:

git clone https://github.com/Enerccio/Marginalia.git
cd Marginalia/marginalia
mvn package -DskipTests                     # target/marginalia-1.6.0.war

Deploy target/marginalia-1.6.0.war (or the exploded target/marginalia-1.6.0/ folder) to Tomcat 11 or Jetty 12, or use docker compose up --build from the repository root. Building from source has the details.

Pages in this guide

Page What it covers
Building from source Requirements, Maven builds, running locally, tests, plugins, the manual.
Architecture The big picture: layers, startup, wiring, threading, extension mechanism.
Project structure Packages, resources and what lives where.
Domain model Entities (books, parts, lorebooks, providers, protocols...), ownership, soft delete.
Database & migrations SQLite, Flyway migrations, adding an entity or a column.
Services Service and repository layer, transactions, the current user.
Folders Folders of books and the settings they pass down: data, resolution, services, windows, backups, agents.
Version history The versions of the text of a part: data, recording, limit and pruning, restoring, search, backups, migrations, windows.
Generation pipeline How a story part is generated, step by step.
Agents How agents work inside: runs and their states, the runner, the tools, references, the files, the screens.
Templating & macros Prompt templates, template data, the macro translator.
User interface Routes, workspace, dialogs, push and background threads.
Custom components The components that draw with a JavaScript library (story tree, charts, graphs), how they work and how to add one.
Plugin development Writing extensions: bundles, @Extendable hooks, extended attributes, UI extensions.
Testing Running tests, test bases, the fake LLM server, CRUD contracts, writing tests.
Packaging & releases WAR, Docker image, desktop app, CI, making a release.
Contributing Reporting bugs, workflow, commits, pull requests, code style, documentation.

Conventions used in this guide

  • Paths like ui/workspace/Workspace.java are relative to marginalia/src/main/java/com/github/enerccio/marginalia/ unless they start with marginalia/ or another top-level folder.

  • Book and part are the user-facing names of Manuscript and ChatMessage - the code still uses the old names. Likewise inference provider is AI, protocol is Protocol.

  • Commands are run from the marginalia/ folder unless said otherwise.