ClientEcho is an enterprise-grade, multi-tenant B2B SaaS platform engineered for solo creators, developers, and agencies to collect 1-click magic link approvals, import offline praise with hardcoded trust signals, and embed sandboxed, zero-CLS social proof widgets in minutes.
ClientEcho is built strictly adhering to 13 fundamental architectural pillars:
- Every table (
creators,widgets,testimonials,magic_link_tokens,admin_audit_log,password_reset_tokens) has RLS enabled. - Data isolation is strictly enforced via
auth.uid() = creator_id, ensuring tenant workspaces cannot query, modify, or delete cross-tenant social proof.
- Generates 32-byte cryptographically random raw tokens (
crypto.randomBytes(32)-> 64 hex chars). - Plaintext tokens are transmitted strictly via transactional email; PostgreSQL stores SHA-256 hashes (
token_hash). - Single-use enforcement (
used_at) with atomic PostgreSQL transactions prevents double-spending token race conditions.
- Step 1: Cloudflare Turnstile CAPTCHA verification (
verifyTurnstileToken). - Step 2: Strict Zod schema parsing (
publicFormSchema). - Step 3: Server-side DOMPurify sanitization (
sanitizeHtml,sanitizePlainText) stripping<script>, event handlers, and dangerous tags. - Step 4: Upstash Dual Sliding-Window Rate Limiting (5 req/min per IP, 20 req/min per widget slug).
- Step 5: Video URL allowlist validation (YouTube, Vimeo, Loom).
- Supports importing manual client feedback (Slack DMs, tweets, email screenshots).
- Automatically tagged with hardcoded immutable trust badges:
Verified Magic Link: Cryptographic client 1-click approval.Verified Submission: Public widget form with Turnstile bot protection.Self-Reported / Imported: Manual creator import with transparent audit label.
- Serves sandboxed iframe embeds (
/embed/[slug]) withContent-Security-Policy: frame-ancestors *. - Auto-resizing cross-origin
postMessagelistener updates host iframe height dynamically without layout shifts or scrollbars inside the iframe.
- All authenticated and sensitive surfaces (
/dashboard/*,/settings/*,/billing/*,/admin/*,/login,/signup) strictly emit:X-Frame-Options: DENYContent-Security-Policy: frame-ancestors 'none'X-Content-Type-Options: nosniff
- Separate
/adminroute restricted toapp_metadata.role = 'tech_admin'. - PostgreSQL RLS explicitly blocks Tech Admins from modifying or deleting creator testimonials (
COALESCE((auth.jwt() -> 'app_metadata' ->> 'role'), '') != 'tech_admin'). - All admin suspension actions write non-repudiable logs to
admin_audit_log.
- Tiered feature limits enforced between Starter Free Plan ($0/forever, 1 widget limit, 25 approved testimonials cap) and Pro Workspace Plan ($19/mo, unlimited widgets, custom Google Fonts, white-label branding removal).
- Fully integrated with PCI-compliant Stripe Checkout and Customer Portal.
- Embed payloads check Upstash Redis cache first (
getCachedWidgetPayload), reducing database load. - Automatic cache invalidation (
invalidateWidgetCache) fires on testimonial approval, rejection, deletion, or theme modification.
- Branded CSS token palette (
--ink-900: #2D2D2D,--ink-800: #33363B,--surface-light: #EFF3F6,--surface-white: #FFFFFF). - Syne font for display headings, Manrope for body text, with smooth glassmorphism and subtle micro-interactions.
- Fixed 64px header (
.app-navbar,position: fixed,top: 0,height: 64px,z-index: 50) outside the scroll container. - Dedicated scrollable region (
.app-scroll-region,margin-top: 64px,height: calc(100vh - 64px),overflow-y: auto). - Scoped custom scrollbars ensure scrollbar thumbs visually start below the top header across all routes.
- Zero Cumulative Layout Shift (CLS) loading states via
SkeletonBlock.tsx. - Replaces generic text/spinners with exact footprint shimmer loaders.
- Full compliance with
@media (prefers-reduced-motion: reduce)accessibility standards.
- Automated background maintenance route (
/api/cron/purge-tokens) purges expired or used magic link tokens. - PostgreSQL
ON DELETE CASCADEforeign key references ensure clean account deletion and data lifecycle hygiene.
| Layer | Technology |
|---|---|
| Framework | Next.js 14 (App Router, Server Actions, Edge Middleware) |
| Database & Auth | PostgreSQL (Supabase Auth & SSR Client, Drizzle ORM) |
| Security & Spam | Cloudflare Turnstile, isomorphic-dompurify, Upstash Redis Rate Limiting |
| Styling & UI | TailwindCSS, Framer Motion, Lucide React, Syne & Manrope Fonts |
| Payments | Stripe Checkout API & Stripe Customer Portal |
git clone https://github.com/your-org/client-echo.git
cd client-echo
npm installCreate a .env file in the root directory:
NEXT_PUBLIC_APP_URL=http://localhost:3000
# Supabase Configuration
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
# Database Connection (IMPORTANT: In serverless / production Vercel environments, use Supabase Transaction Pooler port 6543)
DATABASE_URL=postgresql://postgres.your-project-ref:password@aws-0-region.pooler.supabase.com:6543/postgres?pgbouncer=true
# (Direct connection port 5432 should only be used for migrations/local dev, NOT production serverless)
# Upstash Redis Rate Limiting & Cache
UPSTASH_REDIS_REST_URL=https://your-redis.upstash.io
UPSTASH_REDIS_REST_TOKEN=your-redis-token
# Cloudflare Turnstile CAPTCHA
TURNSTILE_SECRET_KEY=your-turnstile-secret-key
# Stripe Billing
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...Apply the PostgreSQL schema and RLS policies:
npx drizzle-kit pushnpm run devOpen http://localhost:3000 in your browser.
| Subsystem | File Path | Efficiency Rating | Architectural Audit Notes |
|---|---|---|---|
| Edge Routing | src/middleware.ts |
🟢 High | Performs session checks and injects security framing headers (X-Frame-Options: DENY) before reaching page handlers. |
| Public Intake | /api/testimonials/public/route.ts |
🟢 High | Early Turnstile & Zod validation prevents wasteful DB queries on invalid/bot payloads. |
| Token Approval | /api/testimonials/approve-token/route.ts |
🟢 High | Atomic DB transaction prevents double-spending token race conditions. Purges Redis cache instantly upon state update. |
| Embed Delivery | /embed/[slug]/page.tsx |
🟢 High | Cache-first strategy (getCachedWidgetPayload) bypasses Postgres queries for high-volume embed requests. |
| Scroll & Layout | src/app/globals.css |
🟢 High | Separates fixed 64px header from .app-scroll-region container, guaranteeing clean scrollbar thumb positioning. |
| Skeleton System | SkeletonBlock.tsx |
🟢 High | Replaces layout-shifting spinners with exact footprint shimmer blocks; handles prefers-reduced-motion. |