Skip to content

Latest commit

 

History

History
230 lines (158 loc) · 17.9 KB

File metadata and controls

230 lines (158 loc) · 17.9 KB
status ACTIVE

CEO Plan: Magazine CMS MVP (Print-ready PPTX, Electron, Hindi+English)

Generated by /plan-ceo-review on 2026-04-21 Branch: (no git repo yet) | Mode: SELECTIVE EXPANSION Repo: /Users/siraj/Print CMS (slug: PrintCMS) Approach: A (build brief as written)

Document scope

This is a CEO-level decision summary. It captures:

  • Accepted scope additions on top of the brief (5 items, below)
  • Deferred items and why
  • Blocking preconditions that must be answered before Phase 2 implementation begins

It is NOT an engineering spec. Detailed acceptance criteria, tool choices (exact diff tool, file-lock mechanism, CSV parser, measurement pipeline), and test matrices live in /plan-eng-review, which runs after this document and Phase 1 verification.

The source of truth for product scope is the original product brief (52-template inventory, 12 classified types, 11 ad slots, 13-phase build order, print-readiness checklist, out-of-scope list, open questions).

Problem

A single non-technical operator produces print-ready magazine issues (.pptx → PDF in PowerPoint) for an Indian regional publisher. A4 + A5, English + Hindi + bilingual, classifieds, ads, covers, auto-fit, auto-versioning, offline-first. Eventually SaaS.

10x vision (not MVP)

AI-assisted editorial copilot: raw transcript → proposed headline + deck + pull quote + cover lines; Whisper+LLM classifieds intake; image crop suggestions; per-issue copyedit. MVP preserves the architectural hooks for this (structured templates, content types, content-addressable assets) but implements none of it.

Accepted scope (on top of brief as written)

1. Pretext → PPTX mapping harness — Phase 2 gate

Pretext is confirmed real (https://github.com/chenglou/pretext). Pure JS/TS, uses Canvas 2D measureText() as ground truth via the browser's font engine. Runs in the Electron renderer (browser context). Server-side support is still "soon."

Pretext gives pixel-perfect measurement of the web/Electron editor preview. That preview is the source of truth. The architecture question the harness answers: how faithfully can we map Pretext's measured layout into a PPTX such that PowerPoint renders it identically?

PowerPoint must be constrained to a display surface, not allowed to re-typeset. OOXML mechanisms available to us:

  • EMU-precise positioning (914400 units/inch) for text box placement (<a:off> / <a:ext>).
  • Explicit pre-computed line breaks (<a:br/> or paragraph-per-line) so PowerPoint's line-break algorithm never runs.
  • Disabled autofit (<a:normAutofit/> off) so PowerPoint doesn't rescale.
  • Precise leading via <a:lnSpc> values matching Pretext's output.
  • Run-level explicit positioning for fine kerning control where needed.
  • Embedded font subsets so PowerPoint uses the same glyph outlines Pretext measured against.

Harness job: take a representative template × content pair, render the editor preview (Pretext), generate PPTX, open in PowerPoint, compare. Acceptance: every line in the PPTX appears at the same pixel coordinate as the Pretext preview, within a defined tolerance. Tolerance, measurement method, and automation tooling are /plan-eng-review work.

Phase 2 gate: at least the Standard Feature A4 English Editorial Serif template must pass the mapping fidelity test. Subsequent templates in Phase 4+ each pass the same harness before merging.

Gate failure consequence: the mapping approach is revisited. Likely fallbacks (decided at the time by engineering + user):

  • Tighter pre-breaking (paragraph-per-line instead of paragraph-per-block).
  • Single-text-box-per-line at explicit EMU coordinates (loses editability in PowerPoint, which is fine per brief).
  • SVG embedding for problem text blocks (loses text selection; last resort).

A full architectural pivot (Paged.js + HTML export) is NOT in MVP scope.

2. Devanagari-in-PPTX validation — Phase 3 gate

Target platforms for MVP gate: whichever PowerPoint versions the pilot publisher's operator actually uses (resolved by Blocking Precondition #2, "Pilot publisher OS target," below). MVP gate covers exactly those; additional platforms are out of scope.

Coverage: sample Hindi articles exercising shirorekha, conjuncts, matra stacking, nukta forms, mixed-script with English brand names and Arabic numerals, and Devanagari poetry (left-aligned).

Gate pass criterion: operator reviews rendered PPTX on the target platforms; no glyph drops, no conjunct breakage, no overflow. Manual review with tooling assistance (diff tool choice is /plan-eng-review work).

Gate failure consequence: Hindi release blocked. Two options to choose between:

  • 2a: Engineering addresses the specific rendering issue (font substitution, template spacing adjustment, pptxgenjs configuration).
  • 2b: Hindi ships in v1.1 instead of MVP, English-only MVP proceeds.

This is a DEFERRED CEO DECISION, not a deferred engineering detail. When Phase 3 starts and a specific failure type is known, the user decides between 2a and 2b based on the estimated fix cost and the project timeline at that moment. Do not start Phase 3 work without a committed fallback choice. A third option — rearchitecting to Paged.js + HTML export just for Hindi — is NOT in MVP scope. If Hindi doesn't work in PPTX, it's deferred, not rearchitected.

3. "Check my issue" pre-export screen

Standalone screen runs brief Section 21 checks without generating a PPTX. Shared library between this screen and export — no duplicated logic. Warnings are non-blocking (no per-issue ignore list). Errors block export until fixed.

4. Crash recovery UX + snapshot integrity

In scope at decision altitude:

  • Detect prior-unclean-exit on Electron startup.
  • Offer a non-technical "Recover / Discard / Open-Fresh" prompt referencing the last auto-save time.
  • Integrity check runs in background and does not block startup.
  • Operator sees an understandable remediation flow if any image is corrupted (replace / continue / restore-from-backup), with "restore from backup" being the operator's own external backup, not an in-system recovery of content-addressed bytes.

Implementation details (exact lock mechanism, integrity cadence, hash-verification strategy, dialog wording, remediation flow UI) are /plan-eng-review work.

5. CSV bulk import for classifieds (re-estimated to M, ~1 week)

  • Per-type CSV template matching the field set of each of the 12 classified types.
  • Accept UTF-8 with or without BOM. Reject non-UTF-8 with a clear error. (Hindi CSV content is UTF-8 regardless; the BOM is a Windows Excel artifact we tolerate.)
  • Preview grid shows parsed rows with validation errors highlighted. Operator imports only-valid-rows, fixes and re-uploads, or cancels.
  • Size cap: 1000 rows per CSV, reject larger with a suggestion to split.
  • Duplicate detection on (phone number + billing reference) — ASCII-safe fields only to avoid Hindi-name normalization complexity. Duplicates shown in preview with per-row import-anyway / skip.
  • Image-attached classifieds reference images by filename; images must already be in the Content Library.

Note on estimate: this is M (≈ 1 week CC) because of 12 per-type schemas × validation × preview UI × duplicate handling. Could be de-risked further by cutting to the 3 highest-volume classified types for MVP (matrimonial with photo, public notice, obituary) and expanding later, but not recommended since form entry already covers all 12 and CSV is the scale tool.

Deferred to TODOS.md (not MVP)

  • Voice intake for classifieds via local Whisper + LLM extraction.
  • Font substitution safety check.
  • Typography pairing preview page.
  • Cover variant thumbnails.
  • Classifieds deduplication beyond phone+billing-ref.
  • Template style tokens (per-issue accent color, etc.).
  • Issue-to-web HTML export.
  • Printer profile upload.
  • Backup-as-ZIP export.
  • Issue structure duplication ("clone last issue's skeleton").
  • Crash recovery thumbnail previews.
  • Per-issue ignore list for pre-export warnings.

NOT in scope

Defer entirely to brief Section 22.

Multi-tenant future — minimum carry-forward constraints

The brief says "do not preclude multi-tenancy." To meet that promise with minimum scope creep:

  1. Issue-level tenant scoping: SQLite issues table carries a tenant_id column, constant publisher_default in MVP. Other tables reference issues (FK); they don't need their own tenant_id — it cascades through the issue relationship. Migration to real multi-tenancy is a schema change, not a re-architecture.
  2. Asset storage prefix: assets/{tenant-id}/{...}, tenant-id hardcoded to publisher_default in MVP.

That's the complete list. No template_overrides table, no tenant-scoped font override table, no tenant-specific fonts directory. Multi-tenancy UI surface, RBAC, admin tooling — all deferred.

Publisher Profile (dynamic input, not hardcoded)

Per user direction (Temporal 1 answer): pilot-publisher-specific inputs are dynamic config inside the app, not hardcoded assumptions in the brief or code. A "Publisher Profile" is the first-run configuration screen the operator fills out:

  • Publication name
  • Masthead logo (upload)
  • House-style accent color (picker; applies to section dividers, pull quotes if templates support)
  • Typography pairing default (pick one of the four; overridable per issue)
  • Primary language default (en / hi / bilingual)
  • Default page size (A4 / A5)
  • Default issue cadence (weekly / fortnightly / monthly) — informs "next issue" date suggestions
  • Printer contact info + delivery method (email / courier / portal URL) — free-text, displayed at export time
  • Ad position label list (operator types their own, brief Section 15.2 is default suggestion)
  • Classifieds "billing reference" label (operator types their own term, e.g., "Invoice #")

This means none of the brief's pilot-publisher-driven open questions need to be answered before Phase 1 — they become user-settable config. The product ships usable to any publisher. This is also how the SaaS future works naturally.

Dev environment target (per user direction)

macOS-only for dev and first deploy. Windows is a roadmap pathway, not a Phase-1 concurrent target. Specifically:

  • Phase 1-13 implementation on macOS.
  • Installer built for macOS (.dmg, signed + notarized).
  • Devanagari Phase 3 gate tests on Office 365 macOS only for MVP.
  • Code is kept Windows-portable (no macOS-specific APIs outside well-scoped modules) so Windows build is a later deliverable.
  • Windows installer + Windows PowerPoint testing is a named post-MVP milestone, NOT a gate or dependency.

This simplifies the Pretext harness (no Windows VM needed for MVP), the Devanagari QA suite (one OS), and the installer work.

Blocking preconditions (resolve in Phase 1, before Phase 2)

Definition of "Phase 1 complete": 3 technical blockers. Everything else is Publisher Profile config (first-run UI, no engineering dependency).

  1. Pretext → PPTX mapping probe. Pretext confirmed real. Phase 1 builds a minimal template, runs it through Pretext measurement, generates PPTX with explicit pre-breaks (approach options listed in Accepted Scope #1), opens in Office 365 macOS, measures the rendering drift. If tolerance is met, proceed to Phase 2. If not, try the next fallback mapping approach until tolerance is met. Phase 2 cannot begin until at least one mapping approach passes.
  2. PowerPoint scripting probe (macOS). Can we drive Office 365 macOS via AppleScript (or alternative: LibreOffice headless, or convert-to-PDF-and-measure) well enough to automate the mapping harness? If no path works, the harness is manual; update timelines.
  3. Font subset embedding verification. Confirm pptxgenjs (or a direct OOXML writer if needed) can embed Google Font subsets that render correctly in Office 365 macOS. Non-trivial because PowerPoint's font embedding preferences have changed over versions.

Publisher Profile fields (NOT blockers — dynamic config, resolve at first-run)

These are no longer Phase-1 blockers; they surface in the Publisher Profile first-run UI.

  • Publication name and house style.
  • First-issue content mix (informs which templates the operator opens first; doesn't gate development).
  • Lite mode toggle for fewer templates.
  • Ad position label list.
  • Backup workflow guidance text.
  • Printer contact info + delivery method.
  • Image pathway (informational; operator may upload from wherever).
  • Existing publication assets (upload-as-needed at first run).
  • Network context (informational; product works offline regardless).

Unresolved from brief Section 24 (confirm in /plan-eng-review)

  1. Framework choice (React vs Svelte vs Solid).
  2. Styling approach (Tailwind vs vanilla CSS vs CSS-in-JS).

Reviewer Concerns (unresolved after spec review, deliberate deferrals)

These remain open deliberately — resolution belongs in Phase 1 or /plan-eng-review:

  • PowerPoint scripting feasibility (macOS). Phase 1 probe.
  • Devanagari rendering diff tool + tolerance. /plan-eng-review work.
  • CSV parser + encoding edge cases. /plan-eng-review work.
  • File-lock mechanism for crash recovery. /plan-eng-review work.
  • Pretext → PPTX mapping approach selection (paragraph-per-line vs. text-box-per-line vs. SVG fallback). /plan-eng-review locks, Phase 1 probe validates.

Section-by-section CEO decisions (captured during /plan-ceo-review)

Section Decision # Topic Choice
1 1H Re-export rollback UX B — default to current editor state, operator can override via history panel
1 1I Silent font-load fallback A — block editor with "fonts missing" error if required font unavailable
2 2A+2B Data-loss protections (OOXML validation + SQLite backup) A — both in scope for MVP
2 2C Classified entry too tall for column A — Extended Notice page (dedicated full-width)
3 3C Electron security update mechanism B — no update mechanism in MVP; operator manually reinstalls
4 4B Article already placed, dragged to another page A — move with confirmation
4 4C Bulk import partial failure UX A — review screen shows success + failure, operator proceeds with successful
4 4F Form idempotency vs double-click A — debounce 500ms + client-side dedup check
8 8A+8E Local logging + Diagnostics menu A — structured local logs (7-day rotation) + Diagnostics export-as-zip button
9 9C+9F First-run wizard + rollback doc A — first-run wizard in scope; rollback via prior .dmg install
11 11A IA structure A — 8-tab structure (Issue Board / Articles / Classifieds / Ads / Images / Templates / History / Settings)

Outside voice findings (Claude subagent, codex unavailable)

Nine findings, three presented as decisions:

OV # Topic User choice
OV1 Phase 2 gate framing (pixel-identical vs. tolerance) B — Keep pixel-identical framing; accept risk. User takes conviction position: the mapping IS solvable with the right OOXML approach.
OV2 Precondition sequencing (#3 before #1?) B — Run #1 and #3 in parallel. Moderate-risk, faster Phase 1.
OV3 Pilot commitment + Hindi positioning B — Proceed without pilot; Publisher Profile generics are enough.

Outside voice findings not translated to decisions (flagged as background risk):

  • OV #1 (rasterizer mismatch Canvas vs CoreText): real and needs Phase 1 empirical validation. If the probe shows drift > tolerance, this re-surfaces as a hard decision.
  • OV #4 (paragraph-per-line is a product change, not an engineering detail): if fallback hits, operator UX changes. Worth documenting in the help text.
  • OV #5 (Phase 2 harness needs ground-truth renderer): AppleScript flakiness is Reviewer Concern; LibreOffice is not a proxy. /plan-eng-review picks the path.
  • OV #6 (InDesign/Affinity alternative at 10x less work): explicitly rejected via Approach A commitment. Named here for archaeology.
  • OV #7 (template bundle hardens from guesswork without pilot): risk accepted per OV3B. First-issue feedback from the eventual pilot will cause template rework.
  • OV #8 (Hindi-in-v1.1 = positioning change): risk accepted per OV3B. If the Phase 3 Hindi gate fails, re-review positioning before committing to 2b.
  • OV #9 (Office point-release rendering breakage): no rollback mechanism in MVP. Reviewer Concern; needs v1.1 monitoring.