I built a Next.js 16 store starter for perfume & cosmetics (and learned a few things)

Honestly a bit scary to post this. I’m a self-taught dev, and Aura is the first thing I’ve actually finished and put up for sale. It’s a Next.js 16 storefront starter, but I didn’t want to make “another generic shop”, so I built it specifically for perfume and cosmetics.

Live demo: https://aura-starter.vercel.app

Here’s why I niched it, and two things that confused me while building, in case it helps someone.

Why perfume & cosmetics

I kept noticing fragrance and cosmetics aren’t sold like normal products:

  • People buy decants first (2, 5 or 10 ml of a scent) before paying for a full bottle. So instead of a product photo, my hero is three little apothecary vials, filled to different heights by size.
  • Every fragrance has a note pyramid (top / heart / base). Buyers actually care how it opens and where it lands.
  • Cosmetics need real shade swatches and a short ingredients list.

Most templates ignore all that. I figured building around how people actually buy is what makes it worth something.

Thing that confused me #1: React 19 and refs

I have a hover panel that slides in with product info, and I wanted it to keep showing the last product while it slides away. I reached for a ref:

const lastShown = useRef(null);
if (active) lastShown.current = active; // React 19 yelled at me here
Enter fullscreen modeExit fullscreen mode

Turns out React 19 has a new lint rule that won’t let you read or write refs during render. Took me a while to get it. The fix was just to keep it in state and set it in the handler:

const [shownSlug, setShownSlug] = useState(null);
const open = (slug) =>  setActiveSlug(slug); setShownSlug(slug); ;
Enter fullscreen modeExit fullscreen mode

Cleaner in the end, honestly.

Thing that confused me #2: making graphics work in dark mode

The decant vials are just divs, not images. I didn’t want to draw them twice for light and dark, so instead of fixed colors I used CSS variables for the fill:

style= background: 'linear-gradient(180deg, var(--accent), var(--accent-strong))' 
Enter fullscreen modeExit fullscreen mode

Since the variable flips with the theme, the same vials just work in both. No dark: copies, no second SVG. Small thing, but it made me happy.

Also, Next 16 + Tailwind v4

If you’re starting fresh: params and searchParams are promises now (you await them), and Tailwind v4 config lives in globals.css. Took me a minute coming from older versions.


That’s it really. It’s typed, has tests, light/dark, and the hover thing.

Demo: https://aura-starter.vercel.app
If it’s useful to anyone, it’s up here: https://maegami.gumroad.com/l/aura/LAUNCH

This is genuinely my first time selling something I made, so any feedback (design, code, whatever) would mean a lot. Thanks for reading 🙏

 

Leave a Reply

Your email address will not be published. Required fields are marked *