libreshop/shop originated as the white-label Nuxt 3 frontend behind muellerprints-paperwork.com and was planned as a runtime-extendable base image for adapters (with mp being the first adapter). The plan was:
libreshop/shop ships brand-neutral, deployable as-is for demos
Adapters extend via Nuxt layers (extends: mechanism), Docker FROM libreshop/shop:vX
An "override surface" would be defined and semver-protected
Tailwind config, composables, components would all be layerable
A feasibility analysis (ref: notebook in mp/dummy/ planning, 2026-05-04) revealed:
Product schema is notebook-specific — ProductCover.binding, ProductPages, ProductRuling, ProductPattern types and their Strapi backing tables assume a notebook product. Generalising to a generic "ProductAttribute" requires substantial refactor.
Composables hardcode content — usePageContent.ts (287 lines) contains literal MP legal/contact text that all 11 page files import directly. useProductContent.ts (369 lines) hardcodes notebook feature narratives ("Klassische Fadenheftung", "VIVUS 89 Papier", "FSC® C018175") that would need to move to per-adapter composables.
Nuxt layers don't merge tailwind config or runtimeConfig defaults automatically — adapters would need explicit factory pattern + .env pre-baking
The override surface would need semver discipline — every component rename, every slot signature change, every frontmatter field rename = breaking major. For a 1-adapter use case (mp), this is heavy maintenance.
The mp adapter wants full freedom to add a Druckerei section, an Über uns area, and brand-specific content depth without negotiating upstream.
Decision
Pivot libreshop/shop from "runtime base image" to reference template / starter:
libreshop/shop stops shipping a deployable image at the next major release. The repo retains the source as a complete worked example.
README is rewritten as a "copy this and modify" guide, not "depend on this".
The current production consumer (libretech/mp) forks the source into its own tree (mp/shop/) and owns it from that point forward.
Future adapters do the same: degit libreshop/shop my-shop, then customize freely.
What libreshop/shop becomes:
A curated public reference for "what a libretech-style Nuxt+Strapi shop looks like"
Documentation: README explains the architecture (Nuxt SSR, Strapi v4 CMS, PayPal, mail/pdf services) so newcomers understand the moving parts before they copy
Optionally: shared TypeScript types / composables published as a small npm package (@libreshop/types, @libreshop/composables) — only if multiple consumers emerge and ask for it. Default: no.
What libreshop/shop stops being:
A registry image consumed by mp's compose.yml
A semver-stable override surface
A multi-tenant runtime
Consequences
Pros:
mp gets full ownership and freedom — no upstream coordination
Code is easier to evolve without breaking changes against an unknown universe of adapters
The reference value is preserved — anyone wanting a libretech-flavoured shop has working code to start from
Cons:
Future fork divergence: bug fixes in libreshop/shop don't reach mp automatically. Consumers must manually port. Acceptable cost — we have only 1 consumer (mp) and bug-fix cherry-picking is straightforward when source structure stays close.
git.librete.ch/libreshop/shop:v0.1.0 image becomes orphaned (already pinned by mp). Acceptable — mp's own image takes over, libreshop registry image deleted at end of grace period.
Sub-issues to action
#X — Last brand-strip pass: ensure repo is the canonical neutral reference (no MUELLERPRINTS hardcoded). Tag v0.x.0 final.
#X — Drop CI publishing to registry once mp has cut over to its own image
#X — Optional: extract @libreshop/types npm package (only if asked)
Predecessor
Supersedes #2 epic and its sub-issues #3–#9 (close those after this ADR is accepted).
# ADR — Pivot libreshop/shop from runtime image to reference template
## Status
Proposed (2026-05-04). Awaiting acceptance + supersedes prior epic https://git.librete.ch/libreshop/shop/issues/2.
## Context
`libreshop/shop` originated as the white-label Nuxt 3 frontend behind `muellerprints-paperwork.com` and was planned as a runtime-extendable base image for adapters (with `mp` being the first adapter). The plan was:
- libreshop/shop ships brand-neutral, deployable as-is for demos
- Adapters extend via Nuxt layers (`extends:` mechanism), Docker `FROM libreshop/shop:vX`
- An "override surface" would be defined and semver-protected
- Tailwind config, composables, components would all be layerable
A feasibility analysis (ref: notebook in `mp/dummy/` planning, 2026-05-04) revealed:
1. **27 files** in libreshop/shop hardcode MUELLERPRINTS branding, Stuttgart address, Inhaber email, paperwork-logo
2. **Product schema is notebook-specific** — `ProductCover.binding`, `ProductPages`, `ProductRuling`, `ProductPattern` types and their Strapi backing tables assume a notebook product. Generalising to a generic "ProductAttribute" requires substantial refactor.
3. **Composables hardcode content** — `usePageContent.ts` (287 lines) contains literal MP legal/contact text that all 11 page files import directly. `useProductContent.ts` (369 lines) hardcodes notebook feature narratives ("Klassische Fadenheftung", "VIVUS 89 Papier", "FSC® C018175") that would need to move to per-adapter composables.
4. **Nuxt layers don't merge tailwind config or runtimeConfig defaults** automatically — adapters would need explicit factory pattern + `.env` pre-baking
5. **The override surface would need semver discipline** — every component rename, every slot signature change, every frontmatter field rename = breaking major. For a 1-adapter use case (mp), this is heavy maintenance.
The mp adapter wants full freedom to add a Druckerei section, an Über uns area, and brand-specific content depth without negotiating upstream.
## Decision
Pivot libreshop/shop from "runtime base image" to **reference template / starter**:
- libreshop/shop **stops shipping a deployable image** at the next major release. The repo retains the source as a complete worked example.
- README is rewritten as a **"copy this and modify" guide**, not "depend on this".
- The current production consumer (`libretech/mp`) **forks** the source into its own tree (`mp/shop/`) and owns it from that point forward.
- Future adapters do the same: `degit libreshop/shop my-shop`, then customize freely.
What libreshop/shop **becomes**:
- A curated public reference for "what a libretech-style Nuxt+Strapi shop looks like"
- Documentation: README explains the architecture (Nuxt SSR, Strapi v4 CMS, PayPal, mail/pdf services) so newcomers understand the moving parts before they copy
- Optionally: shared TypeScript types / composables published as a small npm package (`@libreshop/types`, `@libreshop/composables`) — only if multiple consumers emerge and ask for it. Default: no.
What libreshop/shop **stops being**:
- A registry image consumed by mp's `compose.yml`
- A semver-stable override surface
- A multi-tenant runtime
## Consequences
**Pros:**
- mp gets full ownership and freedom — no upstream coordination
- libreshop maintainer (us) drops "support contract" obligation toward adapters
- Code is easier to evolve without breaking changes against an unknown universe of adapters
- The reference value is preserved — anyone wanting a libretech-flavoured shop has working code to start from
**Cons:**
- Future fork divergence: bug fixes in libreshop/shop don't reach mp automatically. Consumers must manually port. Acceptable cost — we have only 1 consumer (mp) and bug-fix cherry-picking is straightforward when source structure stays close.
- `git.librete.ch/libreshop/shop:v0.1.0` image becomes orphaned (already pinned by mp). Acceptable — mp's own image takes over, libreshop registry image deleted at end of grace period.
## Sub-issues to action
- [ ] #X — Last brand-strip pass: ensure repo is the canonical neutral reference (no MUELLERPRINTS hardcoded). Tag v0.x.0 final.
- [ ] #X — Rewrite README as "copy this, customize freely" guide; remove "deploy as-is" language; document architecture
- [ ] #X — Drop CI publishing to registry once mp has cut over to its own image
- [ ] #X — Optional: extract `@libreshop/types` npm package (only if asked)
## Predecessor
Supersedes https://git.librete.ch/libreshop/shop/issues/2 epic and its sub-issues #3–#9 (close those after this ADR is accepted).
Folded into the single muellerprints.de tracker libretech/mp#50 during the 2026-09-24 cleanup: no activity since 2026-05-04. Reopen when work resumes.
Folded into the single muellerprints.de tracker https://git.librete.ch/libretech/mp/issues/50 during the 2026-09-24 cleanup: no activity since 2026-05-04. Reopen when work resumes.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
ADR — Pivot libreshop/shop from runtime image to reference template
Status
Proposed (2026-05-04). Awaiting acceptance + supersedes prior epic #2.
Context
libreshop/shoporiginated as the white-label Nuxt 3 frontend behindmuellerprints-paperwork.comand was planned as a runtime-extendable base image for adapters (withmpbeing the first adapter). The plan was:extends:mechanism), DockerFROM libreshop/shop:vXA feasibility analysis (ref: notebook in
mp/dummy/planning, 2026-05-04) revealed:ProductCover.binding,ProductPages,ProductRuling,ProductPatterntypes and their Strapi backing tables assume a notebook product. Generalising to a generic "ProductAttribute" requires substantial refactor.usePageContent.ts(287 lines) contains literal MP legal/contact text that all 11 page files import directly.useProductContent.ts(369 lines) hardcodes notebook feature narratives ("Klassische Fadenheftung", "VIVUS 89 Papier", "FSC® C018175") that would need to move to per-adapter composables..envpre-bakingThe mp adapter wants full freedom to add a Druckerei section, an Über uns area, and brand-specific content depth without negotiating upstream.
Decision
Pivot libreshop/shop from "runtime base image" to reference template / starter:
libretech/mp) forks the source into its own tree (mp/shop/) and owns it from that point forward.degit libreshop/shop my-shop, then customize freely.What libreshop/shop becomes:
@libreshop/types,@libreshop/composables) — only if multiple consumers emerge and ask for it. Default: no.What libreshop/shop stops being:
compose.ymlConsequences
Pros:
Cons:
git.librete.ch/libreshop/shop:v0.1.0image becomes orphaned (already pinned by mp). Acceptable — mp's own image takes over, libreshop registry image deleted at end of grace period.Sub-issues to action
@libreshop/typesnpm package (only if asked)Predecessor
Supersedes #2 epic and its sub-issues #3–#9 (close those after this ADR is accepted).
Folded into the single muellerprints.de tracker libretech/mp#50 during the 2026-09-24 cleanup: no activity since 2026-05-04. Reopen when work resumes.