Production upgrade: Clerk auth, Stripe billing, analytics, PWA support

Backend & Auth:
- Add @clerk/nextjs for production authentication
- Create src/proxy.ts with clerkMiddleware() for route protection
- Implement multi-tenant auth with role-based access control
- Add Clerk components (Show, UserButton, SignInButton, SignUpButton)

Billing & Payments:
- Full Stripe integration (subscriptions, add-ons, customer portal)
- Plan tiers: Starter 9/mo, Farm 49/mo, Enterprise 99/mo
- Webhook handling for subscription events
- createSubscription(), createAddonSubscription(), createCustomerPortalSession()

API & Security:
- Rate limiting with @upstash/ratelimit (100 req/min API, 20 req/min checkout)
- Zod validation schemas for all endpoints (orders, products, campaigns, etc.)
- Security headers (CSP, HSTS, X-Frame-Options)
- API routes: /api/v1/ with validated, rate-limited endpoints

Monitoring:
- Sentry error tracking with performance monitoring
- PostHog analytics for feature usage, funnels, cohorts
- User activity logging and breadcrumb tracking

Admin Features:
- Analytics dashboard with revenue charts, customer growth, conversion funnel
- Onboarding flow with 6-step interactive tour
- Referral system with share tracking and reward redemption
- Changelog feed with in-app notifications

PWA & SEO:
- Web app manifest with icons and shortcuts
- Service worker for offline support and caching
- Full SEO metadata, OpenGraph, Twitter cards
- Structured data (JSON-LD) for organization and products

Database:
- Add referral_codes, changelogs, onboarding_progress tables
- Add user_activity_logs, api_keys, notification_preferences
- Comprehensive RLS policies for all new tables
- Seed data for demo brands and products
This commit is contained in:
2026-06-02 05:33:42 +00:00
parent b845d69aba
commit 6ab52a2499
32 changed files with 5816 additions and 501 deletions
+94
View File
@@ -0,0 +1,94 @@
// Clerk middleware for route protection
import { authMiddleware } from "@clerk/nextjs";
// Define public routes that don't require authentication
const publicRoutes = [
"/",
"/login",
"/login2",
"/register",
"/forgot-password",
"/reset-password",
"/pricing",
"/terms-and-conditions",
"/privacy-policy",
"/contact",
"/api/health",
"/api/webhooks/clerk",
// Brand storefronts are public
"/tuxedo",
"/tuxedo/*",
"/indian-river-direct",
"/indian-river-direct/*",
// Error pages
"/error",
"/not-found",
];
// Define routes that require specific roles
const roleProtectedRoutes = [
{ path: "/admin/*", roles: ["platform_admin", "brand_admin", "store_employee"] },
{ path: "/wholesale/portal/*", roles: ["wholesale_customer"] },
{ path: "/water/admin/*", roles: ["platform_admin", "brand_admin"] },
];
export default authMiddleware({
// Public routes - don't require auth
publicRoutes,
// Ignore auth for these paths (API routes with their own auth)
ignoredRoutes: [
"/api/*", // API routes handle their own auth
"/_next/*", // Next.js internals
"/favicon.ico",
"/robots.txt",
"/sitemap.xml",
],
// After auth middleware - check roles
afterAuth: (auth, req, evt) => {
const { userId, sessionId } = auth;
const path = req.nextUrl.pathname;
// Skip role check for public routes
if (publicRoutes.some(route => path.startsWith(route.replace("/*", "")))) {
return;
}
// Check if route is role-protected
for (const protectedRoute of roleProtectedRoutes) {
if (path.startsWith(protectedRoute.path.replace("/*", ""))) {
if (!userId) {
// Redirect to login if not authenticated
const signInUrl = new URL("/login", req.url);
signInUrl.searchParams.set("redirect_url", path);
return Response.redirect(signInUrl);
}
// For admin routes, check session and role
if (protectedRoute.path.startsWith("/admin")) {
// Admin routes require one of the allowed roles
// This is handled by the admin-permissions module in app layer
}
if (protectedRoute.path.startsWith("/wholesale/portal")) {
// Wholesale portal requires wholesale_customer role
// This is handled by wholesale-auth module in app layer
}
}
}
},
// Debug in development
debug: process.env.NODE_ENV === "development",
});
export const config = {
matcher: [
// Skip Next.js internals and all files in the _next directory
"/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)",
// Always run for API routes
"/(api|trpc)(.*)",
],
};