andrew.bloyce / docs
v3.4.0

Case study · Personal project

A framework-free family-management PWA, built with native Web Components — shared shopping lists, tasks, and events for my own family. Equal parts practical family tool and a serious Web Components sandbox.

Year
2024
Role
Solo — design & build
Stack
Web Components · Vite · Supabase · Tailwind
Status
Personal project · sandbox

01 Why I built it

When I became a parent, life admin got hard. Every waking moment was preoccupied with a very demanding small human, and the usual ways of keeping on top of things fell apart. I built The Fridge so my wife and I could share the load — one place for shopping lists, tasks, and events, in sync on both our phones.

It was also an excuse. I'd wanted to try a serious project in native Web Components ever since Josh Wardle built Wordle that way, with no framework, and sold it for a small fortune. That was the nudge to see how far I could get with just the platform.

02 What I built

The Fridge is an installable PWA for couples, families, and sharehouses: shared shopping lists, tasks, events, and photos, all collaborative and live across devices. It's built from the platform up, around 50 native Web Components, with Vite for the build, Tailwind for styling, and Supabase (Postgres and real-time) as the backend, deployed on Netlify. It caches to localStorage so it opens instantly and tolerates a flaky connection. It has a few playful touches too: type "apples" into the list and you get a burst of 🍎 confetti.

Under the hood

~50 native Web Components, no framework, real-time across devices via Supabase, installable as a PWA.

03 Highlights

Clear, beautiful, mobile-first

It had to be mobile-first, since the phone is where household admin happens. I wanted it very clear but also good-looking, so most of the design time went into the typography and a simple colour palette. Clarity first, with enough warmth that it never felt like a chore app.

Native Web Components, no framework

No framework at all, just custom elements, the DOM, and a thin base class. Components register themselves with customElements.define and manage their own rendering. Shadow DOM shows up only where encapsulation earns it (modals), with Tailwind doing the rest in the light DOM. I wanted to see how far the platform alone could carry a real app.

Real-time sync with Supabase

The shopping list is the heart of the app, so it had to feel properly shared. A Supabase Postgres-changes channel pushes every insert, update, and delete to every connected device, so when one person ticks off milk at the shop it vanishes from everyone's list. Optimistic local updates make it feel instant, and the subscription keeps everyone in sync.

src/pages/lists.js js
// Live shopping list — every device stays in sync
supabase.channel('shopping-list')
  .on('postgres_changes', { event: '*', table: 'list_items' }, (payload) => {
    if (payload.eventType === 'INSERT') this.onDBInsert(payload)
    if (payload.eventType === 'UPDATE') this.onDBUpdate(payload)
    if (payload.eventType === 'DELETE') this.onDBDelete(payload)
  })
  .subscribe()

04 What it looked like

From direction, to design, to the built app.

A moodboard of app, branding, and UI references collected to set the visual direction for The Fridge.
A moodboard to lock the direction before designing.
Figma frames of The Fridge: the landing screen, register and sign-in, onboarding, household settings, and the colour palette.
Designing the onboarding and household flows in Figma.
Figma frames of The Fridge notes feature: the note editor and several note styles.
Exploring the notes editor and its styles.
Five screens of the built Fridge app: the branded landing screen, the home overview, the shared shopping list, the family tasks view, and upcoming events.
And the built app — landing, home, shopping list, tasks, and events.

05 What I learned

Three things stuck. I learned a lot of Supabase: auth, Postgres, and real-time channels. I learned how to orchestrate state and events between Web Components without a framework holding my hand. And I learned why JS frameworks exist in the first place: the platform gets you a long way, but the biggest thing missing from Web Components is a real templating engine. By the end, I really missed JSX.