Skip to content

Friendly release: readable repo layout + sidebar publish/drift status #6

Description

@nktrjsk

Goal

One "release" feature with two halves:

  1. Human-browsable repo — replace opaque flyers/<12-hex-publishId>/vN.md folders with readable slug folders.
  2. Sidebar release status — show which flyers are published and flag when the working copy has drifted from the last release (original Friendly release: readable repo layout + sidebar publish/drift status #6).

Two distinct "fingerprints", kept separate: publishId (the hex folder name — the un-friendly one, being killed) vs lastPublishedHash (invisible content hash for drift — kept).

Repo layout

flyers/
  otevrene-hranice/        ← readable slug (display only)
    v1.md                  ← frontmatter keeps publishId = a3f9c2e8… (true identity)
    v2.md
    v2-logo.png
  otevrene-hranice-a3f9/   ← only on slug collision with a different flyer
  • Identity stays publishId in frontmatter; import matches on it, never the folder name.
  • Slug: strip diacritics → lowercase → hyphenate → cap ~60; empty/degenerate → flyer-<publishId>.
  • Retitle → folder renames: move all prior versions + logos into the new folder, delete the old one (history stays together).
  • Collision (different flyer, same slug) → append short id (-a3f9).
  • Migration: lazy, on next publish — a detected <hex>/ folder is renamed to its slug.
  • Locate current folder: store lastPublishedSlug on the concept row (O(1)); if missing after a DB wipe → one repo scan, then repopulate.

Sidebar release status

Persist lastPublishedHash + lastPublishedAt on publish. Three states, following the existing reviewStatus badge/stripe pattern, --ui-* chrome only:

State Condition Indicator
Unpublished publishId == null none
Published, clean hash(current) == lastPublishedHash calm dot, tooltip v3 · 8.7.
Published, drifted hash(current) != lastPublishedHash brass left stripe + "změněno", tooltip v3 · změněno

Vocabulary: keep "Publikovat"/"Publikováno"; drift = "změněno".

Implementation notes (seams)

  1. Drift hash excludes version + publishedAtserializeFlyer embeds both, so they'd always read as drifted. Hash a normalized payload (markdown + effectiveMeta + logo).
  2. Collision check = one GET on the target slug folder: 404 → use slug; contains my publishId → same flyer, new version; contains a different publishId → append short id.
  3. Non-atomic move (contents API is per-file): copy all versions → verify → delete old last. A mid-failure leaves harmless duplicates, never data loss; locate-logic tolerates a publishId in two folders (pick highest version, clean stragglers next run).
  4. Version derived before the move; new folder ends contiguous v1..vN.

Touches: src/lib/githubPublish.ts, src/lib/flyerFile.ts, src/db/schema.ts (add lastPublishedHash, lastPublishedAt, lastPublishedSlug), handlePublish in EditorLayout.tsx, Sidebar.tsx.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions