Files
teaching-design/docs/superpowers/specs/2026-06-16-remove-cover-page-design.md

3.9 KiB

Remove Cover Page Design

Goal

Remove the cover page feature completely from the teaching book workflow, including UI entry points, editable cover state, and legacy saved cover data in book JSON.

Scope

In scope:

  • Remove TeachingBook.cover from the domain model.
  • Change TeachingBook.selectedId from 'cover' | DesignId to DesignId | null.
  • Make newly created books start with no selected page.
  • Migrate existing stored book JSON by deleting cover.
  • Migrate existing selectedId: 'cover' to the first lesson id, or null when the book has no lessons.
  • Remove the sidebar "封面" navigation item.
  • Remove cover rendering and cover update events from the A4 workspace.
  • Stop passing cover state through WorkspaceView.vue.
  • Delete the unused CoverPage.vue component and cover-specific CSS.
  • Update tests for the domain model, store behavior, sidebar, workspace, DB migration, and route persistence.

Out of scope:

  • Removing book names from the book list. BookRecord.name remains the management/display name for each saved book.
  • Changing lesson rendering, print layout, Markdown export, ZIP export, or generated lesson content.
  • Creating a user-facing migration screen.

Data Model

TeachingBook becomes lesson-only:

export interface TeachingBook {
  schemaVersion: typeof BOOK_SCHEMA_VERSION
  designs: TeachingDesign[]
  selectedId: DesignId | null
  updatedAt: string
}

createEmptyBook() returns an empty designs array and selectedId: null.

The schema version can stay at 1 because the server migration normalizes stored JSON at load/open time. The app does not need to preserve old cover data.

Legacy Data Migration

The server will normalize every stored book when opening the SQLite database:

  • Parse books.data.
  • Delete data.cover when present.
  • If data.selectedId === 'cover', set it to data.designs[0].id when a first lesson exists, otherwise null.
  • If data.selectedId points to a missing lesson id, set it to the first lesson id or null.
  • Persist the normalized JSON back into the row only when it changed.

This ensures old database rows no longer contain cover after the app starts, not just after a user edits the book.

UI Behavior

The workspace has no cover page:

  • LessonSidebar.vue lists lessons only.
  • Empty books continue to show the upload dropzone instead of an A4 page.
  • A4Workspace.vue renders TeachingDesignPage only when there is a selected lesson.
  • WorkspaceView.vue no longer passes cover props or listens for cover update events.

Selection behavior becomes:

  • Importing lessons into an empty book selects the first imported/sorted lesson.
  • Generating a lesson selects the generated lesson.
  • Deleting the selected lesson selects the next lesson, then previous lesson, then null.
  • Clearing all lessons sets selectedId to null.

Removed Code

Delete:

  • src/components/CoverPage.vue
  • Cover-specific CSS rules in src/style.css

Keep:

  • Book list names and backend book metadata.
  • Existing print/export behavior, which already renders lessons without a cover page.

Testing

Domain tests verify:

  • New books do not have cover.
  • New books start with selectedId: null.
  • Independent book creation still produces independent lesson arrays.

DB tests verify:

  • Opening a database migrates old cover data out of saved book JSON.
  • Old selectedId: 'cover' becomes the first lesson id when lessons exist.
  • Old selectedId: 'cover' becomes null when no lessons exist.
  • Invalid selected ids are normalized.

Store/component tests verify:

  • useTeachingBook no longer exposes updateCover.
  • Clear/delete/import/generate selection behavior uses null or lesson ids only.
  • LessonSidebar does not render a cover button.
  • A4Workspace does not import or render CoverPage.
  • WorkspaceView does not pass cover props.

Verification will run the frontend tests, backend tests, and production build.