refactor: rename marketplace to storefront across the entire monorepo
Build & Deploy / Build & Push Docker Image (push) Successful in 1m2s
Test / Type Check (all packages) (push) Failing after 28s
Test / API Unit Tests (push) Has been skipped
Test / Homepage Unit Tests (push) Has been skipped
Test / Storefront Unit Tests (push) Has been skipped
Test / Admin Unit Tests (push) Has been skipped
Test / Dashboard Unit Tests (push) Has been skipped
Test / API Integration Tests (push) Has been skipped
Build & Deploy / Deploy to VPS (push) Successful in 3s
Build & Deploy / Build & Push Docker Image (push) Successful in 1m2s
Test / Type Check (all packages) (push) Failing after 28s
Test / API Unit Tests (push) Has been skipped
Test / Homepage Unit Tests (push) Has been skipped
Test / Storefront Unit Tests (push) Has been skipped
Test / Admin Unit Tests (push) Has been skipped
Test / Dashboard Unit Tests (push) Has been skipped
Test / API Integration Tests (push) Has been skipped
Build & Deploy / Deploy to VPS (push) Successful in 3s
Comprehensive rename of all marketplace references to storefront: - API module: apps/api/src/modules/marketplace/ → storefront/ - Components: MarketplaceHeader → StorefrontHeader, MarketplaceShell → StorefrontShell, MarketplaceFooter → StorefrontFooter - Types: marketplace-homepage.ts → storefront-homepage.ts - Test files: employee-marketplace-* → employee-storefront-* - All source code identifiers, imports, route paths, and strings - Documentation (docs/), CI config (.gitlab-ci.yml), scripts - Dashboard, admin, storefront workspace references - Prisma field names preserved (isListedOnMarketplace, marketplaceRating, marketplaceFunnelEvent) as they map to database schema Validation: - API type-check: 0 errors - Storefront type-check: 0 errors - Dashboard type-check: 0 errors - Full monorepo type-check: only pre-existing admin TS18046
This commit is contained in:
@@ -28,7 +28,7 @@ This reduces cognitive load, reduces privacy anxiety, and makes mobile completio
|
||||
|
||||
Replace the current booking form with the revised version in:
|
||||
|
||||
`apps/marketplace/src/components/BookingForm.tsx`
|
||||
`apps/storefront/src/components/BookingForm.tsx`
|
||||
|
||||
Acceptance criteria:
|
||||
|
||||
@@ -50,7 +50,7 @@ Recommended behavior:
|
||||
|
||||
Backend candidate:
|
||||
|
||||
- Add or expose `GET /marketplace/:slug/vehicles/:id/availability?startDate=&endDate=`.
|
||||
- Add or expose `GET /storefront/:slug/vehicles/:id/availability?startDate=&endDate=`.
|
||||
- Reuse the existing `getVehicleAvailabilitySummary` service instead of inventing yet another inconsistent truth source, because apparently systems enjoy lying to themselves.
|
||||
|
||||
### Phase 3: Booking Status Transparency
|
||||
|
||||
+7
-7
@@ -20,7 +20,7 @@ docker compose -f docker-compose.dev.yml --profile full up --build
|
||||
|
||||
Services:
|
||||
|
||||
- marketplace: `http://localhost:3000`
|
||||
- storefront: `http://localhost:3000`
|
||||
- dashboard: `http://localhost:3000/dashboard`
|
||||
- admin: `http://localhost:3000/admin`
|
||||
- public-site: `http://localhost:3003`
|
||||
@@ -31,12 +31,12 @@ Each dev app now runs in its own container and can be started independently with
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.dev.yml --profile api up --build
|
||||
docker compose -f docker-compose.dev.yml --profile marketplace up --build
|
||||
docker compose -f docker-compose.dev.yml --profile storefront up --build
|
||||
docker compose -f docker-compose.dev.yml --profile dashboard up --build
|
||||
docker compose -f docker-compose.dev.yml --profile admin up --build
|
||||
docker compose -f docker-compose.dev.yml --profile public-site up --build
|
||||
docker compose -f docker-compose.dev.yml --profile tools up --build
|
||||
docker compose -f docker-compose.dev.yml --profile api --profile marketplace --profile dashboard --profile admin up --build
|
||||
docker compose -f docker-compose.dev.yml --profile api --profile storefront --profile dashboard --profile admin up --build
|
||||
```
|
||||
|
||||
Notes:
|
||||
@@ -121,7 +121,7 @@ Add an A record for every subdomain to your server's public IP before deploying
|
||||
|
||||
| Subdomain | Service |
|
||||
|---|---|
|
||||
| `rentaldrivego.ma` | marketplace and public site |
|
||||
| `rentaldrivego.ma` | storefront and public site |
|
||||
| `api.rentaldrivego.ma` | API |
|
||||
| `pgmanage.rentaldrivego.ma` | pgManage (DB admin) |
|
||||
| `portainer.rentaldrivego.ma` | Portainer |
|
||||
@@ -163,7 +163,7 @@ Open `.env.docker.production` and fill in every value. The minimum required secr
|
||||
|
||||
Production now derives `DATABASE_URL` inside the app container from `POSTGRES_HOST`, `POSTGRES_PORT`, `POSTGRES_DB`, `POSTGRES_USER`, and `POSTGRES_PASSWORD` when `DATABASE_URL_FROM_POSTGRES=true`. That avoids Prisma auth failures when the database password contains reserved URL characters such as `@`, `:`, or `/`.
|
||||
|
||||
The example file uses `rentaldrivego.ma` for the marketplace and public site. The dashboard and admin panel are routed under that same host at `/dashboard` and `/admin`.
|
||||
The example file uses `rentaldrivego.ma` for the storefront and public site. The dashboard and admin panel are routed under that same host at `/dashboard` and `/admin`.
|
||||
Set `PORTAINER_DOMAIN=portainer.rentaldrivego.ma` in `.env.docker.production` to expose Portainer through Traefik.
|
||||
Set `PGMANAGE_DOMAIN=pgmanage.rentaldrivego.ma` to expose pgManage through Traefik, and set `PGMANAGE_LICENSE_KEY` if you are running the enterprise image.
|
||||
Set `REGISTRY_DOMAIN=registry.rentaldrivego.ma` to expose the Docker registry through Traefik.
|
||||
@@ -255,7 +255,7 @@ npm run docker:prod:start:traefik
|
||||
npm run docker:prod:start:postgres
|
||||
npm run docker:prod:start:redis
|
||||
npm run docker:prod:start:api
|
||||
npm run docker:prod:start:marketplace
|
||||
npm run docker:prod:start:storefront
|
||||
npm run docker:prod:start:dashboard
|
||||
npm run docker:prod:start:admin
|
||||
npm run docker:prod:start:frontends
|
||||
@@ -268,7 +268,7 @@ npm run docker:prod:start:api && npm run docker:prod:start:frontends
|
||||
|
||||
Docker will:
|
||||
1. Build the monorepo image on the server
|
||||
2. Start all app services (`api`, `marketplace`, `dashboard`, `admin`, `pgmanage`)
|
||||
2. Start all app services (`api`, `storefront`, `dashboard`, `admin`, `pgmanage`)
|
||||
|
||||
Traefik automatically picks up the containers and provisions TLS certificates. Services are live at their `https://` URLs within ~30 seconds.
|
||||
|
||||
|
||||
+12
-12
@@ -1,10 +1,10 @@
|
||||
# 🚗 RentalDriveGo— Multi-Tenant Car Rental SaaS + Marketplace
|
||||
# 🚗 RentalDriveGo— Multi-Tenant Car Rental SaaS + Storefront
|
||||
|
||||
## Platform Model
|
||||
|
||||
**Rental Companies (B2B)** — pay RentalDriveGoa subscription (AmanPay or PayPal), get:
|
||||
- A fully private dashboard (zero data overlap with any other company)
|
||||
- Fleet management with vehicle photo upload (photos auto-appear on global marketplace)
|
||||
- Fleet management with vehicle photo upload (photos auto-appear on global storefront)
|
||||
- Promotional offers management
|
||||
- A white-label site at `company.RentalDriveGo.com` where renters book and pay
|
||||
|
||||
@@ -29,21 +29,21 @@
|
||||
|
||||
---
|
||||
|
||||
## 🌐 Marketplace is Discovery Only — No Booking on RentalDriveGo.com/explore
|
||||
## 🌐 Storefront is Discovery Only — No Booking on RentalDriveGo.com/explore
|
||||
|
||||
The global marketplace shows all vehicles with photos from all companies. When a renter clicks "Book this vehicle", they are **redirected to the company's branded site** (`{slug}.RentalDriveGo.com/book?vehicleId=X&from=Y&to=Z&ref=marketplace`). The booking form is pre-filled. All payment happens on the company site using the company's own payment accounts.
|
||||
The global storefront shows all vehicles with photos from all companies. When a renter clicks "Book this vehicle", they are **redirected to the company's branded site** (`{slug}.RentalDriveGo.com/book?vehicleId=X&from=Y&to=Z&ref=storefront`). The booking form is pre-filled. All payment happens on the company site using the company's own payment accounts.
|
||||
|
||||
---
|
||||
|
||||
## 📸 Vehicle Photos → Marketplace Visibility
|
||||
## 📸 Vehicle Photos → Storefront Visibility
|
||||
|
||||
```
|
||||
Company uploads photos in /dashboard/fleet
|
||||
→ Stored in Cloudinary
|
||||
→ Vehicle.photos[] holds the URLs
|
||||
→ First photo = cover image on marketplace cards
|
||||
→ All photos shown in marketplace vehicle gallery
|
||||
→ isPublished=true makes vehicle appear on marketplace
|
||||
→ First photo = cover image on storefront cards
|
||||
→ All photos shown in storefront vehicle gallery
|
||||
→ isPublished=true makes vehicle appear on storefront
|
||||
```
|
||||
|
||||
---
|
||||
@@ -52,7 +52,7 @@ Company uploads photos in /dashboard/fleet
|
||||
|
||||
```
|
||||
Layer 1A: RentalDriveGo.com — B2B marketing site
|
||||
Layer 1B: RentalDriveGo.com/explore — B2C marketplace (discovery + redirect only)
|
||||
Layer 1B: RentalDriveGo.com/explore — B2C storefront (discovery + redirect only)
|
||||
Layer 2: app.RentalDriveGo.com — Company dashboard (private, subscription-gated)
|
||||
Layer 3: {slug}.RentalDriveGo.com — Company branded site (booking + payment here)
|
||||
Layer 4: api.RentalDriveGo.com — REST API
|
||||
@@ -66,9 +66,9 @@ Layer 4: api.RentalDriveGo.com — REST API
|
||||
rental-car-site/
|
||||
├── README.md
|
||||
├── docs/
|
||||
│ ├── ARCHITECTURE.md ← Payment providers, marketplace redirect model, photo flow
|
||||
│ ├── ARCHITECTURE.md ← Payment providers, storefront redirect model, photo flow
|
||||
│ ├── DESIGN_SYSTEM.md
|
||||
│ ├── PAGES.md ← All pages. Marketplace = discovery only. Booking = company site.
|
||||
│ ├── PAGES.md ← All pages. Storefront = discovery only. Booking = company site.
|
||||
│ ├── FEATURES.md
|
||||
│ └── DEPLOYMENT.md
|
||||
└── skills/
|
||||
@@ -80,7 +80,7 @@ rental-car-site/
|
||||
│ ├── api-routes.md ← All routes
|
||||
│ ├── payment-service.md ← AmanPay + PayPal implementation ← KEY FILE
|
||||
│ ├── subscription-service.md ← Manual renewal, plan prices in MAD/USD/EUR
|
||||
│ ├── subdomain-service.md ← Marketplace redirect + company site
|
||||
│ ├── subdomain-service.md ← Storefront redirect + company site
|
||||
│ └── notification-service.md ← All 5 channels
|
||||
└── rental-car-i18n/
|
||||
```
|
||||
|
||||
@@ -60,15 +60,15 @@ Changed files:
|
||||
|
||||
- `apps/api/src/app.ts`
|
||||
- `apps/dashboard/src/middleware.ts`
|
||||
- `apps/marketplace/src/middleware.ts`
|
||||
- `apps/storefront/src/middleware.ts`
|
||||
- `apps/admin/src/middleware.ts`
|
||||
- `apps/dashboard/src/middleware.test.ts`
|
||||
- `apps/marketplace/src/middleware.test.ts`
|
||||
- `apps/storefront/src/middleware.test.ts`
|
||||
|
||||
What changed:
|
||||
|
||||
- API now rejects requests containing `x-middleware-subrequest` before route handling.
|
||||
- Dashboard, marketplace, and admin Next middleware now reject the same header at the app layer.
|
||||
- Dashboard, storefront, and admin Next middleware now reject the same header at the app layer.
|
||||
- Added/updated middleware tests for the rejection path.
|
||||
|
||||
Security effect:
|
||||
|
||||
@@ -15,7 +15,7 @@ Creating an account registers a new rental company on the platform. The flow has
|
||||
|
||||
## 1. Accessing the Sign-up Page
|
||||
|
||||
### From the marketplace homepage (port 3000)
|
||||
### From the storefront homepage (port 3000)
|
||||
|
||||
- Click **"Create Agency Space"** in the header navigation.
|
||||
- Click **"Get Started"** on any pricing plan card (`/pricing` page).
|
||||
@@ -26,7 +26,7 @@ Both actions navigate to:
|
||||
http://localhost:3000/dashboard/sign-up
|
||||
```
|
||||
|
||||
The marketplace proxies this request to the dashboard app (port 3001), which renders the multi-step form.
|
||||
The storefront proxies this request to the dashboard app (port 3001), which renders the multi-step form.
|
||||
|
||||
### URL parameters (optional)
|
||||
|
||||
@@ -111,7 +111,7 @@ Select one of three plans:
|
||||
| Plan | Description |
|
||||
|---|---|
|
||||
| **STARTER** | Core fleet, offers, and bookings |
|
||||
| **GROWTH** | Featured marketplace placement and more room to scale |
|
||||
| **GROWTH** | Featured storefront placement and more room to scale |
|
||||
| **PRO** | Full white-label and premium controls |
|
||||
|
||||
Additional options:
|
||||
@@ -213,7 +213,7 @@ Navigate to `/sign-in` (redirects to `/dashboard/sign-in`). Enter the owner emai
|
||||
After first sign-in, the user is directed to the **onboarding** page (`/onboarding`) where they can:
|
||||
|
||||
1. **Step 1 — Company profile**: Set display name, tagline, brand color, and public location.
|
||||
2. **Step 2 — Payments**: Configure AmanPay merchant ID / PayPal email and marketplace listing preference.
|
||||
2. **Step 2 — Payments**: Configure AmanPay merchant ID / PayPal email and storefront listing preference.
|
||||
3. **Step 3 — Completion**: Redirect to the dashboard home.
|
||||
|
||||
### Subscription
|
||||
@@ -228,7 +228,7 @@ New accounts start on a **90-day free trial** with the selected plan. The subscr
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `apps/marketplace/src/app/renter/sign-up/page.tsx` | Marketplace redirect page to dashboard sign-up |
|
||||
| `apps/storefront/src/app/renter/sign-up/page.tsx` | Storefront redirect page to dashboard sign-up |
|
||||
| `apps/dashboard/src/app/sign-up/[[...sign-up]]/page.tsx` | Main multi-step sign-up form (4 steps, 937 lines) |
|
||||
| `apps/dashboard/src/components/ui/BilingualInput.tsx` | Bilingual (FR/AR) input component |
|
||||
| `apps/dashboard/src/components/layout/PublicShell.tsx` | Public layout wrapper for the sign-up page |
|
||||
@@ -241,10 +241,10 @@ New accounts start on a **90-day free trial** with the selected plan. The subscr
|
||||
|
||||
| File | Location |
|
||||
|---|---|
|
||||
| `apps/marketplace/src/components/MarketplaceHeader.tsx` | "Create Agency Space" button |
|
||||
| `apps/marketplace/src/components/WorkspaceTabs.tsx` | "Owner sign in" link |
|
||||
| `apps/marketplace/src/app/(public)/pricing/PricingClient.tsx` | "Get Started" pricing CTA |
|
||||
| `apps/marketplace/src/app/(public)/HomeContent.tsx` | Homepage CTA |
|
||||
| `apps/storefront/src/components/StorefrontHeader.tsx` | "Create Agency Space" button |
|
||||
| `apps/storefront/src/components/WorkspaceTabs.tsx` | "Owner sign in" link |
|
||||
| `apps/storefront/src/app/(public)/pricing/PricingClient.tsx` | "Get Started" pricing CTA |
|
||||
| `apps/storefront/src/app/(public)/HomeContent.tsx` | Homepage CTA |
|
||||
|
||||
### Backend
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ docker compose -f docker-compose.dev.yml up -d redis
|
||||
|
||||
# app services
|
||||
docker compose -f docker-compose.dev.yml --profile api up --build
|
||||
docker compose -f docker-compose.dev.yml --profile marketplace up --build
|
||||
docker compose -f docker-compose.dev.yml --profile storefront up --build
|
||||
docker compose -f docker-compose.dev.yml --profile dashboard up --build
|
||||
docker compose -f docker-compose.dev.yml --profile admin up --build
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
## 3. What to Redesign (Inspired by isysolution.com)
|
||||
|
||||
### 3.1 Marketplace — Public Pages
|
||||
### 3.1 Storefront — Public Pages
|
||||
|
||||
#### Home Page (`/`)
|
||||
Current issues to fix:
|
||||
@@ -70,7 +70,7 @@ Stats Strip
|
||||
How It Works
|
||||
├── Step 1: Create your workspace
|
||||
├── Step 2: Add your fleet
|
||||
├── Step 3: Go live on marketplace
|
||||
├── Step 3: Go live on storefront
|
||||
└── Step 4: Manage everything from dashboard
|
||||
|
||||
Services / Features Grid
|
||||
@@ -154,8 +154,8 @@ Redesign:
|
||||
## 4. Component Redesign Checklist
|
||||
|
||||
### Shared Components
|
||||
- [ ] `MarketplaceHeader` — add mobile hamburger menu, improve nav spacing
|
||||
- [ ] `MarketplaceFooter` — add logo, social links, newsletter input
|
||||
- [ ] `StorefrontHeader` — add mobile hamburger menu, improve nav spacing
|
||||
- [ ] `StorefrontFooter` — add logo, social links, newsletter input
|
||||
- [ ] `BookingForm` — improve step layout, add progress indicator
|
||||
- [ ] `WorkspaceTabs` — improve active tab styling
|
||||
|
||||
@@ -187,7 +187,7 @@ Redesign:
|
||||
| Numbered step process | Home "How it works" |
|
||||
| Stats/counters strip | Home page |
|
||||
| Testimonials carousel | Home page |
|
||||
| Mega footer with columns | Marketplace footer |
|
||||
| Mega footer with columns | Storefront footer |
|
||||
| Sidebar with grouped nav | Dashboard |
|
||||
| KPI metric cards | Dashboard home |
|
||||
|
||||
@@ -202,7 +202,7 @@ Redesign:
|
||||
- Wide: `xl: 1280px`, `2xl: 1536px`
|
||||
|
||||
### Mobile Improvements Needed
|
||||
- [ ] Hamburger menu for marketplace header
|
||||
- [ ] Hamburger menu for storefront header
|
||||
- [ ] Collapsible sidebar for dashboard
|
||||
- [ ] Stack pricing cards vertically
|
||||
- [ ] Full-width booking form
|
||||
@@ -228,7 +228,7 @@ Redesign:
|
||||
|
||||
## 8. Implementation Phases
|
||||
|
||||
### Phase 1 — Marketplace Public Pages (Priority)
|
||||
### Phase 1 — Storefront Public Pages (Priority)
|
||||
1. Home page redesign
|
||||
- Stats strip
|
||||
- How it works section
|
||||
@@ -254,15 +254,15 @@ Redesign:
|
||||
|
||||
## 9. Files to Modify
|
||||
|
||||
### Marketplace
|
||||
### Storefront
|
||||
| File | Change |
|
||||
|---|---|
|
||||
| `src/app/(public)/HomeContent.tsx` | Add stats, how-it-works, testimonials sections |
|
||||
| `src/app/(public)/features/page.tsx` | Alternating layout |
|
||||
| `src/app/(public)/pricing/PricingPageContent.tsx` | Toggle + improved cards |
|
||||
| `src/app/(public)/explore/ExploreVehicleGrid.tsx` | Improved vehicle cards |
|
||||
| `src/components/MarketplaceHeader.tsx` | Mobile menu |
|
||||
| `src/components/MarketplaceFooter.tsx` | Mega footer |
|
||||
| `src/components/StorefrontHeader.tsx` | Mobile menu |
|
||||
| `src/components/StorefrontFooter.tsx` | Mega footer |
|
||||
| `src/app/globals.css` | No changes needed |
|
||||
|
||||
### Dashboard
|
||||
|
||||
@@ -70,13 +70,13 @@ Replace the rigid 4-step form with an explicit состояние/state on the `
|
||||
| `DRAFT` | Step 0 above | Browsing dashboard UI, exploring settings, reading docs |
|
||||
| `IDENTIFIED` | Owner first/last name + company display name | Personalizing UI, inviting teammates |
|
||||
| `LISTABLE` | Company contact info + address | Creating/saving a fleet item or offer as **draft** |
|
||||
| `PUBLISHABLE` | Legal identity block (legal name, legal form, RC, ICE, IF, license) | Publishing a listing live on the marketplace |
|
||||
| `PUBLISHABLE` | Legal identity block (legal name, legal form, RC, ICE, IF, license) | Publishing a listing live on the storefront |
|
||||
| `PAYABLE` | Payment provider config (AmanPay/PayPal) + responsible person | Accepting bookings/payments |
|
||||
| `SUBSCRIBED` | Plan + billing period selection | Past the 90-day trial, billed account |
|
||||
|
||||
Each state is just a derived boolean/computed field (`companyState`) based on which fields are filled — not a separate workflow table. The UI reads this state to decide what to show/lock.
|
||||
|
||||
This also directly maps the **existing legal/compliance fields** (RC, ICE, IF, operating license) to the **one moment they actually matter**: right before something goes live on the marketplace. Today they're collected on day 1, before the user has even decided to publish anything.
|
||||
This also directly maps the **existing legal/compliance fields** (RC, ICE, IF, operating license) to the **one moment they actually matter**: right before something goes live on the storefront. Today they're collected on day 1, before the user has even decided to publish anything.
|
||||
|
||||
---
|
||||
|
||||
@@ -171,7 +171,7 @@ Confirmation email still sends immediately after Step 0, but its copy changes fr
|
||||
| Risk | Mitigation |
|
||||
|---|---|
|
||||
| Users abandon before ever reaching `PUBLISHABLE`/`PAYABLE` | That's expected and fine — they were never going to finish the old form either. Track funnel by state instead of all-or-nothing. |
|
||||
| Marketplace ends up with unpublishable "ghost" companies | `DRAFT`/`IDENTIFIED` companies are simply never shown publicly — only `PUBLISHABLE`+ companies appear, so this is a non-issue by construction. |
|
||||
| Storefront ends up with unpublishable "ghost" companies | `DRAFT`/`IDENTIFIED` companies are simply never shown publicly — only `PUBLISHABLE`+ companies appear, so this is a non-issue by construction. |
|
||||
| Legal/compliance requirements might mandate some data before *any* account exists, in some jurisdictions | Confirm with legal/compliance which fields (if any) are truly required by regulation before allowing a transaction vs. before allowing signup at all. Likely only the `PAYABLE` gate has real regulatory weight. |
|
||||
| Users get repeatedly interrupted by modals | Batch by group (Section 5), not by individual field; show the completion indicator so users see how close they are; never re-ask for data already given. |
|
||||
| Existing accounts (already fully filled out under the old flow) | No migration needed — they'll simply compute as `SUBSCRIBED`/fully complete already. |
|
||||
|
||||
@@ -53,7 +53,7 @@ whenever new endpoints are added.
|
||||
Integration tests exist, but the heaviest workflows still benefit from deeper coverage:
|
||||
|
||||
- subscription billing transitions
|
||||
- marketplace reservation intake
|
||||
- storefront reservation intake
|
||||
- public booking and payment initialization
|
||||
- reservation inspection and close flows
|
||||
- admin billing operations
|
||||
|
||||
@@ -52,7 +52,7 @@ We do not use analytics cookies, advertising cookies, or third-party tracking co
|
||||
| **Scope** | All pages (`path=/`) |
|
||||
| **Third-party** | No |
|
||||
|
||||
**Purpose:** Stores your chosen display language so the interface appears in your preferred language on every visit across all parts of the platform (public marketplace, dashboard, and admin panel). Supported values are English (`en`), French (`fr`), and Arabic (`ar`).
|
||||
**Purpose:** Stores your chosen display language so the interface appears in your preferred language on every visit across all parts of the platform (public storefront, dashboard, and admin panel). Supported values are English (`en`), French (`fr`), and Arabic (`ar`).
|
||||
|
||||
**When it is set:** When you change the language using the language selector, or automatically on first visit based on your browser's language settings.
|
||||
**Can you opt out?** You can block this cookie. If you do, the platform will fall back to a default language and you may need to select your language on every visit.
|
||||
@@ -97,7 +97,7 @@ We do not use analytics cookies, advertising cookies, or third-party tracking co
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Names** | `dashboard-language`, `marketplace-language` |
|
||||
| **Names** | `dashboard-language`, `storefront-language` |
|
||||
| **Category** | Functional / preference |
|
||||
| **Duration** | 1 year |
|
||||
| **Scope** | All pages (`path=/`) |
|
||||
|
||||
@@ -4,7 +4,7 @@ This document lists the features that are active in the current codebase.
|
||||
|
||||
Source of truth:
|
||||
|
||||
- `apps/marketplace`
|
||||
- `apps/storefront`
|
||||
- `apps/dashboard`
|
||||
- `apps/admin`
|
||||
- `apps/api`
|
||||
@@ -14,7 +14,7 @@ Source of truth:
|
||||
|
||||
The current workspace contains four active apps:
|
||||
|
||||
- `apps/marketplace`
|
||||
- `apps/storefront`
|
||||
- `apps/dashboard`
|
||||
- `apps/admin`
|
||||
- `apps/api`
|
||||
@@ -61,12 +61,12 @@ There is no separate frontend app for a white-label company public site in this
|
||||
- Notification inbox and preferences
|
||||
- Subscription management
|
||||
|
||||
### Marketplace and public platform
|
||||
### Storefront and public platform
|
||||
|
||||
- Public marketing homepage
|
||||
- Public pricing page
|
||||
- Public features page
|
||||
- Public marketplace/explore flow
|
||||
- Public storefront/explore flow
|
||||
- Explore company profile pages under `/explore/[slug]`
|
||||
- Public review submission page via review token
|
||||
- Public legal/app policy pages
|
||||
@@ -120,7 +120,7 @@ There is no separate frontend app for a white-label company public site in this
|
||||
- Billing operations
|
||||
- Pricing configuration and promotions
|
||||
- Notification review
|
||||
- Marketplace/site config management
|
||||
- Storefront/site config management
|
||||
|
||||
## Present But Not Active Product Features
|
||||
|
||||
@@ -144,9 +144,9 @@ The following old design ideas should not be treated as active features unless c
|
||||
- standalone about/contact page set
|
||||
- Google renter auth
|
||||
- automatic custom-domain provisioning
|
||||
- Zapier/webhook marketplace integrations beyond the current API/webhook handlers
|
||||
- Zapier/webhook storefront integrations beyond the current API/webhook handlers
|
||||
|
||||
## Notes
|
||||
|
||||
- The database still contains legacy fields such as `Employee.clerkUserId`, but those fields are no longer evidence of active Clerk integration.
|
||||
- Some renter-facing `/renter/*` pages exist in the marketplace app, but the auth entrypoints they depend on are not active. They are therefore not listed as active product scope here.
|
||||
- Some renter-facing `/renter/*` pages exist in the storefront app, but the auth entrypoints they depend on are not active. They are therefore not listed as active product scope here.
|
||||
|
||||
@@ -4,15 +4,15 @@ This document lists the pages that are actually present in the current frontend
|
||||
|
||||
Source of truth:
|
||||
|
||||
- `apps/marketplace/src/app`
|
||||
- `apps/storefront/src/app`
|
||||
- `apps/dashboard/src/app`
|
||||
- `apps/admin/src/app`
|
||||
|
||||
## Marketplace App
|
||||
## Storefront App
|
||||
|
||||
App:
|
||||
|
||||
- `apps/marketplace`
|
||||
- `apps/storefront`
|
||||
|
||||
### Public routes
|
||||
|
||||
@@ -37,11 +37,11 @@ App:
|
||||
|
||||
- `/` is the public marketing home.
|
||||
- `/pricing` consumes platform pricing from `/site/platform/pricing`.
|
||||
- `/explore` is the public marketplace search/discovery page.
|
||||
- `/explore/[slug]` is the company marketplace profile page.
|
||||
- `/explore` is the public storefront search/discovery page.
|
||||
- `/explore/[slug]` is the company storefront profile page.
|
||||
- `/review` is the review submission page driven by a reservation review token.
|
||||
|
||||
### Not present in the current marketplace app
|
||||
### Not present in the current storefront app
|
||||
|
||||
- `/about`
|
||||
- `/contact`
|
||||
@@ -51,7 +51,7 @@ App:
|
||||
|
||||
### Renter routes present in code but not active product entrypoints
|
||||
|
||||
These routes exist in the marketplace app:
|
||||
These routes exist in the storefront app:
|
||||
|
||||
- `/renter/dashboard`
|
||||
- `/renter/notifications`
|
||||
@@ -114,7 +114,7 @@ Base path:
|
||||
- `/dashboard` shows KPIs and booking-source analytics.
|
||||
- `/dashboard/fleet*` manages vehicles, maintenance, and calendar blocks.
|
||||
- `/dashboard/reservations*` manages the booking lifecycle and inspection workflows.
|
||||
- `/dashboard/online-reservations` handles public/marketplace booking intake.
|
||||
- `/dashboard/online-reservations` handles public/storefront booking intake.
|
||||
- `/dashboard/customers` is the company CRM view.
|
||||
- `/dashboard/offers` manages promotions.
|
||||
- `/dashboard/team` manages employees.
|
||||
@@ -164,7 +164,7 @@ App:
|
||||
- `/dashboard/billing` manages platform billing operations.
|
||||
- `/dashboard/pricing` edits platform pricing, features, and promotions.
|
||||
- `/dashboard/notifications` inspects platform notifications.
|
||||
- `/dashboard/site-config` edits marketplace/site configuration content.
|
||||
- `/dashboard/site-config` edits storefront/site configuration content.
|
||||
|
||||
## Deliberately Not Listed
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
## Summary
|
||||
|
||||
A full security review of the API codebase identified 3 confirmed, high-confidence vulnerabilities. All 3 were fixed in the same session. A separate frontend scan (dashboard, admin, marketplace, public-site) found no confirmed vulnerabilities above the reporting threshold.
|
||||
A full security review of the API codebase identified 3 confirmed, high-confidence vulnerabilities. All 3 were fixed in the same session. A separate frontend scan (dashboard, admin, storefront, public-site) found no confirmed vulnerabilities above the reporting threshold.
|
||||
|
||||
| # | Severity | Category | Status |
|
||||
|---|----------|----------|--------|
|
||||
@@ -127,7 +127,7 @@ An authenticated employee from Company A could fetch the full maintenance histor
|
||||
|
||||
### Exploit Scenario
|
||||
|
||||
An employee of Company A calls `GET /api/v1/vehicles/<vehicleId_from_company_B>/maintenance`. Vehicle UUIDs can leak through marketplace listings, shared bookings, or support interactions. The response contains the complete maintenance history of Company B's vehicle — including service records, mileage data, and operational schedules — across tenant boundaries.
|
||||
An employee of Company A calls `GET /api/v1/vehicles/<vehicleId_from_company_B>/maintenance`. Vehicle UUIDs can leak through storefront listings, shared bookings, or support interactions. The response contains the complete maintenance history of Company B's vehicle — including service records, mileage data, and operational schedules — across tenant boundaries.
|
||||
|
||||
### Fix
|
||||
|
||||
@@ -156,7 +156,7 @@ An employee of Company A calls `GET /api/v1/vehicles/<vehicleId_from_company_B>/
|
||||
|
||||
## Frontend Scan Results
|
||||
|
||||
A full scan of all four frontend applications (dashboard, admin, marketplace, public-site) was performed. No vulnerabilities above the reporting threshold (confidence ≥ 8/10) were confirmed.
|
||||
A full scan of all four frontend applications (dashboard, admin, storefront, public-site) was performed. No vulnerabilities above the reporting threshold (confidence ≥ 8/10) were confirmed.
|
||||
|
||||
### Hardening Recommendations (not vulnerabilities)
|
||||
|
||||
@@ -164,7 +164,7 @@ Two items were identified as best-practice improvements:
|
||||
|
||||
1. **Admin auth-redirect `next` param** (`apps/admin/src/app/auth-redirect/page.tsx`) — Validate the `next` query parameter is a relative path (starts with `/`, does not contain `://`) before passing it to `router.replace`. The router itself does not perform cross-origin navigation, but defense-in-depth is recommended.
|
||||
|
||||
2. **`postMessage` wildcard origin + missing `frame-ancestors` CSP** (`apps/dashboard/src/app/sign-in/[[...sign-in]]/SignInPageClient.tsx`, `apps/dashboard/next.config.js`) — Replace `targetOrigin: '*'` with the marketplace origin, and add `Content-Security-Policy: frame-ancestors 'self' <marketplace-origin>` to prevent the sign-in page from being embeddable by arbitrary third-party domains.
|
||||
2. **`postMessage` wildcard origin + missing `frame-ancestors` CSP** (`apps/dashboard/src/app/sign-in/[[...sign-in]]/SignInPageClient.tsx`, `apps/dashboard/next.config.js`) — Replace `targetOrigin: '*'` with the storefront origin, and add `Content-Security-Policy: frame-ancestors 'self' <storefront-origin>` to prevent the sign-in page from being embeddable by arbitrary third-party domains.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ This is the default for dashboard/company management routes.
|
||||
|
||||
### Subscription Guard
|
||||
|
||||
`requireSubscription` blocks company routes when the company status is `PENDING` or `SUSPENDED`. Public site and marketplace routes are intentionally not behind this guard.
|
||||
`requireSubscription` blocks company routes when the company status is `PENDING` or `SUSPENDED`. Public site and storefront routes are intentionally not behind this guard.
|
||||
|
||||
### Role-Based Access Control
|
||||
|
||||
@@ -90,7 +90,7 @@ Admin roles are hierarchical:
|
||||
|
||||
`requireRenterAuth` validates a Bearer token with `type === "renter"` and attaches `req.renterId`.
|
||||
|
||||
`optionalRenterAuth` is used on marketplace routes so public reads still work without a token.
|
||||
`optionalRenterAuth` is used on storefront routes so public reads still work without a token.
|
||||
|
||||
### API Key
|
||||
|
||||
@@ -136,7 +136,7 @@ The table below describes the current route groups mounted in `app.ts`.
|
||||
| `/api/v1/auth/employee` | Public plus employee JWT | Employee login, password reset, profile, language | Dashboard/staff authentication path |
|
||||
| `/api/v1/auth/renter` | Renter JWT for profile routes | Renter profile and push token | `signup` and `login` are currently disabled in this codebase |
|
||||
| `/api/v1/admin` | Admin JWT | Platform operations | Includes company admin, billing, subscriptions, pricing, audit, and admin-user management |
|
||||
| `/api/v1/marketplace` | Public, optional renter JWT | Marketplace discovery and reservation intake | Designed for discovery and lead capture across companies |
|
||||
| `/api/v1/storefront` | Public, optional renter JWT | Storefront discovery and reservation intake | Designed for discovery and lead capture across companies |
|
||||
| `/api/v1/site` | Public | White-label company site APIs | Drives each company-branded booking site |
|
||||
| `/api/v1/subscriptions` | Mixed | Plan listing, webhooks, subscription lifecycle | Public, webhook, and authenticated sub-routers share the same prefix |
|
||||
| `/api/v1/vehicles` | Employee JWT + tenant + subscription | Fleet management | Includes photos, status, calendar blocks, maintenance, and availability |
|
||||
@@ -228,17 +228,17 @@ Customers are company-scoped CRM records, even when a renter identity also exist
|
||||
|
||||
This is intentionally separate from renter identity because one renter may interact with multiple companies while each company still needs its own operational customer record.
|
||||
|
||||
### Marketplace and public site
|
||||
### Storefront and public site
|
||||
|
||||
The public surface is split in two modules on purpose.
|
||||
|
||||
`marketplace` is the cross-company discovery layer:
|
||||
`storefront` is the cross-company discovery layer:
|
||||
|
||||
- featured/public offers
|
||||
- marketplace cities
|
||||
- storefront cities
|
||||
- listed companies
|
||||
- vehicle search
|
||||
- marketplace reservation intake
|
||||
- storefront reservation intake
|
||||
- review submission by token
|
||||
- company public pages under `/:slug`
|
||||
|
||||
@@ -318,7 +318,7 @@ The admin router is broad because it covers platform operations across multiple
|
||||
- billing account and billing invoice operations
|
||||
- pricing config, plan features, and promotions
|
||||
- subscription overrides and extensions
|
||||
- marketplace homepage configuration
|
||||
- storefront homepage configuration
|
||||
|
||||
This is the only route group allowed to work across tenants.
|
||||
|
||||
|
||||
@@ -243,7 +243,7 @@ Purpose:
|
||||
- public contact and social metadata
|
||||
- default locale and currency
|
||||
- company-owned payment provider settings for renter payments
|
||||
- marketplace visibility and rating
|
||||
- storefront visibility and rating
|
||||
- homepage/menu JSON configuration
|
||||
|
||||
Important uniqueness:
|
||||
|
||||
Reference in New Issue
Block a user