Immersive audio engineering, hand-tuned in Dar es Salaam, Tanzania. A high-performance e-commerce frontend integrated with Supabase database, real-time search, interactive profile forms, and custom-tailored sound.
Write this like a product launch announcement.
Audenic Audio makes super-cool, premium headphones and speakers that make your favorite music sound like the band is playing right inside your room, hand-crafted with love in Dar es Salaam!
For developers, Audenic Audio is an ultra-premium, production-ready React 18 e-commerce SPA built on Vite, TypeScript 5, and Tailwind CSS. It features micro-interactions and scroll-driven typography animations powered by GSAP, ScrollTrigger, and Framer Motion. The data layer is decoupled and powered by a Supabase Postgres engine (with local cache fallbacks), supporting OTP magic-link authentication, custom row-level security (RLS) policies, order placement, and live client-side address auditing.
For the business, Audenic solves the critical high-friction barriers of online direct-to-consumer (DTC) sales in East Africa. By integrating local Swahili-friendly terms, supporting mobile money payment workflows (M-Pesa, Tigo Pesa, Airtel Money), and optimizing for fast page-load speeds on mobile connections through server-free SPA routing and highly optimized asset delivery, Audenic captures a rapidly growing middle-class demographic looking for local premium quality over imported generic electronics.
- Current Version:
v2.0.0 - Status Badge: π’ Production Ready / Stable
- Built by: Mwijay Davie (mwijay.com) to prove that high-end DTC audio equipment can have a digital shopping experience that is as smooth, premium, and tactile as the hardware itself.
- The Audenic Difference: Unlike generic, template-built e-commerce sites that look like standard AI-generated retail templates, Audenic features a high-fidelity signature design token palette (
cream,ink,flame), physical-feeling 3D tilt spotlights on cards, and full smooth scroll animations using Lenis. We completely avoid "AI slop" aesthetics in favor of a clean, editorial layout reminiscent of physical design magazines.
The current state of the system today.
| Component | Status | What It Does | Tech Used |
|---|---|---|---|
| Frontend UI | π’ Active | Renders responsive pages, landing hero, product lineup, specifications, and cart. | React 18, Vite, Tailwind CSS |
| Animation Engine | π’ Active | Handles Lenis smooth scroll, GSAP ScrollTrigger features, and Framer Motion page routes. | GSAP 3, Lenis, Framer Motion |
| Search Engine | π’ Active | Real-time keyboard-navigable slide-over search across names, categories, and tags. | React State, Lucide, Zustand |
| Auth System | π’ Active | Magic-link (OTP) logins and user sessions with Supabase. | Supabase Auth, useSession hook |
| User Profile & Addresses | π’ Active | Editable profile data, phone number, and address lists synced to database. | React Forms, Supabase Postgres |
| Shopping Cart & Checkout | π’ Active | Zustand store for cart lines, promo code deductions, and order creation. | Zustand, LocalStorage, Supabase DB |
- Fully Working Features:
- Real-time search modal (Ctrl+K or Search button triggers) with instant product results.
- Interactive user account profile updater (updates full name, phone number, and marketing preferences).
- Address book manager with label customization, default address constraints, and deletions.
- Promo code discount manager supporting Tanzanian coupon campaigns (
KARIBU10,DARFREE,AUDENIC20). - Wishlist ("Vipendwa") tab allowing users to save products locally and sync to the cloud on login.
- Lenis smooth scrolling bound to GSAP ScrollTrigger for parallax sections.
- Dynamic particle field generator on the landing hero.
- Partially Working Features:
- Real-time payment verification (the payment method field is selected, but is currently mock-checked rather than sending SMS payloads to telecommunication push gateways).
- Avatar upload (UI exists but file uploading to Supabase Storage bucket requires bucket creation permissions).
- Planned Features (Not Started):
- Interactive sound tuner widget (a 3-band graphic equalizer playing mock audio waves to match product sound stages).
- Swahili / English localization translation system switcher in the navigation bar.
- Tried and Abandoned:
- Global CSS Parallax: Replaced by GSAP ScrollTrigger as default CSS parallax caused severe layout stuttering on WebKit browsers (Safari iOS).
A detailed map of how data moves through Audenic.
+-------------------------------------------------+
| User Browser |
| |
| [React SPA] ----(Ctrl+K)----> [Search Drawer] |
| | |
| +--(Add to Cart)----> [Zustand Cart] |
| | |
| +--(Save)------------> [Wishlist Store] |
+--------+--------------------------+-------------+
| |
(HTTPS Rest / WS) (JSON Sync)
| |
v v
+-------------+-------------+ +-------+-------+
| Supabase Client | | LocalStorage |
+------+-----+-------+------+ | (Offline |
| | | | Fallback) |
(Auth OTP) | | | (Postgres | |
+-------------+ | | Queries) +---------------+
| | |
v v v
+-----+------+ +--------+-------+--------+
| Supabase | | Supabase Database |
| Auth Guard | | (PostgreSQL + RLS) |
+------------+ +--------+-------+--------+
| |
+-------+ +--------+
| |
v v
[profiles] [addresses]
[orders] [order_items]
[wishlists] [newsletter_subscribers]
- User interaction: User clicks "Weka Kikapuni" (Add to Cart) on a product card or clicks "Add to Cart" on the product detail page.
- State modification: The event triggers
useCart.getState().add(product, color, quantity). - Zustand pipeline: Zustand searches
state.linesfor a match onproductIdandcolor.name. If found, it increments the quantity. If not, it pushes a newCartLineobject. It commits to state, triggers a local storage sync (audenic-cart), and callsget().open()to open the side drawer. - Checkout Transition: The user hits "Checkout" and is redirected to
/checkout. - Pricing Computation:
calcTotalcalculates the subtotal, checks if the user has applied a coupon code (e.g.,KARIBU10for 10% off), applies the discount, computes Dar-es-Salaam free shipping or flat rate, and sets the total. - DB Submission: On submitting the shipping address form,
createOrderruns:- Inserts order row into
orderstable. - Supabase database executes
assign_order_number()trigger to auto-createAUD-2026-NNNNNNformatted ID. - Inserts line items into
order_itemsreferencing the returnedorder_id. - Clears the cart on success and redirects the user to the
/order/:idconfirmation screen.
- Inserts order row into
The layout of the codebase and file responsibilities.
audenic-audio-premium/
βββ .env.example # Template for local environment variables
βββ .gitignore # Rules for excluding files from git tracking
βββ index.html # Main HTML template containing Google Font imports
βββ package.json # Project dependencies, scripts, and authors metadata
βββ postcss.config.js # PostCSS configuration for Tailwind compiler
βββ tailwind.config.js # Custom Tailwind spacing, fonts, and Audenic tokens (flame, ink, cream)
βββ tsconfig.json # Root TypeScript config
βββ tsconfig.app.json # TypeScript compiler rules for the React app
βββ tsconfig.node.json # TypeScript compiler rules for the Vite node scripts
βββ vite.config.ts # Vite compiler configuration with tsconfig paths alias mapping
βββ public/ # Static raw assets
β βββ favicon.ico # Website icon
βββ supabase/ # Database initialization folder
β βββ README.md # Supabase specific setup instructions
β βββ schema.sql # Core SQL script to create tables, indexes, and triggers
β βββ rls.sql # Row-Level Security rules for data access control
β βββ seed.sql # Initial products & mock data inserts
βββ src/ # Source code
βββ App.tsx # Main application routing and route guards
βββ index.css # Main stylesheet declaring custom fonts and design tokens
βββ main.tsx # Application mount file
βββ vite-env.d.ts # TypeScript environment declarations
βββ components/ # Reusable UI elements
β βββ BlurText.tsx # Split-text entry animator using framer-motion
β βββ CartDrawer.tsx # Slide-over shopping cart drawer
β βββ ColorSwatches.tsx # Component to render product color options
β βββ Cursor.tsx # Magnetic/hover-reactive custom mouse pointer
β βββ Footer.tsx # Global footer containing newsletter sign-up
β βββ HorizontalShowcase.tsx # GSAP horizontal product slide trigger
β βββ Layout.tsx # Standard layout container with Nav, Footer, and Modals
β βββ MagnetButton.tsx # Magnetic-pull UI button component
β βββ Marquee.tsx # Infinite scrolling text marquee
β βββ Nav.tsx # Global navigation with bag indicator and Search trigger
β βββ Parallax.tsx # Parallax scroll animator
β βββ ParticleField.tsx # HTML Canvas-based interactive landing particle animation
β βββ Reveal.tsx # Fade-in-up element reveal on scroll
β βββ ScrollLetterShift.tsx # Character displacement animator
β βββ ScrollProgress.tsx # Top-page thin linear progress bar
β βββ SearchModal.tsx # Ctrl+K modal overlay with instant product matching
β βββ SpotlightCard.tsx # 3D tilting card with spotlight gradient follow-effect
β βββ Stats.tsx # Animated counting numeric showcase
βββ data/ # Static catalogs
β βββ products.ts # Products, extra products, specifications, and features data
βββ hooks/ # Custom React hooks
β βββ useSmoothScroll.ts # Custom Lenis scroll initialization bound to GSAP
βββ lib/ # Utilities and client wrappers
β βββ orders.ts # Typed database interfaces for order submission
β βββ supabase.ts # Singleton instance configuration and newsletter helper
β βββ useSession.ts # Session tracking with localStorage demo mode fallbacks
β βββ utils.ts # Tailwind merge helper and currency formatter
βββ store/ # Global states
βββ cart.ts # Cart store with promo code deductions
βββ search.ts # Modal open state controller
βββ wishlist.ts # Wishlist item toggles with Supabase cloud-sync
Get Audenic running locally from scratch.
Ensure you have the following software installed:
- Node.js (v18.0.0 or higher): Download Node.js
- Git: Download Git
- VS Code (Recommended): Download VS Code
Create a .env file in the root of the project.
# Copy from template
cp .env.example .envFill out the variables as follows:
# Supabase credentials (Get these from your Supabase dashboard > Project Settings > API)
VITE_SUPABASE_URL=https://your-project-id.supabase.co
VITE_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Note
If you leave these variables empty or omit the .env file, the application will automatically boot in Demo Mode (No-DB Mode) using LocalStorage, allowing you to test all pages and forms.
Run the following commands in your terminal:
# 1. Clone the repository
git clone https://github.com/mwijay-davie/audenic-audio-premium.git
cd audenic-audio-premium
# 2. Install dependencies
npm install
# 3. Start the development server
npm run devExpected Output for npm run dev:
VITE v5.4.11 ready in 345 ms
β Local: http://localhost:5173/
β Network: use --host to expose
β press h + enter to show help
Open your browser and navigate to http://localhost:5173/.
- Scroll down to see if the Lenis smooth scroll and GSAP animations run cleanly.
- Press
Ctrl + K(orCmd + Kon Mac) to verify the Search Modal opens. - Add an item to the cart. If the Cart Drawer slides open with your item, the installation is verified!
- Error:
VITE_SUPABASE_URL is undefinedWarning in Console- Reason: The
.envfile was not created or Vite is not loading it. - Fix: Make sure the file is named exactly
.env(not.env.txtor.env.local) and is placed in the root directory next topackage.json. Restart the dev server (Ctrl+Candnpm run dev).
- Reason: The
- Error:
Port 5173 is already in use- Reason: Another development server is running in the background.
- Fix: Vite will automatically assign a different port (e.g.
5174), or you can kill the existing process usingnpx kill-port 5173.
- Error:
TypeScript compilation errors during build- Reason: Node module version mismatch or strict type check failure.
- Fix: Run
npm run lintto identify lines causing the warning, or clean modules and reinstall:rm -rf node_modules package-lock.json && npm install.
Code guidelines and usage patterns.
You can trigger the search modal from any custom button or link:
import { useSearch } from '@/store/search'
export default function SearchTrigger() {
const openSearch = useSearch((s) => s.open)
return <button onClick={openSearch}>Tafuta Sasa</button>
}Here is how order requests are structured and submitted to the Postgres backend:
import { createOrder, type CreateOrderInput } from '@/lib/orders'
const checkoutInput: CreateOrderInput = {
userId: "user-uuid-1234",
lines: [
{
productId: "p-001",
slug: "audenic-classic-red",
name: "Audenic Classic",
price: 43500, // whole TSh
image: "https://images.unsplash.com/...",
color: { name: "Flame Red", hex: "#ff4d1a" },
quantity: 1
}
],
shipping: {
recipient_name: "Mwijay Davie",
phone: "+255712345678",
line1: "Plot 45, Mikocheni B",
city: "Dar es Salaam",
region: "Dar es Salaam",
country: "Tanzania"
},
paymentMethod: "mpesa",
customerNote: "Tafadhali piga simu kabla ya kufika."
}
// Submit transaction
const result = await createOrder(checkoutInput)
if (result.ok) {
console.log("Order placed: ", result.order.order_number)
} else {
console.error("Order failed: ", result.message)
}- Empty Cart Checkout: If a checkout is attempted with
lines.length === 0,createOrderreturns{ ok: false, code: 'EMPTY_CART', message: 'Cart ni tupu.' }without hitting the DB. - Database Connection Loss: If network timeouts occur during submission, the client returns a structured object allowing the checkout page to preserve the user's state.
Audenic runs on a robust relational Postgres schema.
Stores customer credentials and preferences (linked to auth.users).
id:uuid(Primary Key) β Links toauth.users(id)email:text(Indexed) β Customer email addressfull_name:text(Nullable) β First & last namephone:text(Nullable) β Contact numberavatar_url:text(Nullable) β Profile photo locationmarketing_opt_in:boolean(Default:false) β Opt-in for updatesrole:text(Default:'customer') β Check:'customer','admin','staff'created_at/updated_at:timestamptzβ Timestamp records
Stores delivery details.
id:uuid(Primary Key, Default:gen_random_uuid())user_id:uuid(Indexed) β Referencesprofiles(id)label:text(Default:'Home') β Lebo (e.g. Ofisini, Nyumbani)recipient_name:textβ Jina la mpokeajiphone:textβ Delivery phone numberline1:textβ Street name / House numberline2:text(Nullable) β Landmarkscity:textβ Mji (e.g. Dar es Salaam)region:textβ Mkoapostal_code:text(Nullable)country:text(Default:'Tanzania')is_default:boolean(Default:false) β Primary address
Header table for checkouts.
id:uuid(Primary Key, Default:gen_random_uuid())user_id:uuid(Indexed) β Referencesprofiles(id)order_number:text(Unique, Indexed) β Friendly IDAUD-YYYY-NNNNNNstatus:text(Default:'pending') β Check:'pending','paid','processing','shipped','delivered','cancelled','refunded'subtotal_tsh:integerβ Subtotal in TShshipping_tsh:integerβ Shipping feetax_tsh:integerβ Tax feetotal_tsh:integerβ Total paidpayment_method:text(Nullable) β Check:'mpesa','tigopesa','airtel_money','card','cod'payment_reference:text(Nullable) β Mobile Money transaction IDpaid_at:timestamptz(Nullable)shipping_address:jsonbβ Address snapshotcustomer_note:text(Nullable)
Line items for each order.
id:uuid(Primary Key)order_id:uuid(Indexed) β Referencesorders(id)product_id:text(Indexed) β References product ID catalogproduct_slug:textβ For routingproduct_name:textβ Product nameproduct_image:textcolor_name/color_hex:textβ Selected configurationunit_price_tsh:integerquantity:integerline_total_tsh:integer
Dynamic copy generation and sound tuning descriptors.
The project is structured to optionally query LLMs via the multi-key resilient pool declared in the .env configuration (supporting Gemini, Groq, OpenRouter, and Cerebras).
- Primary Model:
gemini-2.5-flashvia Google AI Studio API. - Why this model: Low response latency, free-tier quotas (15 RPM / 1M TPM), and excellent translation/Swahili cultural optimization.
- Prompt Construction:
For newsletter copy:
Wewe ni muuzaji mkuu wa bidhaa za sauti Audenic Audio kutoka Dar es Salaam. Andika ujumbe mfupi wa kuvutia kwa barua pepe kumkaribisha mteja mpya aliyesajili email: [email]. Ujumbe uwe na lugha mchanganyiko ya Kiswahili na Kiingereza (Sheng ya Dar), ukitaja bidhaa zetu kuu (Mwanga Buds, Audenic Classic). Usiweke maneno mengi ya ki-AI (mfano "Kumbuka kwamba", "Hakika"). Andika kifupi sana na kwa hisia ya muziki mzuri. - Error Mitigation: The application automatically implements a multi-key rotation array. If a query returns a
429 Rate Limitor quota error, the client attempts the next key in the comma-separatedGEMINI_KEYSstring.
Brutally honest roadmap items.
- Database Constraints: The database unique constraint on default address (
uniq_addresses_default_per_user) will raise an error if client-side verification fails to clear existing defaults before marking a new default. - Mobile Money Syncs: The payment flow is currently a mock input form. No direct mobile money USSD push API is connected.
- Hydration Differences: The Lenis scroll engine can sometimes conflict with browser page layout heights during rapid SPA route transitions.
- Security Debt: Row-Level Security (RLS) is defined, but the anonymized select permissions allow any guest to query the
newsletter_subscriberstable if the exact matching email is passed.
Customizing the Audenic experience.
- Difficulty: ββ (2/5)
- Time: 4 hours
- Files to modify: Nav.tsx, Layout.tsx
- New files to create:
src/hooks/useLanguage.ts - Guide: Create a context provider to store active language (
sworen). Replace static UI text blocks with a translations object dictionary mapping values. Add a layout button in the navbar to switch flags.
- Difficulty: βββ (3/5)
- Time: 8 hours
- Files to modify: Account.tsx
- Dependencies: none (
@supabase/supabase-jsis already installed) - Guide: Add a file picker input on the Profile tab. On select, write the file to the
avatarsbucket viasupabase.storage.from('avatars').upload(...). Save the resulting URL link to the profiles row.
Go live with your Audenic store.
- Set up your build settings on the hosting dashboard:
- Build Command:
npm run build - Publish Directory:
dist
- Build Command:
- Add your environment variables in the project settings:
VITE_SUPABASE_URLVITE_SUPABASE_ANON_KEY
- Hit Deploy.
Ensure you push database tables and RLS rules to your Supabase instance:
# Run schema and security settings in the SQL editor
psql -h your-db-host -U postgres -f supabase/schema.sql
psql -h your-db-host -U postgres -f supabase/rls.sqlEstimate running costs.
| Service | Free Tier | Paid Tier | Cost at 100 users | Cost at 1000 users |
|---|---|---|---|---|
| Supabase | DB (500MB), Auth, Storage (1GB) | $25 / month | $0 (Free tier covers this) | $0 (Free tier covers this) |
| Hosting (Vercel) | Full SPA Hosting, bandwidth | $20 / month | $0 | $0 |
| Gemini API | 15 RPM / 1M TPM free limits | Pay-as-you-go | $0 | $0 |
| Total | $0 / month | $0 / month |
Where Audenic goes next.
- Fix Lenis route transition jumping.
- Connect a mockup payment checkout notification receipt email via resend API.
- Add a visual equalizer animation to the product pages.
- Improve fuzzy matching logic in search results.
- Cache product details locally in Zustand for instant detail page loading.
- Implement full checkout integrations with local mobile money providers.
- Create a dashboard panel for administrative stock tracking.
- Introduce custom sound profile configuration uploads.
- Launch native iOS/Android client apps using Capacitor or React Native.
Takeaways from building Audenic.
- Animation Coordination: Relying on GSAP for page scroll triggers and Framer Motion for page route layouts requires careful hook design to avoid page-height miscalculations. Always initialize Lenis after the DOM has finished mounting.
- Database fallback design: Building a solid mock client-side offline store means the UI can be showcased in developer meetings without needing live cloud endpoints.
- Color preservation: Editorial and DTC websites stand out when they avoid boring generic dark modes and stick to clean, high-contrast, specific design brand colors.
Your cheat sheet for development.
# Run local Vite web app dev server
npm run dev
# Run TypeScript typechecks
npm run lint
# Compile production-ready assets to /dist
npm run build- Database Setup SQL script:
supabase/schema.sql - Database RLS Rules script:
supabase/rls.sql - Products Catalog:
src/data/products.ts - Supabase Client Singleton:
src/lib/supabase.ts
- Missing DB Connection: Clear local session cache by clearing site storage
audenic-authin browser developer tools console to return to clean guest state.