@iamsajaldubey
Module 04BorrowBox: turn a page into a working app
@iamsajaldubey
PROJECT LAB / MODULE 04

BorrowBox: turn a page into a working app

Track a borrowed drill, a book and a folding chair without losing the list on refresh.

The situation

Your community lends objects. A resident needs to add an item, change it from available to borrowed, filter the list and recover the same state after refresh.

Your goal

Build a browser lending tracker with explicit state, validation and local persistence.

A first win

Add one item and change its status.

Keep this artifact

A local BorrowBox app with add, filter, status change and refresh tests.

Explore the mechanism

This interactive model teaches the mechanism. It does not call a model, search your files or send messages.

Why this works

State is the source of truth

Keep records in an array with stable IDs. Render the screen from those records. Reading the current DOM as your only database makes changes difficult to reason about.

Persistence is separate from display

localStorage can save a JSON string for this browser origin. It does not create a shared community database or a cross-device backup.

Inputs are untrusted text

Trim empty names, prevent duplicates according to your rule and render names using textContent. Treat an entered HTML tag as text, not executable markup.

Build it, step by step

  1. Define your record

    Use borrowbox-items.json. Define id, name and status. Write the two allowed statuses and what happens for an empty name.

    Check: You have an example valid record and invalid record.

    Need a hint?

    Keep due dates as an extension until the basic state model works.

  2. Build add and render

    Create an input, add button and list. Add a new record to state, then rerender. Render user text safely.

    Check: Adding a name shows one new item exactly once.

    Need a hint?

    Use stable IDs for updates, not changing array positions.

  3. Add transitions and filters

    Implement available-to-borrowed and borrowed-to-available. Add an all, available and borrowed filter.

    Check: Changing status updates the record and the filter results.

    Need a hint?

    A filter should not delete records from state.

  4. Persist and restore

    Serialize records into localStorage after changes. On load, parse inside try/catch and validate the shape before rendering.

    Check: Refresh restores the same list on the same origin.

    Need a hint?

    Serve on localhost for consistent tests. Private browsing or denied storage can fail.

  5. Break the happy path

    Try an empty name, duplicate name, very long name and a literal HTML tag. Put invalid JSON in the app storage key using developer tools.

    Check: The app explains invalid input and recovers from damaged storage.

    Need a hint?

    Do not clear unrelated localStorage keys.

  6. Explain its boundary

    Write a short handoff note: local device only, no account sync, how to export or reset your own records.

    Check: Your partner understands why another phone sees a different list.

    Need a hint?

    A real shared app needs a backend and access rules.

Build with a clear contract

Build a single-file BorrowBox lending tracker. Each record has a stable id, name and status (available or borrowed). Add records, switch status and filter without deleting hidden records. Trim and reject empty names; show duplicate warnings. Persist JSON in a namespaced localStorage key, recover visibly from invalid JSON or storage denial, and render input with textContent. Explain the state transitions and give manual tests. This is a local-only demo, not a shared database.

When it goes sideways

Refresh loses items

The app never writes state, or the origin changed.

Try: Check the storage key, saved JSON and current page origin.

Filter destroys hidden records

The filtered view replaced the original array.

Try: Compute a visible subset and keep the complete state.

Entered HTML changes the page

User input was inserted with innerHTML.

Try: Render the item name with textContent.

Review your evidence

Tick a criterion only after checking your own artifact. These are self-reported checks, not an automated certification.

Make it your own

Add a due-date view

Introduce a due date and an overdue filter. Test the boundary at midnight and with a missing date.

  • Filter does not modify stored records.
  • Invalid dates are handled.
  • Exported records can be inspected as JSON.

Check the mental model

Why can a second phone see an empty list?

How should item names be rendered?

Remember the distinction

State is the source of truth

Persistence is separate from display

Inputs are untrusted text

Go to the source

Original community projects. Interactive scenes are teaching simulations. Tool outputs vary. Your evidence stays on this browser unless you export it.