Create a fully functional, multi-page Next.js MVP application for a mobile-first grocery ordering platform called 'GroceryPal'. The application will leverage reverse-engineered APIs (initially REWE, with potential for expansion) to allow users to easily order groceries, track deliveries, and manage their shopping lists.
**1. PROJECT OVERVIEW:**
GroceryPal aims to revolutionize the grocery shopping experience by providing a seamless, intuitive, and intelligent mobile application. The problem it solves is the time-consuming and often tedious process of manual grocery ordering, especially for busy individuals. Users often face repetitive tasks, difficulty in managing shopping lists, and a lack of personalized recommendations. GroceryPal offers a solution by integrating with supermarket APIs (initially REWE), enabling users to quickly create orders based on past purchases, saved favorites, or smart suggestions. The core value proposition is saving users significant time and effort while providing a personalized and efficient shopping experience.
**2. TECH STACK:**
- **Framework:** Next.js (App Router)
- **Language:** TypeScript
- **Styling:** Tailwind CSS
- **ORM:** Drizzle ORM (PostgreSQL with Vercel Postgres or similar)
- **UI Library:** shadcn/ui for components
- **Authentication:** NextAuth.js (for email/password, Google/GitHub OAuth)
- **State Management:** Zustand or React Context API for global state, component-level state where appropriate.
- **Form Handling:** React Hook Form with Zod for validation.
- **API Client:** Axios or native fetch API.
- **Deployment:** Vercel
- **Database:** Vercel Postgres (or Supabase/Neon)
**3. DATABASE SCHEMA (Drizzle ORM - PostgreSQL Syntax):**
```sql
-- Users table
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255),
email VARCHAR(255) UNIQUE NOT NULL,
emailVerified TIMESTAMP WITH TIME ZONE,
image TEXT,
password TEXT, -- Hashed password
createdAt TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updatedAt TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Accounts table (for NextAuth.js)
CREATE TABLE accounts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
userId UUID REFERENCES users(id) ON DELETE CASCADE,
type VARCHAR(255) NOT NULL,
provider VARCHAR(255) NOT NULL,
providerAccountId VARCHAR(255) NOT NULL,
refresh_token TEXT,
access_token TEXT,
expires_at BIGINT,
token_type VARCHAR(255),
scope VARCHAR(255),
id_token TEXT,
UNIQUE (provider, providerAccountId)
);
-- Sessions table (for NextAuth.js)
CREATE TABLE sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
sessionToken VARCHAR(255) UNIQUE NOT NULL,
userId UUID REFERENCES users(id) ON DELETE CASCADE,
expires TIMESTAMP WITH TIME ZONE NOT NULL
);
-- Verification tokens table (for NextAuth.js)
CREATE TABLE verification_tokens (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
identifier VARCHAR(255) NOT NULL,
token VARCHAR(255) NOT NULL,
expires TIMESTAMP WITH TIME ZONE NOT NULL,
UNIQUE (identifier, token)
);
-- Supermarkets table
CREATE TABLE supermarkets (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) UNIQUE NOT NULL,
baseUrl TEXT, -- e.g., for REWE API base URL
authType VARCHAR(50), -- e.g., 'mTLS', 'OAuth'
isActive BOOLEAN DEFAULT TRUE,
createdAt TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Products table
CREATE TABLE products (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
supermarketId UUID REFERENCES supermarkets(id) ON DELETE CASCADE,
externalId VARCHAR(255) NOT NULL, -- ID from the supermarket's API
name TEXT NOT NULL,
description TEXT,
imageUrl TEXT,
price DECIMAL(10, 2) NOT NULL,
unit VARCHAR(50), -- e.g., 'kg', 'piece', 'liter'
isAvailable BOOLEAN DEFAULT TRUE,
createdAt TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updatedAt TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE (supermarketId, externalId)
);
-- UserFavorites table
CREATE TABLE userFavorites (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
userId UUID REFERENCES users(id) ON DELETE CASCADE,
productId UUID REFERENCES products(id) ON DELETE CASCADE,
addedAt TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE (userId, productId)
);
-- Orders table
CREATE TABLE orders (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
userId UUID REFERENCES users(id) ON DELETE CASCADE,
supermarketId UUID REFERENCES supermarkets(id) ON DELETE CASCADE,
status VARCHAR(50) DEFAULT 'pending', -- e.g., pending, processing, shipped, delivered, cancelled
totalAmount DECIMAL(10, 2) NOT NULL,
orderDate TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deliveryAddress TEXT,
deliverySlot TEXT, -- e.g., '2024-07-28 14:00-16:00'
createdAt TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updatedAt TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- OrderItems table
CREATE TABLE orderItems (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
orderId UUID REFERENCES orders(id) ON DELETE CASCADE,
productId UUID REFERENCES products(id) ON DELETE CASCADE,
quantity INTEGER NOT NULL CHECK (quantity > 0),
price DECIMAL(10, 2) NOT NULL, -- Price at the time of order
createdAt TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Potential AI/Recommendation tables (for future iterations)
-- CREATE TABLE userPreferences (...);
-- CREATE TABLE productRecommendations (...);
```
**4. CORE FEATURES & USER FLOW:**
**A. User Authentication (NextAuth.js):**
- **Flow:** Users can sign up using email/password or OAuth (Google, GitHub). Upon successful sign-up/login, a session is created. Protected routes redirect unauthenticated users to the login page.
- **Pages:** `/auth/signin`, `/auth/signup`, `/auth/reset-password`
- **Components:** Sign-in Form, Sign-up Form, OAuth Buttons.
- **Edge Cases:** Invalid credentials, account lockout, password reset flow, email verification.
**B. Onboarding & Market Selection:**
- **Flow:** First-time logged-in users are prompted to select their preferred supermarket(s). The app fetches available supermarkets from the `supermarkets` table. Users can select one or more.
- **Components:** `MarketSelectionModal`, `MarketCard`.
- **Edge Cases:** No supermarkets available, user skips selection.
**C. Product Browsing & Search:**
- **Flow:** Users can browse products from their selected supermarket(s) or search using keywords. Search results display product image, name, price, and unit. Users can add products to their cart or to their favorites list.
- **API:** `/api/products?search=<query>&supermarket=<id>` (GET request to fetch products).
- **Components:** `ProductSearchInput`, `ProductList`, `ProductCard`, `AddToCartButton`, `AddToFavoritesButton`.
- **Edge Cases:** No search results, product out of stock, API error.
**D. Favorites Management:**
- **Flow:** Users can view their list of favorite products. From the favorites page, they can add items to the current cart or remove them from favorites.
- **API:** `/api/favorites` (GET, POST, DELETE requests).
- **Components:** `FavoritesList`, `FavoriteItemCard`.
- **Edge Cases:** Empty favorites list.
**E. Shopping Cart & Checkout:**
- **Flow:** Users can view their shopping cart, adjust quantities, remove items, and see the subtotal. Proceeding to checkout prompts for delivery details (address, preferred slot) and payment. Upon successful payment confirmation, an order is placed.
- **API:** `/api/cart` (GET, POST, PUT, DELETE), `/api/orders` (POST for placing order), `/api/payment` (POST for initiating payment).
- **Components:** `ShoppingCart`, `CartItem`, `CheckoutForm`, `PaymentForm`.
- **Edge Cases:** Empty cart, item price changes before checkout, payment failure, invalid delivery address.
**F. Order History & Tracking:**
- **Flow:** Users can view a list of their past orders, including status, date, and total amount. Clicking on an order shows details and itemized list. Real-time status updates (simulated for MVP or via webhook if API supports) are displayed.
- **API:** `/api/orders` (GET to list orders), `/api/orders/[id]` (GET to fetch specific order details).
- **Components:** `OrderHistoryList`, `OrderItem`, `OrderDetailView`, `OrderStatusTracker`.
- **Edge Cases:** No past orders, order status not updating.
**G. REWE API Integration (Placeholder/Mock for MVP):**
- **Flow:** The backend will have a service responsible for interacting with the REWE API (or a mock API for development). This service will handle fetching product data, pricing, stock information, and potentially placing orders.
- **Note:** The actual reverse-engineering and mTLS handling are complex. For the MVP, we'll simulate this interaction, assuming successful API responses based on the provided details. The prompt implies the existence of a working, albeit unofficial, API.
- **Key Functions:** `fetchProducts(query, supermarketId)`, `getProductDetails(productId, supermarketId)`, `placeOrder(orderData, supermarketId)`.
**5. API & DATA FETCHING:**
- **Next.js App Router:** Utilize Server Components for data fetching where possible to improve performance and reduce client-side load. Use Client Components for interactive elements.
- **API Routes:** Define API routes in `app/api/` for handling client-server communication (e.g., `/api/auth/*`, `/api/products`, `/api/cart`, `/api/orders`, `/api/favorites`).
- **Data Fetching Strategy:**
- Server Components: Fetch data directly using async functions within the component, leveraging Drizzle ORM.
- Client Components: Use `fetch` or libraries like `swr` or `zustand`'s API integration for client-side data fetching and caching, especially for real-time updates or user-specific interactions.
- **Request/Response:** Standard JSON format. Use Zod for request validation and response shaping.
- **Example API Route (`app/api/products/route.ts`):**
```typescript
// POST /api/products
// Request Body: { query: string, supermarketId: string }
// Response Body: { products: Product[], error?: string }
export async function POST(request: Request) {
const { query, supermarketId } = await request.json();
// ... validation ...
try {
// Call to REWE API service (or mock)
const products = await REWEService.searchProducts(query, supermarketId);
return NextResponse.json({ products });
} catch (error) {
return NextResponse.json({ error: 'Failed to fetch products' }, { status: 500 });
}
}
```
**6. COMPONENT BREAKDOWN (Next.js App Router):**
- **`app/layout.tsx`:** Root layout, includes global styles, providers (Auth, Theme).
- **`app/page.tsx`:** Landing/Home page (for logged-out users) or Dashboard (for logged-in users).
- **`app/(auth)/signin/page.tsx`:** Sign-in page.
- **`app/(auth)/signup/page.tsx`:** Sign-up page.
- **`app/dashboard/page.tsx`:** (Logged-in) Shows overview, quick actions, recent orders, suggested products.
- **`app/browse/page.tsx`:** Product browsing and search page.
- `components/SearchInput.tsx`
- `components/ProductGrid.tsx`
- `components/ProductCard.tsx`
- **`app/favorites/page.tsx`:** User's favorite products.
- `components/FavoriteList.tsx`
- `components/FavoriteItem.tsx`
- **`app/cart/page.tsx`:** Shopping cart view.
- `components/CartItemList.tsx`
- `components/CartItem.tsx`
- `components/CheckoutButton.tsx`
- **`app/checkout/page.tsx`:** Checkout process (address, delivery slot, payment).
- `components/AddressForm.tsx`
- `components/DeliverySlotSelector.tsx`
- `components/PaymentForm.tsx` (integrates with payment gateway)
- **`app/orders/page.tsx`:** Order history list.
- `components/OrderList.tsx`
- `components/OrderItem.tsx`
- **`app/orders/[id]/page.tsx`:** Specific order details page.
- `components/OrderDetail.tsx`
- `components/OrderStatusTracker.tsx`
- **`app/settings/page.tsx`:** User profile and settings.
- `components/ProfileForm.tsx`
- `components/AccountSettings.tsx`
- **`components/ui/`:** Re-export shadcn/ui components (Button, Input, Card, Dialog, etc.).
- **`components/Auth/`:** Sign-in/Sign-up forms, Provider buttons.
- **`components/Layout/`:** `Navbar`, `Footer`, `Sidebar` (if applicable).
- **`lib/`:** Utility functions, API clients, database connection, Drizzle schema definitions.
- **`hooks/`:** Custom React hooks (e.g., `useCart`).
- **`store/`:** Zustand store definitions.
**7. UI/UX DESIGN & VISUAL IDENTITY:**
- **Style:** Modern, Clean, Minimalist with a touch of warmth.
- **Color Palette:** Primary: `#007AFF` (Vibrant Blue), Secondary: `#FF9500` (Warm Orange), Accent: `#34C759` (Success Green). Neutrals: `#F2F2F7` (Light Gray), `#E5E5EA` (Medium Gray), `#1C1C1E` (Dark Gray/Background). White: `#FFFFFF`.
- **Typography:** Use a clean, sans-serif font family like Inter or SF Pro Display for readability. Define headings (H1, H2, H3), body text, and button text styles.
- **Layout:** Mobile-first approach. Use a consistent grid system (e.g., 8px grid). Clear visual hierarchy. Ample whitespace. Sticky footer/navbar for navigation.
- **Visual Elements:** High-quality product images. Intuitive icons. Subtle gradients or shadows for depth on interactive elements (buttons, cards).
- **Responsive Rules:** Optimized for mobile screens (vertical scrolling). Desktop view should utilize horizontal space effectively, perhaps with a sidebar or multi-column layout for browsing.
**8. SAMPLE/MOCK DATA:**
- **User:** `{ id: '...', name: 'Max Mustermann', email: 'max@example.com', image: '...' }`
- **Supermarket:** `{ id: '...', name: 'REWE City', baseUrl: 'https://api.rewe.de/v1', authType: 'mTLS' }`
- **Product (REWE):** `{ id: '...', supermarketId: '...', externalId: '1234567', name: 'Bio-Bananen (1kg)', description: 'Süß und biologisch angebaut', imageUrl: 'https://images.rewe.de/image/...', price: 1.99, unit: 'kg', isAvailable: true }`
- **Product (REWE):** `{ id: '...', supermarketId: '...', externalId: '7654321', name: 'Milka Vollmilch (100g)', description: 'Klassische Vollmilchschokolade', imageUrl: 'https://images.rewe.de/image/...', price: 1.29, unit: 'Stück', isAvailable: false }`
- **Favorite:** `{ id: '...', userId: '...', productId: '...' }`
- **Cart Item:** `{ productId: '...', quantity: 2, price: 1.99, name: 'Bio-Bananen (1kg)', imageUrl: '...' }` (Client-side cart representation)
- **Order (Pending):** `{ id: '...', userId: '...', supermarketId: '...', status: 'pending', totalAmount: 25.50, orderDate: '2024-07-27T10:00:00Z', deliveryAddress: 'Musterstraße 1, 12345 Berlin', deliverySlot: '2024-07-28 10:00-12:00' }`
- **OrderItem:** `{ id: '...', orderId: '...', productId: '...', quantity: 2, price: 1.99 }`
- **Order (Delivered):** `{ id: '...', userId: '...', supermarketId: '...', status: 'delivered', totalAmount: 25.50, orderDate: '2024-07-26T10:00:00Z', ... }`
**9. TURKISH TRANSLATIONS:**
- **App Title:** GroceryPal (Kolay Alışveriş)
- **Sign In:** Giriş Yap
- **Sign Up:** Kayıt Ol
- **Search Products:** Ürün Ara
- **Add to Cart:** Sepete Ekle
- **Add to Favorites:** Favorilere Ekle
- **My Cart:** Sepetim
- **Checkout:** Ödeme
- **Order History:** Siparişlerim
- **Favorites:** Favorilerim
- **Settings:** Ayarlar
- **Welcome:** Hoş Geldiniz
- **Choose Your Supermarket:** Marketinizi Seçin
- **Enter Delivery Address:** Teslimat Adresini Girin
- **Confirm Order:** Siparişi Onayla
- **Order Placed Successfully:** Siparişiniz Başarıyla Oluşturuldu
- **Track Order:** Siparişi Takip Et
- **Pending:** Bekliyor
- **Processing:** Hazırlanıyor
- **Shipped:** Yolda
- **Delivered:** Teslim Edildi
- **Cancelled:** İptal Edildi
- **Search results for:** '...' için arama sonuçları
- **No products found:** Ürün bulunamadı.
- **Item added to cart:** Ürün sepete eklendi.
- **Item added to favorites:** Ürün favorilere eklendi.
**ANIMATIONS:**
- **Page Transitions:** Subtle fade-in/fade-out or slide animations between pages using `Framer Motion` or Next.js's built-in features.
- **Button Hovers:** Slight scale-up or background color change on hover.
- **Loading States:** Use skeleton loaders or spinners (e.g., `react-spinners`) for data fetching. Apply subtle shimmer effect on skeleton loaders.
- **Add to Cart:** A small animation of the item flying into the cart icon in the navbar.
- **List Items:** Fade-in animation when items are added to lists (cart, favorites).
**EDGE CASES:**
- **Authentication:** Handle expired sessions, invalid tokens, OAuth errors gracefully.
- **API Errors:** Implement robust error handling for all API calls (supermarket API, payment gateway). Display user-friendly error messages. Implement retry mechanisms where appropriate.
- **Validation:** Use Zod for comprehensive validation on all user inputs (forms, search queries, quantities).
- **Empty States:** Design informative and engaging empty states for Cart, Favorites, Order History, and Search Results.
- **Stock/Price Changes:** Clearly indicate if a product's price or availability has changed since it was added to the cart. Prompt user for confirmation.
- **Network Issues:** Provide feedback to the user during network interruptions and suggest actions.
- **Authorization:** Ensure users can only access and modify their own data (orders, favorites).
This comprehensive prompt provides a detailed blueprint for building the GroceryPal MVP, ensuring a robust, functional, and visually appealing application.