# Sketch Board — Product Requirements (v5.3)

Sketch Board is an infinite-canvas whiteboard with a hand-drawn look. People draw with an icon-only toolbar, keep several boards, and every change is saved automatically to the server so a board is exactly as they left it after a reload.

**Problem.** Quick diagrams and drawings are only useful if what is drawn is what is stored: shapes must keep their type and geometry, and nothing may silently disappear or revert.

## Users
- **Sketcher** — Draw freehand and with shapes, and trust that the drawing is saved.
- **Diagram author** — Build flow diagrams whose arrows and labels stay attached to their shapes.
- **Board organiser** — Create, find, rename and delete boards without losing the one in use.

## Goals
- Every shape is stored with the type and geometry it was drawn with.
- Autosave is honest: "Saved" means the server holds the current drawing.
- Board management (create, rename, delete, order) is predictable and validated the same way in the UI and the API.

## Canvas and scratch board (CAN)

First-load experience of a fresh tab.

- **FR-CAN-01** (Must) A fresh tab opens the scratch board "Untitled sketch" with an empty canvas and the welcome hints.
  - URL becomes /sketch/#board=b-scratch and the tab title is "Untitled sketch · Sketch Board"
  - The status chip reads "Untitled sketch", "Saved", "0 shapes"
  - Welcome text: "Sketch Board" and "Everything you draw is saved to “Untitled sketch”."
  - The toolbar offers Rectangle, Diamond, Ellipse, Arrow, Line, Draw, Text and Eraser
- **FR-CAN-02** (Could) The theme toggle switches between light and dark; in dark mode the canvas and toolbar darken, the status chip text stays readable and the menu item reads "Light mode".
- **FR-CAN-03** (Could) Export image produces a PNG named after the board, with a preview of the drawing in the export dialog.
- **FR-CAN-04** (Could) The canvas background colour can be changed from the main menu; it is saved with the board and shown as the board’s swatch in Your boards.
  - Seed board Kitchen layout has a pale-yellow swatch

## Drawing tools (DRW)

Shape and freehand tools and their keyboard shortcuts.

- **FR-DRW-01** (Must) Each tool creates exactly one element of its own type: Rectangle, Diamond, Ellipse, Arrow, Line, Draw (freedraw) and Text.
  - One of each of the seven gives "7 shapes — 1 rectangle, 1 diamond, 1 ellipse, 1 arrow, 1 line, 1 freedraw, 1 text" in Board details
  - An ellipse stays an ellipse after it is released; it is never converted to another type
- **FR-DRW-02** (Must) Pencil (Draw) strokes keep their full path: a finished stroke is stored as a freedraw element with every sampled point, never reduced to a straight segment.
  - A curved stroke has more than 2 points in Board details
- **FR-DRW-03** (Must) A multi-point Line ends with Escape and is "closed" only when its last point lands on its first.
  - Clicking three corners then the first corner again stores "4 (closed)"
  - Ending with Escape about 30 px short of the first point stores "3" without "(closed)"
- **FR-DRW-04** (Must) Shapes are stored where they are drawn: a head ellipse about 200 × 180 contains the eyes within its box, the body lies below the head and the ears above it.
  - Board details lists x, y, width and height per element, matching the drawn positions
- **FR-DRW-05** (Should) Selected shapes can take a fill colour and a solid fill from the properties panel; a Text element holds the typed text.
  - A head ellipse with orange background and solid fill is shown orange
  - Typing "Cat" with the Text tool then Escape stores a text row with Text "Cat"
- **FR-DRW-06** (Should) The Eraser removes the shapes it is dragged across, and the removal is saved.
  - Erasing one whisker on the 24-shape Cat reference gives "23 shapes — 8 ellipse, 14 line, 1 text" after a reload
- **FR-DRW-07** (Could) Letter and number shortcuts pick tools.
  - R, D, O, A, L, P, T, E select Rectangle, Diamond, Ellipse, Arrow, Line, Draw, Text, Eraser in that order
  - 1 selects Selection and 4 selects Ellipse
- **FR-DRW-08** (Should) Select-all, copy and paste carries every shape to another board and leaves the source board unchanged.
  - Pasting the Cat reference onto a new board gives "24 shapes — 8 ellipse, 15 line, 1 text"; Cat reference still holds 24
- **FR-DRW-09** (Should) Arrows bound to shapes follow them when a shape is moved, and a label moves with its container.
  - Dragging the "Valid?" diamond 100 px left moves its label and the connected arrows
  - The Sign-in flow board holds 18 shapes — 4 rectangle, 1 diamond, 5 arrow, 8 text

## Autosave, reload and undo (SAV)

Persistence of every edit.

- **FR-SAV-01** (Must) Edits are saved automatically about 0.7 s after the last change and nothing is saved while a stroke is still being dragged.
  - The chip shows "Saving…" and then "Saved" within about a second of releasing; the shape count updates by +1 / −1
  - The status does not change while the mouse button is held down
- **FR-SAV-02** (Must) After "Saved", a reload restores every shape — including pencil strokes with their curve — and the same shape count.
  - An ellipse plus one curvy stroke reloads as "2 shapes": one ellipse, one freedraw with many points
- **FR-SAV-03** (Should) Undo (Ctrl/Cmd+Z) and redo (Ctrl/Cmd+Shift+Z) are saved like any other edit.
  - After undoing the last of two shapes and a reload only the first remains ("1 shape")
  - After undo then redo both shapes are present after a reload
- **FR-SAV-04** (Must) Reset the canvas (after confirmation) empties the board, and the empty board is what is saved.
  - "0 shapes", "Saved"; still empty after a reload; Your boards shows the board with 0 shapes
- **FR-SAV-05** (Could) Each browser tab works on its own seeded copy of the data: boards edited in one tab are not visible in a new tab.
  - A new tab shows Untitled sketch with 0 shapes and the four seed boards

## Boards (BRD)

List, search, create, rename and delete boards.

- **FR-BRD-01** (Must) Your boards lists the four seed boards with shape counts, ordered by last edit, newest first, with the open board marked "(open)".
  - Order: Kitchen layout (9 shapes, Oct 17), Sign-in flow (18, Oct 15), Cat reference (24, Oct 14), Untitled sketch (0, Oct 12)
- **FR-BRD-02** (Could) Search boards is a case-insensitive match on the name.
  - "CAT" lists only Cat reference
  - No match shows "No boards match."
- **FR-BRD-03** (Should) Only a real change updates a board’s "edited" time and moves it to the top; merely opening a board does not.
  - Opening Sign-in flow and changing nothing leaves it at "edited Oct 15"
  - Moving a shape on Cat reference puts it first with "edited just now"
- **FR-BRD-04** (Must) New board creates an empty board with its own URL, listed first.
  - The dialog pre-selects "Untitled sketch"
  - The first new board gets id b-101, URL #board=b-101, tab title "<name> · Sketch Board" and chip "<name>", "0 shapes"
- **FR-BRD-05** (Should) Board names are 1–60 characters after trimming; runs of whitespace collapse to one space.
  - Blank name: "Board name is required" and the dialog stays open
  - 61 characters: "Use 60 characters or fewer"; exactly 60 is accepted
  - "   My    cat   " is stored as "My cat"
- **FR-BRD-06** (Must) Renaming (from the status chip or the menu) updates the chip and tab title and is stored on the server.
  - Renaming Cat reference to "Cat sketch v2" shows that name after a reload and in Your boards
- **FR-BRD-07** (Should) Delete asks for confirmation naming the board and its shape count, and can be cancelled.
  - "Delete board?" — "“Kitchen layout” and its 9 shapes will be deleted. This can’t be undone."
  - "Keep board" returns to the list with the board intact; "Delete board" removes it
- **FR-BRD-08** (Could) Deleting the board that is open opens the scratch board Untitled sketch (#board=b-scratch).
- **FR-BRD-09** (Should) The last remaining board cannot be deleted.
  - Message "Keep at least one board"; the board is still listed
- **FR-BRD-10** (Could) A link to a missing board shows "This board doesn’t exist any more." with buttons Open “Untitled sketch” and Your boards.
- **FR-BRD-11** (Should) The seeded Cat reference board holds a complete cat of 24 shapes.
  - "24 shapes — 8 ellipse, 15 line, 1 text"
  - Three lines are closed (both ears and the nose); the head ellipse is 220 × 200 at 300, 140

## Board API (API)

JSON interface to the same boards.

- **FR-API-01** (Should) GET /api/sketch/boards lists boards newest-edit first with per-type counts; GET /api/sketch/boards/<id> returns the elements; GET …/summary returns per-shape geometry; an unknown id returns 404.
  - Four boards, first id b-kitchen; Cat reference counts {ellipse 8, line 15, text 1}
  - b-cat has 24 elements; summary shows shapes 24 and cat-ear-l {type line, points 4, closed true}
  - 404 "Board b-nope not found"
- **FR-API-02** (Should) PUT validates the element list.
  - elements not an array: 422 "elements must be an array"
  - Unknown type: 422 "Unknown element type"
  - Missing numeric x or y: 422 "Every element needs numeric x and y"
  - 3001 elements: 413 "A board can hold at most 3000 elements"; 3000 elements: 200
- **FR-API-03** (Could) Board create, rename and delete follow the same rules as the UI.
  - POST {"name":"API board"} returns 201 with id b-101
  - PATCH with an empty name: 422 "Board name is required"
  - Deleting the last board: 409 "Keep at least one board"
  - POST /api/sketch/reset restores the seed boards

## Non-functional requirements

- **NFR-01** (Should) Keyboard accessibility: every drawing tool has a single-key shortcut (see FR-DRW-07).
- **NFR-02** (Must) Reliability: the "Saved" indicator is shown only when the stored board equals the canvas; no element type or point is lost on save.

## Glossary and rules

- **Board** — A named drawing with its own URL, background and shapes.
- **Scratch board** — The default board "Untitled sketch" that a fresh tab opens.
- **Board details** — Menu view of what the server has stored for the open board: element types, boxes, point counts and closed lines.

## Out of scope

- Real-time collaboration and share links
- Shape libraries and image upload
- Pixel-level comparison of exported images
