Lossless Changelog
fleet

Nine plugins, one splash, one branch model

Seven plugin repos relocated from the monorepo root into content-farm as submodules. Nine submodules aligned onto a development → main → master tier model. And a brand-new Astro splash page that ships from main to GitHub Pages — the pseudomonorepo finally has a face to put with its name.

Michael StatonMusic Editoraugmented with Claude Code on Claude Opus 4.7 (1M context)

Why Care?

If you've ever watched a folder of related plugins drift into chaos — wrong submodule URLs, branches that don't line up, no front door for outsiders — you'll recognize what content-farm looked like a week ago. The plugins existed; the farm did not.

This entry covers three changes that, together, make content-farm legible. The Obsidian plugins now live where they belong. Every repo on the farm shares one branch convention. And there's a public splash page at https://lossless-group.github.io/content-farm/ — the first instance of a pattern we plan to roll out across every Lossless repo.

If you write in Obsidian and want to know what we ship there, the splash is now your front door. If you're another team aspiring to a similar "free landing page per repo" pattern, this is a working example you can copy.

What's New?

  • Seven plugins relocated. cite-wide, grab-reference, image-gin, perplexed, plunk-it, filestarter (renamed from obsidian-plugin-starter), and file-transporter (renamed from obsidian-google-docs) now live at content-farm/plugin-modules/ as proper git submodules — joining the existing lmstud-yo and obsidian-git.

  • Nine submodules + content-farm aligned on development. Created missing main and/or development branches via fast-forward pushes on four repos that were running with only master. Every .gitmodules entry now has branch = development.

  • Splash page shipped. An Astro static site at content-farm/splash/, deploying via .github/workflows/pages.yml on push to main. Plugin gallery is sourced from a content collection — one .md per plugin, sorted by an order integer with alphabetical tiebreak. Hand-curated, no manifest scraping.

  • A new convention encoded. Added references/branch-alignment.md to the pseudomonorepos skill capturing the development → main → master tier model and the safe FF-push recipe for catching a missing or behind branch up to its leading sibling.

The arc

We started the session intending to do one thing — clean up content-farm's submodule shape — and ended up doing three. Every step uncovered the next one.

The mess we walked into

The lossless-monorepo root's .gitmodules was wired wrong in several places:

[submodule "cite-wide"]                  → url: lossless-group/content-farm.git   ❌
[submodule "obsidian-plugin-starter"]    → url: lossless-group/cite-wide.git      ❌
[submodule "perplexed"]                  → url: lossless-group/obsidian-plugin-starter.git  ❌
[submodule "image-wrangler"]             → url: lossless-group/obsidian-plugin-starter.git  ❌
[submodule "image-gin"]                  → url: lossless-group/image-gin-plugin.git         ❌

Each of those local clones had the correct origin set in .git/config, so the working state was fine — but the parent's view of where to clone from was a copy-paste accident waiting to embarrass someone. And the plugins were dangling at the monorepo root next to ~25 other top-level directories, instead of grouped under their natural parent (content-farm/).

Step one: relocate

For each plugin: deinit at the root, remove the working tree and the .git/modules/<name> artifact, then add the correct remote URL as a submodule under content-farm/plugin-modules/. Two plugins (image-gin, perplexed) had uncommitted in-flight work that we pushed to their respective development branches first, then re-cloned — losing nothing.

Two plugins were renamed in flight per a long-pending intent:

  • obsidian-plugin-starter → filestarter

  • obsidian-google-docs → file-transporter (with the GitHub remote staying as google-docs-api-plugin.git until the eventual rename)

The vault symlinks at ~/content-md/lossless/.obsidian/plugins/ got re-pointed at the new locations. Obsidian noticed nothing.

Step two: align the branches

Once the plugins were in place, the next mismatch surfaced: cite-wide was tracking main, grab-reference and image-gin were tracking master, and lmstud-yo and obsidian-git had no branch tracked at all. The agreed convention is:

development  →  main  →  master
   ↑              ↑          ↑
working edge   noteworthy   stable

Activity lands on development. When something noteworthy lands, it gets promoted to main. When the dust settles, it crosses to master. (And, honestly, when humans get lazy, work piles up on development and never gets promoted — that's expected, not a bug.)

Four repos were missing main, one was missing both main and development. We created them via fast-forward pushes from each repo's leading branch — a non-destructive operation that simply registers the new branch on origin at the same tip as master. Then git submodule sync to propagate every branch = development line into .git/config.

Final shape:

PluginBranchTip
cite-widedevelopment999e46f
grab-referencedevelopmentad32d19
image-gindevelopment94dead1
perplexeddevelopmentbe2fad7
plunk-itdevelopment3d27cd5
filestarterdevelopmentc2172fe
file-transporterdevelopment3d39b99
lmstud-yodevelopment7771c10
obsidian-gitdevelopmenta2a9fcb

content-farm itself: also on development, with a freshly-created main branch.

Step three: the splash

A habit doc had been sitting in lossless-monorepo/context-v/habits/ since November 2025: Maintain a Github Splash Page for each Repo. The premise — every Lossless repo deserves a free landing page off GitHub Pages — was clear; the implementation for content-farm was not yet written.

We wrote a spec stub at content-farm/context-v/specs/Github-Splash-Page-for-Content-Farm.md, locked in four decisions in dialog (location, deploy URL, build trigger, gallery data shape), and improvised the layout:

  • Hero with a stat triplet and gradient title

  • Asymmetric plugin grid — three featured cards span 4 columns each, the other six take 2 columns. Pointer-tracked radial highlight on hover (vanilla JS, no React, no framework).

  • Philosophy section — four cards explaining why a pseudomonorepo of plugins is the unit, not a single mega-plugin

  • Latest changelog teaser — the page you're reading now will be the first card

  • Notes CTA linking to /context-v/

The plugin gallery is content-collection driven: one markdown file per plugin under splash/src/content/plugin-highlights/. Frontmatter carries display props; an order: <int> field drives sort, with alphabetical-by-filename tiebreak — never throws on collision. Adding or reordering a plugin is now editing a markdown file, nothing else.

YAML
# splash/src/content/plugin-highlights/image-gin.md
---
title: image-gin
lede: Generate, search, and place AI images without leaving Obsidian.
order: 10
status: Beta
repo: https://github.com/lossless-group/image-gin
icon: 🖼️
featured: true
tags: [Imagery, AI, Modals]
---

A unified wide-modal interface for image work across multiple providers...

changelog/[slug] and context-v/[...slug] pages are wired to the parent directories at content-farm/changelog/ and content-farm/context-v/. This very entry will render at lossless-group.github.io/content-farm/changelog/2026-05-04_01/ after the next deploy.

Deploy

YAML
# .github/workflows/pages.yml
on:
  push:
    branches: [main]

actions/deploy-pages@v4, submodules fetched recursively, pnpm install --ignore-workspace then pnpm build. Output lands in splash/dist/. The first build produced eight pages from the content already in the repo, weighing 108KB.

To activate: GitHub Settings → Pages → Source = "GitHub Actions", then push to main. That's it.

What we punted

  • LFM (Lossless Flavored Markdown) integration. The habit doc explicitly calls for LFM rendering. The first instance of the pattern (memopop-site) punted it; we did the same. Markdown renders through Astro's built-in render(entry).Content for now. The prose class in detail pages is the styling target where LFM-rendered components will eventually plug in. Adding LFM later is additive, not a rewrite.

  • OG image generation per page. Currently only the global OG card.

  • Per-plugin detail pages that aggregate each submodule's README and its own changelog. Possible Phase 2.

  • The cross-cutting blueprint. This is now the second instance of the splash pattern (memopop is the first). The third repo to want one is the trigger for generalizing a template — likely a stub at astro-knots/sites/ or a small CLI scaffold. Logged as a refactor candidate.

What this enables

The same shape now works for every other Lossless repo. Drop a splash/ directory, point its content collections at the parent's changelog/ and context-v/, write an index page that introduces what's there, push to main. Free hosting, free analytics (kind of), no marketing-site dependency, no excuses.

We've got eleven other repos that could use one tomorrow. The bus is leaving.