Build the ThriftHub Marketplace
Build a responsive marketplace prototype with search, filters, and reports.
Introduction
30 Second Summary
Secondhand shopping becomes frustrating when listings hide the details people need. Clear descriptions make it easier to decide whether an item deserves a closer look.
In this project, you will build a responsive ThriftHub catalog that visitors can search by text or category. You will also produce a proposal and project report that document the prototype.
What You'll Build
Your finished ThriftHub page opens as a responsive catalog where each search instantly leaves only the matching secondhand items on screen.
By the end of this project, you'll have:
- A responsive catalog that shows six item cards with readable prices and condition labels. Its semantic HTML and CSS Grid keep the page structured across wide and narrow previews.
- Working search and category filters that update the visible cards immediately. An accessible form keeps every control labeled. A polite live region announces the result count.
- Submission-ready documentation in proposal.md and report.md. The documents cover the required academic sections. They include a schedule and references. They explain the prototype through Rapid Application Development.
- Secret Mission: An optional challenge to add a labeled seller form that creates a listing for the current page session.
Are there any prerequisites?
You only need basic familiarity with files and folders. All code is provided. Visual Studio Code and its integrated browser are enough to complete the project.
Before We Start
Before any hands-on work begins, this is your moment to commit to ThriftHub's purpose and scope. ThriftHub is a free local frontend prototype plus an academic documentation package for secondhand shoppers who need clear item details. Production marketplace features and payment processing sit outside this project's scope.
Set Up the ThriftHub Workspace
ThriftHub needs one local home for its website. The same workspace will hold its academic documents.
A small file structure keeps setup from crowding out the marketplace work. Visual Studio Code can preview this static page without a runtime or package installation.
In this step, get ready to:
- Create the local ThriftHub workspace.
- Add five starter files.
- Preview the starter page in the integrated browser.
Create and open the workspace
A workspace is the folder Visual Studio Code treats as one project. Keeping every file inside thrifthub makes the links between them predictable.
- Press Windows+E to open File Explorer.
- Select Desktop in the navigation pane.
- Select New in the File Explorer toolbar.
- Select Folder.
- Name the folder thrifthub.
- Press Enter to finish creating the folder.
Your project now has a clear home on the Desktop.
- Press the Windows key to open search.
- Type Visual Studio Code into the search field.
- Press Enter to open Visual Studio Code.
- Select Open Folder on the welcome screen.
- Select Desktop in the folder dialog.
- Select the thrifthub folder.
- Confirm the folder selection.
Visual Studio Code may ask whether you trust the folder because project files can contain executable code.
- Select Yes, I trust the authors if the trust prompt appears.
You'll see the empty thrifthub workspace in the Explorer sidebar.
Why plain browser files?
HTML provides the page structure. CSS controls its presentation. JavaScript handles its behavior.
Plain files fit this prototype because the browser can read them directly. A framework would add setup that does not support the project goals.
Create the website starter files
The Explorer sidebar acts as a map of the project. Each file has one clear responsibility.
- Use the new-file control at the top of the Explorer sidebar to create index.html inside thrifthub.
- Use the same control to create styles.css inside thrifthub.
You'll see both website files listed in the Explorer sidebar.
- Create app.js inside thrifthub.
- Create proposal.md inside thrifthub.
- Create report.md inside thrifthub.
Good progress. The Explorer sidebar now shows all five project files.
- Select index.html in the Explorer sidebar.
- Build the starter page by replacing the file contents with this code:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ThriftHub | Secondhand Marketplace</title>
<link rel="stylesheet" href="styles.css">
<script src="app.js" defer></script>
</head>
<body>
<main><p>ThriftHub workspace ready.</p></main>
</body>
</html>
What does this page establish?
- The document declaration tells the browser to use modern HTML rules.
- The page title identifies the ThriftHub marketplace.
- The stylesheet link connects styles.css to the page.
- The script element loads app.js. The defer attribute waits until the page has been parsed.
- The main element holds the visible workspace message.
- Save index.html with Ctrl+S.
- Right-click index.html in the Explorer sidebar.
- Select Open in Integrated Browser.
You'll see ThriftHub workspace ready. in the preview. That first render confirms the workspace can display ThriftHub.
Preview missing the message?
- Check that index.html is saved inside the thrifthub folder.
- Check that the paragraph text matches the code above.
Ask for help with the file or preview path: Why is my integrated browser preview missing the ThriftHub workspace message?
The browser already applies default styles. A short CSS rule gives the starter page a consistent font across the project.
- Select styles.css in the Explorer sidebar.
- Set the starter font by adding this code:
body{font-family:Arial,Helvetica,sans-serif;}
What does this style do?
The rule gives the page an Arial font when it is available. Helvetica or a system sans-serif font provides the fallback.
- Save styles.css.
- Return to the integrated browser from earlier.
- Refresh the preview.
You'll see the workspace message use a clean sans-serif font.
Font still looks unchanged?
- Check that the filename is exactly styles.css.
- Check that index.html contains the stylesheet link shown above.
Get help tracing the stylesheet connection: Why is styles.css not changing the font in my ThriftHub preview?
A console message gives JavaScript a small observable result. It confirms that the browser loaded app.js.
- Select app.js in the Explorer sidebar.
- Add the workspace message with this code:
console.log("ThriftHub workspace ready");
What does this script do?
The console.log() call writes a message to the browser's developer console. This proves that index.html found the script file.
- Save app.js.
- Return to the integrated browser.
- Refresh the page.
- Select Toggle Developer Tools in the browser toolbar.
You'll see ThriftHub workspace ready in the console output.
Console message missing?
- Check that the script filename is exactly app.js.
- Check that index.html contains the script element shown above.
- Refresh the integrated browser after saving both files.
Get help tracing the script connection: Why is my app.js console message missing from the integrated browser?
Finish the documentation starters
Markdown uses plain text symbols to structure documents. These starter headings give the proposal and report distinct academic purposes.
- Select proposal.md in the Explorer sidebar.
- Add the proposal title with this content:
# THRIFTHUB
## A Frontend Prototype for a Secondhand Marketplace
Project Proposal
What does this starter define?
The first heading names the project. The second heading describes the prototype.
The final line identifies this document as the project proposal.
- Save proposal.md.
You'll see the project title followed by the prototype subtitle and proposal label.
- Select report.md in the Explorer sidebar.
- Add the report title with this content:
# THRIFTHUB WEBSITE PROJECT REPORT
## A Frontend Prototype for a Secondhand Marketplace
What does this starter define?
The main heading identifies the website project report. The subtitle keeps its scope focused on the frontend prototype.
- Save report.md.
You'll see a report title followed by the same prototype subtitle used in the proposal.
- Choose the tab that matches how you want to check the five starter files.
✔️ Awesome, I've got everything!
Great. Confirm that all five files are saved in the thrifthub workspace.
ⓧ I'd like to double check the full code
Compare each file with the complete starter content below.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ThriftHub | Secondhand Marketplace</title>
<link rel="stylesheet" href="styles.css">
<script src="app.js" defer></script>
</head>
<body>
<main><p>ThriftHub workspace ready.</p></main>
</body>
</html>
Index File Role
This complete file connects the page structure to its stylesheet and script.
body{font-family:Arial,Helvetica,sans-serif;}
Stylesheet Role
This complete file supplies the starter font stack.
console.log("ThriftHub workspace ready");
Script Role
This complete file confirms that the browser loaded the JavaScript.
# THRIFTHUB
## A Frontend Prototype for a Secondhand Marketplace
Project Proposal
Proposal Role
This complete file establishes the proposal title and prototype scope.
# THRIFTHUB WEBSITE PROJECT REPORT
## A Frontend Prototype for a Secondhand Marketplace
Report Role
This complete file establishes the report title and prototype scope.
Before you run the final check, do you expect one local folder to provide both the page preview and the document starters?
- Right-click index.html in the Explorer sidebar.
- Select Open in Integrated Browser.
The preview shows ThriftHub workspace ready. Your five-file workspace is now connected and ready to expand.
Your ThriftHub foundation is ready. Next you'll turn the starter message into a responsive six-item marketplace catalog.
Build the Marketplace Catalog
Your thrifthub workspace already proves that the page loads inside Visual Studio Code. The next goal is to turn that starter message into a marketplace shoppers can understand at a glance.
Search has value once shoppers can see a clear catalog. This step creates that recognizable marketplace with six secondhand listings.
Semantic HTML gives each part of the page a meaningful role. CSS Grid keeps the listings readable across wide and narrow previews.
In this step, get ready to:
- Build semantic page regions with six static listing cards.
- Apply the ThriftHub colors and component styles.
- Confirm that the catalog adapts to a narrow preview.
Build the semantic page and listings
Each article represents one independent listing. The surrounding page regions help browsers understand where navigation, primary content, supporting information, and the footer belong.
- Select index.html in the Explorer sidebar.
- Replace the contents of index.html by pasting the code below:
<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="ThriftHub frontend secondhand marketplace prototype."><title>ThriftHub | Secondhand Marketplace</title><link rel="stylesheet" href="styles.css"><script src="app.js" defer></script></head>
<body>
<a class="skip-link" href="#mainContent">Skip to main content</a>
<header class="site-header"><a class="brand" href="#top">ThriftHub</a><nav aria-label="Primary navigation"><a href="#marketplace">Browse</a><a href="#about">About</a></nav></header>
<main id="mainContent">
<section class="hero" id="top"><p class="eyebrow">Pre-loved goods, new possibilities</p><h1>Find your next favorite secondhand item</h1><p>Browse affordable finds with clear condition details.</p><a class="button-link" href="#marketplace">Browse listings</a></section>
<section class="marketplace" id="marketplace">
<p class="eyebrow">Marketplace</p><h2>Browse secondhand finds</h2>
<div id="productGrid" class="product-grid">
<article class="product-card"><div class="product-visual">DJ</div><div class="product-content"><p class="eyebrow">Clothing</p><h3>Vintage Denim Jacket</h3><span class="condition">Good condition</span><p>Classic blue denim with light wear and a relaxed fit.</p><p class="price">$18</p><button>View item</button></div></article>
<article class="product-card"><div class="product-visual">LS</div><div class="product-content"><p class="eyebrow">Accessories</p><h3>Leather Satchel</h3><span class="condition">Very good condition</span><p>Structured brown satchel with an adjustable shoulder strap.</p><p class="price">$24</p><button>View item</button></div></article>
<article class="product-card"><div class="product-visual">CV</div><div class="product-content"><p class="eyebrow">Home</p><h3>Ceramic Vase</h3><span class="condition">Good condition</span><p>Neutral glazed vase suited to shelves, desks, or flowers.</p><p class="price">$12</p><button>View item</button></div></article>
<article class="product-card"><div class="product-visual">DL</div><div class="product-content"><p class="eyebrow">Home</p><h3>Retro Desk Lamp</h3><span class="condition">Fair condition</span><p>Compact green lamp with visible character from regular use.</p><p class="price">$15</p><button>View item</button></div></article>
<article class="product-card"><div class="product-visual">CS</div><div class="product-content"><p class="eyebrow">Footwear</p><h3>Classic Sneakers</h3><span class="condition">Good condition</span><p>Everyday low-top sneakers with clean soles and soft lining.</p><p class="price">$20</p><button>View item</button></div></article>
<article class="product-card"><div class="product-visual">PB</div><div class="product-content"><p class="eyebrow">Books</p><h3>Paperback Bundle</h3><span class="condition">Very good condition</span><p>Four contemporary novels with tidy covers and pages.</p><p class="price">$10</p><button>View item</button></div></article>
</div>
</section>
<section class="about" id="about"><p class="eyebrow">About</p><h2>A focused circular-shopping prototype</h2><p>Listings and prices are illustrative. This site does not process accounts, messages, payments, delivery, or permanent data.</p></section>
</main>
<footer><p>ThriftHub frontend prototype for academic demonstration.</p></footer>
</body></html>
What does this HTML establish?
- The header holds the brand and primary navigation.
- The main element contains the hero, marketplace, and about sections.
- Each article.product-card keeps one item's details together.
- The skip link gives keyboard users a direct route to mainContent.
- Save index.html.
- Switch back to the integrated browser preview from the previous step.
- Refresh the preview.
You'll see the hero text followed by six unstyled listings. You now have the complete catalog structure that the visual design can build on.
Missing a listing or page region?
- Confirm that all six article elements sit inside productGrid.
- Check that the closing tags after Paperback Bundle match the code above.
- Save index.html before refreshing the preview.
Help me compare my semantic catalog markup with the expected structure.
✔️ Awesome, I've got everything!
Your saved index.html now contains the full static marketplace structure.
ⓧ I'd like to double check the full code
The complete index.html file should match this structure.
<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="ThriftHub frontend secondhand marketplace prototype."><title>ThriftHub | Secondhand Marketplace</title><link rel="stylesheet" href="styles.css"><script src="app.js" defer></script></head>
<body>
<a class="skip-link" href="#mainContent">Skip to main content</a>
<header class="site-header"><a class="brand" href="#top">ThriftHub</a><nav aria-label="Primary navigation"><a href="#marketplace">Browse</a><a href="#about">About</a></nav></header>
<main id="mainContent">
<section class="hero" id="top"><p class="eyebrow">Pre-loved goods, new possibilities</p><h1>Find your next favorite secondhand item</h1><p>Browse affordable finds with clear condition details.</p><a class="button-link" href="#marketplace">Browse listings</a></section>
<section class="marketplace" id="marketplace">
<p class="eyebrow">Marketplace</p><h2>Browse secondhand finds</h2>
<div id="productGrid" class="product-grid">
<article class="product-card"><div class="product-visual">DJ</div><div class="product-content"><p class="eyebrow">Clothing</p><h3>Vintage Denim Jacket</h3><span class="condition">Good condition</span><p>Classic blue denim with light wear and a relaxed fit.</p><p class="price">$18</p><button>View item</button></div></article>
<article class="product-card"><div class="product-visual">LS</div><div class="product-content"><p class="eyebrow">Accessories</p><h3>Leather Satchel</h3><span class="condition">Very good condition</span><p>Structured brown satchel with an adjustable shoulder strap.</p><p class="price">$24</p><button>View item</button></div></article>
<article class="product-card"><div class="product-visual">CV</div><div class="product-content"><p class="eyebrow">Home</p><h3>Ceramic Vase</h3><span class="condition">Good condition</span><p>Neutral glazed vase suited to shelves, desks, or flowers.</p><p class="price">$12</p><button>View item</button></div></article>
<article class="product-card"><div class="product-visual">DL</div><div class="product-content"><p class="eyebrow">Home</p><h3>Retro Desk Lamp</h3><span class="condition">Fair condition</span><p>Compact green lamp with visible character from regular use.</p><p class="price">$15</p><button>View item</button></div></article>
<article class="product-card"><div class="product-visual">CS</div><div class="product-content"><p class="eyebrow">Footwear</p><h3>Classic Sneakers</h3><span class="condition">Good condition</span><p>Everyday low-top sneakers with clean soles and soft lining.</p><p class="price">$20</p><button>View item</button></div></article>
<article class="product-card"><div class="product-visual">PB</div><div class="product-content"><p class="eyebrow">Books</p><h3>Paperback Bundle</h3><span class="condition">Very good condition</span><p>Four contemporary novels with tidy covers and pages.</p><p class="price">$10</p><button>View item</button></div></article>
</div>
</section>
<section class="about" id="about"><p class="eyebrow">About</p><h2>A focused circular-shopping prototype</h2><p>Listings and prices are illustrative. This site does not process accounts, messages, payments, delivery, or permanent data.</p></section>
</main>
<footer><p>ThriftHub frontend prototype for academic demonstration.</p></footer>
</body></html>
Style the ThriftHub frame
CSS variables give the page one reusable color palette. The base rules also make links, buttons, and keyboard focus states visually consistent.
- Select styles.css in the Explorer sidebar.
- Replace the contents of styles.css by pasting the foundation styles below:
:root{--ink:#17211b;--muted:#5f6d64;--paper:#fbfaf6;--surface:#fff;--forest:#24523b;--dark:#173b2a;--sage:#dce9df;--sand:#f0e7d6;--line:#d8ded9;--shadow:0 14px 36px rgba(23,33,27,.1)}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;color:var(--ink);background:var(--paper);font-family:Arial,Helvetica,sans-serif;line-height:1.6}
a{color:inherit}
button,input,select{font:inherit}
button,.button-link{border:0;border-radius:999px;padding:.8rem 1.15rem;color:#fff;background:var(--forest);cursor:pointer;font-weight:700;text-decoration:none}
button:hover,.button-link:hover{background:var(--dark)}
a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible{outline:3px solid #b45f06;outline-offset:3px}
.skip-link{position:absolute;left:1rem;top:-5rem;z-index:10;padding:.7rem 1rem;color:#fff;background:var(--dark)}
.skip-link:focus{top:1rem}
.site-header{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:1rem clamp(1rem,5vw,5rem);background:var(--surface);border-bottom:1px solid var(--line)}
.brand{color:var(--dark);font-size:1.45rem;font-weight:800;text-decoration:none}
nav{display:flex;gap:1rem}
nav a{font-weight:700;text-decoration:none}
What does this CSS establish?
- The variables keep ThriftHub's colors and shadow consistent.
- The global rules create predictable sizing and typography.
- The focus rule gives keyboard users a visible orange outline.
- The header rules separate the brand from the navigation.
- Save styles.css.
- Switch back to the integrated browser preview.
- Refresh the preview.
- Press Tab to move keyboard focus through the links.
You'll see a spaced white header with a dark green brand. The focused link receives a visible orange outline.
Still seeing plain browser styles?
- Confirm that index.html still links to styles.css.
- Check that styles.css is saved inside the thrifthub folder.
- Refresh the integrated browser after saving the stylesheet.
Help me find why my ThriftHub stylesheet is not appearing.
The page frame now has a visual identity. The next CSS chunk turns the six listings into responsive cards.
- Append the catalog styles to the bottom of styles.css by pasting the code below:
.hero,.marketplace,.about{padding:clamp(3rem,8vw,6rem) clamp(1rem,6vw,6rem)}
.hero{min-height:65vh;display:grid;align-content:center;justify-items:start;background:linear-gradient(135deg,var(--sage),var(--sand))}
.hero h1{max-width:760px;margin:0 0 1rem;font-size:clamp(2.4rem,7vw,5rem);line-height:1.02}
.hero>p:not(.eyebrow){margin:0 0 1.5rem;font-size:1.1rem}
.eyebrow{margin:0 0 .5rem;color:var(--forest);font-size:.8rem;font-weight:800;letter-spacing:.12em;text-transform:uppercase}
h2{margin-top:0;font-size:clamp(1.8rem,4vw,3rem)}
.product-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:1.25rem}
.product-card{overflow:hidden;background:var(--surface);border:1px solid var(--line);border-radius:20px;box-shadow:var(--shadow)}
.product-visual{min-height:160px;display:grid;place-items:center;color:var(--dark);background:linear-gradient(135deg,var(--sage),var(--sand));font-size:2rem;font-weight:800}
.product-content{padding:1.1rem}
.product-content h3{margin:0 0 .45rem}
.condition{display:inline-block;margin-bottom:.5rem;border-radius:999px;padding:.25rem .65rem;color:var(--dark);background:var(--sage);font-size:.8rem;font-weight:800}
.price{color:var(--dark);font-size:1.3rem;font-weight:800}
.product-content button{width:100%}
.about{background:var(--sage)}
footer{padding:1.5rem;color:#fff;background:var(--dark);text-align:center}
@media(max-width:720px){.site-header{align-items:flex-start;flex-direction:column}}
How does the catalog respond?
- The section rules give the hero and catalog room to breathe.
- The grid creates as many columns as the available width can hold.
- The card rules separate each item's visual label from its details.
- The media rule stacks the header when the preview becomes narrow.
- Save styles.css.
- Switch back to the integrated browser preview.
- Refresh the preview.
You'll see a green and sand hero followed by six white listing cards. Each card now has a condition badge, a bold price, and a full-width button.
Cards still appearing as plain text?
- Confirm that the grid uses the class name product-grid.
- Check that every listing uses the class name product-card.
- Look for a missing closing brace near the end of styles.css.
Help me diagnose why my ThriftHub product cards are not styled.
✔️ Awesome, I've got everything!
Your saved styles.css now contains the complete catalog styling.
ⓧ I'd like to double check the full code
The complete styles.css file should match this version.
:root{--ink:#17211b;--muted:#5f6d64;--paper:#fbfaf6;--surface:#fff;--forest:#24523b;--dark:#173b2a;--sage:#dce9df;--sand:#f0e7d6;--line:#d8ded9;--shadow:0 14px 36px rgba(23,33,27,.1)}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;color:var(--ink);background:var(--paper);font-family:Arial,Helvetica,sans-serif;line-height:1.6}
a{color:inherit}
button,input,select{font:inherit}
button,.button-link{border:0;border-radius:999px;padding:.8rem 1.15rem;color:#fff;background:var(--forest);cursor:pointer;font-weight:700;text-decoration:none}
button:hover,.button-link:hover{background:var(--dark)}
a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible{outline:3px solid #b45f06;outline-offset:3px}
.skip-link{position:absolute;left:1rem;top:-5rem;z-index:10;padding:.7rem 1rem;color:#fff;background:var(--dark)}
.skip-link:focus{top:1rem}
.site-header{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:1rem clamp(1rem,5vw,5rem);background:var(--surface);border-bottom:1px solid var(--line)}
.brand{color:var(--dark);font-size:1.45rem;font-weight:800;text-decoration:none}
nav{display:flex;gap:1rem}
nav a{font-weight:700;text-decoration:none}
.hero,.marketplace,.about{padding:clamp(3rem,8vw,6rem) clamp(1rem,6vw,6rem)}
.hero{min-height:65vh;display:grid;align-content:center;justify-items:start;background:linear-gradient(135deg,var(--sage),var(--sand))}
.hero h1{max-width:760px;margin:0 0 1rem;font-size:clamp(2.4rem,7vw,5rem);line-height:1.02}
.hero>p:not(.eyebrow){margin:0 0 1.5rem;font-size:1.1rem}
.eyebrow{margin:0 0 .5rem;color:var(--forest);font-size:.8rem;font-weight:800;letter-spacing:.12em;text-transform:uppercase}
h2{margin-top:0;font-size:clamp(1.8rem,4vw,3rem)}
.product-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:1.25rem}
.product-card{overflow:hidden;background:var(--surface);border:1px solid var(--line);border-radius:20px;box-shadow:var(--shadow)}
.product-visual{min-height:160px;display:grid;place-items:center;color:var(--dark);background:linear-gradient(135deg,var(--sage),var(--sand));font-size:2rem;font-weight:800}
.product-content{padding:1.1rem}
.product-content h3{margin:0 0 .45rem}
.condition{display:inline-block;margin-bottom:.5rem;border-radius:999px;padding:.25rem .65rem;color:var(--dark);background:var(--sage);font-size:.8rem;font-weight:800}
.price{color:var(--dark);font-size:1.3rem;font-weight:800}
.product-content button{width:100%}
.about{background:var(--sage)}
footer{padding:1.5rem;color:#fff;background:var(--dark);text-align:center}
@media(max-width:720px){.site-header{align-items:flex-start;flex-direction:column}}
Test the responsive catalog
Responsive layouts adapt to the space available in the preview. A narrow check confirms that the catalog remains usable without hiding item information.
Before you resize the preview, how many columns do you expect the catalog to keep at a narrow width?
- Switch back to the integrated browser preview.
- Refresh the preview.
- Count the visible listing cards.
- Drag the preview edge inward until its width is below 720px.
- Check the item names, condition badges, descriptions, and prices at the narrow width.
You'll see the hero followed by all six styled cards. The cards rearrange into fewer columns while every listing detail remains readable.
That is the marketplace foundation working: shoppers can scan the catalog at different screen widths without losing the information that describes each item.
Your responsive catalog now presents six clearly described secondhand items. Next, you'll add controls that reveal the missing search and filtering behavior.
Add Search and Category Controls
Your six-card catalog is already visible in Visual Studio Code. Visitors can browse the listings across wide and narrow previews.
A larger catalog needs controls that help visitors narrow what they see. This step adds those controls before testing whether the catalog responds to them.
In this step, get ready to:
- Add a labeled search field to the marketplace.
- Add a category selector with feedback elements.
- Test whether the six static cards respond to the controls.
Add the filter toolbar
An accessible form gives every control a visible label. Each label connects to its control through matching for and id values.
- Switch back to index.html in the editor.
- Find the marketplace heading that contains Browse secondhand finds.
- Place the filter toolbar directly below that heading by adding this code:
<form class="toolbar" id="filterForm" role="search">
<div class="field"><label for="searchInput">Search listings</label><input id="searchInput" name="search" type="search" placeholder="Try denim, lamp, or books"></div>
<div class="field"><label for="categoryFilter">Category</label><select id="categoryFilter" name="category"><option value="All">All categories</option><option value="Clothing">Clothing</option><option value="Accessories">Accessories</option><option value="Home">Home</option><option value="Footwear">Footwear</option><option value="Books">Books</option></select></div>
<button type="submit">Apply filters</button>
</form>
What does this form do?
- The role="search" value identifies the toolbar as the page's search area.
- The searchInput field collects words such as denim.
- The categoryFilter selector offers the five catalog categories plus an option for every listing.
- The submit button gives visitors a clear way to apply their choices.
- Save index.html.
- Return to the integrated browser preview from earlier.
- Refresh the preview.
You should see the labeled search field and category selector above the six cards. The toolbar is now part of the marketplace.
Do not see the toolbar?
- Check that the form sits inside section.marketplace.
- Confirm that every opening form or division tag has a matching closing tag.
Ask for help checking the form structure if the preview still looks unchanged: Help me check where my ThriftHub filter form belongs in index.html and find any unmatched HTML tags.
Add feedback and responsive styling
The control panel also needs space for live feedback. A polite live region can announce a changing result count without interrupting the visitor's current task.
- Find the first static article.product-card in index.html.
- Place the first line below directly above that article.
- Place the second line directly below the Paperback Bundle article:
<p id="resultCount" class="result-count" aria-live="polite"></p>
<p id="emptyState" class="empty-state">No listings match those filters. Try another search or category.</p>
What do these elements provide?
- The empty resultCount paragraph reserves a place for the number of matching listings.
- The aria-live="polite" value makes future count updates available to assistive technology.
- The emptyState paragraph provides guidance when no listings match.
- Save index.html.
- Return to the integrated browser preview.
- Refresh the preview.
You should see the no-results message beneath the cards for the moment. The next edit hides that message until a future filter produces zero matches.
Responsive CSS keeps the controls aligned on wide previews. It stacks them into one column when the available space becomes narrow.
- Switch back to styles.css in the editor.
- Add the first two lines below immediately before the existing narrow-screen media rule.
- Replace the existing narrow-screen media rule with the final line below:
.toolbar{display:grid;grid-template-columns:minmax(0,2fr) minmax(180px,1fr) auto;align-items:end;gap:1rem;margin:2rem 0 1rem;padding:1rem;background:var(--surface);border:1px solid var(--line);border-radius:18px;box-shadow:var(--shadow)}.field{display:grid;gap:.35rem}.field label{font-weight:700}.field input,.field select{width:100%;min-height:46px;border:1px solid #9daaa1;border-radius:10px;padding:.65rem .75rem;background:#fff}.result-count{min-height:1.5rem;color:var(--muted);font-weight:700}
.empty-state{display:none;padding:1rem;text-align:center;background:var(--sand)}.empty-state.show{display:block}
@media(max-width:720px){.site-header{align-items:flex-start;flex-direction:column}.toolbar{grid-template-columns:1fr}.toolbar button{width:100%}}
What does this styling do?
- The .toolbar grid gives more space to the search field while keeping the selector and button aligned.
- The .field rules place each visible label above its control.
- The .empty-state rule hides the no-results message until the show class is added.
- The narrow-screen rule stacks the toolbar controls into one column.
- Save styles.css.
- Return to the integrated browser preview.
- Refresh the preview.
- Narrow the preview to test the responsive toolbar.
You should see a bordered control panel above the six cards. On a narrow preview, the search field, category selector, and button should stack without becoming difficult to read.
Does the toolbar stay in one row?
- Confirm that the updated @media(max-width:720px) rule appears at the end of styles.css.
- Check that the form uses the toolbar class.
- Check that each label and control pair sits inside an element with the field class.
Ask for help comparing the toolbar classes if the controls do not stack: Help me compare my ThriftHub toolbar HTML with its responsive CSS classes.
Prove the controls are inactive
Before you test the toolbar, do you think changing both controls will alter the six cards?
- Enter denim in the Search listings field.
- Select Home from the Category selector.
- Click Apply filters.
You will still see all six static cards. The count remains blank.
What did this test prove?
The controls collect values, but no code reads those values yet. The unchanged catalog exposes the missing interaction.
The next step adds JavaScript that filters the product data and renders the matching cards.
✔️ Awesome, I've got everything!
Your toolbar is styled and responsive. Your test also confirms that all six static cards remain visible.
ⓧ I'd like to double check the full code
Compare the marketplace additions in index.html with these exact sections.
<form class="toolbar" id="filterForm" role="search">
<div class="field"><label for="searchInput">Search listings</label><input id="searchInput" name="search" type="search" placeholder="Try denim, lamp, or books"></div>
<div class="field"><label for="categoryFilter">Category</label><select id="categoryFilter" name="category"><option value="All">All categories</option><option value="Clothing">Clothing</option><option value="Accessories">Accessories</option><option value="Home">Home</option><option value="Footwear">Footwear</option><option value="Books">Books</option></select></div>
<button type="submit">Apply filters</button>
</form>
<p id="resultCount" class="result-count" aria-live="polite"></p>
<p id="emptyState" class="empty-state">No listings match those filters. Try another search or category.</p>
Compare the new control styles in styles.css with these exact rules.
.toolbar{display:grid;grid-template-columns:minmax(0,2fr) minmax(180px,1fr) auto;align-items:end;gap:1rem;margin:2rem 0 1rem;padding:1rem;background:var(--surface);border:1px solid var(--line);border-radius:18px;box-shadow:var(--shadow)}.field{display:grid;gap:.35rem}.field label{font-weight:700}.field input,.field select{width:100%;min-height:46px;border:1px solid #9daaa1;border-radius:10px;padding:.65rem .75rem;background:#fff}.result-count{min-height:1.5rem;color:var(--muted);font-weight:700}
.empty-state{display:none;padding:1rem;text-align:center;background:var(--sand)}.empty-state.show{display:block}
@media(max-width:720px){.site-header{align-items:flex-start;flex-direction:column}.toolbar{grid-template-columns:1fr}.toolbar button{width:100%}}
You have exposed the catalog's missing behavior through a real test. Next, you will replace the static cards with product data and make both controls work.
Make Search and Filtering Work
Your catalog now looks like a marketplace. Its controls still leave all six cards untouched.
This step moves the listings into JavaScript. The page can then render matches for the current search. It also respects the selected category.
In this step, get ready to:
- Store the six listings as JavaScript data.
- Render card elements from product objects.
- Filter the rendered listings using both controls.
Replace static cards with an empty grid
The static cards helped expose the missing interaction. The same grid now becomes a target that JavaScript can refill.
- Switch back to index.html in Visual Studio Code.
- Find the productGrid container inside the marketplace section.
- Remove the six article.product-card elements from that container.
- Leave the empty container as shown below:
<div id="productGrid" class="product-grid"></div>
What Changes Here?
The empty productGrid becomes the destination for generated cards. Your product data can now decide which cards appear.
- Save index.html.
- Refresh the integrated browser preview.
You'll see the toolbar with no item cards underneath it. This confirms that the six static cards are gone.
Still Seeing the Static Cards?
Check that every product article was removed from inside productGrid. Keep the grid container itself in place.
Save index.html before refreshing the preview.
Help me restore the empty product grid.
✔️ Awesome, I've got everything!
Your saved index.html now contains an empty productGrid for JavaScript to populate.
ⓧ I'd like to double check the full code
Compare your saved index.html with this complete version.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="ThriftHub frontend secondhand marketplace prototype.">
<title>ThriftHub | Secondhand Marketplace</title>
<link rel="stylesheet" href="styles.css">
<script src="app.js" defer></script>
</head>
<body>
<a class="skip-link" href="#mainContent">Skip to main content</a>
<header class="site-header">
<a class="brand" href="#top">ThriftHub</a>
<nav aria-label="Primary navigation"><a href="#marketplace">Browse</a><a href="#about">About</a></nav>
</header>
<main id="mainContent">
<section class="hero" id="top">
<p class="eyebrow">Pre-loved goods, new possibilities</p>
<h1>Find your next favorite secondhand item</h1>
<p>Browse affordable finds with clear condition details.</p>
<a class="button-link" href="#marketplace">Browse listings</a>
</section>
<section class="marketplace" id="marketplace">
<p class="eyebrow">Marketplace</p><h2>Browse secondhand finds</h2>
<form class="toolbar" id="filterForm" role="search">
<div class="field"><label for="searchInput">Search listings</label><input id="searchInput" name="search" type="search" placeholder="Try denim, lamp, or books"></div>
<div class="field"><label for="categoryFilter">Category</label><select id="categoryFilter" name="category"><option value="All">All categories</option><option value="Clothing">Clothing</option><option value="Accessories">Accessories</option><option value="Home">Home</option><option value="Footwear">Footwear</option><option value="Books">Books</option></select></div>
<button type="submit">Apply filters</button>
</form>
<p id="resultCount" class="result-count" aria-live="polite"></p>
<div id="productGrid" class="product-grid"></div>
<p id="emptyState" class="empty-state">No listings match those filters. Try another search or category.</p>
</section>
<section class="about" id="about">
<p class="eyebrow">About</p><h2>A focused circular-shopping prototype</h2>
<p>Listings and prices are illustrative. This site does not process accounts, messages, payments, delivery, or permanent data.</p>
</section>
</main>
<footer><p>ThriftHub frontend prototype for academic demonstration.</p></footer>
</body>
</html>
How to Use This Reference
Use this complete file to compare the marketplace structure around productGrid. The other page sections remain unchanged.
Render product cards from data
A product object keeps one listing's details together. The DOM references connect that data to the existing page elements.
- Switch back to app.js.
- Replace the existing console line with this catalog data and these page references:
let products = [
{name:"Vintage Denim Jacket",category:"Clothing",condition:"Good",description:"Classic blue denim with light wear and a relaxed fit.",price:"$18",shortName:"DJ"},
{name:"Leather Satchel",category:"Accessories",condition:"Very good",description:"Structured brown satchel with an adjustable shoulder strap.",price:"$24",shortName:"LS"},
{name:"Ceramic Vase",category:"Home",condition:"Good",description:"Neutral glazed vase suited to shelves, desks, or flowers.",price:"$12",shortName:"CV"},
{name:"Retro Desk Lamp",category:"Home",condition:"Fair",description:"Compact green lamp with visible character from regular use.",price:"$15",shortName:"DL"},
{name:"Classic Sneakers",category:"Footwear",condition:"Good",description:"Everyday low-top sneakers with clean soles and soft lining.",price:"$20",shortName:"CS"},
{name:"Paperback Bundle",category:"Books",condition:"Very good",description:"Four contemporary novels with tidy covers and pages.",price:"$10",shortName:"PB"}
];
const productGrid=document.querySelector("#productGrid");
const searchInput=document.querySelector("#searchInput");
const categoryFilter=document.querySelector("#categoryFilter");
const filterForm=document.querySelector("#filterForm");
const resultCount=document.querySelector("#resultCount");
const emptyState=document.querySelector("#emptyState");
What Does This Code Do?
- The products array stores the six listing objects.
- Each object contains the text needed for one complete product card.
- The constants store references to the grid and controls that the next functions update.
Why Plain JavaScript?
This static website runs directly from HTML, CSS, and JavaScript. The approach keeps the filtering logic visible without adding a runtime or package installation.
- Save app.js.
- Refresh the integrated browser preview.
- Open the preview's developer console from its toolbar.
- Evaluate the catalog array by entering:
products
What Does This Check?
Evaluating products reads the array now held by the page. It confirms that the product data loaded before you build any cards.
You'll see an array containing six product objects. Each object includes a name, category, condition, description, price, and short name.
Can't Inspect the Product Array?
Confirm that app.js is saved. Refresh the preview before evaluating the array again.
Check the array's opening bracket and closing bracket if the page reports a syntax problem.
Help me find the problem in my product array.
The product data now needs a reusable card recipe. One function can create the same semantic structure for every object.
- Add createProductCard below the page references by copying this code:
function createProductCard(product){
const card=document.createElement("article");card.className="product-card";
const visual=document.createElement("div");visual.className="product-visual";visual.textContent=product.shortName;
const content=document.createElement("div");content.className="product-content";
const title=document.createElement("h3");title.textContent=product.name;
const condition=document.createElement("span");condition.className="condition";condition.textContent=`${product.condition} condition`;
const description=document.createElement("p");description.textContent=product.description;
const price=document.createElement("p");price.className="price";price.textContent=product.price;
const button=document.createElement("button");button.textContent="View item";
content.append(title,condition,description,price,button);card.append(visual,content);return card;
}
How Does the Card Recipe Work?
- The function creates one semantic article for each product.
- Text properties copy safe listing values into the card elements.
- The final line assembles the card before returning it to the renderer.
- Save app.js.
- Refresh the integrated browser preview.
- Evaluate the card function in the developer console by entering:
createProductCard
What Does This Check?
Evaluating createProductCard asks the browser to display the loaded function. This confirms that the card recipe is available to the page.
You'll see the function definition in the console. The catalog remains empty until the renderer calls that function for each product.
Can't See the Card Function?
Check that createProductCard sits after the page references in app.js.
Compare every closing parenthesis and brace with the code above.
Help me load the product card function.
The renderer turns an array into visible cards. It also keeps the result count and empty state synchronized with that array.
- Add renderProducts below createProductCard by copying this code:
function renderProducts(items){
productGrid.textContent="";
for(const product of items){productGrid.append(createProductCard(product));}
resultCount.textContent=`${items.length} listing${items.length===1?"":"s"} found`;
emptyState.className=items.length===0?"empty-state show":"empty-state";
}
What Does the Renderer Do?
- The grid is cleared before each render so old results cannot remain.
- The loop creates one card for every item it receives.
- The count uses singular wording for one result.
- The empty-state class changes when the received array has no items.
- Add the initial render call at the bottom of app.js using this line:
renderProducts(products);
Why Call the Renderer Once?
The initial call gives the renderer all six products when the page loads. This restores the full catalog from JavaScript data.
- Save app.js.
Before you refresh, how many cards do you expect the product array to produce?
- Refresh the integrated browser preview.
You'll see all six styled cards again. The result count reads 6 listings found.
Cards Did Not Return?
Confirm that renderProducts(products); appears after both functions.
Check that the page still contains productGrid. The identifier must match the JavaScript reference.
Help me restore the six rendered cards.
Connect search and category filters
The catalog can now rebuild itself from any array. The filtering function creates that array by checking the search text and selected category.
- Add filterProducts below renderProducts using this code:
function filterProducts(){
const query=searchInput.value.toLowerCase();const selectedCategory=categoryFilter.value;
const filtered=products.filter((product)=>{
const text=`${product.name} ${product.description} ${product.condition}`.toLowerCase();
return text.includes(query)&&(selectedCategory==="All"||product.category===selectedCategory);
});
renderProducts(filtered);
}
How Does Filtering Work?
- The search value and listing text become lowercase before comparison.
- A product passes the text check when its combined details include the query.
- A product passes the category check when All is selected or its category matches.
- The filtered array is sent to the existing renderer.
- Find the initial render call at the bottom of app.js:
renderProducts(products);
What Does This Line Do Now?
This line loads all six listings once. It currently has no listeners above it to react to the controls.
- Replace that final line with these listeners and the same initial render call:
searchInput.addEventListener("input",filterProducts);
categoryFilter.addEventListener("change",filterProducts);
filterForm.addEventListener("submit",(event)=>{event.preventDefault();filterProducts();});
renderProducts(products);
How Do the Controls Trigger Filtering?
- The search listener filters after direct changes to the search value.
- The category listener filters after a category selection changes.
- The submit listener prevents the form's default navigation.
- The final call still renders all six listings when the page first loads.
- Save app.js.
Before you test the controls, which listings do you expect each filter to keep?
- Refresh the integrated browser preview.
- Enter denim in the Search listings field.
You'll see only Vintage Denim Jacket. The count reads 1 listing found.
- Delete denim from the search field.
- Select Home in the Category field.
You'll see the Ceramic Vase and Retro Desk Lamp cards. The count reads 2 listings found.
- Enter camera in the search field.
You'll see a zero-result count. The no-results message becomes visible.
- Click Apply filters.
The page stays on the marketplace. The zero-result state remains visible because the form's default navigation was prevented.
Filters Not Updating?
Check that the search listener uses input. Check that the category listener uses change.
Confirm that each selector matches the corresponding identifier in index.html.
Help me debug the ThriftHub filters.
✔️ Awesome, I've got everything!
Your saved app.js now renders the catalog and filters it through all three listeners.
ⓧ I'd like to double check the full code
Compare your saved app.js with this complete version.
let products = [
{name:"Vintage Denim Jacket",category:"Clothing",condition:"Good",description:"Classic blue denim with light wear and a relaxed fit.",price:"$18",shortName:"DJ"},
{name:"Leather Satchel",category:"Accessories",condition:"Very good",description:"Structured brown satchel with an adjustable shoulder strap.",price:"$24",shortName:"LS"},
{name:"Ceramic Vase",category:"Home",condition:"Good",description:"Neutral glazed vase suited to shelves, desks, or flowers.",price:"$12",shortName:"CV"},
{name:"Retro Desk Lamp",category:"Home",condition:"Fair",description:"Compact green lamp with visible character from regular use.",price:"$15",shortName:"DL"},
{name:"Classic Sneakers",category:"Footwear",condition:"Good",description:"Everyday low-top sneakers with clean soles and soft lining.",price:"$20",shortName:"CS"},
{name:"Paperback Bundle",category:"Books",condition:"Very good",description:"Four contemporary novels with tidy covers and pages.",price:"$10",shortName:"PB"}
];
const productGrid=document.querySelector("#productGrid");
const searchInput=document.querySelector("#searchInput");
const categoryFilter=document.querySelector("#categoryFilter");
const filterForm=document.querySelector("#filterForm");
const resultCount=document.querySelector("#resultCount");
const emptyState=document.querySelector("#emptyState");
function createProductCard(product){
const card=document.createElement("article");card.className="product-card";
const visual=document.createElement("div");visual.className="product-visual";visual.textContent=product.shortName;
const content=document.createElement("div");content.className="product-content";
const title=document.createElement("h3");title.textContent=product.name;
const condition=document.createElement("span");condition.className="condition";condition.textContent=`${product.condition} condition`;
const description=document.createElement("p");description.textContent=product.description;
const price=document.createElement("p");price.className="price";price.textContent=product.price;
const button=document.createElement("button");button.textContent="View item";
content.append(title,condition,description,price,button);card.append(visual,content);return card;
}
function renderProducts(items){
productGrid.textContent="";
for(const product of items){productGrid.append(createProductCard(product));}
resultCount.textContent=`${items.length} listing${items.length===1?"":"s"} found`;
emptyState.className=items.length===0?"empty-state show":"empty-state";
}
function filterProducts(){
const query=searchInput.value.toLowerCase();const selectedCategory=categoryFilter.value;
const filtered=products.filter((product)=>{
const text=`${product.name} ${product.description} ${product.condition}`.toLowerCase();
return text.includes(query)&&(selectedCategory==="All"||product.category===selectedCategory);
});
renderProducts(filtered);
}
searchInput.addEventListener("input",filterProducts);
categoryFilter.addEventListener("change",filterProducts);
filterForm.addEventListener("submit",(event)=>{event.preventDefault();filterProducts();});
renderProducts(products);
How to Use This Reference
Use this complete file to compare the order of the data, references, functions, listeners, and initial render call.
You closed the interaction gap. Next, you'll document the prototype's method, evidence, limitations, and results.
Complete the Proposal and Project Report
Your working ThriftHub catalog now proves that visitors can browse six listings. They can also search by text or filter by category.
The interface demonstrates feasibility. Your proposal and report explain the need, the Rapid Application Development process, the evidence, the limitations, and the next steps.
In this step, get ready to:
- Complete the proposal with its academic sections, schedule, scope, and references.
- Complete the report with its requirements, implementation, tests, limitations, and appendices.
- Personalize the title pages and verify that both documents describe a frontend prototype.
Complete the proposal
A proposal explains why a project deserves to exist before presenting its planned process and outcomes. Markdown gives the document clear headings, lists, tables, and references without extra software.
Why RAD for ThriftHub?
RAD uses short iterations that produce working application parts for testing and feedback. That approach fits ThriftHub because the catalog could be reviewed before its filtering behavior was added.
A fixed Waterfall sequence would delay interface feedback until later in the project. RAD keeps each improvement connected to something visible and testable.
- In proposal.md, replace the starter content with this title-page template:
# THRIFTHUB
## A Frontend Prototype for a Secondhand Marketplace
Project Proposal
Prepared by: [Your Name]
Student ID: [Student ID]
Institution: [Institution]
Department: [Department]
Course: [Course]
Supervisor: [Supervisor]
Submission Date: [Date]
What does this section establish?
- The two opening headings name ThriftHub and identify it as a frontend prototype.
- The remaining fields reserve space for the academic details required on the title page.
- Save proposal.md.
- Confirm that the proposal now begins with the ThriftHub title and the frontend prototype subtitle.
Does the title page look compressed?
Check that each title-page field ends with two spaces before the line break. Those spaces preserve separate lines when Markdown is rendered.
Ask for help if the spacing remains unclear: Why are my Markdown title-page fields running together?
A table of contents gives the proposal a visible structure. Its entries also create a checklist for the sections that follow.
- Add the proposal contents below the title-page details by pasting:
## Table of Contents
1. Introduction
2. Methodology
3. Scope and Limitations
4. Expected Outcomes
5. Project Schedule
6. References
What does this section establish?
The numbered contents list maps the proposal from its rationale through its references. It also keeps the document aligned with the requested academic sections.
- Save proposal.md.
- Confirm that the table of contents lists six numbered sections ending with References.
Is the contents list missing numbers?
Check that each entry starts on its own line with its number followed by a full stop. Keep a blank line between the heading and the first entry.
Ask for help with the list structure: Why is my Markdown table of contents not displaying as a numbered list?
The introduction connects the marketplace problem to measurable objectives. It also records why the project follows an iterative development process.
- Add the complete introduction below the table of contents by pasting:
## 1. Introduction
### 1.1 Introduction
ThriftHub is a proposed website for discovering clearly described secondhand clothing, accessories, footwear, books, and home items. Its frontend prototype displays names, categories, condition labels, descriptions, and prices in a responsive catalog. It demonstrates browsing without claiming to provide accounts, payments, messaging, delivery, moderation, or permanent storage.
### 1.2 Problem Statement
Secondhand listings can be fragmented, hard to browse, or unclear about condition. Buyers need consistent information and efficient discovery, while sellers need a clear listing structure. ThriftHub addresses this with reusable item cards, text search, category filtering, and accessible controls.
### 1.3 Objectives
General objective:
To design and implement a responsive frontend prototype for a secondhand marketplace named ThriftHub.
Specific objectives:
1. Present each item with a name, category, condition, description, and price.
2. Provide text search and category filtering.
3. Maintain a usable layout on wide and narrow screens.
4. Apply semantic HTML, visible labels, focus styles, and dynamic feedback.
5. Document the process, tests, limitations, and future improvements.
### 1.4 Development Methodology
The project uses Rapid Application Development. RAD emphasizes short iterations, working prototypes, and feedback. This suits an interface-driven marketplace because users can evaluate listing clarity and navigation early. Work moves from requirements to a static catalog, then to working filters, tests, and documentation.
How does the introduction support the proposal?
- The problem statement identifies inconsistent listing details and inefficient discovery as the core issues.
- The objectives convert those issues into visible prototype capabilities.
- The development methodology connects the build sequence to RAD iterations and feedback.
- Save proposal.md.
- Confirm that the introduction includes four numbered subsections and five specific objectives.
Are the introduction headings uneven?
Check that the main Introduction heading uses two hash symbols. Each numbered subsection uses three hash symbols.
Ask for help with the heading levels: How should I fix the heading hierarchy in my proposal introduction?
The next sections explain how the work was carried out and where its boundaries sit. Clear exclusions prevent the prototype from being mistaken for a production marketplace.
- Add the methodology and scope sections below the introduction by pasting:
## 2. Methodology
Requirements planning defines users, core listing fields, search, filters, constraints, and exclusions. User design creates and reviews the visible catalog. Construction uses HTML for structure, CSS for responsive presentation, and JavaScript for data, rendering, matching, counts, and feedback. Testing covers functionality, narrow screens, labels, keyboard focus, and honest scope. Documentation records evidence and recommendations.
## 3. Scope and Limitations
Included: responsive catalog, six samples, text search, category filters, condition and price details, result feedback, and documentation.
Excluded: accounts, database storage, image upload, messaging, cart, checkout, payments, delivery, moderation, disputes, and production security or privacy controls.
Why define the scope explicitly?
The methodology follows the project from requirements through documentation. The scope section draws a clear line around the browser-based demonstration.
That boundary keeps claims about ThriftHub accurate. Readers can see which features were demonstrated and which production systems remain excluded.
- Save proposal.md.
- Confirm that the scope lists the six-sample catalog as included and permanent storage as excluded.
Does the scope overstate the prototype?
Keep every excluded production feature in the final paragraph. The working catalog does not provide accounts, payments, delivery, or permanent storage.
Ask for help checking the boundary: Does my proposal describe ThriftHub as a frontend prototype accurately?
Expected outcomes describe the planned proof of success. The schedule then connects each week to one concrete deliverable.
- Add the expected outcomes and project schedule below the scope by pasting:
## 4. Expected Outcomes
The expected result is a working prototype where a visitor can browse six items, search, filter by category, see an accurate count, and receive no-results feedback. The proposal and report will explain the need, objectives, RAD process, implementation, tests, limits, and production roadmap.
## 5. Project Schedule
| Week | Activity | Deliverable |
| --- | --- | --- |
| 1 | Requirements and research | Problem, users, objectives, scope |
| 2 | Interface planning | Page and listing design |
| 3 | Frontend construction | Responsive catalog |
| 4 | Interaction development | Search, filter, feedback |
| 5 | Testing and refinement | Test record and revisions |
| 6 | Documentation | Proposal, report, demonstration |
How does the schedule support the project?
The expected outcome names the behavior a visitor can demonstrate. The six-week table then shows a progression from requirements to documentation.
- Save proposal.md.
- Confirm that the schedule contains six weeks and one deliverable for each week.
Is the schedule table misaligned?
Check that every row begins and ends with a vertical bar. Keep the separator row directly beneath the column headings.
Ask for help with the table: Why is my Markdown project schedule not rendering as a table?
References show which guidance informed the process, accessibility decisions, and marketplace context. The final proposal uses six sources.
- Finish the proposal by adding this reference section below the schedule:
## 6. References
Etsy. (2026). *Seller Policy: Our House Rules*. https://www.etsy.com/legal/sellers/
IBM. (2026, June 1). *What is rapid application development?* https://www.ibm.com/think/topics/rapid-application-development
International Organization for Standardization. (2026). *ISO/IEC/IEEE 12207:2026: Systems and software engineering - Software life cycle processes*. https://www.iso.org/standard/90219.html
MDN Web Docs. (2026). *HTML: A good basis for accessibility*. https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Accessibility/HTML
World Wide Web Consortium, Web Accessibility Initiative. (n.d.). *Forms tutorial*. https://www.w3.org/WAI/tutorials/forms/
World Wide Web Consortium, Web Accessibility Initiative. (n.d.). *G161: Providing a search function to help users find content*. https://www.w3.org/WAI/WCAG22/Techniques/general/G161.html
What do the references cover?
The sources cover RAD, software life-cycle processes, semantic structure, accessible forms, product search, and honest marketplace representation. Together they support the proposal's method and design choices.
- Save proposal.md.
- Confirm that the References section contains six separate entries.
Are any proposal sections missing?
Compare the section headings with the table of contents. The document should end with six references after the six-week schedule.
Ask for a structural check: Which required section is missing from my ThriftHub proposal?
✔️ Awesome, I've got everything!
Your proposal now contains the title page, contents, introduction, methodology, scope, expected outcomes, schedule, and references.
ⓧ I'd like to double check the full code
Compare your proposal template with the complete proposal.md below. Your personalized title-page values can differ.
# THRIFTHUB
## A Frontend Prototype for a Secondhand Marketplace
Project Proposal
Prepared by: [Your Name]
Student ID: [Student ID]
Institution: [Institution]
Department: [Department]
Course: [Course]
Supervisor: [Supervisor]
Submission Date: [Date]
## Table of Contents
1. Introduction
2. Methodology
3. Scope and Limitations
4. Expected Outcomes
5. Project Schedule
6. References
## 1. Introduction
### 1.1 Introduction
ThriftHub is a proposed website for discovering clearly described secondhand clothing, accessories, footwear, books, and home items. Its frontend prototype displays names, categories, condition labels, descriptions, and prices in a responsive catalog. It demonstrates browsing without claiming to provide accounts, payments, messaging, delivery, moderation, or permanent storage.
### 1.2 Problem Statement
Secondhand listings can be fragmented, hard to browse, or unclear about condition. Buyers need consistent information and efficient discovery, while sellers need a clear listing structure. ThriftHub addresses this with reusable item cards, text search, category filtering, and accessible controls.
### 1.3 Objectives
General objective:
To design and implement a responsive frontend prototype for a secondhand marketplace named ThriftHub.
Specific objectives:
1. Present each item with a name, category, condition, description, and price.
2. Provide text search and category filtering.
3. Maintain a usable layout on wide and narrow screens.
4. Apply semantic HTML, visible labels, focus styles, and dynamic feedback.
5. Document the process, tests, limitations, and future improvements.
### 1.4 Development Methodology
The project uses Rapid Application Development. RAD emphasizes short iterations, working prototypes, and feedback. This suits an interface-driven marketplace because users can evaluate listing clarity and navigation early. Work moves from requirements to a static catalog, then to working filters, tests, and documentation.
## 2. Methodology
Requirements planning defines users, core listing fields, search, filters, constraints, and exclusions. User design creates and reviews the visible catalog. Construction uses HTML for structure, CSS for responsive presentation, and JavaScript for data, rendering, matching, counts, and feedback. Testing covers functionality, narrow screens, labels, keyboard focus, and honest scope. Documentation records evidence and recommendations.
## 3. Scope and Limitations
Included: responsive catalog, six samples, text search, category filters, condition and price details, result feedback, and documentation.
Excluded: accounts, database storage, image upload, messaging, cart, checkout, payments, delivery, moderation, disputes, and production security or privacy controls.
## 4. Expected Outcomes
The expected result is a working prototype where a visitor can browse six items, search, filter by category, see an accurate count, and receive no-results feedback. The proposal and report will explain the need, objectives, RAD process, implementation, tests, limits, and production roadmap.
## 5. Project Schedule
| Week | Activity | Deliverable |
| --- | --- | --- |
| 1 | Requirements and research | Problem, users, objectives, scope |
| 2 | Interface planning | Page and listing design |
| 3 | Frontend construction | Responsive catalog |
| 4 | Interaction development | Search, filter, feedback |
| 5 | Testing and refinement | Test record and revisions |
| 6 | Documentation | Proposal, report, demonstration |
## 6. References
Etsy. (2026). *Seller Policy: Our House Rules*. https://www.etsy.com/legal/sellers/
IBM. (2026, June 1). *What is rapid application development?* https://www.ibm.com/think/topics/rapid-application-development
International Organization for Standardization. (2026). *ISO/IEC/IEEE 12207:2026: Systems and software engineering - Software life cycle processes*. https://www.iso.org/standard/90219.html
MDN Web Docs. (2026). *HTML: A good basis for accessibility*. https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Accessibility/HTML
World Wide Web Consortium, Web Accessibility Initiative. (n.d.). *Forms tutorial*. https://www.w3.org/WAI/tutorials/forms/
World Wide Web Consortium, Web Accessibility Initiative. (n.d.). *G161: Providing a search function to help users find content*. https://www.w3.org/WAI/WCAG22/Techniques/general/G161.html
What does the complete file show?
This reference combines every proposal section in its final order. Use it to spot missing headings, paragraphs, table rows, or references.
Complete the project report
The report records what the finished prototype contains and how it was tested. It also separates demonstrated results from future production work.
- In report.md, replace the starter content with this title-page template:
# THRIFTHUB WEBSITE PROJECT REPORT
## A Frontend Prototype for a Secondhand Marketplace
Prepared by: [Your Name]
Student ID: [Student ID]
Institution: [Institution]
Course: [Course]
Supervisor: [Supervisor]
Submission Date: [Date]
What does the report title page establish?
The title names the report and identifies ThriftHub as a frontend prototype. The remaining fields reserve the academic submission details.
- Save report.md.
- Confirm that the first two headings identify the project report and the frontend prototype.
Does the report title page look incomplete?
Check that the project title sits above the prototype subtitle. Keep every academic field on a separate line.
Ask for help with the front matter: How should I fix the structure of my report title page?
The report contains more evidence sections than the proposal. Its contents list keeps those sections visible before the detailed writing begins.
- Add the report contents below the title-page details by pasting:
## Report Contents
1. Abstract
2. Introduction
3. Related Guidance
4. Development Methodology
5. Requirements Analysis
6. System Design
7. Implementation
8. Testing and Results
9. Limitations and Future Work
10. Conclusion
11. References
12. Appendices
How is the report organized?
The contents move from the project summary through implementation evidence. They finish with limitations, conclusions, references, and appendices.
- Save report.md.
- Confirm that the contents list contains twelve numbered sections.
Is the report numbering broken?
Check that each contents entry starts on a new line. Keep the numbers in sequence from 1 through 12.
Ask for help with the list: Why is my report contents list not showing twelve numbered sections?
The opening report sections summarize the result and explain the guidance behind the interface. They give readers enough context before the technical details.
- Add the abstract, introduction, and related guidance below the report contents by pasting:
## 1. Abstract
ThriftHub is a responsive frontend prototype built with HTML, CSS, and JavaScript. It displays six sample listings and supports text search, category filtering, result counts, and no-results feedback. It also uses semantic regions, visible labels, focus styles, and a polite live region. It has no backend, accounts, payments, permanent data, or paid service.
## 2. Introduction
Secondhand marketplaces can extend the useful life of goods, but buyers need organized and understandable listings. ThriftHub explores this need with a focused catalog and supporting academic documentation.
## 3. Related Guidance
W3C guidance supports accessible labels, notifications, and shopping-site search. MDN supports semantic page structure and native controls. Etsy's policy is not a rule for ThriftHub, but its emphasis on accurate representation supports showing clear condition and description information.
What do the opening sections contribute?
- The abstract summarizes the visible features and the excluded production systems.
- The introduction frames the secondhand-listing problem.
- The related guidance connects accessible design and accurate representation to the prototype.
- Save report.md.
- Confirm that the abstract identifies six sample listings and states that the prototype has no backend.
Does the abstract make production claims?
Keep the final abstract sentence intact. It records the missing backend, accounts, payments, permanent data, and paid service.
Ask for help checking the wording: Does my abstract clearly describe a frontend prototype?
Methodology records the iterative build process. Requirements analysis turns the finished behavior into functional and non-functional evidence.
- Add the development methodology and requirements analysis below the related guidance by pasting:
## 4. Development Methodology
The project uses RAD: requirements planning, user design, construction, continuous testing, and feedback. A visible catalog is created first, its inactive controls expose a limitation, and JavaScript then fixes it.
## 5. Requirements Analysis
Functional requirements: display six listings; show name, category, condition, description, and price; search text; filter categories; combine filters; update the count; show no-results feedback.
Non-functional requirements: adapt to narrow screens; label controls; show focus; announce updates politely; run locally; identify excluded production systems.
How do requirements connect to the prototype?
The functional requirements describe what visitors can do with the catalog. The non-functional requirements describe responsiveness, accessibility, local operation, and honest scope.
- Save report.md.
- Confirm that the requirements distinguish visitor behavior from accessibility and responsive-layout qualities.
Are the requirements too vague?
Keep the supplied behaviors and qualities concrete. Each requirement should connect to something that can be observed in the finished prototype.
Ask for help reviewing the distinction: Which ThriftHub requirements are functional and which are non-functional?
System design explains the page and product-data structure. Implementation records how each website language contributes to the finished behavior.
- Add the system design and implementation sections below the requirements by pasting:
## 6. System Design
The page contains a header, navigation, hero, filter form, product grid, explanation, and footer. Each JavaScript product has `name`, `category`, `condition`, `description`, `price`, and `shortName`. The initial array is filtered and re-rendered after visitor input.
## 7. Implementation
HTML supplies semantics, CSS supplies responsive presentation, and JavaScript selects page elements, creates cards, filters data, updates counts, and reveals the empty state. Listing text is assigned with DOM text properties rather than inserted as HTML.
What does the design record?
The design section maps the visible page regions to the product data. The implementation section then explains how structure, presentation, and behavior work together.
- Save report.md.
- Confirm that the design lists six product properties and the implementation explains all three website languages.
Are the product properties formatted incorrectly?
Keep each product property inside single backticks. This formatting distinguishes the JavaScript property names from the surrounding sentence.
Ask for help checking the inline code: Why are the product property names not formatted as code in my report?
A testing table turns the prototype's visible behavior into recorded evidence. Each row pairs one action with an expected result and outcome.
- Add the testing section below the implementation by pasting:
## 8. Testing and Results
| Test | Expected result | Outcome |
| --- | --- | --- |
| Open page | Six cards and count appear | Passed |
| Search `denim` | One jacket appears | Passed |
| Select `Home` | Vase and lamp appear | Passed |
| Home plus `lamp` | One lamp appears | Passed |
| Search `camera` | Zero count and message | Passed |
| Narrow preview | Controls stack and cards resize | Passed |
| Keyboard Tab | Focus remains visible | Passed |
These tests validate the browsing prototype, not production security or transactions.
What does the test record prove?
The seven rows cover initial rendering, search, category filtering, combined filtering, no-results feedback, responsive layout, and keyboard focus. The closing sentence limits the evidence to the browsing prototype.
- Save report.md.
- Confirm that the table contains seven Passed outcomes.
Is the testing table malformed?
Check that every test row has three cells separated by vertical bars. Keep the separator row directly below the table headings.
Ask for help checking the rows: Why is my testing table not displaying correctly in Markdown?
The final discussion records what the local prototype cannot retain or process. The conclusion then states what the completed work demonstrates.
- Add the limitations and conclusion below the testing section by pasting:
## 9. Limitations and Future Work
Refreshing restores sample data. Future projects should separately add validated backend listings and a database, followed by authentication, image storage, moderation, messaging, and payments. Payment work requires server validation, authorization, data protection, and audit planning first.
## 10. Conclusion
ThriftHub demonstrates a clear secondhand browsing flow with responsive layout, accessible controls, search, filters, and feedback. The proposal and report explain its value while accurately identifying its prototype status.
Why separate future work?
The limitations explain why refreshed pages return to the original sample data. Future production systems are presented as separate work with additional validation, security, and planning requirements.
- Save report.md.
- Confirm that refreshing data and the absence of production systems remain explicit limitations.
Does the report imply permanent storage?
Check that the limitations begin by stating that refreshing restores sample data. Keep backend listings and a database inside future work.
Ask for help reviewing the claim: Does my limitations section imply that ThriftHub stores listings permanently?
References connect the report back to the proposal's source list. Appendices identify the project files and the screenshots that can accompany a submission.
- Finish the report by adding the references and appendices below the conclusion:
## 11. References
Use the six references listed in `proposal.md`.
## 12. Appendices
Appendix A: `index.html`, `styles.css`, `app.js`, `proposal.md`, and `report.md`.
Appendix B: Screenshots of the six-card catalog, one-result search, Home filter, no-results state, and narrow layout.
What belongs in the appendices?
Appendix A identifies the five project files. Appendix B lists screenshots that demonstrate the catalog's initial, filtered, empty, and responsive states.
- Save report.md.
- Confirm that the final two headings are References and Appendices.
Is the report missing its ending?
Check that Appendix A names all five project files. Confirm that Appendix B lists five screenshot states.
Ask for a final structure check: Which ending section is missing from my ThriftHub report?
✔️ Awesome, I've got everything!
Your report now records the prototype's context, requirements, design, implementation, tests, limitations, conclusion, references, and appendices.
ⓧ I'd like to double check the full code
Compare your report template with the complete report.md below. Your personalized title-page values can differ.
# THRIFTHUB WEBSITE PROJECT REPORT
## A Frontend Prototype for a Secondhand Marketplace
Prepared by: [Your Name]
Student ID: [Student ID]
Institution: [Institution]
Course: [Course]
Supervisor: [Supervisor]
Submission Date: [Date]
## Report Contents
1. Abstract
2. Introduction
3. Related Guidance
4. Development Methodology
5. Requirements Analysis
6. System Design
7. Implementation
8. Testing and Results
9. Limitations and Future Work
10. Conclusion
11. References
12. Appendices
## 1. Abstract
ThriftHub is a responsive frontend prototype built with HTML, CSS, and JavaScript. It displays six sample listings and supports text search, category filtering, result counts, and no-results feedback. It also uses semantic regions, visible labels, focus styles, and a polite live region. It has no backend, accounts, payments, permanent data, or paid service.
## 2. Introduction
Secondhand marketplaces can extend the useful life of goods, but buyers need organized and understandable listings. ThriftHub explores this need with a focused catalog and supporting academic documentation.
## 3. Related Guidance
W3C guidance supports accessible labels, notifications, and shopping-site search. MDN supports semantic page structure and native controls. Etsy's policy is not a rule for ThriftHub, but its emphasis on accurate representation supports showing clear condition and description information.
## 4. Development Methodology
The project uses RAD: requirements planning, user design, construction, continuous testing, and feedback. A visible catalog is created first, its inactive controls expose a limitation, and JavaScript then fixes it.
## 5. Requirements Analysis
Functional requirements: display six listings; show name, category, condition, description, and price; search text; filter categories; combine filters; update the count; show no-results feedback.
Non-functional requirements: adapt to narrow screens; label controls; show focus; announce updates politely; run locally; identify excluded production systems.
## 6. System Design
The page contains a header, navigation, hero, filter form, product grid, explanation, and footer. Each JavaScript product has `name`, `category`, `condition`, `description`, `price`, and `shortName`. The initial array is filtered and re-rendered after visitor input.
## 7. Implementation
HTML supplies semantics, CSS supplies responsive presentation, and JavaScript selects page elements, creates cards, filters data, updates counts, and reveals the empty state. Listing text is assigned with DOM text properties rather than inserted as HTML.
## 8. Testing and Results
| Test | Expected result | Outcome |
| --- | --- | --- |
| Open page | Six cards and count appear | Passed |
| Search `denim` | One jacket appears | Passed |
| Select `Home` | Vase and lamp appear | Passed |
| Home plus `lamp` | One lamp appears | Passed |
| Search `camera` | Zero count and message | Passed |
| Narrow preview | Controls stack and cards resize | Passed |
| Keyboard Tab | Focus remains visible | Passed |
These tests validate the browsing prototype, not production security or transactions.
## 9. Limitations and Future Work
Refreshing restores sample data. Future projects should separately add validated backend listings and a database, followed by authentication, image storage, moderation, messaging, and payments. Payment work requires server validation, authorization, data protection, and audit planning first.
## 10. Conclusion
ThriftHub demonstrates a clear secondhand browsing flow with responsive layout, accessible controls, search, filters, and feedback. The proposal and report explain its value while accurately identifying its prototype status.
## 11. References
Use the six references listed in `proposal.md`.
## 12. Appendices
Appendix A: `index.html`, `styles.css`, `app.js`, `proposal.md`, and `report.md`.
Appendix B: Screenshots of the six-card catalog, one-result search, Home filter, no-results state, and narrow layout.
What does the complete file show?
This reference combines every report section in its final order. Use it to identify missing headings, test rows, limitations, or appendices.
Personalize and verify both documents
The supplied title pages use placeholders because academic details vary for each learner. Your final submission should identify you and your institution while preserving the prototype wording.
- Switch back to proposal.md from earlier.
- Replace each title-page placeholder with the corresponding academic detail required by your institution.
- Save proposal.md.
You should see your academic details above the proposal's table of contents.
- Switch to report.md from earlier.
- Replace each title-page placeholder with the same academic details.
- Save report.md.
You should see the matching academic details above the twelve-part report contents.
Before you inspect both files, which phrases do you expect to confirm that ThriftHub remains a prototype without production systems?
- Return to proposal.md and confirm that it contains the title page, contents, introduction, problem statement, objectives, RAD methodology, scope, expected outcomes, schedule, and six references.
- Return to report.md and confirm that it contains the abstract, requirements, design, implementation, testing results, limitations, conclusion, references, and appendices.
Both documents identify ThriftHub as a frontend prototype. They also exclude accounts, payments, delivery, permanent storage, and other production systems.
Do the documents describe different scopes?
Compare the proposal's Scope and Limitations section with the report's Abstract and Limitations and Future Work sections. All three should describe the same browser-based prototype boundary.
Ask for help comparing the claims: Where do my proposal and report disagree about ThriftHub's scope?
You have completed the academic package. The working catalog now has a proposal that justifies it and a report that records its implementation, evidence, and limits.
Secret mission
Add a Sell-an-Item Form
Your catalog already helps buyers discover items. In this mission, you will add a labeled seller form that creates a listing for the current page session. A refresh will prove that the prototype still has no permanent storage.
Clean Up Your Resources
Clean Up Your Resources
Everything in ThriftHub stays on your computer. This project costs $0 because it creates no cloud resources or billable services.
Decide whether to keep your resources running, pause them to come back later, or delete them entirely.
Resources you used:
- The local thrifthub folder containing index.html, styles.css, app.js, proposal.md, plus report.md.
Keep everything running
No action needed. Choose this if you want to keep editing or presenting ThriftHub.
- Keep the thrifthub folder in its current location.
- Return to the folder in Visual Studio Code whenever you want to continue working.
- Open index.html in the integrated browser whenever you want to demonstrate the prototype.
Pause - I'll come back to this later
Pausing closes the workspace without removing any local files. Your prototype remains ready for later.
- Close the integrated browser preview tab.
- Close Visual Studio Code.
- Leave the thrifthub folder in its current location.
Delete - I don't want to use this again
Deleting the folder is permanent once you remove it from your computer. Only the local ThriftHub files are affected.
- Close the integrated browser preview tab.
- Close Visual Studio Code.
- Press the Windows key to open search.
- Type File Explorer into search.
- Press Enter to open Windows File Explorer.
- Locate the thrifthub folder from earlier.
- Delete the thrifthub folder.
You'll see the folder disappear from its previous location. Your ThriftHub website files and documentation are now removed.
Nice Work!
Nice Work!
You did it! ThriftHub now combines a responsive marketplace prototype with submission-ready proposal and report documents.
You've learned how to:
- Build a responsive six-item catalog with semantic HTML and CSS Grid so listing details remain readable across screen sizes.
- Turn inactive controls into working search and category filters with DOM rendering, accurate result counts, no-results feedback, and polite live announcements.
- Produce a complete proposal and project report grounded in Rapid Application Development, test evidence, documented limitations, a realistic schedule, and references.
- Secret Mission: Added an accessible seller form that creates a new listing for the current page session. Its polite feedback confirms a successful submission.
Ready to quiz yourself?