T/T
Back to work

Personal project · 2026

DECKED

Ride. Style. Repeat.

The DECKED homepage: a skater riding into a Venice Beach sunset under the site's headline

What it is

DECKED is a Venice Beach skate shop for a brand that only exists in my head. You can browse forty-two products across six categories, filter the catalogue, view product pages, fill a cart, create an account, check out and come back later to find your past orders waiting for you.

Built with plain HTML, a single stylesheet and vanilla JavaScript, it has no framework, no build step and no backend.

What makes it interesting is that every feature a real shop would normally rely on a server for, from the cart to user accounts and order history, runs entirely in the browser.

The DECKED cart drawer slid out from the right, showing items with quantity controls and a subtotal
The cart drawer, holding its contents across every page.

The problem

Making it look like a skate shop wasn't the difficult part. Making it behave like a real shop without anything running behind it was.

A real store remembers your cart between pages, keeps you logged in and stores your orders after you close the browser. I wanted all of that while still deploying as a collection of static files on GitHub Pages.

The challenge is that DECKED is a true multi-page site. Every page navigation starts a fresh JavaScript environment, so nothing survives in memory. The cart on the catalogue page and the cart at checkout aren't the same running application, they're separate pages that have to rebuild the same state every time they load.

The decisions

One place for the truth

Everything the shop remembers lives in localStorage under four keys. Every page reads them when it loads and writes back immediately when something changes, making localStorage the single source of truth.

Key What it holds
decked_cart Product IDs and quantities
decked_user Name and email, or nothing
decked_orders Number, date, items, total
decked_stock Any stock levels I overrode

The cart stores only product IDs and quantities rather than complete product data. Prices, names and images always come from the catalogue itself, ensuring every page shows the latest information without duplicating it.

Keeping every page in sync

A shared script runs across the entire site. On every page load it rebuilds the cart drawer, updates the cart counter and decides whether the navigation greets the user by name or shows a login link.

That lets each page focus on its own job rather than worrying about how the application's shared state was created.

A login that plays its part

Registration stores a name directly. Logging in only asks for an email address, then generates a display name from it, so jordan.vega@email.com becomes Jordan Vega.

Checkout and the account page both require a user. Visitors who aren't logged in are redirected to the login page before being returned to where they originally intended to go.

Turning a cart into an order

Completing checkout generates a DKD reference number, calculates shipping, saves the order, clears the cart and displays a confirmation without leaving the page.

Because the order is written to localStorage first, it remains in the account history even after the browser is closed.

The DECKED account page showing a past order with its DKD reference number, date and total
Order history, still present after the tab was closed and reopened.

What I'd do differently

The biggest limitation is that the login only plays the part. Passwords are never stored or verified, so any password works. Since users and orders both live in localStorage, anyone with browser developer tools can modify them. The checkout accepts payment details without processing them, and stock levels can be edited just as easily.

None of that is accidental. It reflects the limits of a project designed to run entirely as static files. Supporting real payments would mean moving carts, accounts and orders somewhere visitors couldn't access or change.

As a demonstration of how much of an e-commerce experience can live entirely in the browser, the approach achieved exactly what I wanted. As the foundation of a production store, it would be the first thing I'd replace.

More work on the home page, or the full history on the CV.