Chapter 47 — Capstone Planning: MyDay Dashboard
Section 1
MyDay Dashboard is a small personal dashboard for tasks and notes, built with only HTML, CSS and JavaScript, with no framework and no server. It brings together everything you have learned so far into one useful page that a person can open every day, add a task, write a note, and see at a glance how the day is going. The dashboard has three panels: a tasks panel, a notes panel, and an overview panel that counts tasks and shows progress. Those three panels are the whole project, and keeping them in view at the same time is what makes the dashboard feel calm and practical rather than scattered across many screens. A good capstone plan starts by naming the job in one sentence, because a project without a clear job tends to grow until it cannot be finished. MyDay Dashboard helps one person keep tasks and notes in one place, find them again quickly, and see progress without any extra effort. Every feature in this chapter must serve that job, and every feature that does not serve it should be left out, however interesting it might seem on its own. That discipline is not about limiting ambition; it is about finishing something real, testing it properly, and being able to explain it clearly to someone else. Planning also means deciding what the project will not do, and writing those limits down before any code is written. MyDay Dashboard will not use a framework, will not need a server, will not ask anyone to create an account, and will not share data between devices or browsers. Its data lives only in the browser where it was entered, which is honest, simple, and easy to test, and it is the reason the footer in the finished project says so plainly. When a limit is stated early, later decisions become easier, because any suggestion can be checked against the limit in seconds. This chapter is the plan for the next three chapters, and it previews them in the order you will build them. Chapter 48 covers structure and style: the HTML for the three panels and the CSS that makes them readable, calm, and responsive. Chapter 49 covers behaviour and data: the JavaScript that adds, changes, filters, searches, saves, and counts tasks and notes. Chapter 50 covers finishing, portfolio presentation, and next steps: testing the whole flow, writing a short readme and case study, and choosing what to learn after this project. Nothing in this plan goes beyond what those chapters deliver, so you can trust it as a map. Before you build, read this chapter with a pen in hand and mark every decision you agree with and every decision you would question. A plan you have merely skimmed will not guide you when building gets difficult, but a plan you have argued with, even briefly, becomes a tool you can return to. Keep your written plan beside you through chapters 48, 49 and 50, and check the finished dashboard against it at the end, panel by panel and feature by feature.
Check: In one sentence, what job does MyDay Dashboard do for its user?
Section 2
MyDay Dashboard is for one person at a time, and that person is its only user, its only editor, and its only audience for the data it holds. Picture someone starting the day with a short list of things to do, a few reminders they do not want to lose, and a wish to see progress by evening. That person does not need a team tool, a shared workspace, or a complicated setup process; they need a page that opens quickly, accepts a task in seconds, and remembers what was entered after the page is closed and reopened. Designing for that single person keeps every decision simple, because there is no need to handle permissions, sharing, or conflicting edits from other people. The same person may use the dashboard in very different moments, and the plan must serve all of them. In the morning, they may add several tasks quickly and want the form to stay out of the way, with focus returning so the next task can be typed at once. During the day, they may glance at the overview to see how many tasks are done and how many remain, without reading every item again. In the evening, they may search for a note they wrote earlier, pin the note they need most, and clear tasks that are already finished. A dashboard that only works well for one of those moments, and frustrates the others, has not understood its user. A second audience matters too, even though they will never type a task into the dashboard: the person who reviews the finished project. That reviewer might be a teacher, a future employer, or a fellow learner, and they will judge the project in a few minutes by opening it, trying a task, and reading a short description. For that reviewer, the dashboard must explain itself at once: a clear title, a short purpose line, panels with plain headings, and generic demo data that shows the features without exposing anyone's private thoughts. Private tasks and notes must never appear in screenshots or in a shared demo, because a portfolio piece should show skill, not personal information. A third audience is you, later in the build, when you return to code you wrote days earlier and need to understand it quickly. Clear file names, honest class names, small functions with plain names, and short comments that explain why a decision was made all serve that future version of you. Planning for that reader now, by keeping the structure simple and the naming consistent, saves far more time than it costs, and it is a habit that carries into every project after this one. Finally, the dashboard should work for someone using a small phone screen, a keyboard without a mouse, or a screen reader, because accessibility is not a separate audience but a quality of the whole design. Large enough tap targets, visible labels, real buttons, and a clear heading order help everyone, not only people who rely on assistive technology. When you plan each panel in the sections that follow, keep asking whether a hurried person on a phone, a keyboard-only user, and a first-time visitor could all use it without help.
Check: Who are the three audiences your plan must serve, and what does each one need most?
Section 3
The problem MyDay Dashboard solves is ordinary, which is exactly why it is worth solving well: tasks and notes tend to scatter across many places, and scattered information is easy to lose track of. A task written on paper may be left at home, a note typed into one app may be forgotten in another, and a mental list may simply fade by afternoon. When tasks live in several places, a person cannot see at a glance what remains, what is already done, or which note holds the detail they need. The result is not laziness or poor organisation; it is the predictable cost of having no single, trusted place to look. MyDay Dashboard answers that problem by putting tasks and notes side by side on one page, with a small overview that summarises the whole picture. A task can be added with text and a priority, marked done when it is finished, and removed when it is no longer needed. A note can be added with a title and a body, pinned to the top when it matters most, edited when it changes, and deleted when it is spent. A search box can find a task or a note by its words, and filters can show all tasks, only active tasks, or only done tasks, so the list shown always matches the question the user is asking at that moment. The overview panel is the part that turns a list into a dashboard, because it answers questions the lists alone cannot answer quickly. How many tasks are there in total, how many are done, and how many are still active? What share of the work is complete, shown as a simple progress bar and a percentage? How many tasks sit at each priority level, shown as a small bar display? Those counts are calculated from the same data as the lists, never typed by hand, so they cannot drift out of date when a task is added, completed, or deleted. A user who trusts the counts can trust the dashboard. It is equally important to be honest about what the dashboard does not solve, because that honesty shapes every design choice. It does not sync data between devices, it does not send reminders, and it does not store data anywhere except the browser on the device where it was entered. If a person opens the dashboard in a different browser, their tasks and notes will not be there, and the project must say so plainly rather than letting them discover it with surprise. That limit is acceptable for a personal capstone, and naming it early prevents the project from promising what a front-end-only page cannot deliver. Framing the problem this way gives you a test for every later feature: does this feature make it easier to capture, find, complete, or review a task or a note? A feature that passes that test belongs in the plan, and a feature that fails it, however clever, should be left out or saved for a later project. Use that test whenever a tempting addition appears during chapters 48, 49 and 50, and the dashboard will stay focused, finishable, and genuinely useful.
Check: What scattered-information problem does MyDay Dashboard solve, and what does it deliberately not solve?
Section 4
Success for MyDay Dashboard is not a vague feeling that the page looks pleasant; it is a set of behaviours a reviewer can test in a few minutes, without being told how the code works inside. A successful dashboard loads as a single page, shows its title and purpose at once, and presents the tasks panel, the notes panel, and the overview panel in a layout that reads clearly on a phone and on a wider screen. A visitor can add a task, see it appear in the list with its priority shown, add a note, see it appear with its title and body, and reload the page to find both items still there. Those basic behaviours, working reliably, are the core of success. A second measure of success is that changing data updates every panel that depends on it, without any manual refresh or second step. When a task is marked done, it should move between filtered views as expected, the overview counts should change, the progress bar should move, and the bar display by priority should still reflect the full list correctly. When a note is pinned, it should rise to the top of the notes list, and when a note is edited, the updated title and body should be the ones shown and saved. When a task or note is deleted, the list, the counts, and the empty state, if the list is now empty, should all agree at once. A dashboard whose panels disagree with each other cannot be trusted, even if each panel looks fine on its own. A fourth measure is quality across devices and input methods, because a dashboard is used repeatedly and often in a hurry. Panels should stack on a narrow screen, buttons should be large enough to tap comfortably, text should remain readable without zooming, and every action should be reachable with a keyboard alone, using Tab, Enter, and Space. Headings should be in order, labels should be visible and connected to their inputs, and counts that change should be announced politely for screen reader users. An empty list should show a helpful message, such as No tasks yet, with a hint about what to do next, rather than a blank space that looks broken. Finally, success includes finishing and presenting the work, which chapter 50 covers in detail. The three files should be clean, with no leftover debug output and no dead code, and a short readme should explain what the project is and how to run it by opening the main file in a browser. A portfolio entry and a short case study should describe the problem, the approach, the result, and what you would improve next, honestly and without invented figures. A project that works locally but is never tested end to end, cleaned up, or explained to a reviewer has not fully succeeded, and this plan states those measures now so they are not forgotten at the end.
Check: List three observable tests a reviewer could run to judge whether MyDay Dashboard succeeds.
Section 5
MyDay Dashboard has three panels, and understanding each panel's job before you build any of them prevents the common mistake of letting one panel try to do everything. The tasks panel is where work is captured and tracked: it holds the add-task form, the filter bar, the search box, and the list of tasks themselves. Its job is to make adding a task quick, marking it done satisfying, and finding a particular task easy, even when the list grows to a dozen or more items. Everything in the tasks panel serves that job, and nothing in it should distract from it, such as a long explanation or an extra control that is rarely used. The notes panel is where short thoughts, reminders, and reference details are kept, and its job is different from the tasks panel in an important way. Notes are not marked done or filtered by completion; they are kept, pinned, edited, and deleted, and they are shown with pinned notes first so the most important note is always easy to find. A note has a title and a body, which is enough structure to make it searchable and scannable, but not so much structure that writing a note feels like filling in a form. Keeping notes simple is a deliberate choice, because a note that takes too long to write will not be written at all, and the dashboard will lose one of its main uses. Together, the three panels form a complete working loop that a user can repeat every day. Add a task in the tasks panel, write a supporting note in the notes panel, check the overview to see progress, filter or search to focus on what remains, complete tasks one by one, and watch the overview move toward full completion. That loop is the product, and it is small enough to build well in three chapters, yet rich enough to practise structure, style, behaviour, data, testing, and presentation. When you are tempted to add a fourth panel, ask whether it strengthens that loop or merely adds surface area that must be built, styled, tested, and maintained. The order of the panels on the page matters too, and chapter 48 settles it as tasks, notes, and overview, with headings in that order, so a visitor can understand the whole page from its headings alone. On a wide screen, tasks and notes can sit side by side with the overview spanning the full width, while on a narrow screen the panels stack in the same order, so the reading order never changes between devices. Planning that order now means the HTML, the CSS layout, and the screen reader experience all tell the same story, which is what makes a simple page feel carefully designed rather than merely assembled.
Check: What is the single job of each of the three panels, and why does the overview panel have no inputs?
Section 6
MyDay Dashboard is a single page, and that choice shapes almost every other decision in this plan, so it deserves a clear explanation before any code is written. A single page means all of the work happens in one view: tasks, notes, and the overview are visible together, without navigation, routing, or duplicated headers to maintain. A user never has to remember which screen holds a note, because the note is on the same page as the task it supports, and a reviewer never has to click through several screens to understand what the project does. For a first capstone, that simplicity is a strength, not a limitation, because it lets you spend your effort on making one page excellent instead of spreading it thinly across many. A single page also keeps the technical scope honest and achievable with only HTML, CSS and JavaScript. There is no framework to learn, no build step to configure, and no server to run, which means the project can be opened by double-clicking its main file in a browser, or by copying three files to a static host for a public link. That low barrier matters for testing too: every change can be checked by reloading one page, and every bug can be traced to one of three files without wondering whether a routing layer or a build tool introduced it. When something breaks, the search area is small, and the fix is usually close to the symptom. A single page does not mean a long, shapeless page, and the plan guards against that risk with labelled sections, a clear heading order, and a layout that groups related controls together. The header holds the title, a short purpose line, and the current date as text, the main area holds the three panels, and the footer holds a short status line and a note about where data is stored. Each panel has its own container, so styling and behaviour can target one panel without disturbing the others, and each list has a planned empty message for when it holds no items. Structure first, style second, behaviour third is the build order, and this chapter keeps that order visible throughout. Finally, a single page makes the finish line clear, which is important for motivation as well as for quality. The project is done when one page lets a user add, complete, delete, filter, search, pin, edit, and reload tasks and notes, with counts and progress that always match the lists. There is no second page waiting to be built, no hidden screen that could quietly remain unfinished, and no navigation state to test separately. That clarity is why this plan insists on one page, and why chapters 48, 49 and 50 can each be checked against a single, visible result.
Check: Why is a single page the right scope for this capstone, and what does it make easier to test?
Section 7
The project folder holds exactly three files, and planning that folder before you write any code prevents a surprising amount of confusion later. The folder can have any sensible name that describes the project, and inside it sit index.html, styles.css, and app.js, side by side, with no subfolders and no extra files to track. That flat layout means every link between files is a short relative path in the same folder, so opening the page locally and copying the folder to a static host both work without adjusting paths. A beginner who can find every file in one glance can also reason about the whole project in one glance, which is a real advantage when debugging. Each file's job should be stated in one sentence and then respected throughout the build. Index.html holds the structure: the header, the three panels, the forms, the filter bar, the search box, the lists, the overview counts, the progress bar, and the footer. Styles.css holds the presentation: colours, type, spacing, layout, cards, buttons, badges, bars, focus styles, and responsive rules, organised in a clear order from general to specific. App.js holds the behaviour and the data: the state, the storage, the rendering, the event handlers, and the startup sequence that loads saved data and draws the page for the first time. If a change belongs in more than one file, pause and ask which file owns the decision, because a change smeared across files is harder to test and harder to explain. Naming inside the files matters as much as naming the files themselves, and chapter 48 plans a simple rule: identifiers mark single elements that JavaScript must find, such as the task list and the task form, while class names describe reusable patterns, such as a card, a button, or a muted text style. A class should describe the job of the element, not only how it happens to look today, so a class that means a task item remains correct even if its colour changes later. Honest names reduce the need for comments, because the code already says what it means, and they make the stylesheet easier to audit, since a reviewer can see which patterns are reused and which are used only once. Finally, keep a working version saved after each step, and test the page after each change, including reloading to confirm that saved tasks and notes are still there. A three-file project invites the habit of changing one file, reloading, and checking the result before moving on, and that habit is worth more than any clever technique in this book. When a change breaks the page, undo the last change, re-read the code around it, and try a narrower fix, because a calm, step-by-step check usually finds the problem faster than rewriting a whole file. The folder plan is small, but the working habits it supports are the real capstone skill.
Check: What job does each of the three files own, and why must the script run after the markup exists?
Section 8
The header is the first thing a visitor sees, and its plan is deliberately short: a title, a short purpose line, and the current date shown as text. The title is MyDay Dashboard, which names the project in the same words the user will use to describe it, and the purpose line is a single calm sentence, such as tasks and notes in one calm place, which tells a first-time visitor what the page is for without requiring them to read further. The current date, shown as text, gives the page a sense of today, which suits a dashboard meant to be used daily, and it also helps a reviewer understand at a glance that the page is meant for the present day rather than for an archive. The header uses a real header element, so the top of the page is a landmark that assistive technology can recognise, not merely a styled division that happens to sit at the top. That choice costs nothing in effort and gains a great deal in clarity, because landmarks let keyboard and screen reader users jump to regions of the page without reading through everything in order. Inside the header, the title is the page's single level-one heading, which means the heading outline of the whole page starts here and then moves to level-two headings for the panels. A clean outline lets a visitor understand the entire page from its headings alone, which is a simple test you can run in any browser's accessibility tools. The date in the header deserves a brief note, because it is easy to overbuild. Chapter 48 shows it as text, not as an input and not as a control that changes what is displayed, which keeps the header honest about its role. The dashboard does not organise tasks by date in this project, and the header date should not imply that it does; it simply states today, as context for the tasks and notes below. If a future project adds date-based views, that project can earn a more complex header, but this capstone should not pretend to have features it does not build, and a plain text date is the right level of ambition. Finally, the header sets the visual tone for the rest of the page, and chapter 48 styles it with the same calm, light theme used throughout: dark text on a light background, a comfortable type scale, and generous spacing, with one restrained accent colour reserved for primary actions. A consistent header makes the panels below feel like parts of one product rather than three separate widgets placed on the same page, and it gives the portfolio screenshots a clear, professional first impression. Plan the header first, keep it short, and let it do the quiet work of orientation well.
Check: What three pieces of information does the header contain, and why is it kept short?
Section 9
Everything after the header belongs in one main element, divided into labelled sections for tasks, notes, and the overview, and that structure is the backbone of the whole page. The main element is a landmark, just as the header is, so assistive technology can jump straight to the main content without passing through the header again on every visit. Inside it, each panel is a section with its own level-two heading and a label that names it for everyone, including screen reader users, so the page can be understood by region as well as by visual layout. A visitor who cannot see the layout can still navigate by headings and landmarks, and that equivalence between visual and structural order is a mark of good front-end work. Each section needs its own container for a practical reason as well as an accessibility reason: styling and behaviour can target one panel without disturbing the others. The tasks section can hold its form, filter bar, search box, and list as separate parts inside it, the notes section can hold its form and list, and the overview section can hold its counts, progress bar, and bar display, each with a clear container. When a later change affects only one panel, such as restyling the filter bar, the developer can work inside that section with confidence, and when a bug appears in one panel, the search for its cause starts in a small, well-defined area. Good containers are therefore a debugging tool as well as a layout tool. The footer sits outside the main element, after it, and holds a short status line, such as how many tasks are shown, and a note that data is stored only in this browser. That placement matters, because the footer is supporting information, not main content, and separating it from the main area keeps the landmark structure clean. A footer status line is honest and useful: it tells the user where their data lives and what the page is currently showing, without requiring them to guess or to trust an unstated assumption. Chapter 48 plans the footer as a short, quiet area, not as a second dashboard, and that restraint keeps the page focused on its three panels. Finally, the main area is where the build order becomes visible, because chapter 48 starts with the header and the main sections as empty containers, then fills each panel in turn, checking the page after each step. That order lets you verify the structure before any style or behaviour is added, by viewing the page with styles switched off and confirming that the outline still makes sense. A page whose outline makes sense without styles is a page whose structure is doing its job, and every later layer, from CSS to JavaScript, builds on that solid foundation rather than compensating for a weak one.
Check: Why does the main area use one landmark divided into labelled sections, and why must source order stay stable?
Section 10
The tasks panel is the busiest panel in the dashboard, and its plan groups its parts so each part can be built, styled, and tested on its own. At the top sits a level-two heading, Tasks, which names the panel for sighted users and for assistive technology alike, and which anchors the section in the page outline. Below the heading sits the add-task form, then the filter bar, then the search box, then the list itself, each in its own container, so a change to one part, such as restyling the filters, does not ripple into the form or the list by accident. That grouping is the tasks panel's structure in miniature, and chapter 48 builds it in exactly that order. The filter bar sits below the form, with three buttons, All, Active, and Done, and the active filter is marked so the user can see the current choice at a glance. Filters are buttons, not links, because they change the view without leaving the page, and each button carries its filter value in a way JavaScript can read simply, such as a data attribute in the markup. That small markup decision, planned now, keeps the later JavaScript simple and the intent visible in the HTML, which is a good example of how structure choices made in chapter 48 make behaviour choices in chapter 49 easier. A filter bar that is clear in markup is also clear to a reviewer reading the HTML alone. The search box is a single text input with a visible label, placed above the lists it affects, and one search box serves both tasks and notes in this project, which keeps the interface simple and the behaviour easy to explain. A user who types a word sees matching tasks and matching notes, without having to remember which box belongs to which panel, and the overview counts continue to count all tasks, not only the visible ones, so searching never makes the summary misleading. That rule, that search filters what is shown but not what is counted, is worth stating now, because it is easy to get wrong later, and a dashboard whose counts change with every keystroke would confuse rather than inform. Finally, the task list itself is an unordered list, because it shows a collection of similar items, and each item, when rendered, will hold a checkbox-style button, the task text, a priority badge, and a delete button. The list starts empty in the markup, ready for JavaScript to fill it, and it has a planned empty message, such as No tasks yet, for when it holds no visible items. Planning the empty message as part of the structure, rather than discovering it when the first user sees a blank panel, is a small habit that makes the finished dashboard feel intentional from the very first run, even before any task has been added.
Check: What parts does the tasks panel contain, in order, and why does it use one search box for both lists?
Section 11
The notes panel is quieter than the tasks panel, and that quietness is intentional, because notes are meant to be captured quickly and found again without fuss. Its structure, planned in chapter 48, is a level-two heading, Notes, followed by an add-note form and a list for notes, with a pin control on each note once it is rendered. Notes are shorter than tasks in this project in the sense that they carry less behaviour: a title and a body, plus a pinned flag that controls their order, and no completion state, no priority, and no filter of their own. That restraint keeps the notes panel easy to explain, easy to style, and easy to use, and it prevents the dashboard from becoming two task managers wearing different labels. Each note in the list, when rendered, shows its title, its body, a pin button, an edit button, and a delete button, and the list is an unordered list, just as the task list is, because it too shows a collection of similar items. Sorting happens at render time, with pinned notes first, which keeps the stored order simple and puts the display rule in one place where it can be changed without rewriting the stored data. Pinning is therefore a display preference stored with the note, not a separate list, and unpinning a note simply returns it to its normal position among the unpinned notes. That design is worth naming now, because it explains why pinning feels instant and why it survives a reload: the flag is saved with the note, and the render rule does the rest. Editing a note reuses the same form that adds a note, which is another deliberate simplification that chapter 49 implements carefully. When the edit button is pressed, the form is filled with that note's title and body, the project remembers which note is being edited, and submitting the form updates that note instead of creating a new one. Reusing one form for add and edit keeps the interface small and the code focused, but it also creates a responsibility: the form must make clear, by its button label or a short heading change, whether it is adding or editing, so the user is never surprised by what a submit will do. Planning that clarity now prevents a confusing moment later, when a user edits a note and wonders whether they have just duplicated it. Finally, the notes panel has its own planned empty message, shown when no notes are visible, just as the tasks panel does, and its own behaviour for the last-note case: when the final note is deleted, the empty state appears as a normal render result, not as a special case handled by hand. That consistency, where empty states are simply what rendering produces when a list is empty, is a principle that runs through the whole project, and it is why chapter 49 centralises rendering instead of scattering display logic across many handlers. A notes panel that is simple, honest, and predictable will be used, and a notes panel that is clever but confusing will be ignored, which is the real test of this panel's plan.
Check: How does the notes panel differ from the tasks panel, and why does it reuse one form for adding and editing?
Section 12
The overview panel summarises the dashboard, and its plan is to show information, not to collect it, which is why it contains no inputs of its own. At the top sits a level-two heading, Overview, followed by three counts: total tasks, completed tasks, and active tasks, each clearly labelled so a visitor can read them without guessing what a number means. Below the counts sits a progress bar, with a text label giving the percentage, and below that a simple bar display of tasks by priority, with one row per priority level, each row showing a label, a bar, and a count. Those elements together answer the three questions a user asks most often: how much is there, how much is done, and where is the remaining work concentrated? Progress is a simple calculation from the same state, and planning its edge case now prevents a common bug later. Progress means completed tasks divided by total tasks, multiplied by one hundred and rounded, with zero tasks giving zero percent rather than a division error or a misleading full bar. A dashboard with no tasks yet has made no progress, but it has also not failed, and showing zero percent with an empty bar says that plainly, while showing one hundred percent would celebrate work that does not exist. Chapter 49 guards that empty case explicitly, and chapter 48 styles the bar as a track with a filled portion whose width represents the percentage, plus a text label, so the progress is readable even if colour alone is not perceived. The bar display by priority extends the same idea to a different question, and its plan is equally simple. The code counts tasks per priority, finds the largest count, and sizes each bar relative to that largest count, with the count itself shown as text beside the bar, so the display is never colour-only or width-only. The bars are built from plain divisions styled with widths set by JavaScript, which is data rather than design, and is therefore the one place where an inline width is acceptable, unlike general styling, which belongs in the stylesheet. That distinction, between a width that represents data and a style that represents design, is worth stating now, because it explains an exception that might otherwise look like an inconsistency. Finally, the overview panel's position and presentation matter for trust as well as for appearance. On a wide screen it spans the full width, so its counts and bars can be read at a glance without competing with the lists, and on a narrow screen it stacks with the other panels in the same source order, so its information remains easy to find. Its counts sit in a polite live region, planned in chapter 49, so screen reader users hear updated counts without the page interrupting them, and its text labels ensure that no information is conveyed by colour or bar length alone. An overview that is calculated, labelled, and reachable is not decoration; it is the part of the dashboard that lets a user trust the whole page.
Check: Why must overview counts always be calculated from the task list, and what should progress show when there are no tasks?
Section 13
The footer is a small area with a large job, because it tells the user, honestly and briefly, where their data lives and what the page is currently showing. Chapter 48 plans it as a short status line, such as how many tasks are shown, plus a note that data is stored only in this browser, placed after the main element so it is supporting information rather than main content. That note is not legal fine print to be hidden at the bottom; it is a promise about the project, and placing it in the footer, where it is always present but never in the way, is the right balance between visibility and restraint. A user who understands where their data lives can make sensible decisions about which browser to use and what to expect after switching devices. The footer also closes the page visually and structurally, which matters more than it might seem on a single-page dashboard. Without a footer, a page that ends abruptly after the last panel can feel unfinished, especially on a wide screen where the panels may not fill the height of the window. With a short footer, the page has a clear ending, the eye knows where the content stops, and the status note has a natural home that does not compete with the panels above it. That sense of completeness is part of why chapter 48 treats the footer as a planned region from the start, rather than as an afterthought added when the rest of the page is done. Accessibility and responsiveness apply to the footer just as they apply to the panels, even though the footer is small. Its text must remain readable at the same sizes and contrasts as the rest of the page, it must not require horizontal scrolling on a narrow screen, and it must not contain links or controls that are unreachable by keyboard. If the footer later gains a link, such as a link to a portfolio page in a deployed version, that link must be checked in the same way as every other link in chapter 50, because one broken or unreachable element in a quiet area still counts as a broken page. Small regions deserve the same care as large ones, because users notice inconsistency even when they cannot name it. Finally, the footer is a good place to practise the plan's overall principle: say what is true, in plain words, and say nothing more. It does not claim that data is backed up, synced, or shared, because none of those things are true for this project, and it does not apologise for those limits, because they are deliberate choices that keep the project simple and finishable. A footer that states its limits plainly builds more trust than a footer that promises more than the project can deliver, and that trust is what turns a learning exercise into a portfolio piece a reviewer can respect.
Check: What two pieces of information does the footer carry, and why must the status line differ from the overview counts?
Section 14
The add-task form is the dashboard's most-used control, and its plan keeps it to two fields, because two fields are enough to capture a task well and short enough to use many times a day without friction. The first field is the task text, a plain text input with a visible label, such as New task, connected to its input so clicking the label focuses the field. The second field is a priority choice, Low, Medium, or High, presented as a select control with Medium as the default, so a user who is in a hurry can type the task and submit without making a second decision, while a user who cares about priority can choose deliberately. A submit button labelled Add task completes the form, and its type is submit, so pressing Enter inside the text field submits the form in the browser's usual way, without extra code to mimic that behaviour. Validation for the add-task form is planned as a simple, forgiving rule, implemented in chapter 49: the text is trimmed, so accidental spaces at the start or end do not create a task that looks empty, and an empty result is rejected, with a short message near the form explaining what is missing, instead of silently doing nothing. The required attribute on the input supports that rule in the browser, but the JavaScript check remains the real guard, because it runs even when browser validation is bypassed and because it controls the message the user sees. Validation should preserve what the user typed, so a rejected submission does not force them to retype a long task, and it should explain the fix in plain words, such as asking for the task text, rather than showing a technical error code. After a task is added successfully, two small behaviours, planned in chapter 49, make repeated adding pleasant rather than tedious. First, the form is cleared, so the next task starts from a clean field, and second, focus returns to the first field of the form, so adding several tasks in a row needs no mouse movement between entries. Those details may seem minor, but they are the difference between a form that feels designed for real use and a form that feels designed only for a single demonstration. A dashboard is used repeatedly, so the cost of a small friction is paid many times, and the benefit of a small kindness is also paid many times, which is why this plan names focus and clearing explicitly rather than leaving them to chance. Finally, the add-task form must be tested as a user would use it, not only as a developer would test it, and chapter 50 includes that test in its end-to-end walk-through. Add a task with each priority, add a task by pressing Enter, try to submit an empty form and read the message, add several tasks quickly using only the keyboard, and reload the page to confirm the tasks survive. If any of those steps fails, the form is not finished, even if it looks correct in a screenshot, because a form's job is to accept input reliably, not merely to display input fields. That testing standard, stated here in the plan, is what turns a form sketch into a working control.
Check: What two fields does the add-task form contain, and what happens when it is submitted empty?
Section 15
The add-note form mirrors the add-task form in spirit but differs in its fields, because notes and tasks are different kinds of information and should not be forced into the same shape. It asks for a note title and a note body, both as plain text fields, each with a visible label, and a submit button that makes the action clear. The title is the short handle by which the note will be found again, in the list and in search results, while the body holds the detail, which may be a sentence, a paragraph, or a short list of reminders in plain text. Keeping both fields as plain text, rather than adding formatting controls, keeps notes easy to render, easy to edit, and easy to store, and it keeps the form short enough that writing a note never feels like a chore. Editing a note reuses this same form, and the plan must therefore answer a question that a separate edit screen would answer by its very existence: how does the user know whether submitting will add a new note or update an existing one? Chapter 49 answers it by filling the form with the note's title and body when its edit button is pressed, remembering which note is being edited, and changing the form's button or heading to reflect the editing state, so the action is visible before the user submits. After the edit is saved, the form returns to its adding state, cleared and ready for a new note, so the next submission cannot accidentally overwrite the note that was just edited. That return to a clean adding state is a small detail with a large effect on trust, and it is why the plan names it explicitly. Focus behaviour for notes follows the same principle as for tasks: after a note is added, focus returns to the first field, so several notes can be written in a row without reaching for the mouse, and after an edit is saved, focus returns to a sensible place in the panel, so a keyboard user is not left stranded. Those focus decisions are planned in chapter 49 alongside the task form's focus behaviour, because focus is part of behaviour, not an afterthought, and because a dashboard that loses focus after every action quickly becomes frustrating for keyboard users. Testing focus is therefore part of the chapter 50 keyboard test, not a separate accessibility extra. Finally, the add-note form, like the add-task form, must be judged by real use rather than by appearance, and the plan sets that test now. Add a note with a title and body, try to add one without a title and read the message, edit a note and confirm the list shows the updated text and the saved data matches after a reload, pin a note and confirm it rises to the top, and delete a note and confirm the empty state appears when the last note is gone. A form that passes those tests is a working part of the dashboard, and a form that only looks like a form in a screenshot is not yet finished, however polished its styling may be.
Check: What does the add-note form require, and how does the user know when it is editing rather than adding?
Section 16
Labels, button types, and accessible names are small details that prevent a whole class of confusing bugs, and this plan treats them as structure, not as polish to be added at the end. Every input in the dashboard has a visible label connected with a for attribute, which means the label's text is programmatically linked to its control, so clicking the label focuses the input and assistive technology announces the label when the control receives focus. That single rule covers the task text, the priority select, the note title, the note body, and the search box, and it removes an entire category of guesswork from the interface: no user, sighted or not, should have to infer what a field is for from its position alone or from placeholder text that disappears as soon as typing begins. Accessible names cover the third detail, for buttons that show only an icon or a short symbol, such as a pin or delete control, where the visible text alone does not explain the action. Each such button needs an accessible name, for example through an aria-label, that states its action in words, so a screen reader user hears Delete task or Pin note rather than an unexplained symbol. The visible label and the accessible name should agree, so a sighted user and a screen reader user receive the same information, and the name should include enough context, such as which action it performs, to be useful when heard out of visual context. Chapter 49 keeps those names correct when items are rendered dynamically, because a button created by JavaScript needs its accessible name just as much as a button written by hand in HTML. These three rules also make testing easier, which is a practical benefit that is easy to overlook when they are described only as accessibility requirements. A labelled input can be found by its label during manual testing, a correctly typed button can be reasoned about without running the page, and an accessible name can be checked in developer tools without a screen reader, by inspecting the element's computed accessibility properties. Chapter 50's keyboard and screen reader checks therefore build directly on the work planned here, rather than starting from scratch, and a dashboard that passes those checks has usually also passed the label and type checks, because the same underlying structure supports both. Finally, the plan warns against a common shortcut: using placeholder text as a substitute for a label, or using colour alone to convey a button's meaning. Placeholder text disappears, is often low contrast, and is not reliably announced as a label, while colour alone fails for users who cannot perceive it and for anyone viewing the page in greyscale or bright sunlight. Visible labels, correct button types, and real accessible names cost little to plan and a great deal to retrofit, which is why this section places them in the planning chapter, before chapter 48 writes a single line of markup, rather than in the finishing chapter, where they would arrive too late to shape the structure.
Check: What are the three labelling rules in this plan, and what bug does a correct button type prevent?
Section 17
Filters are how a user narrows the task list to the slice they need right now, and this plan gives them exactly three choices, All, Active, and Done, because three choices cover the useful questions without adding decisions that slow the user down. All shows everything, Active shows unfinished tasks, and Done shows completed ones, and the filter is based on a single done flag on each task, so the rule is easy to state, easy to implement, and easy to test. A user who wants to see what remains chooses Active, a user who wants to check what has been finished chooses Done, and a user who wants the whole picture chooses All, and no other filter is needed for a personal dashboard of this size. In markup, chapter 48 plans the filter bar as three buttons in a row, with the active filter marked so the user can see the current choice without having to remember it. Filters are buttons, not links, because they change the view without leaving the page, and the selected button should be distinguishable by more than colour alone, for example by a stronger background plus a text or border change, so the choice remains clear in greyscale or for users who cannot distinguish the colours used. The filter bar sits inside the tasks panel, close to the list it affects, so the relationship between control and result is obvious, and changing a filter re-renders the list at once, without a separate apply step that would add friction to a frequent action. Filtering must also interact correctly with the other parts of the dashboard, and the plan names those interactions now so chapter 49 does not have to guess. Completing a task while viewing Active should make that task disappear from the visible list at once, because it no longer matches the filter, while completing a task while viewing All should keep it visible with its completed styling, because it still matches. The overview counts, by contrast, should not change their meaning when the filter changes: they count all tasks, not only visible ones, so a user who filters to Done still sees the true totals in the overview. The footer status line, meanwhile, may report how many tasks are shown, which does change with the filter, and keeping those two numbers distinct is part of the plan's honesty about what each number means. Finally, filters must be tested in combination, not only in isolation, and chapter 50 includes that combination in its end-to-end walk-through. Add tasks, complete some of them, filter to Active and confirm only unfinished tasks appear, filter to Done and confirm only completed tasks appear, return to All and confirm everything appears again, then reload and confirm the dashboard opens on All with the full list intact. A filter that works alone but breaks when combined with search, or that disagrees with the overview counts, has not passed the plan's test, even if each individual filter button appears to work in a quick demonstration.
Check: What three filter choices does the dashboard offer, and why does it open on All after a reload?
Section 18
Search is the dashboard's fastest way to find a particular task or note, and this plan gives it one box that serves both lists, because one box is simpler to learn, simpler to style, and simpler to explain than two boxes that must be kept in sync. The search box is a single text input with a visible label, placed above the lists it affects, inside the tasks panel in the markup planned by chapter 48, but its effect reaches the notes panel as well, so a word typed once finds matching tasks and matching notes together. A user who remembers a word from a note does not have to decide in advance whether that word belongs to a task or a note; they type it once and see both kinds of match, which matches how memory actually works. Combining filter and search is one of the plan's key behaviours, and it deserves a precise statement now, because it is easy to implement incorrectly. Visible tasks are those that pass the filter and match the search query, applied in that order to the same array, so searching inside the Active view shows only active tasks that match, and searching inside the Done view shows only done tasks that match. Notes are filtered by search alone, since they have no completion filter, so a search term narrows both lists at once while the filter narrows only the tasks. The overview still counts all tasks, not only visible ones, as planned earlier, so a search never makes the summary misleading, and the footer status can report how many items are shown, which does change with search. Those distinctions, stated plainly here, are what make the combined behaviour feel predictable rather than magical. Performance for search is also planned, and the decision is refreshingly simple: typing in the search box re-renders immediately, with no debounce delay, because the dashboard holds a small personal list, not thousands of items, and rebuilding such a list on each keystroke is fast enough to feel instant. Chapter 49 explains that no debounce is needed here, and it warns against adding one by habit, because a delay would make the interface feel sluggish without buying any real performance benefit at this scale. That judgement, choosing the simplest approach that meets the actual need, is a useful habit to practise, because many real projects are slowed by optimisations added before any slowness was measured. Finally, search must handle its empty and no-match cases gracefully, as part of rendering rather than as an afterthought. When the query is empty, all items allowed by the filter are shown, as if no search were active, and when a query matches nothing, each affected list shows its empty message, so the user sees a clear result rather than a blank panel that might look broken. Chapter 50 tests search by adding items, searching for a word that matches some of them, searching for a word that matches none, clearing the search, and confirming the full lists return, all without reloading. A search that passes those steps is a tool the user can trust, and a search that only works for one lucky word is not yet finished.
Check: How does one search box find both tasks and notes, and how does it combine with the Active filter?
Section 19
Priority is how a user says which tasks matter most, and this plan treats it as a simple, visible property of each task, not as a complex scheduling system. When a task is added, its priority is chosen as Low, Medium, or High, with Medium as the default, and that choice is shown as a small badge on the task item, reading Low, Medium, or High in words, with a distinct but muted colour for each level. The badge text carries the meaning, so the information survives greyscale printing, colour vision differences, and any future theme change, while the colour merely reinforces it for users who perceive it easily. A priority system that relied on colour alone would fail the plan's own accessibility standard, and a system that hid priority in a tooltip would fail its usability standard, so the badge is both textual and coloured by design. The bar display in the overview panel uses the same priority data in a different way, and planning both uses together prevents them from disagreeing. The bar display counts tasks per priority, finds the largest count, and sizes each bar relative to that largest count, with the count itself shown as text beside the bar, so a user can see at a glance whether most remaining work is High, Medium, or Low priority. Chapter 49 also counts tasks by priority as a helper that feeds both the overview and the bar display, so the two presentations share one calculation rather than duplicating it in two places that could drift apart. A single helper for priority counts is an example of the small, pure helper functions that chapter 49 favours: functions that take data in and return a result, without touching the document, which makes them easy to test in the console. Priority must also interact sensibly with filtering, searching, and completion, and the plan states those interactions now. Filtering to Active shows active tasks in priority order, filtering to Done shows completed tasks in the same order, and searching narrows the list without changing the priority order of the items that remain, so a user can always predict where a task will appear. Completing a High task does not remove its priority, it simply moves it between filtered views and updates the counts and progress, while the bar display continues to count it by priority, because the bar display reports all tasks, not only active ones. Those rules may sound detailed, but they are exactly the kind of detail that prevents a dashboard from feeling unpredictable after a few days of real use. Finally, priority should be presented honestly in the portfolio, as a simple choice that helps a user focus, not as an intelligent scheduling feature, because the dashboard does not reschedule, remind, or reprioritise anything on its own. Chapter 50's case study describes priority in those plain terms, and the readme lists it alongside filtering and searching as a way to organise a personal list, without claiming more than it does. A feature described accurately is more impressive to a reviewer than a simple feature dressed up as something grand, and accuracy is also kinder to the next developer, who will not have to unlearn an exaggerated description before they can maintain the code.
Check: In what order are tasks displayed by priority, and why is sorting done at display time rather than in storage?
Section 20
Empty states are the messages a dashboard shows when a list has nothing to display, and this plan treats them as part of the design, not as accidents to be apologised for afterwards. Each list has a planned empty message, such as No tasks yet for the tasks panel and a similar message for the notes panel, shown when its list is empty, and the message should tell the user what to do next, such as adding a first task or a first note, rather than merely stating that nothing is there. An empty state is a normal state for a personal dashboard, especially on first use, and a dashboard that treats it as an error, with a blank panel or a technical message, will make a new user feel as though they have already done something wrong. Styling for empty states is planned in chapter 48 as muted text, generous padding, and a short instruction, so an empty panel looks intentional rather than broken, and so it does not compete visually with panels that hold real content. Muted text signals that the message is guidance rather than content, generous padding gives the panel a finished shape even when it holds only a sentence, and a short instruction gives the user a next step without requiring them to hunt for a form or button. An empty panel that looks designed reassures the user that the dashboard is working correctly, while an empty panel that looks like a missing piece makes them doubt the whole page, even if every other panel is working perfectly. Empty states also interact with actions that remove the last item, and the plan names that case explicitly because it is easy to miss in testing. When the last task is deleted, or when completed tasks are cleared and none remain, the tasks panel should immediately show its empty message, confirming that the deletion worked, rather than leaving a stale list on screen. When the last note is deleted, the notes panel should do the same, and when a search matches nothing, both affected lists should show their empty messages, so the user understands that the search, not a bug, produced the empty result. Chapter 50 tests those transitions deliberately, because a dashboard that only shows empty states correctly on first load, but not after deletions, has only half-implemented the feature. Finally, empty states are a useful portfolio detail, because they show a reviewer that the developer thought about the whole lifecycle of the product, not only its fullest, most attractive state. Screenshots in chapter 50 should therefore include a panel with real content, not only empty panels, but the case study can mention empty states as an example of careful design, and the readme can note that the dashboard handles empty lists gracefully. A reviewer who sees that a developer planned for emptiness, for no matches, and for the last-item deletion will reasonably trust that the same developer planned for other edge cases too, which is exactly the impression a capstone should leave.
Check: Why should an empty list show a designed message, and how should that message change when a search matches nothing?
Section 21
Headings, landmarks, and accessible names form the structural layer that makes the dashboard usable for everyone, and this plan places them in chapter 48's structure work, not in chapter 50's finishing work, because structure cannot be retrofitted without rewriting markup. The page has one level-one heading, the dashboard title in the header, and level-two headings for Tasks, Notes, and Overview, in that order, so the outline of the page reads as a short table of contents. A visitor who lists the headings should be able to understand the whole page without reading any other text, and a visitor who jumps by heading should land in the panel they expected, not in a decorative heading that was chosen for its size rather than its meaning. Heading levels must therefore follow meaning, not appearance, and visual size must be set by CSS, not by choosing a larger heading level for a bigger look. Accessible names for controls complete the layer, covering every input and every button, including buttons that show only an icon or a short symbol. Each input has a visible label, each filter button has text that states its choice, and each list button has an accessible name that states its action, such as completing, deleting, pinning, or editing the item it belongs to. When JavaScript creates list items dynamically in chapter 49, it must create those accessible names at the same time, because a button without a name is invisible in a meaningful sense to a screen reader user, even if it is perfectly visible on screen. Testing accessible names in developer tools, by inspecting an element's computed properties, is a skill chapter 50 includes in its basic screen reader checks, and it is a check that can be done without specialist software. The plan also sets a rule for how structure should be verified before style or behaviour is added: view the page with styles switched off and confirm that the outline still makes sense, that the headings are in order, that the forms are labelled, and that the lists are real lists rather than rows of divisions. A page that makes sense without styles has a structure that assistive technology and search tools can work from, while a page that only makes sense with styles is relying on appearance to carry meaning, which is fragile. Chapter 48 encourages that check early, after the markup is written and before the stylesheet is polished, because fixing structure at that stage is cheap, while fixing it after behaviour depends on it is expensive and error-prone. Finally, structure is also a maintenance promise to the next developer, who may be you in a few weeks, returning to add a feature or fix a bug. Clear landmarks, a clean heading outline, and honest class and identifier names make it possible to find the right place to change without reading every file from start to finish, and they make it possible to explain the page to a reviewer in a minute, by walking through its regions in order. A dashboard whose structure is clear is a dashboard that can grow, even if this particular capstone deliberately stays small, and that clarity is why this plan spends a full section on headings and landmarks before any discussion of colours or layout.
Check: What heading order does the dashboard use, and why must headings follow meaning rather than visual size?
Section 22
The visual direction for MyDay Dashboard is calm, light, and restrained, and chapter 48 plans it as a system rather than as a collection of one-off choices, because a system is easier to keep consistent and easier to explain. The theme uses a light page background, white cards, dark text, and one restrained accent colour for primary actions, with the accent used sparingly so that the primary add buttons stand out without the page feeling loud. A dashboard is used repeatedly, often in the morning when the user is planning and in the evening when they are tired, so calm, readable panels matter more than a striking first impression that tires the eye after a few days. That judgement, favouring sustained readability over novelty, is the visual direction in one sentence. Typography follows a small scale, with the page title largest, panel headings smaller, and body text at a comfortable reading size, with a comfortable line height that lets dense lists breathe. A scale, rather than a set of unrelated sizes chosen panel by panel, makes the page feel designed, because the eye learns the hierarchy after seeing it once and can then scan new content quickly. Headings should be bold enough to stand out from body text without shouting, and the priority badges, counts, and progress labels should use sizes that fit their role as supporting information, not as headlines competing with the panel titles. Chapter 48 keeps the scale small, with only a few steps, because a dashboard has only a few levels of importance to express, and extra steps would add noise rather than clarity. Spacing follows a scale as well, using a few repeated values, such as 8, 16, and 24 pixels, for gaps, padding, and margins throughout the dashboard, so panels, cards, and form controls share the same rhythm. A spacing scale is what makes a page feel orderly even when its content varies, because the eye senses regular intervals even if it cannot name them, and it makes auditing possible: chapter 48 ends its style work with a spacing audit, opening every panel and checking that gaps, padding, and alignment match the scale, fixing outliers one by one. Without a scale, spacing tends to drift as each panel is styled separately, and the result is a page that feels slightly off in ways that are hard to diagnose, because no single panel looks wrong on its own. Finally, the plan insists that styles live in the stylesheet, not in inline style attributes on elements, with the single exception of widths set by JavaScript on bars, which represent data rather than design. That rule keeps design decisions in one place, makes the stylesheet the single source of truth for appearance, and makes it possible to change the theme by editing variables rather than editing markup. Short comments in the stylesheet record decisions, such as why the accent is used only for primary actions, so a later reader understands the system rather than merely seeing its rules. A calm theme, a small type scale, a repeated spacing scale, and a single stylesheet are not glamorous choices, but together they are what make a simple dashboard look professional.
Check: What is the dashboard's visual direction, and why are colours, type, and spacing planned as scales?
Section 23
Layout for MyDay Dashboard starts with a centred column, because a centred column keeps lines readable on wide screens and prevents panels from stretching into long, tiring rows. The page content sits in a column with a maximum width, centred on the page, so on a very wide monitor the dashboard remains a comfortable reading width, with calm space on either side, rather than spreading its panels to the edges and forcing the eye to travel across the whole screen for each glance. That maximum width is a readability decision as much as a visual one, and it is planned in chapter 48 before any panel layout is discussed, because it constrains every layout choice that follows in a helpful way. Cards are the basic unit of the layout inside the panels, and chapter 48 plans each task and note as a card: a white surface with padding, rounded corners, and a light border, grouped so related controls are visually together. Cards group a task's text, badge, and buttons into one recognisable unit, and a note's title, body, and buttons into another, so scanning a list means scanning cards, not scanning a flat wall of text and buttons. The card rule is reused for every panel, so changing its padding or radius changes every panel at once, which keeps the dashboard visually consistent and makes a single change easy to verify. A card that is used everywhere is also a card that can be audited everywhere, by checking one rule rather than many. Buttons and form controls follow the same reuse principle, sharing padding, radius, and font, with the primary add button using the accent colour and secondary buttons using a neutral style, so the most important action in each panel is visually distinct without shouting. Text inputs and selects share padding, borders, and font size, so a form feels like one coherent control set rather than a collection of unrelated fields, and filter buttons sit in a row with a small gap, with the selected filter using the accent background while the others stay neutral. Those shared rules are what make the dashboard feel designed rather than assembled, because the eye learns one button style and one form style and then recognises them instantly in every panel. Finally, layout must be checked with developer tools, not merely by eye, and chapter 48 plans that check as part of the style work. When a panel looks wrong, inspecting the element shows its box model and which rule set a size or colour, which is faster and more reliable than guessing at values in the stylesheet, and it reveals the common layout bugs, such as a fixed width that is too large or a long unbroken word that forces overflow. Fixing overflow usually means removing a fixed width, allowing text to wrap, or adjusting a grid track, rather than adding a workaround that hides the symptom, and the plan states that principle now so it is available when the first overflow appears. A layout that is centred, grid-based, card-based, and checked with tools is a layout that can be trusted on screens of many sizes.
Check: How does the layout change between narrow and wide screens, and why does the page use a centred column?
Section 24
Styling the dashboard's details, the badges, the progress bar, the bar display, and the empty states, is where the plan's visual system meets its data, and each detail has a rule that keeps it readable and honest. Priority badges are small, with text reading Low, Medium, or High, and a distinct but muted colour for each level, so the badge is informative without dominating the task item it belongs to. The badge text carries the meaning, as planned earlier, while the colour reinforces it, and the badge's size is small enough to sit beside the task text without pushing the delete or complete buttons out of comfortable reach. The simple bar display, which shows tasks by priority, is built from plain divisions styled with widths, with one row per priority, each row showing a label, a bar, and a count. That construction is deliberately plain, using the same card and spacing language as the rest of the page, so the bar display feels like part of the overview rather than like a chart imported from elsewhere. The bars are sized relative to the largest priority count, as planned in the overview section, so the longest bar always represents the largest group, and the counts are shown as text, so the display can be understood without judging lengths by eye. A bar display that required precise length judgement would be a poor summary, while one that pairs each bar with its count is a summary that can be read quickly and checked easily. Empty states, filter buttons, and focus styles complete the detail styling, and each follows the same calm, consistent language. Empty states use muted text, generous padding, and a short instruction, so an empty panel looks intentional rather than broken, while filter buttons use a small gap and a clear selected state, so the current filter is obvious without being loud. Every focusable element gets a visible outline or ring when focused by keyboard, using the focus-visible approach so mouse users are not distracted by outlines on click, while keyboard users always see where they are. Hover states change buttons and list items subtly, and active states press buttons slightly, giving immediate feedback for every click without resorting to dramatic animations that would distract from the dashboard's daily use. Finally, the stylesheet is organised in a clear order, variables, base, layout, panels, forms, buttons, badges, bars, and responsive rules, with short comments marking each part, so a reviewer can find any rule quickly and a developer can add a rule in the right place without guessing. Reusable utility classes, such as a muted text style and a small gap helper, are kept few and used only where the same small job recurs, because too many utilities would fragment the system they were meant to simplify. Avoiding inline styles, except for data-driven bar widths, keeps that organisation honest, and a final spacing audit, checking every panel against the scale, closes the style work with a concrete verification rather than a vague impression that the page looks fine.
Check: How are priority badges, the progress bar, and the bar display each made readable without relying on colour or length alone?
Section 25
Responsive design for MyDay Dashboard is planned small-screens-first, which means the base styles describe the narrow-screen layout, and wider-screen rules are added only where they genuinely improve the experience. On a phone-width screen, the panels stack vertically, forms use full-width inputs, and buttons are large enough to tap comfortably, so the dashboard works well in the context where it is most likely to be glanced at quickly, perhaps while standing or walking. That base layout is not a degraded version of the desktop layout; it is the primary layout, and it must be complete, readable, and fully functional on its own, because a user who only ever visits on a phone should never feel as though they are using a lesser product. Responsive design also affects the details inside panels, not only the panel arrangement, and chapter 48 plans those details alongside the grid. Form controls that are full width on a narrow screen may sit more compactly on a wider screen, but they must never shrink below a comfortable tap size, and filter buttons that sit in a row on a wide screen must wrap or remain tappable on a narrow screen without forcing horizontal scrolling. Long task text and long note bodies must wrap within their cards, and a long unbroken word, such as a pasted web address in a note, must not force its card wider than the screen, which is the overflow case chapter 48 teaches how to fix. Checking the page at a narrow width early, not at the end, is the habit that catches those details while they are still cheap to fix, and the plan insists on that habit from the first layout draft. Testing responsive design is also planned, rather than left to a final glance, and chapter 50 includes a phone-sized screen test that uses browser device emulation and, if possible, a real phone, to confirm that panels stack, buttons are tappable, and text does not overflow. That test should be run with real tasks and notes in the lists, not with empty panels, because empty panels hide overflow and spacing problems that only appear when content is present. It should also be run after filtering and searching, because a filtered list that looks fine when full may behave differently when it shows only one item, and a search box that works on a wide screen may be cramped on a narrow one if its label and input are not planned together. Finally, responsive design in this plan is not about making the dashboard look identical on every screen, but about making it work equally well on every screen, with the same content, the same actions, and the same information, arranged to suit the space available. A dashboard that hides features on a phone, or that requires a desktop to complete a task, has not been designed responsively, even if its desktop layout is beautiful, because it has divided its users by device. A dashboard that stacks on a phone, sits side by side on a wider screen, and keeps every action reachable on both, has met the plan's standard, and that standard is what chapters 48 and 50 will test, in that order.
Check: What does small-screens-first mean for this dashboard, and what must the phone-sized test check with real content?
Section 26
A task in MyDay Dashboard is a small, well-defined piece of data, and planning its shape before writing any JavaScript prevents a surprising number of later bugs. Each task is an object with a few fields, each with a clear job, and every part of the project that displays or counts tasks reads from objects with those fields, so the dashboard remains consistent. The created timestamp is the field most likely to be questioned, because a personal dashboard could work without showing dates at all, but chapter 49 includes it for a good reason: it gives each task a stable order within its priority level, and it lets rendering show a short, readable date that helps a user remember when a task was added. Dates are stored as numbers, which are easy to compare and sort, and formatted only at display time, which keeps the stored data simple and the displayed format flexible. If the display format later changes, the stored data does not need to change, and if a task is edited, its created date remains the date it was created, not the date it was last changed, because the model distinguishes creation from editing in a way that a single date field could not. Tasks are held in an array inside the app state, in the order they were added, and that stored order is deliberately kept simple, as the sorting section explained, because display sorting happens at render time. Adding a task pushes a new object onto the array, deleting a task removes the object with the matching identifier, and toggling a task flips its done flag in place, each followed by saving and re-rendering, so the screen always reflects the array. That pattern, change the array, save the state, re-render the panels, is the core behaviour loop of chapter 49, and it is worth naming here in the plan, because every task action in that chapter follows it without exception, which makes the code easier to learn and easier to debug. Finally, the task model must be documented in code with clear names, and the plan encourages short comments only where the reason for a field is not obvious from its name, such as why the created value is stored as a number rather than as a formatted string. A clear model is the foundation on which searching, filtering, sorting, counting, and rendering all depend, and getting it right now, before any of those features are built, saves extensive rework later, when a missing or ambiguous field would force changes across rendering, storage, and the overview at once. When you review your written plan at the end of this chapter, check that you can state each task field and its job from memory, because that fluency is the test of whether the model has been understood or merely copied.
Check: What fields does a task hold, and why must its identifier be unique and stable?
Section 27
A note in MyDay Dashboard is even simpler than a task, and that simplicity is deliberate, because notes are meant to be written quickly and read at a glance, without the structure that tasks need for tracking completion. Each note is an object with a few fields: a unique identifier, which distinguishes one note from another and lets edit, pin, and delete actions find the right note; a title, as a plain string, which is required and which serves as the note's handle in the list and in search results; a body, as a plain string, which holds the detail and may be short or moderately long; and a pinned flag, true when the note is pinned and false otherwise, which controls whether the note appears at the top of the notes list. The title deserves emphasis, because it is the note's primary identity in the interface, in a way that task text is not quite, since tasks are often scanned as a list of actions while notes are often searched for by a remembered heading. A note title should therefore be short and descriptive, and the add-note form requires it, as planned earlier, while the body is where the detail lives and where the user can write freely without worrying about length or format. Storing both title and body as plain text keeps rendering simple and safe, because text content cannot break the page structure, and it keeps searching simple, because the search rule can check both fields with the same lower-case substring comparison used for tasks. Notes are held in an array inside the app state, alongside the tasks array, and the two arrays are kept separate, because tasks and notes have different fields and different behaviours, and merging them into one array would force every action to check what kind of item it was handling. Separate arrays make rendering straightforward: one render function for tasks, one for notes, and one for the overview, all called by a single update function, as chapter 49 organises them, so a change to notes cannot accidentally affect tasks, and a change to tasks cannot accidentally affect notes. The state object that holds both arrays, plus the filter and the search query, is the single source of truth for the whole dashboard, and every panel reads from it, which is why the panels always agree with each other when rendering is centralised. Finally, notes, like tasks, must be generic in any demo data, because a portfolio project should never expose real personal notes, and chapter 49's seed data therefore uses generic example notes, such as a note about the dashboard itself, rather than anything private or identifying. When you write your own plan at the end of this chapter, choose generic example notes for testing, and when you take screenshots in chapter 50, check them for personal information before sharing, because a screenshot that shows a real note, name, or address undermines the professionalism of the whole portfolio. A note model that is simple, separate, and safe is a model that serves both the daily user and the future reviewer, which is the standard this plan sets for every piece of data in the project.
Check: What fields does a note hold, and why is pinning stored as a flag on the note rather than as a separate list?
Section 28
The app state is one object with four parts, and writing that shape down before any code is written prevents the rest of the build from inventing new structures on the fly. The four parts are a tasks array, a notes array, a filter value, and a search query, and together they hold everything the dashboard needs to display, without needing any other global variables for its core data. A single shape, agreed in the plan and then used consistently, means that rendering, filtering, searching, saving, and counting all read from the same place, instead of from scattered variables that could disagree with each other after a few changes. State is the single source of truth, which is a phrase worth unpacking, because it is the central idea of chapter 49 and of this plan's data design. It means the screen should show what the state contains, and nothing else, and it means the correct way to change the screen is to change the state first and then re-render, never to edit the displayed page directly and hope the data catches up. When that rule is followed, the screen can never drift away from the data it claims to show, because every render rebuilds the display from the current state, and when it is broken, by editing the page directly, the next render will overwrite the edit and the user will see a confusing flicker or loss. The state also has a lifecycle that the plan must describe, because a dashboard that only works within a single visit is not yet a dashboard that remembers. On startup, chapter 49 loads stored data from localStorage, or falls back to generic seed data if nothing is stored or if the stored data is corrupted, then attaches event listeners, and then renders tasks, notes, and the overview in a fixed order. After every meaningful change, such as adding, completing, deleting, pinning, or editing an item, the state is saved again and the panels are re-rendered, so a closed tab does not lose a finished task and a reload does not lose a pinned note. That save-after-every-change rule is safer than saving only when the page closes, which may never happen cleanly if the browser crashes or the device loses power. Finally, the state shape makes testing possible in a way that scattered variables would not, because a developer can log the state to the console after an action and confirm that the data changed as expected before trusting the screen, and can then remove those logs when the feature works, so the finished code stays clean. Chapter 49 uses that technique during development, and chapter 50 removes any remaining logs as part of its cleanliness pass, because a finished project should not distract a reviewer with debug output. When you write your plan, copy the state shape exactly, in your own words, and check every later feature against it, asking whether it needs a new part of state or whether it can be derived from the four parts already planned, because that question is the test of whether the state design is complete.
Check: What four parts make up the app state, and why must the screen be rebuilt from state rather than edited directly?
Section 29
Storage for MyDay Dashboard uses localStorage, a browser feature that lets a page save text on the user's own device and read it back on a later visit, without any server or account. The plan gives storage a single key, myday-data-v1, and a single rule: saving means turning the state object into text and writing it under that key, and loading means reading the text under that key and turning it back into data, with checks that the result has the expected shape before it is used. That key includes a version, v1, so a future change to the data shape could use a new key or migrate old data deliberately, rather than silently misreading data written by an older version. Versioning is a small habit with a large benefit, because it turns a future change from a mysterious bug into a planned decision. Saving happens after every meaningful change, not only when the page closes, and that frequency is a deliberate safety choice that chapter 49 implements consistently. Adding a task, completing a task, deleting a task or note, pinning or editing a note, and clearing completed tasks are all meaningful changes, and each one triggers a save before the panels are re-rendered, so the saved data always matches the displayed data. Saving only on page close would be fragile, because a tab may be closed abruptly, a browser may crash, or a device may lose power, and any of those events could lose work that the user believed was saved because they saw it on screen. The storage plan also defines what is not stored, because that boundary is part of honesty about the project. The filter value and the search query are part of the state during a visit, but the project resets the filter to All on a fresh load, as planned earlier, and it does not promise to restore a search query across visits, because the dashboard's job is to show the whole picture first and let the user narrow it deliberately. The overview counts and the progress percentage are never stored, because they are calculated from the tasks on every render, and storing them would create a second source of truth that could drift. The bar display data is likewise calculated, not stored, for the same reason, and chapter 49's helpers for counts and progress exist precisely so that calculated values never need to be saved. Finally, storage shapes the portfolio story, because a reviewer who understands localStorage will recognise it as a sensible choice for a front-end-only capstone, while a reviewer who does not will need it explained plainly. Chapter 50's case study therefore names the storage key, the version, and the browser-only limit in plain terms, and the footer note in the finished project states the same limit to the user, so no one is misled about where their data lives. When you write your plan, state the key exactly, state when saving happens, and state what loading does when stored data is missing or corrupted, because those three sentences are the whole storage plan, and a plan that cannot state them has not yet understood its own data.
Check: What storage key does the dashboard use, and what should loading do when stored data is corrupted?
Section 30
Seed data is the generic example content the dashboard shows on a first run, before the user has added any tasks or notes of their own, and its plan is to be helpful without being personal. On a first run, the dashboard shows a few generic example tasks and notes, such as a task to plan the day and a note about the dashboard itself, which demonstrate the features at once: tasks with different priorities, a completed task and an active task, and notes with one pinned and one unpinned, so a first-time visitor can see filtering, sorting, pinning, and progress without having to invent test data. Seed data also serves a testing purpose that is easy to overlook: it gives every later feature a known starting point, so a developer can verify filtering, searching, counting, and progress against data whose expected results can be calculated by hand. If the seed data contains a known number of tasks, with a known number completed and a known distribution across priorities, then the overview counts, the progress percentage, and the bar display can all be checked against those known numbers after the first render, before any user action complicates the picture. That known starting point is what makes the first render test meaningful, and it is why chapter 49 introduces seed data early, before rendering, rather than treating it as a decorative extra to be added at the end. Choosing seed examples also requires care about what they imply, because examples teach by showing, even when they are not meant as instructions. Generic tasks, such as planning the day, reviewing notes, or preparing for tomorrow, are neutral and relatable, while examples that name real people, real workplaces, or real private matters would imply that the dashboard is meant for those specific contexts, or worse, would expose information that should not be shared. Generic notes, such as a note about how the dashboard works or a note with a simple reminder, demonstrate title, body, and pinning without suggesting a particular user's life, and they keep the portfolio screenshots clean. When you write your plan, list your own generic examples, and check each one by asking whether you would be comfortable showing it to a stranger, because that is exactly what a portfolio screenshot does. Finally, seed data should be removable in the user's mind, not only in the code, which means the dashboard must make it clear that the examples are starting points, not permanent content. A user who understands that they can delete the examples, or reset to them later, will treat them as a helpful starting point, while a user who believes the examples are part of the product may hesitate to delete them and may end up with a dashboard cluttered by demo items. Chapter 49's delete and clear actions, combined with the reset action, give the user full control over seed data, and chapter 50's screenshots, taken with generic data, show that control in action. Seed data that is generic, known, replaceable, and resettable is seed data that serves the project, rather than seed data that merely fills an empty page.
Check: Why must seed data be generic, and when is it used instead of saved data?
Section 31
Rendering is how the dashboard turns its state into a visible page, and chapter 49 plans it as a rebuild, not as a series of small edits to the existing page. Rendering the task list clears it and rebuilds it from the visible tasks, creating a list item, a checkbox-style button, text, a priority badge, and a delete button for each task, in the order determined by priority sorting and by the current filter and search. Rendering the notes list sorts pinned notes first, then shows each note's title, body, pin button, edit button, and delete button, in that sorted order. Rendering the overview counts totals, completed tasks, and active tasks from the task array, calculates progress, builds the bar display data, and writes all of those values into the overview panel. Rebuilding from state, on every render, guarantees that the screen matches the state after every change, which is the practical meaning of state as the single source of truth. Separate render functions exist for tasks, notes, and the overview, all called by one update function, and that separation is a deliberate organisational choice that chapter 49 explains and this plan endorses. A change to one panel, such as restyling how a task item is built, can be made inside its render function without touching the other panels, while the single update function ensures that no panel is forgotten after a state change, because updating always means calling all three renders in a fixed order. That structure also makes debugging easier: if the task list is wrong but the overview is right, the problem is likely in the task render function, while if all panels are wrong in the same way, the problem is likely in the state or in the shared update function. Without separate renders, a bug could hide anywhere, and without a single update function, a developer could easily update one panel and forget another, producing the disagreement between panels that this plan works so hard to prevent. Finally, rendering is where the plan's accessibility promises are kept or broken, because dynamically created elements must carry the same labels, button types, and accessible names as elements written by hand in HTML. Chapter 49 therefore creates list items with real button elements, with text content rather than markup for user-entered text, and with accessible names for icon-only controls, so the rendered page is as navigable as the static page planned in chapter 48. Chapter 50 tests rendering by performing real actions in order, add, complete, filter, search, reload, and confirming the result survives each step, because a render that only works on first load, but not after an action, has not yet implemented the rebuild pattern this plan describes. When you write your plan, describe rendering as rebuild-from-state, with separate functions and one update call, because that sentence is the whole rendering architecture in miniature.
Check: Why does rendering rebuild each list from state, and why is it triggered only once per action?
Section 32
Overview counts and progress are calculated values, and this plan treats their calculation as a small, testable piece of logic that deserves the same care as any visible feature, because users trust numbers more readily than they trust lists, and a wrong number therefore misleads more effectively than a wrong list item. The overview reads the task list and counts totals, completed tasks, and active tasks, then writes those numbers into the panel, using simple array operations that can be checked by hand against a known set of tasks. Counting by priority, a related calculation, filters the task array three times, once per level, and stores the three numbers for the overview and the bar display, so both presentations share one set of counts rather than calculating them separately and risking disagreement. Progress calculation itself is a single formula with one important guard, and the plan states both parts explicitly so they can be tested without ambiguity. Progress is completed tasks divided by total tasks, multiplied by one hundred, and rounded, with zero tasks giving zero percent rather than a division error, a blank result, or a misleading full bar. Guarding the empty case is a habit worth forming in every calculation, because division by zero is a common source of confusing results, and because a dashboard with no tasks yet is a normal state, not an error, that deserves a sensible, calm display. Chapter 49 also updates the progress bar width from the calculated percentage, and writes the same percentage as text inside or beside the bar, so the visual length and the numeric label always agree, and a user who cannot judge length by eye can still read the number. The bar display data extends the same calculation pattern to priority, and its plan is equally precise, so it can be checked by hand. The code counts tasks per priority, finds the largest count, and sizes each bar relative to that largest count, with the count itself shown as text beside the bar, so the longest bar always represents the largest group and the display never relies on length alone. If all priority counts are zero, the bars should show as empty with zero counts, rather than attempting a division by a largest count of zero, which is the same empty-case guard as for progress, applied to a different calculation. That parallel, two calculations with the same guard, is a useful pattern to notice, because it shows how a habit formed in one place, guarding division, transfers naturally to another place where the same risk appears. Finally, counts and progress should be described honestly in the portfolio, as calculated summaries of a personal list, without invented claims about productivity, time saved, or habits improved, because the dashboard measures tasks, not outcomes, and claiming more would mislead a reviewer. Chapter 50's case study describes the overview in those plain terms, as counts and a progress bar that help a user see where they stand, and the readme lists the same features without exaggeration. A number that is calculated correctly and described accurately is a small trust-building detail, and a dashboard full of such details is a dashboard a reviewer can believe, which is the real goal of the overview plan.
Check: How is progress calculated, and why must the overview be recalculated on every render rather than stored?
Section 33
The bar display is the overview's visual summary of tasks by priority, and its plan is to be simple, readable, and always in agreement with the counts it visualises. It shows one row per priority, High, Medium, and Low, with each row containing a label, a bar, and a count, built from plain divisions styled with widths that represent data. The bars are sized relative to the largest priority count, so the longest bar always belongs to the largest group, and the counts are shown as text, so the display can be understood by reading numbers alone, without judging bar lengths by eye. Styling the bar display follows the dashboard's calm visual system, with the same spacing, muted colours, and text sizes as the rest of the overview, so the bars feel like part of the panel rather than like a foreign element. Chapter 48 styles each row as a label, a track, and a count, with the filled portion using a muted version of the accent or a neutral colour, depending on the theme decision in that chapter, and with the width set by JavaScript as data, which is the one place where an inline width is acceptable. That exception is worth restating, because it explains why bar widths are not in the stylesheet: a width that represents a count is data, and data belongs in JavaScript, while a width that represents design, such as a panel's maximum width, belongs in CSS. Keeping that distinction clear prevents a stylesheet full of data-driven values that would quickly become stale. The bar display must also update after every action, through the same single update function as the rest of the overview, so adding, completing, deleting, or clearing tasks changes the bars at once, without any separate refresh step. A bar display that only updated after adding a task, but not after deleting one, would quickly mislead the user about where their remaining work sits, and chapter 50 tests it by changing the priority distribution and checking the bars after each change. The display should also remain correct when filtered or searched, because it reports all tasks, not only visible ones, just as the overview counts do, so a user who filters to Active still sees the true priority distribution in the overview, while the task list shows only the filtered slice. Finally, the bar display should be described in the portfolio as what it is, a simple summary of tasks by priority, not as analytics or insights, because those words would imply a larger, more sophisticated feature than the project builds. Chapter 50's case study mentions the bar display alongside the counts and the progress bar, as part of the overview's job of helping a user see where they stand, and the readme lists it in the same plain terms. A simple display, calculated correctly, styled calmly, and described honestly, is a better portfolio detail than a grand claim about a simple display, and it is the standard this plan sets for every feature in the dashboard.
Check: How is each bar's width calculated, and why does the bar display report all tasks rather than only visible ones?
Section 34
Task actions are the behaviours that make the tasks panel feel alive, and chapter 49 implements them as a small set of handlers that all follow the same pattern: change the state, save the state, and re-render. Adding a task reads the form, trims the text, rejects an empty value, creates a task object with a unique identifier, and pushes it into the state before saving and re-rendering, with the priority taken from the form and the done flag set to false and the created timestamp set to the current time. Each step is small, and the order matters, because creating the object before saving ensures that the saved data matches the displayed data, and re-rendering after saving ensures that the screen matches the saved data, so no step can be skipped without producing a dashboard that disagrees with itself in some subtle way. Toggling a task complete finds the task by its identifier, flips its done flag, saves, and re-renders, which moves it between filtered views and updates the progress, the counts, and the bar display at once. One flag drives the checkbox styling, the filter, the counts, and the progress together, which is why toggling feels so satisfying when it works and so confusing when it does not: a single change propagates everywhere, and the user sees the whole dashboard respond to one click. That propagation is the benefit of centralised rendering, and it is also the reason toggling must be tested in each filtered view, because toggling while viewing Active should make the task disappear from that view, while toggling while viewing All should keep it visible with its completed styling, and both behaviours must be correct for the feature to be trusted. Clearing completed tasks is the bulk action that completes the task behaviour set, and its plan is to remove every task whose done flag is true, then save and re-render, leaving active tasks untouched. That action is useful at the end of a day, when completed tasks have served their purpose and the user wants a clean list for tomorrow, and it is also a good test of the rendering architecture, because it changes many items at once and the overview, progress, and bar display must all reflect the change immediately. Before clearing, the dashboard asks for confirmation with a simple inline step, as noted above, because clearing cannot be undone in this project, and a user who clears by accident would lose a record of what they had finished. Finally, task actions must be reachable by keyboard as well as by mouse, because list buttons are real button elements, so they are focusable and activatable with Enter and Space without extra code, and because the add-task form submits with Enter in the usual way. Chapter 49 plans keyboard accessibility for list buttons as a consequence of using real buttons, not as a separate feature, and chapter 50 tests it by completing, deleting, and clearing tasks using only the keyboard. A task action that only works with a mouse is not a complete action, however well it works in a demonstration, and the plan's standard, that every action must work by keyboard, by mouse, and after a reload, is the test that task behaviours must pass before they are called finished.
Check: What pattern do all task actions follow, and why does clearing completed tasks ask for confirmation while deleting one task does not?
Section 35
Note actions are the behaviours that make the notes panel feel as alive as the tasks panel, and chapter 49 implements them with the same change, save, and re-render pattern, adapted to the note model's fields. Adding a note reads the title and body, trims both, requires at least a title, creates a note object with its pinned flag set to false, and then saves and re-renders, so the new note appears in the list at once and survives a reload. A note without a title is rejected, with a short message near the form, because a titleless note would be hard to find later, and the rejection preserves any body text already typed, so the user does not lose work because of one missing field. Pinning a note flips its pinned flag, saves, and re-renders, which brings pinned notes to the top of the notes list, because rendering sorts pinned notes first. Pinning is a display preference stored with the note, not a separate list, so unpinning returns the note to its normal position without losing it, and pinning survives a reload because the flag was saved. That simple behaviour is surprisingly useful in daily use, because it lets a user keep one or two notes, such as a key reminder or a reference detail, always visible at the top, without having to search for them each time. Chapter 49 also notes that pinning does not affect the overview, which counts tasks only, so a pinned note changes the notes list but not the task summary, and that separation is correct, because notes and tasks are different kinds of information with different summaries. Deleting a note removes it by its identifier, saves, and re-renders, and if the last note is removed, the empty state appears as a normal render result, not as a special case handled by hand. That consistency, where deletion, editing, and pinning all flow through the same update function, is what keeps the notes panel predictable, and it is why chapter 49 separates render functions for notes, tasks, and the overview, while calling them all from one update function. A note action that updated the list directly, without going through the update function, might look correct in the moment but would leave the saved data or the empty state out of sync, and the next reload would reveal the disagreement. Centralised updating is therefore not an abstract preference; it is the mechanism that makes note actions trustworthy over time. Finally, note actions, like task actions, must work by keyboard and after a reload, and chapter 50 tests them in that order: add a note, pin it, edit it, delete it, reload after each step, and confirm the result survives. Focus after adding a note returns to the first field, so several notes can be written in a row, and focus after editing returns to a sensible place in the panel, so a keyboard user is not stranded. Those focus details, planned in chapter 49 alongside the handlers, are part of what makes the notes panel feel designed for repeated use rather than for a single demonstration, and they are the reason this plan names focus explicitly for both forms, rather than leaving it as an implied consequence of using real form controls.
Check: How do adding, editing, pinning, and deleting a note each follow the same change, save, and re-render pattern?
Section 36
Filter and search combine to decide which tasks are visible, and this plan states their combination precisely, because a combination that is not stated will be implemented inconsistently and will feel unpredictable to the user. Visible tasks are those that pass the filter and match the search query, applied in that order to the same array, so the filter narrows the list first, to All, Active, or Done, and the search then narrows that result further, to items whose text contains the lower-cased query. Notes are filtered by search alone, since they have no completion filter, so a search term narrows both lists at once, while the filter narrows only the tasks, and the overview continues to count all tasks, not only visible ones, so the summary never changes its meaning when the user searches or filters. Validation and empty submissions are the companion behaviours that keep filter and search honest, because a list that is filtered to nothing by a search term should show an empty message, not a stale list, and a form that is submitted empty should show a message, not create a blank item. Chapter 49 shows validation messages near the form when a submission is empty, explaining what is missing, instead of silently doing nothing, which would leave the user wondering whether the button worked, and it prevents empty submissions by trimming input and checking the result before any state change, with the required attribute as a browser-level support rather than as the only guard. Event handling for lists ties these behaviours together, and chapter 49 plans it as event delegation, with one click listener on each list handling buttons inside it, using the closest method to find the button that was pressed and a data attribute to identify the action and the item. One listener per list is simpler and more robust than a listener per button, especially when buttons are created dynamically during rendering, because a per-button listener would need to be reattached after every render, while a delegated listener on the list itself continues to work for buttons added later. Delegation also centralises the logic for completing, deleting, pinning, and editing, so a bug in one action can be found in one place, and a new action can be added by extending the delegation handler rather than by scattering listeners across the code. Finally, the combination of filter, search, sorting, validation, and delegation must be tested together, not only separately, and chapter 50 includes that combined test in its end-to-end walk-through. Add tasks with different priorities and completion states, filter to Active, search for a word that matches some active tasks, confirm the visible list is the intersection of filter, search, and priority order, clear the search, return to All, and confirm the full list returns in priority order, then reload and confirm the same full list appears. A dashboard that passes its features in isolation but fails when they are combined has not yet implemented the combination logic this plan describes, and the combined test is the only test that can reveal that failure before a reviewer does.
Check: In what order are filter, search, and priority sorting applied, and why does one listener per list handle all its buttons?
Section 37
Keeping the screen and the state in sync is the central discipline of chapter 49, and this plan states it as a rule rather than as a hope: after every state change, the code saves and then re-renders all affected panels, so no panel shows an older version of the data. That rule is enforced by structure, through the single update function that calls the task, note, and overview render functions in a fixed order, rather than by asking each handler to remember which panels to update, because memory is unreliable and structure is not. If two panels disagree, one of them is reading stale data, so tracing both back to the same state object usually reveals the cause, whether it is a handler that edited the page directly, a render function that was not called, or a count that was stored separately instead of calculated. That diagnostic habit, trace both panels to the same state, is worth learning now, because it applies to every front-end project that renders from data, not only to this dashboard. Keyboard behaviour is also part of sync, in the sense that the user's focus must stay in sync with the action they just performed, rather than being lost or left in a confusing place. Because add-task and add-note are real forms with submit buttons, pressing Enter in a field submits the form, which the handler prevents from reloading the page, trims and validates, and then processes, and after a successful addition, focus returns to the first field, so adding several items in a row needs no mouse movement. List buttons, being real buttons, are focusable and activatable with Enter and Space, and after an item is deleted, focus should remain in a sensible place in the list, rather than disappearing with the deleted element. Chapter 49 plans those focus behaviours alongside the handlers, and chapter 50 tests them with a keyboard-only walk-through, because a dashboard that loses focus after every action is a dashboard that is out of sync with its user's intentions, even if its data is perfectly correct. Finally, sync must survive a reload, which is the ultimate test of whether the screen, the state, and the storage agree. After any action, reloading the page should show the same lists, counts, progress, and bar display as before the reload, because the action saved the state and the startup sequence loads that saved state before rendering. Chapter 49's startup order, load stored data or fall back to seed data, attach event listeners, and then render, ensures that the first render after a reload is based on saved data, not on empty defaults, and chapter 50's end-to-end test reloads after each major action to confirm that order. A dashboard that is in sync during a visit but out of sync after a reload has only half-implemented the sync discipline, and the reload test is what reveals that half-implementation before a reviewer does.
Check: What does it mean for the screen and state to be in sync, and how does a single update function enforce it?
Section 38
Storage errors, corrupted data, and version changes are the edge cases that separate a dashboard that works in a demonstration from a dashboard that works in daily use, and chapter 49 plans for all three, rather than assuming storage always works perfectly. Saving is wrapped in a try and catch, so if storage is full or unavailable, the dashboard still works for the session and shows a plain message, rather than crashing, silently discarding the user's work, or leaving the user wondering why a task disappeared after a reload. That message should be plain and specific, explaining that saving did not work and that the current session's data will not survive a reload, without using technical language that a non-technical user cannot act on. Handling corrupted stored data follows a similar principle of graceful fallback, and its plan is to validate before trusting, rather than to trust and then crash. If stored text cannot be parsed, or if the parsed value lacks tasks and notes arrays, loading falls back to generic seed data, and the dashboard continues to work, with its features intact, even though the previous data could not be recovered. That fallback is a deliberate trade-off: it loses the corrupted data, which cannot be reliably recovered in any case, but it preserves the dashboard itself, so the user can start again immediately rather than facing a broken page. Chapter 49 also notes that stored data should be treated as untrusted, because a user may have an older version, a cleared store, or a value another tool changed, and that scepticism, applied consistently, is what makes loading robust rather than fragile. Exporting data as a file and resetting to demo data are the two user-facing actions that complete the storage plan, and both are planned in chapter 49 with appropriate caution. Export creates a JSON file from the state and offers it as a download, so the user can keep a copy of their tasks and notes, which is a simple, honest form of backup that requires no server and no account, and which a user can store wherever they choose. Reset restores the generic seed data, after confirmation, which is useful for demonstrating the dashboard or recovering from a messy test state, but which discards the user's current data, so it must ask for confirmation and must be clearly labelled, rather than being a button that can be pressed accidentally. Finally, storage edge cases must be tested, even though they are harder to test than happy paths, and chapter 50 includes them in its triage and testing work, by asking what happens when storage is unavailable or when stored data is corrupted, and by checking that the dashboard's answers match the plan's answers. A developer can simulate corrupted data by editing the stored value in developer tools, then reloading, and confirming that the dashboard falls back to seed data and continues to work, which is a concrete test that can be performed in minutes. A dashboard that has been tested in its edge cases, as well as in its happy paths, is a dashboard that can be presented with confidence, because its developer knows how it behaves when things go wrong, not only when things go right.
Check: What should the dashboard do when storage is full, when stored data is corrupted, and when the user asks to reset?
Section 39
Organising app.js is the last structural decision in chapter 49, and it matters because a well-organised script can be read, debugged, and explained, while a disorganised script, even if it works, cannot be maintained or presented with confidence. Chapter 49 organises the script in order: state, storage, helpers, rendering, event handlers, and startup, with short comments marking each part, so a reader can find any piece of logic by its role rather than by searching the whole file. That order is not arbitrary; it follows the flow of data through the project, from the state that holds it, through the storage that saves it, through the helpers that calculate from it, through the rendering that displays it, through the handlers that change it, to the startup that brings it all together. Short comments in app.js should explain why, not what, and chapter 49, like chapter 48 for CSS, plans comments that record decisions, such as why progress guards against zero tasks, rather than comments that restate the next line of code. A comment that says a function saves the state adds no information beyond the function name, while a comment that says saving happens after every change, because a closed tab should not lose a finished task, records a decision that a future reader might otherwise question or undo. Comments should therefore be few, short, and decision-focused, and they should be removed along with the code they describe, so a comment never outlives the decision it recorded and misleads a later reader. That discipline, applied to both CSS and JavaScript, is part of what makes the finished project feel professional rather than merely functional. Startup is the final part of the script, and its order is fixed in chapter 49 as: load stored data or fall back to seed data, attach event listeners, and then render tasks, notes, and the overview. That order matters for a practical reason: listeners must be attached before the user can interact, but rendering must happen after loading, so the first display reflects saved data rather than empty defaults, and attaching listeners before rendering ensures that dynamically created buttons, handled by delegation on their lists, are covered from the first render onwards. A startup that rendered before loading would flash empty panels before showing saved data, which would look like a bug even if it corrected itself a moment later, and a startup that attached listeners after rendering might miss early interactions. Fixing the startup order in the plan prevents both of those subtle, hard-to-reproduce issues. Finally, performance on a small list is planned as a non-issue handled by simplicity, rather than as a problem to be optimised prematurely. Rebuilding small lists on each action is fast enough here, because the dashboard holds tens of items, not thousands, and choosing the simplest render that is easy to read and easy to reason about is the right trade-off at this scale. Chapter 49 explains that no debounce is needed for search, that rendering once per action is sufficient, and that clever optimisation would add complexity without a measurable benefit, and those judgements, stated plainly, are themselves a skill worth presenting in an interview.
Check: In what order is app.js organised, and in what order does startup run?
Section 40
Chapter 48 is the first build chapter, and this plan previews it in the order it will be built, so you can see how structure and style become a complete-looking dashboard before any behaviour works. It opens with the capstone project itself, naming MyDay Dashboard and its three panels, then plans the folder and the three files, and then settles the single-page structure, with a semantic header, a main landmark divided into labelled sections, and a footer with a status area. That opening sequence matters, because it fixes the shape of the page before any detail is added, and it gives every later section a container to belong to, so no panel is built in isolation from the page that holds it. A builder who starts with details, such as a single button style, before settling the page structure, will often have to redo those details when the structure changes, while a builder who starts with structure can add details with confidence. The second half of chapter 48 turns to style, and it does so as a system, in the order variables, base, layout, panels, forms, buttons, badges, bars, and responsive rules. It starts with base styles, a calm starting point with a readable font and comfortable line height, then a colour palette with variables, a typography scale, and a spacing scale, which together define the visual language for everything that follows. It then covers page layout as a centred column, panel layout with grid, cards for tasks and notes, styling for buttons and form controls, styling for the filter bar, visible focus styles, hover and active states, priority badges, the progress bar, the bar display, and empty states, each building on the scales defined earlier. That order, system first, details second, is what keeps the styling consistent, because a badge or a button styled after the palette and scales are defined will naturally match the rest of the page, while a badge styled first might introduce a colour or size that later has to be corrected everywhere. The chapter closes with responsive design, small screens first and then wider screens, a light calm theme kept consistent throughout, reusable utility classes kept few, avoidance of inline styles except for data-driven bar widths, organisation of the stylesheet, and checking with developer tools. It covers fixing overflow, checking contrast and readability, auditing spacing against the scale, writing style notes in comments, and reviewing structure and style together, before a final checkpoint that states what should be true at the end of the chapter. By that checkpoint, the dashboard should look complete and calm even before any behaviour works: header, panels, forms, filters, lists, counts, bars, and footer all present and readable, with empty states in place, ready for JavaScript to fill them. That checkpoint is the promise chapter 48 makes, and this plan repeats it here so you can check chapter 48 against it when you finish it, rather than discovering at the end of chapter 49 that the structure was never quite complete.
Check: What does chapter 48 deliver, in order, and what should be true at its checkpoint?
Section 41
Chapter 49 is the second build chapter, and this plan previews its first half in the order it will be built, because that order is the order in which behaviour becomes trustworthy. It opens with the shape of the app state, one object with tasks, notes, filter, and search query, then covers seed data for a first run, loading data from localStorage under the key myday-data-v1, and saving data to the same key after every meaningful change. That opening is the data foundation, and it is built before any visible behaviour, because every later feature reads from, writes to, or saves that state, and a foundation that is vague or inconsistent would make every later feature harder to test. A builder who starts with a visible feature, such as adding a task, before settling the state shape, will often have to rewrite that feature when the shape changes, while a builder who starts with the shape can add features with confidence that they will fit. The action group follows, and it is built in the order a user would use the dashboard: adding a task, adding a note, toggling a task complete, deleting a task, deleting a note, editing a note in place, and pinning a note. Each action follows the same pattern, change the state, save, and re-render, and each action is small enough to be tested on its own, by performing it, checking the screen, and reloading to confirm the change survived. That order, add before toggle before delete before edit before pin, is also a sensible learning order, because adding is the simplest change, toggling introduces the idea of a flag driving several displays at once, deleting introduces removal by identifier, editing introduces reusing a form for two purposes, and pinning introduces ordering as a display rule. A learner who follows that order will encounter each new idea once, in a context where it is the only new idea, rather than encountering several new ideas at once in a complex feature. By the middle of chapter 49, therefore, the dashboard should already be usable in its core loop, even though its polish behaviours have not yet been built: a user can add, complete, delete, edit, pin, filter, search, and reload tasks and notes, with counts and progress that match the lists. That midpoint is a useful checkpoint for your own build, because it lets you test the core loop end to end before adding validation messages, delegation details, keyboard refinements, and storage edge cases, which are important but which should not distract from verifying that the core loop works. If the core loop fails at that point, the polish chapters will not fix it, and if it passes, the remaining work in chapter 49 can be built on a solid, tested foundation, which is exactly the order this plan recommends.
Check: What does the first half of chapter 49 deliver, in order, and why is rendering built before the action handlers?
Section 42
The second half of chapter 49 adds the polish behaviours that turn a usable dashboard into a trustworthy one, and this plan previews them in the order they appear, so you can see how each one builds on the core loop rather than replacing it. It opens with showing validation messages and preventing empty submissions, so a form submitted empty shows a short message near the form explaining what is missing, instead of silently doing nothing, and so trimming and checking happen before any state change, with the required attribute as browser support rather than as the only guard. Event delegation follows, with one click listener on each list handling buttons inside it, using the closest method to find the button pressed and a data attribute to identify the action, which is the technique that makes dynamically rendered buttons work without reattaching listeners after every render. Keeping the screen and state in sync is then stated as a discipline, with the single update function as its mechanism, and unique identifiers, built from the current time plus a counter, are explained as the reliable way to find an item, as opposed to fragile alternatives such as position or text. Clearing completed tasks and confirming a destructive action are the next pair, and they are paired for the same reason as validation and prevention: a bulk action that discards data should ask for a second thought, while a single-item action should remain quick. Clearing removes every task whose done flag is true, then saves and re-renders, leaving active tasks untouched, and before clearing, the dashboard asks for confirmation with a simple inline step on the button itself, rather than a separate dialog, so the confirmation is visible in context and cannot be dismissed as an unrelated interruption. The chapter then covers exporting data as a file, counting tasks by priority, updating the progress bar width from the calculated percentage, combining filter and search, and explaining why no debounce is needed for search on a small list, followed by avoiding duplicate renders, separating render functions, and writing small pure helper functions. Those sections are the performance and organisation polish that make the code maintainable, and they are placed after the features they polish, so the reader understands what is being polished before learning how to polish it. That checkpoint, that the dashboard should be fully usable at the end of chapter 49, is the promise this plan repeats here, so you can check chapter 49 against it when you finish it. Fully usable means add, complete, delete, edit, pin, filter, search, and reload all work, with counts, progress, and bar display matching the lists, with validation messages for empty submissions, with keyboard access to every action, and with storage that saves after every change and falls back gracefully when data is corrupted. A dashboard that meets that checkpoint is ready for chapter 50's finishing work, while a dashboard that only meets part of it should be fixed before moving on, because finishing work cannot compensate for a core behaviour that does not yet work reliably.
Check: What polish behaviours does the second half of chapter 49 add, and what should be true at its checkpoint?
Section 43
Chapter 50 is the finishing chapter, and this plan previews it in the order it will be carried out, starting with testing, because a project cannot be finished until it has been tested as a user would use it. It opens with what finished means, defined as every promised feature working end to end, with tasks and notes able to be added, changed, filtered, searched, and reloaded without a broken step, and with finished meaning complete, tested, and demonstrable, not perfect. It then covers end-to-end testing of the whole flow, walking the dashboard as a user, adding a task, completing it, filtering to Done, searching for it, reloading, and confirming it is still there, because one full walk-through catches more than many isolated checks. Testing on a phone-sized screen, using device emulation and, if possible, a real phone, confirms that panels stack, buttons are tappable, and text does not overflow, while testing with the keyboard only, using Tab, Enter, Space, and Shift plus Tab, confirms that every control and every action is reachable without a mouse, and basic screen reader checks confirm that headings are in order, labels are announced, and overview counts are reachable. Writing the case study is the portfolio's story, told in four parts, the problem, the approach, the result, and what you would improve, in four short paragraphs that are honestly written and that beat a page of adjectives. Showing the problem first means starting with scattered tasks and notes making it easy to lose track, showing the build means naming the three files, the state shape, and localStorage persistence, and explaining why no framework was used, and showing the result honestly means describing what works, using the features themselves as evidence, and avoiding invented numbers about users or speed. If the dashboard has no real users yet, the case study should say it is a personal project, which is true and respectable, and it should list honest next improvements, such as keyboard shortcuts for common actions and editing a task in place, which show a reviewer that the developer can judge their own work and knows where it could go. The chapter then covers a final code cleanliness pass, removing unused variables, dead functions, and duplicated code, and giving unclear names better ones, followed by removing console logs and dead code, because development logs and commented-out experiments distract a reviewer and suggest the project was never finished. Comments that explain why, such as why progress guards against zero tasks, are kept, while comments that restate code are removed, because a comment that records a decision adds value while a comment that restates code adds noise. Deploying a static site, by copying the three files to a static host so the dashboard has a public link, and checking the deployed version, by opening the public link in a fresh browser session, repeating the end-to-end test, and confirming the live copy matches the local copy, complete the finishing work, because a deployed version is only real once it has been tested live. That sequence, test, triage, polish, document, present, clean, and deploy, is the finishing order this plan previews, and it is the order chapter 50 will follow.
Check: What finishing steps does chapter 50 carry out, in order, before it turns to portfolio presentation?
Section 44
Portfolio presentation in chapter 50 turns the finished dashboard into a piece of work a reviewer can understand in a few minutes, and its plan starts with structuring a portfolio page, then writing the MyDay entry, then describing skills honestly, and then linking the demo and the code. A portfolio page has a short introduction, a list of projects, and a contact section, with each project getting a name, a sentence about the job it does, and a link, before any detail about tools or techniques, because reviewers spend little time on each project and the first screen and the first paragraph must explain the job clearly. The MyDay entry says, in one paragraph, that it is a task-and-notes dashboard built with HTML, CSS, and JavaScript, storing data in the browser, with tasks, notes, filters, search, priority, and an overview, and it does so without claiming a framework, a server, or a user base that the project does not have. That one-paragraph discipline, job first, tools second, honesty throughout, is the portfolio rule that chapter 50 teaches, and it is worth practising here in your written plan, by drafting your own one-paragraph entry before you build, and revising it after you finish, so you can see how your understanding changed during the build. Frameworks, testing, performance, and version control are the next group, and their plan is to introduce each one at the point where it solves a problem the learner has already felt. Frameworks become useful when a project grows large enough that manual rendering becomes painful, and learning one is easier after manual rendering has been understood, because the learner can then see what the framework is doing for them, rather than treating it as magic. Testing front-end code means writing small checks for helpers, such as progress calculation, and manual checklists for the interface, which builds on the console testing already practised in chapter 49. Performance learning covers measuring load time, reducing image sizes, and avoiding unnecessary work, applied to real pages rather than as abstract rules, while version control habits mean small, frequent commits with clear messages, and a repository that shows the project growing over time. Each of those directions is a roadmap, not a requirement to learn everything at once, and chapter 50 presents them as choices to be made one at a time, based on the learner's weakest demonstrable skill. Finally, chapter 50 closes its portfolio and next-steps work with second and third projects, job search and interview preparation, a learning log, open-source first steps, roadmaps, portfolio maintenance, and a final sign-off, which the next section previews in detail. The portfolio section as a whole, however, has a single message that this plan repeats: present the dashboard as it is, with its real features, its real limits, and its real lessons, because honest presentation builds more trust than grand claims, and trust is what turns a finished exercise into a credible portfolio piece. When you draft your portfolio entry in the practical task at the end of this chapter, use that message as your test, and cut any sentence that claims more than the dashboard actually does.
Check: What should a MyDay portfolio entry contain first, and why must demo and code links both be checked before sharing?
Section 45
Chapter 50's closing sections turn from the finished dashboard to the learner's future, and this plan previews them in order, because they form a coherent path rather than a list of unrelated suggestions. A second project, a habit tracker, reuses the dashboard's skills, with a list of habits, a daily check-off, and a simple streak count stored in the browser, which proves that the capstone's skills transfer to a new context, rather than being memorised for one project alone. A third project, a follow-on list project that reuses lists, filters, and storage again, with a status per item, extends the same pattern once more, so the learner builds a small family of projects that share a core architecture but differ in their data and their user job. That progression, from one dashboard to two further projects that reuse its core, is the plan's answer to the question of what comes after a capstone: not a larger, riskier project, but a second and third project that consolidate the same skills in new forms, until those skills feel fluent rather than merely familiar. Keeping the portfolio updated, avoiding tutorial hell, following a weekly practice plan, reviewing the book's skills map, and completing a capstone retrospective are the closing habits, and they are planned as a maintenance loop rather than as a final event. Updating the portfolio whenever a project improves or a new one finishes, and removing or fixing anything broken, on a short regular schedule, keeps the portfolio trustworthy, while avoiding tutorial hell means spending more time building than watching, and choosing a tutorial only when it answers a question from a real project. A weekly plan might be three short building sessions, one review of past code, and one new small feature, repeated for a month, which is a sustainable rhythm that favours consistency over intensity. Reviewing the book's skills map means listing its major skills, marking which can be demonstrated, and choosing the weakest demonstrable one to practise next, while a retrospective asks three questions, what worked, what was difficult, and what would be done differently, answered honestly about MyDay, without exaggeration or false modesty. Sharing without exposing personal data, completing a final sign-off checklist, and looking ahead are the very last steps, and they close the book with the same honesty that opened the capstone. Before sharing, generic demo data must replace any personal tasks or notes, and screenshots must be checked for names, addresses, or private details, because a portfolio should show skill, not personal information. The sign-off checklist repeats the end-to-end test, the keyboard test, the small-screen test, the readme check, and the link check, and the project is only signed off when all of those pass, without a broken step in the middle that requires an apology. From there, the learner builds the second project, keeps the learning log, and returns to the weakest skill on their map, one small project at a time, which is a fitting end for a book that began with small, concrete steps and that ends by trusting the learner to take the next small steps on their own.
Check: What three interview answers should MyDay prepare you to give, and what does the final sign-off checklist repeat?
Section 46
Build order is the plan's practical advice for how to work through chapters 48, 49, and 50 without getting lost, and it can be stated as a simple rule: one panel at a time, one feature at a time, test after each step, and keep a working version saved. That rule sounds obvious, but it is easy to break in practice, especially when enthusiasm for a new feature tempts a builder to change several files at once, or when a bug tempts them to rewrite a whole section instead of undoing the last change and re-reading the code around it. A calm, narrow check usually finds the problem faster than a rewrite, because a rewrite introduces new unknowns while a narrow check isolates the one change that broke the page, and the plan repeats that advice here because it will be needed, not because it is merely good practice in the abstract. When you feel stuck during the build, return to this rule, undo the last change if necessary, and make the next change smaller, because a smaller change is easier to test and easier to undo if it fails. Time and energy are also part of build order, even though they are rarely discussed in technical plans, and this section names them because a capstone that is planned only in technical terms can still fail for human reasons. Work in short, focused sessions with a concrete deliverable for each session, such as completing one panel's markup or one action handler, rather than in long, unfocused sessions that end with many half-finished changes and no working version to save. Take a break when a bug resists a narrow check, because a fresh look after a pause often reveals a mistake that was invisible during focused effort, and ask for help, or re-read the relevant section of this plan, when a feature's purpose is unclear, rather than guessing at its implementation and building the wrong thing well. A capstone is a marathon of small steps, not a sprint of large ones, and the plan's build order is designed to support that rhythm, with checkpoints at the end of each chapter that give a natural place to pause, review, and celebrate progress before continuing. Finally, build order includes knowing when to stop adding features, which is a decision that the plan makes in advance, by fixing the scope in this chapter and by stating that chapters 48 to 50 will build what is planned here, no more and no less. When a tempting addition appears during the build, check it against the plan's test: does it make it easier to capture, find, complete, or review a task or a note, and is it already in chapters 48, 49, or 50? If the answer to either question is no, save the idea for a later project, such as the habit tracker or the follow-on list project, where it can be built properly, rather than squeezing it into a capstone that is already complete. Stopping at the planned scope is not a lack of ambition; it is the discipline that allows a project to be finished, tested, presented, and learned from, which is the whole purpose of a capstone.
Check: What is the one-change-at-a-time build rule, and when should a tempting new feature be saved for a later project?
Section 47
Risks and limits are part of any honest plan, and this chapter names them now, so they can be managed during the build rather than discovered as surprises at the end. The first risk is scope growth, where a small, useful feature, such as an extra field or an extra panel, is added without considering its cost in markup, styling, behaviour, testing, and documentation, until the project becomes too large to finish well. The plan manages that risk by fixing the scope in this chapter, by giving every feature a test based on the dashboard's core job, and by providing later projects, such as the habit tracker, as a legitimate home for ideas that do not fit this capstone. When scope growth is named as a risk, it becomes easier to resist politely, by saying that an idea is good but belongs in a later project, rather than by feeling that refusing it is a failure of ambition. The fourth risk is accessibility failure, where a dashboard that works well with a mouse on a wide screen fails for a keyboard user, a screen reader user, or a phone user, because labels, focus, landmarks, or responsive layout were treated as extras rather than as structure. The plan manages that risk by placing labels, landmarks, heading order, and responsive layout in chapter 48's structure work, by planning focus and live regions in chapter 49's behaviour work, and by including keyboard, phone, and screen reader tests in chapter 50's finishing work, so accessibility is checked at every stage, not only at the end. That staged checking matters, because an accessibility bug found at the end, when behaviour depends on the structure, is expensive to fix, while the same bug found during structure work is cheap, and a plan that checks early is therefore a plan that respects both the user and the builder's time. Finally, the plan names its deliberate limits as limits, not as shortcomings to be apologised for, because a capstone that is clear about its limits can be judged fairly, while a capstone that hides its limits will be judged harshly when they are discovered. MyDay Dashboard has no framework, no server, no account, no sync between devices, no reminders, and no sharing, and those limits are stated in the footer, in the readme, and in the case study, so no reviewer or user is misled about what the project does. Naming limits also clarifies what the next projects are for: the habit tracker and the follow-on list project reuse the same core skills, while later learning, such as fetching data or using a framework, addresses the limits that this capstone deliberately leaves in place. A plan that names its risks and its limits is a plan that can be trusted, and trust is the foundation on which the whole build rests.
Check: What four risks does this plan name, and how does its architecture manage the risk of panels disagreeing?
Section 48
What MyDay Dashboard deliberately excludes is as important as what it includes, because exclusions define the project just as surely as features do, and they protect the build from becoming a different, larger project by accident. The dashboard excludes a framework, because manual rendering with plain JavaScript is the skill this capstone is meant to practise, and because a framework would add learning, configuration, and build steps that would distract from that skill without adding a new user benefit at this scale. It excludes a server, because browser storage is sufficient for a personal dashboard, and because a server would change the project from a front-end capstone into a full-stack project, with accounts, authentication, and data sharing that the plan does not cover. Exclusions also apply at a smaller scale, inside features that are included, and the plan names several of those to prevent quiet scope growth during the build. The add-task form excludes extra fields beyond text and priority, the add-note form excludes formatting controls beyond plain title and body, the filter excludes additional filter dimensions beyond completion, the search excludes advanced search syntax beyond substring matching, and the overview excludes additional summaries beyond counts, progress, and priority bars. Each of those small exclusions follows the same test as the large ones: does the extra detail teach a new front-end concept worth its cost, or does it merely add surface area that must be styled, tested, and documented? The benefit of stating exclusions now is that later decisions become faster and less contentious, both for a solo builder and for a builder working with a reviewer or a teacher. When a suggestion arises, it can be checked against the exclusion list in seconds, and if it matches an exclusion, the response can be that the idea is saved for a later project, rather than debated from scratch each time. That speed matters during a build, because decision fatigue is a real cause of scope growth: a builder who must re-argue every addition from first principles will eventually accept one too many, while a builder with a written exclusion list can decline quickly and return to the planned work. The practical task at the end of this chapter asks you to write your own exclusion list, in your own words, precisely so you have that tool ready before the build begins, rather than trying to invent it under pressure during chapter 49. Finally, exclusions should be presented honestly in the portfolio, as choices, not as gaps to be hidden, because a reviewer who reads a case study that names its exclusions will trust its inclusions more. Chapter 50's case study therefore mentions the no-framework choice and the browser-only storage as deliberate decisions, with their trade-offs stated plainly, and the readme lists what the project does without implying that it does more. A dashboard that says what it does not do, and why, is a dashboard whose developer understands the difference between a finished project and an unfinished ambition, and that understanding is one of the most valuable outcomes of a capstone, even though it is not a feature that appears in any screenshot.
Check: What large exclusions does MyDay Dashboard make, and why does stating them in advance make later decisions faster?
Section 49
Testing the plan, before any code is written, is a habit that this chapter encourages, because a plan that cannot be tested is a plan that cannot be trusted, and testing a plan is cheaper than testing a finished project that was built from a faulty plan. The first test is the completeness test: does the plan cover every feature that chapters 48, 49, and 50 deliver, in the order they deliver them, without promising anything they do not build? Read the plan's previews of those chapters against the chapters themselves, panel by panel and feature by feature, and note any feature in the later chapters that has no home in the plan, or any feature in the plan that has no home in the later chapters. A plan that passes that test is a faithful map, while a plan that fails it will mislead the builder at the moment when the map is most needed, which is when a feature's details are forgotten and the plan is consulted for guidance. The fourth test is the definition-of-done test, which asks whether the plan states, in observable terms, when the project is finished, so that finishing is a checkable event rather than a feeling. The plan states that the project is finished when every promised feature works end to end, when panels agree after every action and after a reload, when keyboard, phone, and screen reader tests pass, when the readme is accurate, when the portfolio entry is honest, when the code is clean, and when the deployed version matches the local version, all of which are checks that chapter 50 performs. A definition of done that is observable lets a builder stop with confidence, rather than continuing to polish indefinitely or stopping prematurely with a broken feature hidden in an untested corner. It also lets a reviewer judge the project fairly, because the reviewer can apply the same checks that the builder applied, and can see that the project was finished against a standard, not merely declared finished. Finally, the plan should be tested for honesty, by asking whether every claim in it can be supported by the finished project, without exaggeration or invention. Does the dashboard really have only three files, really use no framework and no server, really store data only in the browser, really calculate its counts, and really handle empty states, storage errors, and corrupted data as described? If any claim cannot be supported, it should be corrected now, because a plan that overpromises will either force the build to chase an impossible feature or force the portfolio to repeat an untrue claim, both of which damage trust. A plan that passes completeness, journey, edge-case, definition-of-done, and honesty tests is a plan worth building from, and the practical task that follows is your chance to produce such a plan in your own words, before the build begins.
Check: What five tests can you apply to this plan before building, and which one checks edge cases?
Section 50
You are now ready to move from planning to building, and this final section gathers the plan into a checklist that you can carry into chapter 48 and check off as you go. The checklist starts with the project itself: a single page, three files, three panels, no framework, no server, browser-only storage under the key myday-data-v1, and a calm, light theme with a centred column and a grid layout that stacks on narrow screens. It continues with the panels: a tasks panel with an add-task form, a filter bar, a search box, and a list; a notes panel with an add-note form and a list with pin controls; and an overview panel with counts, a progress bar, and a bar display, with no inputs of its own. It continues with the behaviours: adding, toggling, deleting, editing, pinning, filtering, searching, sorting by priority, calculating progress, handling empty states, validating forms, delegating list events, managing focus, handling storage errors and corrupted data, exporting, and resetting, each following the change, save, and re-render pattern. If you can recite that checklist from memory, you understand the plan, and if you cannot, re-read the sections that cover the parts you missed, because the build will require that understanding at every step. Before you turn to chapter 48, complete the practical task that follows, which asks you to write your own plan for MyDay Dashboard, in your own words, covering the panels, the data, the behaviours, the build order, and the definition of done. Writing your own plan is not busywork; it is the act that turns reading a plan into understanding a plan, because writing forces you to make decisions, to notice gaps, and to state rules in your own terms, all of which are necessary before building. Keep your written plan beside you during the build, update it when a decision changes, and check the finished dashboard against it at the end, panel by panel and feature by feature, because a plan that is written, used, and checked is a tool, while a plan that is merely read is soon forgotten. Chapter 48 begins with structure, and it begins with the confidence that the structure has already been planned, which is the best possible starting point for a build. Finally, remember why this capstone matters beyond its own features, because that purpose will sustain you when the build becomes difficult, as every real build does at some point. MyDay Dashboard is a small, useful tool that you designed, built, tested, and presented yourself, using only the core front-end languages, and that experience, of taking a project from a plan to a working, presentable result, is the skill that carries into every later project, whether it is a habit tracker, a follow-on list project, a fetched-data project, or a framework project. The dashboard itself may be simple, but the ability to plan it, build it in order, test it thoroughly, and explain it honestly is not simple, and it is the ability that employers, collaborators, and future versions of yourself will value most. Turn the page, open a new folder with three empty files, and begin with the header, knowing that the plan you have just read, and the plan you are about to write, are already guiding your first steps.
Check: What does your chapter 48 starting point look like, and why should you write your own plan before building it?
Practical task
Write your own written plan for MyDay Dashboard before you build it in chapters 48, 49 and 50. Work on paper or in a plain document, not in code, and keep the plan to a length you can actually consult during the build, such as a few pages, rather than a long document you will never reopen. Start with a one-sentence job description for the dashboard, then list its three panels and, for each panel, the parts it contains, the data it shows, and the actions it supports. Next, describe the three files and the job each one owns, the app state with its four parts, the task and note data shapes, the storage key and when saving happens, and the rules for filtering, searching, priority sorting, progress calculation, and the bar display. Then set out the build order for chapters 48, 49 and 50 in your own words, including the checkpoint that ends each chapter, the working habits you will follow, such as one change at a time and testing after each step, and the exclusions you will respect, including no framework, no server, and browser-only storage. Finish with your definition of done, stated as observable tests a reviewer could run, covering adding, completing, deleting, editing, pinning, filtering, searching, reloading, keyboard use, phone-sized screens, and the readme and portfolio entry. When you have finished, read your plan back and check it against this chapter: does it preview, in order, what chapters 48, 49 and 50 actually deliver, and does it promise nothing beyond those chapters? Keep your plan beside you while you build, update it when a decision changes, and check the finished dashboard against it at the end, panel by panel and feature by feature.
Chapter questions
- What is MyDay Dashboard, what three panels does it contain, and what job does each panel do?
- What three files make up the project, what does each file own, and why must the script run after the markup exists?
- What four parts make up the app state, what storage key is used, and what should happen when stored data is corrupted?
- How do filtering, searching, and priority sorting combine to decide which tasks are visible, and how is progress calculated?
- In what order do chapters 48, 49 and 50 build and finish the project, and what observable tests define when it is done?