Euphoria is a full-stack e-commerce application built with Next.js, TypeScript, and TailwindCSS. It features a custom admin panel, customer dashboard, and a bespoke Stripe-powered payment form. The project is designed to be modular and easy to extend, making it a great starting point for your own e-commerce applications.
- Customer Dashboard: Users can manage their profiles, view order history, and manage their addresses.
- Admin Dashboard: Admins can manage products, orders, and users. view transactions through interactive charts.
- Wishlist: Users can save products for later.
- Cart: Users can add products to their cart and proceed to checkout.
- Checkout: A custom Stripe payment form for secure transactions.
- Authentication: Euphoria comes with built-in authentication using NextAuth.js, supporting GitHub and Google sign-in.
- Responsive Design: The application is fully responsive, ensuring a great user experience on all devices.
- Design System: the project is built with a custom design system, which can be accessed on the
/style-guide
page. - Localized Currency Conversion: The application supports multiple currencies, with a simple conversion logic that can be extended to use real-time APIs.
- Error Tracking: Integrated with Sentry for error tracking and monitoring.
You can view the full Figma file for this project here:
👉 Euphoria Figma UI
Customer View | Admin Dashboard |
---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
The project follows a colocation-first structure:
src/
├── app/ # Pages and API routes (App Router)
│ ├── (main)/ # Public-facing pages
│ └── (admin)/ # Admin dashboard pages
│
├── components/ # Shared/reusable components
├── lib/ # Utility functions, config, constants
├── hooks/ # Custom React hooks
├── actions/ # Server actions
├── schema/ # Zod schema definitions
├── flags/ # Feature toggles and constants
└── types/ # TypeScript types
Each page folder contains its own UI components for colocation, making it easier to manage and understand
This project uses NextAuth for authentication, but with a slight modification — the Prisma Adapter was extended to support role-based authorization (e.g., ADMIN
, CUSTOMER
).
You can check the modified adapter inside the lib/next-auth/adapter.ts
file.
the extended types for session and the adapter are located in the root level of the project within the next-auth.d.ts
folder
Currency values are hardcoded for now, using static exchange rates defined in the lib/constants.ts
file.
If you'd like to integrate a real-time currency conversion service (like fixer.io or OpenExchangeRates), modify the logic inside:
/utils/convertToCurrency.ts
Below are the required env variables for this project:
# App
# DATABASE
DATABASE_URL=
#CLOUDINARY
NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME=
#AUTHENTICATION
GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
NEXTAUTH_COOKIE_NAME=
AUTH_SECRET=
# (Optional)
RESEND_API_KEY=
# PAYMENT
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
# CURRENCY CONVERSION
IP_GEOLOCATION_API_KEY=
- Clone the repo:
git clone https://github.com/your-user/euphoria.git
cd euphoria
-
Install dependencies:
pnpm install
-
Configure environment variables:
Create a
.env
file using the template above. -
Seed the database:
Inside the
prisma/
directory, there is aseed.ts
file. Get your MongoDB URI and run:npx prisma db push tsx prisma/seed.ts
-
Run dev server:
pnpm dev
There are built-in email templates for sending verification and transactional emails. However, due to financial constraints 🥲, Resend was not implemented.
To activate or modify email logic, go to:
flags/email-templates.ts
You can toggle templates or customize values there.
This project includes a custom country selector package for address forms, built from scratch (no third-party bloat). It lives inside:
components/forms/country-selector.tsx
Contributions are welcome.
If you find a bug, want to fix a typo, or build a whole new feature, feel free to fork the repo and go crazy. I don’t really care, but I’ll appreciate it either way 😌
Made with ❤️ by Nathan Somto