by volcanicMole
A simple to use obsidian plugin which adds simple colour selectors and inbuilt fonts
formatForge
formatForge adds simple typography and colour formatting to Obsidian — body and heading colours, fonts, dividers, and related styling UI.
It works on its own for any vault that wants clearer note formatting. It also soft-integrates with the Forge plugin family (storyForge, timelineForge, and others that adopt the formatting API) so those plugins can share fonts, palettes, and styling through formatForge.
Requirements
- Obsidian 1.13.0 or later.
- Desktop only.
- Forge hosts (storyForge, timelineForge, …) are optional. When present, formatForge registers as their typography companion; when absent, editor formatting still applies from formatForge’s own settings.
What formatForge owns
- Editor body and heading colours (H1–H6)
- Editor font sizes (body + H1–H6) when running alone
- Editor font families and weights (H1–H6 and body)
- Heading dividers — configurable border lines above/below each heading level
- Hide H1 links — renders links inside H1 as plain text
- Small caps per heading level
- Bold and italic emphasis colours for body text
- Link colour and underline controls for body links
- Highlight colours (background + text) for
==highlighted==marks - The full Text Styling modal UI, including a live Lorem Ipsum manuscript preview
- Colour palette selection (and Custom swatches) for formatting colour pickers when running alone
- Manuscript editor scrollbar thumb colour and thickness
- Embedded custom fonts (
fonts/+src/fonts.ts)
Forge family integration
When a Forge host is enabled, formatForge can also adjust that host’s formatting surface:
| Host | What formatForge contributes |
|---|---|
| storyForge | Registers as formatting companion; applies editor CSS vars; shared palette / sizes / scrollbar; font pickers on storyForge's interface modal |
| timelineForge | Font catalogue, font picker, and face registration for the timeline rail (controls live in timelineForge’s appearance UI) |
Hosts are detected at runtime. Missing hosts are ignored — there is no required-plugin warning.
How it registers with storyForge
When storyForge API v2+ is available:
app.plugins.getPlugin("storyforge")?.api.formatting.registerCompanion({
pluginId: "formatforge",
version: 1,
onHostStylesApplied: () => plugin.applyEditorStyles(),
resolveFont: (familyId, weight) => resolveCustomFontFamilyParts(font, weight),
registerFacesForDocument: (doc) => registerCustomFontFaces(doc),
});
How it registers with timelineForge
app.plugins.getPlugin("timelineforge")?.api.formatting.registerCompanion({
pluginId: "formatforge",
version: 1,
resolveFont: (familyId, weight) => resolveCustomFontFamilyParts(font, weight),
registerFacesForDocument: (doc) => registerCustomFontFaces(doc),
listFonts: () => CUSTOM_FONTS.map(...),
openFontPicker: (opts) => new FontPickerModal(...).open(),
});
See docs/timelineforge-formatting-api.md and docs/storyforge-formatting-api.md.
Settings storage
| Setting group | Persisted in |
|---|---|
| Editor body/heading colours, fonts, sizes, dividers, H1 link hiding, body links, highlights | formatForge/data.json |
| Colour palette (name, variant, custom colours) | formatForge/data.json standalone; storyForge/data.json when storyForge is present |
| Font sizes (body + H1–H6) | formatForge/data.json standalone; storyForge/data.json when storyForge is present (linked settings API) |
| Manuscript editor scrollbar | formatForge/data.json standalone; storyForge/data.json when storyForge is present |
| storyForge panel chrome | storyForge/data.json via linked settings |
| Timeline rail colours + typography | timelineForge _tf-backstage/folders/*.md |
For plugin developers
Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.