Customer-facing and admin e-commerce platform for jewelry sales built with Next.js 15, React 19, and TailwindCSS.
This is the frontend application for Morango Joyas, a full-stack e-commerce platform featuring:
- ποΈ Product browsing and cart management
- π Checkout flow with MercadoPago integration
- π€ User authentication & account management
- π¦ Order tracking and history
- π Admin dashboard for order and product management
- π Dark mode support
- π± Mobile-responsive design
See also: Backend Repository
- Node.js 18+ and npm
- Backend API running on
http://localhost:3000(or configure viaNEXT_PUBLIC_BACKEND_API_URL)
# Clone and install dependencies
npm install
# Set up environment variables
cp .env.example .env.local
# Edit .env.local with your configuration
# Start development server
npm run devOpen http://localhost:3000 in your browser.
Create .env.local with:
NEXT_PUBLIC_BACKEND_API_URL=http://localhost:4000/api
NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME="asdfgh"
NEXT_PUBLIC_CLOUDINARY_API_KEY=cloudinary-key
NEXT_PUBLIC_MP_PUBLIC_KEY=mp-public-key
NEXT_PUBLIC_FREE_SHIPPING=public-shipping-valueclient/
βββ app/ # Next.js App Router pages
β βββ home/ # Public customer pages
β β βββ page.tsx # Home/product listing
β β βββ products/ # Product details
β β βββ cart/ # Shopping cart
β β βββ orders/ # Order history
β β βββ profile/ # User account
β βββ admin/ # Protected admin routes
β β βββ orders/ # Order management
β β βββ products/ # Product management
β β βββ users/ # User management
β β βββ analytics/ # Sales analytics
β βββ auth/ # Authentication
β β βββ login/
β β βββ register/
β β βββ forgot-password/
β β βββ reset-password/
β βββ checkout/ # Checkout & payment
β β βββ page.tsx
β β βββ success/
β β βββ failure/
β β βββ pending/
β βββ layout.tsx # Root layout with providers
βββ components/ # Reusable React components
β βββ providers/ # Context providers (Query, Theme, Toast, MercadoPago)
β βββ admin/ # Admin-specific components
β βββ checkout/ # Checkout flow components
β βββ home/ # Customer UI components
β βββ auth/ # Authentication forms
β βββ payment/ # Payment status views
β βββ products/ # Product display components
β βββ ui/ # Generic UI components
β βββ skeletons/ # Loading skeletons
βββ src/
β βββ api/ # Axios API clients
β β βββ AuthAPI.ts
β β βββ ProductAPI.ts
β β βββ OrderAPI.ts
β β βββ PaymentAPI.ts
β βββ hooks/ # Custom React hooks
β β βββ useAuth.ts # Authentication state
β β βββ useTimer.ts # Countdown timers
β β βββ useMobile.ts # Mobile detection
β β βββ useFilters.ts # Query parameter filters
β βββ store/ # Zustand state stores
β β βββ useCartStore.ts
β βββ types/ # TypeScript interfaces
β β βββ index.ts # Centralized types
β βββ utils/ # Utility functions
β βββ date.ts # Date formatting
β βββ price.ts # Currency formatting (CLP)
β βββ text.ts # Text transformations
β βββ copy.ts # Clipboard utilities
βββ lib/
β βββ axios.ts # Shared axios instance
βββ public/ # Static assets
βββ globals.css # Global styles
βββ next.config.ts # Next.js configuration
βββ tsconfig.json # TypeScript config
βββ tailwind.config.js # TailwindCSS config
βββ package.json# Development with Turbopack
npm run dev
# Production build
npm run build
# Start production server
npm start
# Lint code
npm run lint- Framework: Next.js 15 (App Router)
- UI Library: React 19
- Styling: TailwindCSS 4 with dark mode
- State Management:
- Server State: React Query (TanStack Query)
- Client State: Zustand
- Async Forms: react-hook-form + zod
- HTTP Client: Axios (shared instance with credentials)
- Payment: MercadoPago SDK
- Icons: Lucide React
- Notifications: React Toastify + SweetAlert2
- Theming: next-themes
Authentication Flow:
- User logs in via
LoginFormβ callsAuthAPI.login() - Backend issues JWT in httpOnly cookie
- Subsequent requests auto-include cookie
useAuth()hook verifies session on app load- Protected routes redirect unauthenticated users to
/auth/login
Shopping Flow:
- User browses products (fetched via
ProductAPI) - Adds items to cart (stored in
useCartStore) - Proceeds to checkout β
CheckoutFormcaptures shipping address - Payment collected via
CheckoutPayment(MercadoPago) - Backend webhook updates order status
- Redirect to success/failure page with order tracking
State Management:
- useQuery: Product lists, user orders, admin data (cached + auto-refetch)
- useMutation: Form submissions with error/success handlers
- Zustand: Cart items (persists across page navigation)
-
Create API client in
src/api/FeatureAPI.tsexport const fetchData = async (params) => { const response = await api.get('/endpoint', { params }); return response.data; };
-
Create components in
components/feature/- Use functional components with hooks
- Keep components focused and single-responsibility
-
Create pages in
app/feature/page.tsx- Leverage Next.js App Router layout nesting
- Use
useQuery/useMutationfor data fetching
-
Add types to
src/types/index.tsexport interface Feature { id: string; name: string; }
Use the status badge pattern from components/admin/orders/OrderEntry.tsx:
const statusConfig: Record<StatusType, { color: string; bgColor: string }> = {
"Active": {
color: "text-green-800 dark:text-green-300",
bgColor: "bg-green-100 dark:bg-green-900/30"
},
};
<div className={`${statusConfig[status].bgColor} ${statusConfig[status].color}`}>
{status}
</div>Reading data:
const { data, isLoading, error } = useQuery({
queryKey: ['products'],
queryFn: () => ProductAPI.getProducts()
});Mutating data:
const { mutate } = useMutation({
mutationFn: (data) => ProductAPI.updateProduct(data),
onSuccess: () => {
toast.success('Updated!');
queryClient.invalidateQueries({ queryKey: ['products'] });
},
onError: (error) => toast.error(error.message)
});All new components should support dark mode:
className="text-zinc-900 dark:text-zinc-100 bg-white dark:bg-zinc-900"docker build -t morango-frontend .
docker run -p 3000:3000 \
-e NEXT_PUBLIC_BACKEND_API_URL=https://api.morango.com \
-e NEXT_PUBLIC_MERCADOPAGO_PUBLIC_KEY=your_key \
morango-frontend- Backend API:
NEXT_PUBLIC_BACKEND_API_URL(Express.js server) - MercadoPago: SDK initialization in
MercadoPagoProvider - Cloudinary: Image hosting via
remotePatternsinnext.config.ts - EmailJS: Contact form submissions (client-side)
- Language: All UI text is in Spanish (es-ES)
- Currency: Chilean Peso (CLP) - use
formatToCLP()utility - Date Format: Use
formatDate()fromsrc/utils/date.ts - Authentication: Always verify routes with
useAuth()before rendering protected content - Caching: Invalidate React Query on mutations:
queryClient.invalidateQueries({ queryKey: [...] })
Made with