Page 1 of 20
System Requirements Document for hardy-todo
1. Introduction
hardy-todo is a simple, single-page todo application. Its product intent is narrow and deliberate: one quiet surface where a single everyday user captures the small obligations they need to remember, sees the list of what remains, marks items complete, and removes items they no longer need — all without navigating anywhere else.
The audience is one person using the app privately and briefly, often several times a day. The product is not a team tool, not a project manager, and not a dashboard. Simplicity is an explicit hard constraint, and the application is explicitly a single page.
The design register is calm competence: a sheet of good paper rather than a UI panel. The app should read as almost empty until the user's own short lines of text arrive.
Page 2 of 20
2. System Overview
hardy-todo is delivered as a single custom page, Todo, which is the public entry surface and the entire application. There is no navigation, no secondary route, and no separate settings, account, or reporting surface.
The only active human actor is the Todo User. The application itself owns the todo list state: the current set of tasks, which of them are complete, and the remaining-task count derived from them.
Accepted behavior on the single page:
- Capture a new task by typing its text and committing it.
- Review the current list of tasks, including which are complete.
- Mark a task complete, which visibly strikes it through and desaturates it.
- Remove a task the user no longer needs.
- Clear all completed tasks at once.
- See the remaining-task count, which updates as tasks are added, completed, removed, or cleared.
Narrow exclusions: no accounts, sign-in, or identity of any kind; no sharing, collaboration, assignment, or multi-user state; no due dates, priorities, tags, projects, or sub-tasks; no notifications or reminders; no recurring tasks; no search, filter, or sort controls; no gamified feedback such as streaks, progress rings, or confetti; no additional pages or routes.
Page 3 of 20
2a. Product Interpretation and Delivery Boundary
Delivery. hardy-todo is a first-party custom web application. The single page is the product. There is no provider-owned surface, no external destination, and no headless delivery path in the accepted requirements.
Access. The page is reachable without any identity step. The Planning Scope records the Todo surface with an access requirement of none, and no accepted requirement asks the user to sign in, create an account, or be recognized on return. The user's list is therefore application-owned state on the page itself, not state bound to a verified person. No account creation, sign-in, invitation, provisioning, or profile management is part of this product.
Current vs. future. Everything described in this document is current. Nothing in the accepted requirements establishes a future horizon, a deferred capability, or a planned expansion. The single-page boundary is a current hard constraint, not a phase-one staging decision.
Simplicity boundary. "Simple" and "single page" are binding constraints on scope and information architecture. They are not an invitation to add conventional todo-app features that the user did not request.
2b. Source Content Inventory
Not applicable. No reference directive in this project declares a content_source, so no source content inventory is produced.
2c. Page Content and Component Coverage
Page 4 of 20
Todo
The single page of hardy-todo. It is the public entry surface and the complete application: the masthead, the task input, the task list, and the list footer all live on this one page, with no navigation away from it.
Information and state
- The wordmark
hardy, set lowercase, large and light, flush left of the column.
- The remaining-task count, in tabular figures, right-aligned to the same baseline as the wordmark, separated from it by a full-measure hairline rule. The count reflects tasks that are not yet complete.
- The current task list: each task's text and its completion state.
- The completion state of each task, expressed as a drawn accent strike line across the text plus a desaturation of that text to muted.
- The empty state: when no tasks exist, the list region holds no rows and the page reads as a sheet with a masthead, an input, and empty paper.
- The all-complete state: when tasks exist but none remain, the count reads zero and the completed rows remain visible until cleared or removed.
Primary actions
- Add a task. The user types task text into the borderless input row and commits it with the small square add control (or by pressing Enter). The new task appears at the end of the list, the input clears, and the remaining count increments.
- Complete a task. The user activates the 16px square checkbox at the far left of a task row. The accent strike line draws across the text and the text desaturates to muted; the remaining count decrements.
- Uncomplete a task. The user activates the checkbox of a completed task. The strike line and desaturation are removed and the remaining count increments.
- Remove a task. The user activates the small
× control at the far right of a task row, which materialises on hover or keyboard focus. The row collapses and disappears; the remaining count adjusts if the removed task was incomplete.
Supporting actions
- Clear completed. A single text link in the card footer removes every completed task at once. It is the only footer control.
Domain entities
- Task — the unit of work the user captures. Carries its text and its completion state. Tasks are ordered by the sequence in which they were added.
- Task list — the ordered collection of all current tasks, complete and incomplete.
- Remaining count — a derived value: the number of tasks in the list that are not complete.
Component responsibilities
- Masthead — renders the wordmark and the remaining count on one shared baseline with a hairline rule beneath, spanning the full column width. Owns the count's cross-fade when the value changes.
- Task input row — a borderless text input on a thin underline with a small square add control. Owns accepting text, rejecting empty or whitespace-only submissions, clearing itself after a successful add, and showing the accent focus ring while focused.
- Task list — renders the ordered task rows, or nothing when the list is empty. Owns the fade-in of a newly added row, the strike-and-desaturate completion gesture, and the collapse of a removed row.
- Task row — a full-width, left-aligned row containing the 16px square checkbox at the far left, the task text, and the
× delete control at the far right. Owns wrapping long task text to a second line rather than truncating it.
- Card footer — a hairline rule and the single
clear completed text link.
States
- Loading — the page renders its masthead, input, and empty list region immediately; there is no blocking spinner and no skeleton placeholder, because the list is application-owned state on the page.
- Empty — no tasks. The list region is genuinely empty paper; the count reads zero; the
clear completed link is inert or absent since there is nothing to clear.
- Success — a task is added, completed, uncompleted, removed, or cleared, and the list and count reflect the change immediately.
- Error — an add attempt with empty or whitespace-only text is rejected: no task is created, the input retains focus, and the count is unchanged. No other error state is accepted, because there is no network dependency, no identity step, and no external service in the accepted behavior.
- Recovery — because every mutation is immediate and local to the page, recovery is simply the inverse action: uncomplete a task completed by mistake, or re-add a task removed by mistake. The page never enters a state the user cannot correct from the page itself.
Page 5 of 20
3. Functional Requirements
FR-1 — Capture a task (explicit)
As a Todo User, I should be able to type a task's text into the input row and commit it, so that the obligation is captured and I no longer have to hold it in my head.
- Trigger/input: the user types text into the borderless input and activates the small square add control, or presses Enter.
- Observable result: the task appears at the end of the list, the input clears, and the remaining-task count increments.
- Access state: no identity required; the page is reachable directly.
- Failure/recovery: if the text is empty or whitespace-only, no task is created, the input keeps focus, and the count is unchanged.
- Continuation: the input is immediately ready for the next task.
FR-2 — Review the current list (explicit)
As a Todo User, I should be able to see all of my current tasks in one place, so that I can tell at a glance what is still outstanding.
- Trigger/input: opening the page, or any change to the list.
- Observable result: every current task is rendered as a full-width row in the order it was added, with its completion state visible.
- Access state: no identity required.
- Failure/recovery: not applicable; the list is application-owned state on the page.
- Continuation: the user can act on any row directly.
FR-3 — See the remaining count (explicit)
As a Todo User, I should be able to see how many tasks remain, so that I know the size of what is left without counting rows myself.
- Trigger/input: any change to the list — add, complete, uncomplete, remove, or clear completed.
- Observable result: the count in the masthead reflects the number of incomplete tasks, in tabular figures, right-aligned to the wordmark's baseline; the numeral cross-fades when it changes.
- Access state: no identity required.
- Failure/recovery: not applicable; the count is derived from the list.
- Continuation: the user continues working the list.
FR-4 — Mark a task complete (explicit)
As a Todo User, I should be able to mark a task complete, so that I can see what I have finished and stop carrying it.
- Trigger/input: the user activates the 16px square checkbox at the far left of a task row.
- Observable result: a 1px accent strike line draws left-to-right across the task text, the text then desaturates to muted, and the remaining count decrements.
- Access state: no identity required.
- Failure/recovery: the action is reversible — activating the checkbox again removes the strike and desaturation and restores the count.
- Continuation: the completed row stays in the list until the user removes it or clears completed tasks.
FR-5 — Uncomplete a task (required_inference)
As a Todo User, I should be able to undo a completion, so that a task marked complete by mistake returns to the outstanding list.
- Trigger/input: the user activates the checkbox of an already-complete task.
- Observable result: the strike line and desaturation are removed, the task text returns to ink, and the remaining count increments.
- Access state: no identity required.
- Failure/recovery: the action is itself reversible by completing the task again.
- Continuation: the task is once more part of the outstanding work.
- Rationale: completion is a state change the user controls directly on the page; without the inverse, a mis-tap would be uncorrectable except by deleting and re-adding the task.
FR-6 — Remove a task (explicit)
As a Todo User, I should be able to remove a task I no longer need, so that the list stays trustworthy and free of stale lines.
- Trigger/input: the user activates the small
× control at the far right of a task row, which materialises on hover or keyboard focus.
- Observable result: the row collapses to zero height and disappears; the remaining count adjusts if the removed task was incomplete.
- Access state: no identity required.
- Failure/recovery: a removed task can be re-added by typing it again; the page never blocks the user from restoring their list.
- Continuation: the list is shorter and the count is accurate.
FR-7 — Clear completed tasks (explicit)
As a Todo User, I should be able to clear all completed tasks at once, so that I can reset the sheet without deleting rows one by one.
- Trigger/input: the user activates the single
clear completed text link in the card footer.
- Observable result: every completed task is removed from the list; incomplete tasks are untouched; the remaining count is unchanged because it counts only incomplete tasks.
- Access state: no identity required.
- Failure/recovery: when no tasks are complete, the link has nothing to act on and the list is unchanged.
- Continuation: the user is left with only outstanding work.
FR-8 — Add a task by keyboard alone (required_inference)
As a Todo User, I should be able to add a task without leaving the keyboard, so that capture stays fast enough to actually use.
- Trigger/input: the user types into the input and presses Enter.
- Observable result: the task is added exactly as if the add control had been activated, and focus remains in the input.
- Access state: no identity required.
- Failure/recovery: empty or whitespace-only text is rejected as in FR-1.
- Continuation: the user can type the next task immediately.
- Rationale: the input row is the primary capture surface and the add control is a small square; a keyboard commit is the indispensable mechanic that makes repeated capture usable.
FR-9 — Reach every row control by keyboard (required_inference)
As a Todo User, I should be able to reach the checkbox and the delete control of any row using the keyboard, so that the list is fully operable without a pointer.
- Trigger/input: the user tabs through the page.
- Observable result: the input, each row's checkbox, each row's
× delete control, and the clear completed link are focusable in reading order; the focused control is visibly indicated, and the × becomes visible when its row is focused.
- Access state: no identity required.
- Failure/recovery: not applicable.
- Continuation: the user can complete, uncomplete, remove, or clear without a pointer.
- Rationale: the delete control is specified to appear on hover or keyboard focus, which is only meaningful if the control is reachable by keyboard.
FR-10 — Respect reduced-motion preference (explicit)
As a Todo User who has asked my system for reduced motion, I should see state changes happen instantly, so that the app does not animate against my preference.
- Trigger/input: the operating system or browser reports
prefers-reduced-motion.
- Observable result: new tasks appear with no fade and no drift; completion applies the strike and desaturation as an instant state change with no drawn stroke; deletion removes the row with no collapse animation; the count changes without a cross-fade.
- Access state: no identity required.
- Failure/recovery: not applicable.
- Continuation: all functionality remains available; only the motion is removed.
Page 6 of 20
4. User Personas
Page 7 of 20
Todo User
Product context. The Todo User is one person using hardy-todo privately, for themselves, on a single page. They are not managing anyone else's work and are not reporting to anyone. They open the app briefly and often — a few seconds at a time — to put something down before it escapes, or to clear something they have just finished. The app is a small private surface, not a workspace they live in.
Primary goal. A single page where their todo list stays current and trustworthy, so that what they see is what is actually left to do. Success is that they never have to wonder whether the list is stale, and never have to navigate anywhere to keep it accurate.
Distinct responsibilities. The Todo User is the sole actor for every accepted capability on the page: capturing a task's text, reviewing the list, reading the remaining count, marking a task complete, undoing a completion, removing a task, and clearing all completed tasks at once. No other human participates in any of these.
Inputs and decisions. Their inputs are short lines of their own text and a small set of direct actions on the list. Their decisions are equally small and frequent: is this worth writing down; is this actually done; do I still need this line; is it time to clear the finished ones away. Each decision is made in the moment, on the page, with no confirmation step.
Interactions with other participants. None. There is no second human actor, no assignee, no reviewer, and no recipient of the user's list. The only other participant in the system is the application itself, which holds the list state and derives the remaining count. This is why the persona's work is entirely self-directed: the user is both the author and the only audience of the list.
Observable success. The list on the page matches what the user believes is outstanding; the remaining count agrees with the number of unstruck rows; completed items read as visibly finished rather than merely checked; and removed items are gone. The user closes the page confident that reopening it will show the same truthful list.
Constraints carried from the source. The user's work happens on exactly one page. The design must be simple. There is no identity, no account, and no sign-in step standing between the user and their list.
Page 8 of 20
5. Core User Flows
Flow 1 — Capture a task (Todo User)
- The Todo User opens hardy-todo. The page loads directly with no sign-in step: the masthead shows the wordmark
hardy and the remaining count, and the card shows the input row, the list, and the footer.
- The user clicks into the borderless input row. The accent focus ring appears on the input.
- The user types the task's text. The text appears in the input at 20px with a roomy line-height.
- The user commits the task — either by activating the small square add control or by pressing Enter.
- Observable result: the task appears at the end of the list, fading in over 400ms with a 6px upward drift; the input clears; the remaining count increments and its numeral cross-fades to the new value.
- Failure branch: if the input holds only whitespace, no task is created, the input keeps focus, and the count is unchanged. The user simply types real text and commits again.
- Continuation: focus remains in the input, so the user can type the next task immediately without reaching for the pointer.
Flow 2 — Review the list and the remaining count (Todo User)
- The Todo User opens hardy-todo, or returns to it after adding or finishing something.
- The page renders every current task as a full-width, left-aligned row in the order it was added, with each row's completion state visible.
- The user reads the remaining count in the masthead, right-aligned to the wordmark's baseline in tabular figures, to gauge how much is left without counting rows.
- Observable result: the count agrees with the number of unstruck rows, and the list reads top to bottom as the user's outstanding and finished work.
- Empty branch: if there are no tasks at all, the list region is genuinely empty paper — the masthead, the input, and the footer rule remain, and the count reads zero.
- Continuation: the user acts directly on whichever row they choose; no navigation is needed.
Page 9 of 20
Flow 3 — Complete a task (Todo User)
- The Todo User is looking at the list and has just finished one of the tasks.
- The user activates the 16px square checkbox at the far left of that task's row.
- Observable result: a 1px accent strike line draws left-to-right across the task text over 320ms; the text then fades to muted over a further 400ms; the remaining count decrements and its numeral cross-fades.
- The completed row remains in the list, visibly finished, until the user removes it or clears completed tasks.
- Recovery branch: if the user struck the wrong row, they activate that row's checkbox again. The strike and desaturation are removed, the text returns to ink, and the count increments back.
- Continuation: the user either completes the next task or moves to clearing the finished ones.
Flow 4 — Remove a task (Todo User)
- The Todo User decides a line on the list is no longer needed.
- The user moves the pointer over that task's row, or tabs to it with the keyboard. The small
× control materialises at the far right of the row.
- The user activates the
×.
- Observable result: the row collapses to zero height over 300ms ease-in-out and disappears; if the removed task was incomplete, the remaining count decrements.
- Recovery branch: if the user removed the wrong row, they type the task again through Flow 1. The page never blocks restoring the list.
- Continuation: the list is shorter and the count is accurate.
Flow 5 — Clear completed tasks (Todo User)
- The Todo User has accumulated several finished rows and wants the sheet back.
- The user activates the single
clear completed text link in the card footer.
- Observable result: every completed task is removed from the list at once; incomplete tasks are untouched; the remaining count is unchanged, because it counts only incomplete work.
- Empty branch: if nothing is complete, the link has nothing to act on and the list is unchanged.
- Continuation: the user is left with only outstanding work and can continue adding or completing tasks.
Page 10 of 20
Flow 6 — Work the list by keyboard alone (Todo User)
- The Todo User opens hardy-todo and does not want to leave the keyboard.
- The user types a task and presses Enter. The task is added exactly as in Flow 1, and focus stays in the input.
- The user tabs forward. Focus moves through the input, then each row's checkbox, then each row's
× delete control, then the clear completed link, in reading order.
- Observable result: the focused control is visibly indicated, and when a row's
× receives focus it becomes visible at the far right of that row.
- The user activates a checkbox to complete a task, or a
× to remove one, without touching the pointer.
- Continuation: the user can keep tabbing and acting until the list reflects what they want.
Flow 7 — Reduced-motion use (Todo User)
- The Todo User's system reports
prefers-reduced-motion.
- The user adds, completes, uncompletes, removes, and clears tasks exactly as in Flows 1, 3, 4, and 5.
- Observable result: every one of those state changes is instant — no fade or drift on add, no drawn strike on completion, no collapse on removal, no cross-fade on the count. The row simply appears, changes, or disappears.
- Continuation: all functionality remains available; only the motion is gone.
6. Visuals, Colors and Theme
The creative direction is authoritative for this section. Its muse is Kenya Hara, and its headline idea is emptiness as content: a todo list that behaves like a sheet of good paper. White is not absence here — it is the content. The app should read as almost empty until the user's own short lines of text arrive.
Page 11 of 20
Color tokens — light mode
| Role | Hex | Use |
|---|
| Background | #F4F1EA | Unbleached paper ground for the page |
| Surface | #FBFAF6 | Slightly brighter sheet for the card and the input field, so the app reads as paper on paper |
| Text | #2B2A27 | Soft charcoal ink — never pure black |
| Primary | #3F3D38 | Warm stone-grey for the wordmark, rules, and the add control — ink, not chrome |
| Accent | #A8503C | Muted persimmon/clay, used only for the completed-state strike line, the remaining-count numeral, and the input focus ring |
| Muted | #8C877C | Timestamps, placeholder text, helper copy, and completed task text |
| Hairline | #D8D3C7 | 1px rules separating the input row from the list and closing the card |
Proportion: roughly 80% paper tones, 15% ink, 5% accent. The accent must feel like a single brushstroke, never a brand colour. Blue, indigo, and violet accents on white are forbidden for this project.
Typography
- Family: Zen Kaku Gothic New for both headings and body.
- Display wordmark: Light 300, lowercase, wide tracking
+0.14em, so hardy reads as a whisper rather than a shout.
- Section labels: Medium 500, small uppercase, generous letterspacing
+0.22em.
- Task text: Regular 400 at 20px with a roomy
1.7 line-height.
- No bold display weights anywhere. Emphasis comes from size, space, and rule lines — never from weight.
- Scale: 1.25 modular on a 16px base —
16 / 20 / 25 / 31 / 44 / 64.
- Display wordmark size:
clamp(44px, 9vw, 64px).
- Labels: 12px uppercase, tracked.
- Numerals: tabular figures for the remaining count.
Page 12 of 20
Shape language
Square and near-square only. The card, input, and buttons are true rectangles with 2px radii — just enough to avoid a razor edge, never a pill. One hairline rule (1px, #D8D3C7) separates the input row from the list, and a second hairline closes the card. Nothing floats: every element sits flush on the paper. No shadows, no blur, no glass, no gradients. The only ornament is empty space and the vertical rhythm of the list rows.
Page 13 of 20
Layout
A single centred column, max-width 640px, on a generous page margin: 24px at 375px, 64px at 768px, and vertically centred in a 1280px viewport with the column holding its measure.
Above the card, the wordmark hardy sits flush left of the column with the remaining-task count right-aligned on the same baseline, separated by a hairline rule spanning the full column width.
The card contains, in order:
- A borderless input row with a thin underline and a small square add control.
- One hairline.
- The task list.
- One hairline.
- A footer row with a single
clear completed text link.
Task rows are full-width and left-aligned, with the checkbox as a 16px square outline at the far left and the delete control appearing as a small × at the far right on hover or focus.
At 375px everything stays inside the viewport: the wordmark and count share the top line, task text wraps to a second line rather than truncating, and the add control becomes a 44px square below the input when the row would otherwise crowd.
Page 14 of 20
Imagery
No photography, no illustration, no icons beyond the functional square checkbox and a 1px × glyph. The visual interest is entirely typographic and material: paper tone, hairline rules, tabular numerals, and the negative space above and below the card. The one permitted graphic gesture is a faint 1px dot-grid — or nothing at all. The page should be describable as "a sheet, a line, some words."
Page 15 of 20
7. Signature Design Concept
The masthead is one line of type, and the first screen is mostly paper.
The public entry is not a marketing hero — the first screen is the app, treated as an editorial page. Its dominant element is the wordmark hardy set at clamp(44px, 9vw, 64px), Light 300, lowercase, tracked wide, flush left on the column's baseline. The remaining-task count sits in tabular figures, right-aligned to that same baseline, and a hairline rule runs the full column width beneath both. The app's entire masthead is that single line.
Below it, a large block of genuine empty paper — roughly 96px at 375px and 160px at 1280px — before the card begins. The first screen is therefore mostly white, with a single line of type at the top and the input underline near the bottom. The composition is asymmetric and top-weighted, not a centred headline with a blue button: there is no button in the hero at all, only an underline and a small square add control.
Palette roles in the hero: paper ground #F4F1EA, ink #2B2A27 for the wordmark and count, hairline #D8D3C7 for the rule, and the accent #A8503C appearing only if the count is non-zero.
The concept recomposes only accepted content and controls — the wordmark, the count, the hairline, the input, and the add control. It introduces no new behavior, page, or destination.
Page 16 of 20
8. Interaction Model & Motion Direction
Interaction Model: Static (direction)
Motion Tempo: still
Hero Dimensionality: flat
The direction's tempo is stillness with one purposeful gesture, and it is copied here rather than re-decided. Nothing performs. The only ambient motion is the remaining-count numeral cross-fading when it changes.
Landing Hero Motion Brief
- Focal subject: the wordmark
hardy and the remaining-task count locked to one baseline, with a full-measure hairline rule beneath them, over a large field of untouched paper.
- Input → transformation → outcome thesis: the user types a short line of text into the borderless input and commits it; the line becomes a task row that fades in over 400ms with a 6px upward drift and no easing overshoot; the remaining count cross-fades to its new value. The page's emptiness is progressively and reversibly filled by the user's own words — and emptied again as tasks are completed and cleared.
- Motion vocabulary: fade-in with a small upward drift on add; a 1px accent strike line drawn left-to-right over 320ms on completion, followed by a 400ms desaturation of the text to muted; a 300ms ease-in-out height collapse on removal; a cross-fade on the count numeral. No overshoot, no bounce, no ambient animation.
- Composed first frame: paper ground
#F4F1EA; the wordmark hardy flush left at clamp(44px, 9vw, 64px) in Light 300, lowercase, tracked +0.14em; the count in tabular figures right-aligned on the same baseline; a hairline rule spanning the column beneath both; then 96–160px of empty paper; then the card's borderless input on its thin underline with the small square add control. No button in the hero.
- Reduced-motion state: under
prefers-reduced-motion, every one of these becomes an instant state change — no drift, no drawn strike, no collapse, no cross-fade. The row simply appears, changes, or disappears, and the count simply reads its new value.
No 3D or WebGL scene is requested by the user or called for by the direction's hero dimensionality, so no Canvas/R3F/Drei requirement is imposed.
Page 17 of 20
9. Non-Functional Requirements
NFR-1 — Single page (explicit)
The application must be a single page. There is exactly one destination, Todo, and no navigation, routing, or secondary surface. Rationale: the user stated "simple single page design of todo application," and the Planning Scope fixes the page count at exactly one.
NFR-2 — Simplicity (explicit)
The design must be simple. This constrains both scope and presentation: no feature beyond the accepted list, and no visual ornament beyond paper tone, hairline rules, tabular numerals, and negative space. Rationale: explicit hard constraint in the user's requirement.
NFR-3 — No identity or account step (explicit)
The page must be reachable without sign-in, account creation, or any identity step. Rationale: the Planning Scope records the Todo surface with an access requirement of none, and no accepted requirement asks the user to be recognized.
NFR-4 — Readable text and controls stay whole at every viewport (explicit)
At 375px, 768px, and 1280px, the wordmark, the count, labels, task text, and every control must stay entirely inside the viewport and inside their container. Task text wraps to a second line rather than truncating; the wordmark scales via clamp(44px, 9vw, 64px); the add control becomes a 44px square below the input when the row would otherwise crowd. No element may cover any part of readable text or a control. Rationale: explicit direction constraint.
NFR-5 — Reduced-motion support (explicit)
Under prefers-reduced-motion, all motion must become instant state changes with no drift, no strike animation, and no collapse, while every function remains available. Rationale: explicit direction constraint.
NFR-6 — Keyboard operability (required_inference)
Every interactive control — the input, each row's checkbox, each row's × delete control, and the clear completed link — must be reachable and operable by keyboard, with a visible focus indication. Rationale: the direction specifies the delete control appears on hover or keyboard focus, which is only meaningful if the control is keyboard-reachable.
NFR-7 — No shadows, blur, glass, or gradients (explicit)
The interface must use no drop shadows, no blur, no glassmorphism, no translucent overlays, and no gradients. Radii are 2px; the only filled shape in the primary flow is the 16px square checkbox. Rationale: explicit direction constraint.
NFR-8 — No gamified feedback (explicit)
No progress rings, streaks, confetti, or gamified completion feedback. Rationale: explicit direction constraint.
NFR-9 — No decorative imagery (explicit)
No photography, illustration, emoji, stickers, or icons beyond the functional square checkbox and the 1px × glyph. Rationale: explicit direction constraint.
NFR-10 — No blue/indigo/violet on white (explicit)
The generic indigo/blue-on-white SaaS template is forbidden for this project. Rationale: explicit direction constraint.
Page 18 of 20
10. Tech Stack
No technology choices were specified by the user. The following are coherent defaults for a single-page client application with no server-side requirement in the accepted behavior.
- Frontend: React, rendering the single
Todo page. [Default — not specified by user]
- Styling: plain CSS with custom properties for the palette tokens in Section 6, so the paper/ink/accent roles stay single-sourced.
[Default — not specified by user]
- State: in-memory application state on the page, holding the task list and deriving the remaining count.
[Default — not specified by user]
- Persistence: none required by the accepted requirements. The Planning Scope establishes no identity and no durable per-user store, and no accepted requirement asks the list to survive a reload.
[Default — not specified by user]
- Backend: none. No accepted capability requires a server, and adding one would exceed the single-page, simple boundary.
[Default — not specified by user]
- Containerization and orchestration: not required. There is no deployment requirement in the accepted sources, so Docker, docker-compose, and Kubernetes are out of scope.
[Default — not specified by user]
Page 19 of 20
11. Assumptions and Constraints
Constraints (binding, from the authoritative source)
- The application is a single page. Exactly one destination exists:
Todo.
- The design must be simple.
- The page is reachable with no identity step.
- The palette, typography, shape language, layout, motion, and imagery rules in Sections 6–8 are binding, including the prohibition on blue/indigo/violet-on-white, shadows, blur, glass, gradients, pill buttons, decorative icons, and gamified feedback.
- Readable text and controls stay whole at 375px, 768px, and 1280px.
Assumptions (narrow, labeled)
- A1 — The user's list is application-owned state on the page, not bound to a verified person, because the Planning Scope sets the Todo surface's access requirement to
none and no accepted requirement asks for identity. [Assumption]
- A2 — Task ordering is the order in which tasks were added, since no accepted requirement specifies sorting, reordering, or prioritization.
[Assumption]
- A3 — The remaining count counts incomplete tasks, matching the direction's description of it as the "remaining-task count."
[Assumption]
- A4 — The
clear completed link is inert or absent when no tasks are complete, since there is nothing for it to act on. [Assumption]
- A5 — Empty or whitespace-only input is rejected rather than creating a blank task row, since a blank row would make the list untrustworthy.
[Assumption]
- A6 — The
× delete control is reachable by keyboard as well as pointer, because the direction specifies it appears on hover or keyboard focus. [Assumption]
Explicit exclusions (not part of this product)
- No accounts, sign-in, profiles, or identity of any kind.
- No sharing, collaboration, assignment, or multi-user state.
- No due dates, priorities, tags, projects, or sub-tasks.
- No notifications or reminders.
- No recurring tasks.
- No search, filter, or sort controls.
- No progress rings, streaks, confetti, or gamified completion feedback.
- No additional pages, routes, or navigation.
Future requirements
None. No accepted requirement in the authoritative thread establishes a future horizon or a deferred capability.
Page 20 of 20
12. Glossary
- hardy-todo — The project name for this simple single-page todo application.
- Todo — The single page of the application, and the entire product surface. It is the public entry surface and requires no identity.
- Todo User — The single active human role: one person using the app privately to capture, review, complete, and remove their own tasks.
- Task — The unit of work the user captures. Carries its text and its completion state.
- Task list — The ordered collection of all current tasks, complete and incomplete, rendered as full-width rows.
- Remaining count — The derived number of tasks that are not complete, shown in tabular figures in the masthead.
- Masthead — The single line at the top of the page holding the wordmark and the remaining count on one shared baseline, with a hairline rule beneath.
- Completion gesture — The 1px accent strike line drawn left-to-right across a task's text, followed by the text desaturating to muted.
- Clear completed — The single footer text link that removes every completed task at once.
- Hairline — A 1px rule in
#D8D3C7, used to separate the input row from the list and to close the card.
- Paper ground — The unbleached background tone
#F4F1EA on which the brighter sheet surface #FBFAF6 sits.
- Reduced motion — The
prefers-reduced-motion system preference, under which all animation becomes an instant state change.
No comments yet. Be the first!