Local food marketplace connecting Romagna's artisan producers directly with consumers.
Farm-to-table e-commerce platform featuring subscription boxes, dynamic pricing, food rescue, agri-tourism, and a community hub — all built for the Forlì/Cesena area of Emilia-Romagna, Italy.
| Domain | Capabilities |
|---|---|
| Marketplace | Product catalog, producer profiles, full-text search, seasonal calendar, category filtering |
| Orders & Checkout | Cart management, Stripe Checkout (Connect split payments), split orders per producer, order tracking, refunds |
| Subscriptions | Weekly/monthly curated boxes, dietary profiling, box composition, A/B experiments, satisfaction tracking |
| Dynamic Pricing | Rule engine (expiry markdown, bulk discount, surge, time-of-day, delivery slot), admin panel |
| Food Rescue | Surplus listings, automatic expiry scanning, discounted near-expiry products |
| Gifts | Gift box builder, unboxing experience with shareable tokens, occasion-based gifting |
| Events & Tourism | Farm visit booking, agri-tourism itineraries, hospitality partnerships, ship-home service |
| Community | Forum, recipe engine with basket builder, adoption programs (olive trees, vineyards), cooperative network |
| Recommendations | Collaborative filtering ("also bought"), content-based similarity, personalized suggestions, trending, contextual (time/season) |
| Analytics | Producer dashboards, customer cohorts, lifecycle analysis, revenue forecasting, category benchmarks, price alerts |
| Traceability | Supply chain timeline, blockchain hash anchoring, certification verification, QR codes |
| Payments | Stripe Connect (standard accounts), platform fees (15%), producer payouts, subscription billing |
| Auth & Security | Session-based auth, OAuth (Google/Apple), MFA, CSRF, rate limiting, CORS, security headers, audit logging |
| GDPR | Consent management, data export, account deletion, cookie consent banner |
| Notifications | In-app, email (Resend), push (VAPID/Web Push), WhatsApp integration, notification digests |
| i18n | Italian (default), English, German, French — with accept-language detection |
| Infrastructure | Vercel deploy, Vercel Blob storage, Upstash Redis, Sentry observability, cron jobs, health checks |
78 Prisma models · 70+ features · 75+ unit tests · 10 E2E test suites
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router, React 19, Turbopack) |
| Language | TypeScript 5 |
| Database | SQLite (dev) / Turso libSQL (prod) via Prisma 7 |
| Payments | Stripe Connect (real SDK with mock fallback) |
| Resend (transactional) | |
| Storage | Vercel Blob / Cloudinary |
| Cache | Upstash Redis (rate limiting, sessions) |
| AI | OpenAI GPT-4o-mini (recipe generation, menu planning) |
| CSS | Tailwind CSS 4 |
| Testing | Vitest (unit) + Playwright (E2E) |
| Observability | Sentry, structured JSON logging |
| Deployment | Vercel (Frankfurt fra1 region) |
- Node.js ≥ 18
- npm ≥ 9
# Clone and install
git clone <repo-url>
cd tavola-romagna
npm install
# Set up environment
cp .env.example .env
# Edit .env with your keys (mock values work for local dev)
# Initialize database
npx prisma generate
npx prisma db push
# Seed sample data (optional)
curl -X POST http://localhost:3000/api/seed
# Start development server
npm run devOpen http://localhost:3000.
See .env.example for the full list. Key groups:
| Variable | Required | Purpose |
|---|---|---|
DATABASE_URL |
✅ | SQLite file path (dev) or Turso/PostgreSQL URL (prod) |
STRIPE_SECRET_KEY |
Mock OK | Stripe Connect payments (falls back to mock) |
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY |
Mock OK | Stripe client-side |
STRIPE_WEBHOOK_SECRET |
Mock OK | Stripe webhook verification |
RESEND_API_KEY |
Mock OK | Transactional email |
BLOB_READ_WRITE_TOKEN |
Optional | Vercel Blob storage |
OPENAI_API_KEY |
Optional | AI recipe/menu generation |
UPSTASH_REDIS_URL |
Optional | Redis-backed rate limiting |
SENTRY_DSN |
Optional | Error tracking |
VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY |
Optional | Push notifications |
💡 Mock mode: The app runs fully offline with mock values. Stripe, email, and storage gracefully degrade to local stubs.
tavola-romagna/
├── prisma/
│ ├── schema.prisma # 78 models across 10+ domains
│ ├── seed.ts # Database seeding
│ └── migrations/ # Prisma migrations
├── src/
│ ├── app/ # Next.js App Router pages & API routes
│ │ ├── api/ # ~60 REST API endpoints
│ │ ├── admin/ # Admin operations center
│ │ ├── auth/ # Login, register
│ │ ├── dashboard/ # Consumer & producer dashboards
│ │ ├── products/ # Product catalog
│ │ ├── producers/ # Producer profiles
│ │ ├── checkout/ # Checkout flow
│ │ ├── subscriptions/ # Subscription box management
│ │ ├── gifts/ # Gift boxes & unboxing
│ │ ├── events/ # Event booking
│ │ ├── community/ # Forum & adoptions
│ │ ├── recipes/ # Recipes & basket builder
│ │ ├── tourism/ # Agri-tourism & ship-home
│ │ ├── surplus/ # Food rescue
│ │ ├── moonshots/ # Innovation portfolio
│ │ └── ...
│ ├── components/ # 30+ React components
│ ├── lib/ # Core business logic (~40 modules)
│ │ ├── auth.ts # Session-based authentication
│ │ ├── stripe.ts # Stripe Connect integration
│ │ ├── prisma.ts # Database client
│ │ ├── pricing-engine.ts # Dynamic pricing rule engine
│ │ ├── recommendations.ts # ML-lite recommendation engine
│ │ ├── i18n.ts # Internationalization (4 locales)
│ │ ├── validation.ts # Input validation
│ │ ├── security.ts # Security headers, CSRF, CORS
│ │ ├── rate-limit.ts # Redis/in-memory rate limiter
│ │ └── ...
│ ├── generated/ # Prisma generated client
│ └── types/ # TypeScript type declarations
├── e2e/ # 10 Playwright E2E test suites
├── vercel.json # Vercel deployment config + cron jobs
├── playwright.config.ts # Playwright configuration
└── vitest.config.ts # Vitest configuration
# Unit tests (Vitest)
npm test # Watch mode
npx vitest run # Single run
# E2E tests (Playwright)
npm run test:e2e # Headless
npm run test:e2e:ui # Interactive UI
# All tests
npm run test:all| Suite | Tests | Scope |
|---|---|---|
validation.test.ts |
Email, password, string, number validation | Input sanitization |
i18n.test.ts |
Locale detection, fallback, translation | Internationalization |
stripe.test.ts / stripe-fees.test.ts |
Stripe integration, fee calculations | Payments |
pricing-engine.test.ts |
Dynamic pricing rules, markdown, bulk | Pricing |
auth.test.ts |
Password hashing, sessions | Authentication |
recommendations.test.ts |
Recommendation algorithms | ML |
security.test.ts |
Headers, CSRF, sanitization | Security |
recipe-engine.test.ts |
Recipe generation | Content |
analytics.test.ts |
Analytics computations | BI |
email.test.ts |
Email templates | Communications |
| E2E (10 suites) | Browse→cart→checkout, auth, producer onboarding, recipes, gifts, search, events, admin, GDPR, API contracts | Full flows |
The project is pre-configured for Vercel with vercel.json:
- Region:
fra1(Frankfurt — closest to Italy) - Build:
npx prisma generate && next build - Cron jobs: Analytics (daily 2am), pricing scan (every 6h), surplus scan (daily 8am), notification digest (weekly Monday 9am)
- Security headers: CSP, HSTS, X-Frame-Options, etc.
vercel deploySet production environment variables in the Vercel dashboard (see vercel.json env section for required secrets).
- API Reference — All REST endpoints with methods, auth requirements, and payloads
- Architecture Overview — System design, data flow diagrams, and domain model
Default locale is Italian (it). Supported: it, en, de, fr.
Locale is detected from the Accept-Language header and can be switched via the language switcher component. Message dictionaries live in src/lib/messages/.
Source code is publicly available. No open-source license has been selected yet.