# Monorepo Strategy — Patrick's Homelab Workshop *Written: 2026-04-04 | Authors: Patrick + Lumen* --- ## 1. Why This Document Exists The repo started as `pi_mcps` — a home for Python MCP servers. Then two older Java web projects arrived: `mss-failsafe` and `Wellmann-Shop`. This is not an accident — it's the beginning of a pattern: a single place to keep all of Patrick's personal engineering work, regardless of language. This document defines the strategy for the repo so that both of us — human and AI — can navigate it without confusion now and in two years from now. --- ## 2. Philosophy: Polyglot Monorepo, Not a Dump A **monorepo is not code colocation**. The key principle from [monorepo.tools](https://monorepo.tools/): projects must have **well-defined relationships** and **clear boundaries**. What we are building is closer to a *workshop* — a curated collection of distinct tools and projects under one roof, organized by language/purpose, each independently buildable and deployable. **We are NOT:** - Sharing dependencies across Java and Python (they live in entirely separate ecosystems) - Using a monorepo build tool like Nx or Turborepo (overkill for a personal homelab) - Creating a monolith (each project is independently deployable) **We ARE:** - Keeping one git history (single place to look for all changes) - Using a clear directory taxonomy to signal *what kind of thing* each project is - Making it easy for an AI (Lumen) or a new contributor to orient quickly - Preventing repo sprawl — one Gitea repo instead of a dozen --- ## 3. Repo Rename: `pi_mcps` → `workshop` The name `pi_mcps` no longer describes what the repo contains. It was named for Raspberry Pi MCP servers — neither of which is accurate anymore (Fedora homelab, not Pi; more than just MCP servers). **Proposed new name:** `workshop` Why `workshop`? - Neutral, language-agnostic - Conveys personal creative output (not corporate, not framework-specific) - Short, memorable - Maps well to `http://192.168.188.119:30008/pplate/workshop` **Action required:** 1. Rename the Gitea repo at `http://192.168.188.119:30008/pplate/pi_mcps` → `workshop` 2. Update the local remote: `git remote set-url origin http://192.168.188.119:30008/pplate/workshop.git` 3. The local folder on disk can stay as `~/pi_mcps/` or be renamed to `~/workshop/` — Patrick's choice. The folder name and repo name do not need to match. --- ## 4. Directory Taxonomy Every directory at the repo root belongs to one of three categories: | Category | Directory | Purpose | |---|---|---| | Language group | `mcp/` | Python MCP servers — FastMCP, uv, pytest | | Language group | `java/` | Java web projects — Maven, Jakarta EE | | Tooling/Config | `.roo/` | IDE config, Roo mode rules, MCP wiring | | Tooling/Config | `plans/` | Architecture plans, assessments, strategy docs | | Root files | `README.md`, `.gitignore` | Navigation index + polyglot ignores | **Future language groups (when they arrive):** | Directory | Purpose | |---|---| | `ts/` | TypeScript MCP servers or web frontends | | `go/` | Go utilities or services | | `scripts/` | Shell/Python one-off automation | ### 4.1 Full Target Structure ``` workshop/ ├── mcp/ # Python MCP servers │ ├── bigmind/ # BigMind persistent memory server │ │ ├── src/server.py │ │ ├── bigmind/ # library code │ │ ├── tests/ │ │ ├── pyproject.toml │ │ └── run.sh │ └── webscraper/ # Web scraping MCP server │ ├── src/server.py │ ├── tests/ │ ├── pyproject.toml │ └── run.sh │ ├── java/ # Java web projects │ ├── mss-failsafe/ # MSS Failsafe (Java EE multi-module, WildFly) │ │ ├── mssfailsafeWeblayer/ │ │ ├── userManagement/ │ │ └── pom.xml │ └── wellmann-shop/ # Wellmann Shop (JSF/PrimeFaces, Java 8, MySQL) │ ├── src/ │ └── pom.xml │ ├── plans/ # Architecture plans and strategy docs │ └── REPO_STRATEGY.md # this file │ ├── .roo/ # Roo Code IDE configuration │ ├── mcp.json # MCP server wiring (paths updated post-move) │ └── rules-*/ # Per-mode Roo rules │ ├── .gitignore # Polyglot: Python + Java + Node + OS └── README.md # Navigation index (the front door) ``` --- ## 5. Naming Conventions Consistency matters — both for humans and for AI tools reading directory listings. | Rule | Convention | Rationale | |---|---|---| | Directory names | `kebab-case` | Unix-friendly, consistent across all languages | | Java project dirs | `kebab-case` matching Maven `artifactId` | No surprise mapping needed | | Python package dirs | `kebab-case` at group level, `snake_case` inside for Python modules | PEP 8 inside, Unix outside | | Plan files | `UPPER_SNAKE.md` in `plans/` | Stands out from code files | | README per project | Required | Each project is independently comprehensible | **Normalization needed:** - `Wellmann-Shop/` → `java/wellmann-shop/` (lowercase the W, move under `java/`) - `mss-failsafe/` → `java/mss-failsafe/` (already correct name, just needs moving) - `bigmind/` → `mcp/bigmind/` - `webscraper/` → `mcp/webscraper/` --- ## 6. Language-Specific Rules ### 6.1 Python (mcp/) - Package manager: **uv** (already standardized) - Framework: **FastMCP** for all MCP servers - Testing: **pytest** with `pytest-mock` and `pytest-cov` - Each server is an **independent Python package** with its own `pyproject.toml` and `.venv` - No shared `requirements.txt` at root — dependency isolation is a feature - Run pattern: `cd mcp/bigmind && ./run.sh` ### 6.2 Java (java/) - Build tool: **Maven** (both existing projects use it) - Java version: Currently Java 8 (Wellmann-Shop) and unspecified (mss-failsafe — legacy NetBeans project) - **Future Java projects should target Java 21+** (current LTS) - Each project has its own `pom.xml` — no shared parent POM at root (cross-language root POMs are an antipattern) - Target servers: WildFly / Payara / GlassFish (Jakarta EE) - No shared Maven `settings.xml` needed — use standard `~/.m2/settings.xml` ### 6.3 Future: TypeScript (ts/) - Package manager: **npm** or **pnpm** - Framework: **FastMCP** (TypeScript flavor) for MCP servers - Each project has its own `package.json` --- ## 7. .gitignore Strategy The root `.gitignore` must cover all languages in the repo. Currently it only covers Python. After the reorganization, it must also cover: **To add:** ```gitignore # Java / Maven target/ *.class *.war *.jar *.ear *.nar .classpath .project .settings/ nb-configuration.xml nbactions.xml *.iml # Node / TypeScript (future) node_modules/ dist/ *.js.map package-lock.json # Test coverage .coverage coverage.xml htmlcov/ ``` **Note:** `nb-configuration.xml` is NetBeans IDE config — already present in `mss-failsafe/` and `Wellmann-Shop/`. It should be in `.gitignore` for new projects but is intentionally tracked here since it carries build configuration for legacy projects. --- ## 8. IDE Wiring: `.roo/mcp.json` After Move The webscraper path in `.roo/mcp.json` currently points to `/home/pplate/pi_mcps/webscraper`. After moving to `mcp/webscraper/`, it must be updated: **Before:** ```json "webscraper": { "args": ["run", "--directory", "/home/pplate/pi_mcps/webscraper", "src/server.py"] } ``` **After:** ```json "webscraper": { "args": ["run", "--directory", "/home/pplate/pi_mcps/mcp/webscraper", "src/server.py"] } ``` *(If the local folder is also renamed to `workshop/`, the path changes to `/home/pplate/workshop/mcp/webscraper`)* The same applies to any external MCP configs (e.g., IntelliJ/PyCharm `mcp.json` files stored outside this repo). --- ## 9. README.md — The Front Door The root `README.md` should function as a **navigation index**, not a tutorial. Readers (Patrick, Lumen, future contributors) should land there and know exactly where to go within 10 seconds. **Structure:** ``` # Workshop — Patrick Plate's Homelab Monorepo ## What's Here [table: project name | language | description | status] ## MCP Servers (mcp/) [short list with links] ## Java Projects (java/) [short list with links] ## Plans & Architecture [link to plans/] ## Gitea [link to homelab Gitea] ``` --- ## 10. Migration Plan (Ordered Steps) ``` Step 1: Rename Gitea repo pi_mcps → workshop (Gitea UI) Step 2: Update local git remote URL Step 3: Move mcp/bigmind ← bigmind/ Step 4: Move mcp/webscraper ← webscraper/ Step 5: Move java/mss-failsafe ← mss-failsafe/ Step 6: Move java/wellmann-shop ← Wellmann-Shop/ (normalize name) Step 7: Update .roo/mcp.json webscraper path Step 8: Update any external MCP configs pointing to old paths Step 9: Expand .gitignore with Java + Node patterns Step 10: Rewrite root README.md as navigation index Step 11: git add -A && git commit -m "chore: reorganize into polyglot monorepo structure" Step 12: git push origin master ``` **Important:** Git tracks renames as move+add. Using `git mv` preserves file history. Use it for each moved file/directory. --- ## 11. Branching Strategy ### 11.1 The One Rule **Never commit directly to `main`.** Every session that touches code or plans starts by creating a branch. Branches are cheap. Broken main history is not. ### 11.2 Branch Naming Convention Format: `type/scope/short-description` | Type | When | |---|---| | `feat` | New feature, new MCP server, new tool | | `fix` | Bug fix | | `docs` | Documentation, plans, strategy files only | | `chore` | Refactoring, config, CI, build tooling | | `spike` | Experimental / throwaway exploration | **Scope** = the affected project area: | Scope | Covers | |---|---| | `bigmind` | mcp/bigmind — the memory MCP server | | `webscraper` | mcp/webscraper | | `cannamanage` | future CannaManage Java project | | `workshop` | repo-level changes (README, .gitignore, structure) | | `roo` | .roo/ — IDE config, modes, skills, rules | | `plans` | plans/ — architecture docs only | | `homelab` | TrueNAS, Docker Compose, infrastructure | **Examples:** ``` feat/bigmind/people-contacts fix/bigmind/health-check-bugs docs/plans/cannamanage-strategy chore/workshop/monorepo-reorganize feat/webscraper/ssl-cert-fallback chore/roo/branching-strategy ``` ### 11.3 Workflow ``` Session starts └─ git checkout -b feat/scope/name ← ALWAYS first step Work happens, commits stack up on the branch Session ends / feature complete └─ git push origin feat/scope/name └─ (optional) open Gitea PR for review └─ git checkout main && git merge --no-ff feat/scope/name └─ git push origin main ``` ### 11.4 Lumen's Responsibility In every homelab session, Lumen must: 1. Check `git branch --show-current` before first edit 2. If on `main` → create a branch before touching any file 3. Include the branch name in `memory_announce_focus()` 4. Use the [`gitea-push skill`](.roo/skills/gitea-push/SKILL.md) which enforces the branch guard The mode rules for `mcp-builder`, `bigmind`, and `homelab` all include this step explicitly. --- ## 12. What We Are NOT Doing It's worth being explicit about choices we considered and rejected: | Considered | Decision | Reason | |---|---|---| | Separate repo per project | Rejected | Polyrepo tax: fragmented history, harder for AI context | | Nx / Turborepo monorepo tools | Rejected | Overkill for personal homelab; adds tooling complexity without benefit | | Shared Maven parent POM at root | Rejected | Java-specific tooling at repo root would confuse Python tooling | | Keeping `pi_mcps` name | Reconsidered | The name no longer describes the content; `workshop` is future-proof | | `src/` at root with language subdirs | Rejected | Less clear at a glance than top-level `mcp/`, `java/` groupings | --- ## 13. Visual Overview ```mermaid graph TD Root[workshop/] --> MCP[mcp/] Root --> Java[java/] Root --> Plans[plans/] Root --> Roo[.roo/] Root --> GI[.gitignore] Root --> RM[README.md] MCP --> BM[bigmind/] MCP --> WS[webscraper/] MCP --> FutMCP[future MCP servers...] Java --> MSS[mss-failsafe/] Java --> WSh[wellmann-shop/] Java --> FutJava[future Java projects...] Plans --> STRAT[REPO_STRATEGY.md] Plans --> FutPlans[future plans...] ``` --- *This document is the living reference for how this repo is organized. Update it when structure changes.*