Build a Task Board You Can Run, Test, and Show
Computer Science
Build a Task Board You Can Run, Test, and Show
Build a Task Board You Can Run, Test, and Show
Turn your React practice into a small, useful Task Board: add tasks, view them by status, and keep the interface clear. You will finish with a Node-powered web project that installs from its committed package-lock.json with npm ci, starts in the browser, builds successfully, and has a focused automated test for its task-filtering behavior.
What you learn by building this
Build it yourself, get guided when you are stuck, and leave with proof you can actually show.
Learning Journey
Shape the Task Board Experience
2 lessonsStart from the React component and state work you have already begun, using it to make a visible board rather than studying concepts in isolation.
Turn the Screen into the Project App
1 lessonMove the working task flow into the generated Task Board application and make its main interaction reliable.
Prove the Board Is Ready to Share
1 lessonFinish with a project that is easy to inspect, reproducible from its lockfile, and demonstrably working in both the browser and command line.
Public lesson
Lay Out the Board as Focused Components
Build the static screen first: someone should understand where to add a task, how to view statuses, and what each task means before anything is clickable.
For this lesson, use a small set of focused React components:
TaskBoard— arranges the screenBoardHeader— title and short descriptionTaskEntry— task input area and buttonStatusControls— All / To do / In progress / DoneTaskCard— one task’s information
Keep this display-only for now. Buttons do not need to work yet.
Tasks
1. Create the board shell
Find the component currently rendered by your React app (often App.tsx).
Replace its current page content with a TaskBoard component. Create a file such as:
src/components/TaskBoard/TaskBoard.tsx
src/components/TaskBoard/TaskBoard.tsx
Start with this structure, filling in the imports and content yourself:
import ...
export function TaskBoard() {
return (
<main>
{/* header */}
{/* task entry */}
{/* status controls */}
{/* task cards */}
</main>
);
}
import ...
export function TaskBoard() {
return (
<main>
{/* header */}
{/* task entry */}
{/* status controls */}
{/* task cards */}
</main>
);
}
Then render <TaskBoard /> from your app.
Check: your browser still loads without a blank screen or red error overlay.
Tasks
2. Add a clear header
Create BoardHeader.tsx in the same feature folder.
It needs:
- an
<h1>with a board name, such as “My Tasks” - one short sentence explaining the board
- optional small text showing a task count, such as “3 tasks”
Use a component rather than placing this directly in TaskBoard; the header will stay separate when the board becomes more complex.
A useful shape is:
export function BoardHeader() {
return (
<header>
<h1>{/* your board title */}</h1>
<p>{/* a one-line description */}</p>
</header>
);
}
export function BoardHeader() {
return (
<header>
<h1>{/* your board title */}</h1>
<p>{/* a one-line description */}</p>
</header>
);
}
Import and place it at the top of TaskBoard.
Check: the heading is the most visually prominent text on the page.
Tasks
3. Build the task-entry area
Create a TaskEntry component with:
- a visible label, such as “New task”
- a text input
- an “Add task” button
For now, the input can be uncontrolled—do not add useState yet.
export function TaskEntry() {
return (
<section aria-labelledby="new-task-heading">
<h2 id="new-task-heading">{/* section title */}</h2>
<label>
{/* label text */}
<input
type="text"
placeholder={/* helpful example task */}
/>
</label>
<button type="button">{/* button label */}</button>
</section>
);
}
export function TaskEntry() {
return (
<section aria-labelledby="new-task-heading">
<h2 id="new-task-heading">{/* section title */}</h2>
<label>
{/* label text */}
<input
type="text"
placeholder={/* helpful example task */}
/>
</label>
<button type="button">{/* button label */}</button>
</section>
);
}
The type="button" prevents this from accidentally behaving like a form submission while it has no behavior yet.
Check: you can click into the input, type text, and see an Add task button beside or below it.
Tasks
4. Add status controls
Create StatusControls.tsx. Show four status choices:
- All
- To do
- In progress
- Done
Use buttons, since these will later change what the board displays. Give “All” a visually selected style for now.
You can repeat a small button structure manually at this stage:
<button
type="button"
aria-pressed={/* true only for the selected status */}
>
{/* status name */}
</button>
<button
type="button"
aria-pressed={/* true only for the selected status */}
>
{/* status name */}
</button>
Put the controls in a <nav aria-label="Filter tasks by status">.
Check: all four controls are visible, and inspecting the first button in DevTools shows aria-pressed="true".
Tasks
5. Make task cards from props
A task card should receive its content through props, rather than hard-coding the same markup three times.
Create TaskCard.tsx. Decide on three props:
- task title
- task status
- task priority
Write the TypeScript type yourself, then use those props in the card. Your component should contain:
- a task title, preferably an
<h3> - a status label
- a priority label
- a small action button, such as “View task” or “Edit”
Aim for this hierarchy:
<article>
<div>
<h3>{/* task title prop */}</h3>
<p>{/* priority prop */}</p>
</div>
<span>{/* status prop */}</span>
<button type="button">{/* action */}</button>
</article>
<article>
<div>
<h3>{/* task title prop */}</h3>
<p>{/* priority prop */}</p>
</div>
<span>{/* status prop */}</span>
<button type="button">{/* action */}</button>
</article>
Tasks
In TaskBoard, render at least three cards with realistic, different data. For example, use tasks from your own life or this project—not identical placeholder cards.
Check: changing the title value passed to one TaskCard changes only that card in the browser.
Tasks
6. Give the page a readable layout
Create a CSS Module next to TaskBoard, for example:
TaskBoard.module.css
TaskBoard.module.css
Import it into TaskBoard.tsx and apply class names with styles.someClass.
Style the board so it has:
- a centered content area with a maximum width
- space between the header, entry area, controls, and cards
- task cards that are visually separate from the page background
- clear contrast between the selected “All” control and the others
- status labels that are easy to scan
Tasks
For the card list, use a wrapping layout so it remains usable on narrow screens:
/* Adapt names and values to your own component */
.cardList {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(/* choose a width */, 1fr));
gap: /* choose spacing */;
}
/* Adapt names and values to your own component */
.cardList {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(/* choose a width */, 1fr));
gap: /* choose spacing */;
}
You may create separate CSS Modules for each component, or keep the first pass in TaskBoard.module.css. Use the approach you can navigate most easily.
Check: shrink the browser window. Cards should stack or reflow instead of forcing horizontal scrolling.
Tasks
7. Final visual review
Look at the page for five seconds without reading closely. You should be able to answer:
- What is this page for?
- Where would I add a task?
- Which status view is selected?
- What status and priority does each task have?
If one answer is unclear, adjust the heading, spacing, label text, or visual emphasis—not the functionality.
At the end, your board should be a static but believable task-management screen built from small components. The next step will be giving the entry area and status controls real state.
Course Outline
3 modules · 4 lessons
Shape the Task Board Experience
Turn the Screen into the Project App
Prove the Board Is Ready to Share
Learn by building your own version.
Remix this public project to open the workspace, follow the guided build, and let the AI mentor teach you through the work instead of doing it for you.