diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..bbe261e --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,71 @@ +# Claude Code Task Management Guide + +## Documentation Available + +📚 **Project Documentation**: Check the documentation files in this directory for project-specific setup instructions and guides. +**Project Tasks**: Check the tasks directory in documentation/tasks for the list of tasks to be completed. Use the CLI commands below to interact with them. + +## MANDATORY Task Management Workflow + +🚨 **YOU MUST FOLLOW THIS EXACT WORKFLOW - NO EXCEPTIONS** 🚨 + +### **STEP 1: DISCOVER TASKS (MANDATORY)** +You MUST start by running this command to see all available tasks: +```bash +task-manager list-tasks +``` + +### **STEP 2: START EACH TASK (MANDATORY)** +Before working on any task, you MUST mark it as started: +```bash +task-manager start-task +``` + +### **STEP 3: COMPLETE EACH TASK (MANDATORY)** +After finishing implementation, you MUST mark the task as completed: +```bash +task-manager complete-task "Brief description of what was implemented" +``` + +## Task Files Location + +📁 **Task Data**: Your tasks are organized in the `documentation/tasks/` directory: +- Task JSON files contain complete task information +- Use ONLY the `task-manager` commands listed above +- Follow the mandatory workflow sequence for each task + +## MANDATORY Task Workflow Sequence + +🔄 **For EACH individual task, you MUST follow this sequence:** + +1. 📋 **DISCOVER**: `task-manager list-tasks` (first time only) +2. 🚀 **START**: `task-manager start-task ` (mark as in progress) +3. 💻 **IMPLEMENT**: Do the actual coding/implementation work +4. ✅ **COMPLETE**: `task-manager complete-task "What was done"` +5. 🔁 **REPEAT**: Go to next task (start from step 2) + +## Task Status Options + +- `pending` - Ready to work on +- `in_progress` - Currently being worked on +- `completed` - Successfully finished +- `blocked` - Cannot proceed (waiting for dependencies) +- `cancelled` - No longer needed + +## CRITICAL WORKFLOW RULES + +❌ **NEVER skip** the `task-manager start-task` command +❌ **NEVER skip** the `task-manager complete-task` command +❌ **NEVER work on multiple tasks simultaneously** +✅ **ALWAYS complete one task fully before starting the next** +✅ **ALWAYS provide completion details in the complete command** +✅ **ALWAYS follow the exact 3-step sequence: list → start → complete** + +## Final Requirements + +🚨 **CRITICAL**: Your work is not complete until you have: +1. ✅ Completed ALL tasks using the mandatory workflow +2. ✅ Committed all changes with comprehensive commit messages +3. ✅ Created a pull request with proper description + +Remember: The task management workflow is MANDATORY, not optional! diff --git a/app/layout.tsx b/app/layout.tsx index 4b014ae..341b73a 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,6 +1,7 @@ import type { Metadata } from 'next' import localFont from 'next/font/local' import './globals.css' +import { ClerkProvider } from '@clerk/nextjs' const geistSans = localFont({ src: './fonts/GeistVF.woff', @@ -14,8 +15,9 @@ const geistMono = localFont({ }) export const metadata: Metadata = { - title: 'CodeGuide Starter Pro', - description: 'Starter kit from codeguide.dev', + title: 'Landing Page Analyzer - AI-Powered Optimization Tool', + description: 'Get instant AI-powered insights to optimize your landing page copywriting and layout. Boost conversions with data-driven recommendations.', + keywords: 'landing page analyzer, AI website optimization, conversion rate optimization, landing page copywriting', } export default function RootLayout({ @@ -24,8 +26,10 @@ export default function RootLayout({ children: React.ReactNode }>) { return ( - - {children} - + + + {children} + + ) } diff --git a/app/page.tsx b/app/page.tsx index e22f95a..8917237 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,209 +1,15 @@ -"use client" - -import { AuroraBackground } from '@/components/ui/aurora-background' -import { PlaceholdersAndVanishInput } from '@/components/ui/placeholders-and-vanish-input' -import { useState } from 'react' -import { AnalysisResult } from '@/components/analysis-result' -import { Button } from '@/components/ui/button' -import { Download, Loader2, X } from 'lucide-react' -import { Alert, AlertDescription } from '@/components/ui/alert' -import { useLocalStorage } from 'usehooks-ts' -import { formatDistanceToNow } from 'date-fns' - -interface Report { - url: string - analysis: string - timestamp: number -} - -export default function Home() { - const [isAnalyzing, setIsAnalyzing] = useState(false) - const [error, setError] = useState(null) - const [reports, setReports] = useLocalStorage('webpage-reports', []) - const [expandedReports, setExpandedReports] = useState>(new Set()) - - const placeholders = [ - "Enter a website URL to analyze (e.g., https://example.com)", - "Let's analyze your website content", - "Get insights about your website's copywriting", - "Discover layout improvement suggestions", - "Find out how to enhance your website", - ] - - const handleChange = (e: React.ChangeEvent) => { - if (error) setError(null) - } - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault() - const form = e.target as HTMLFormElement - const input = form.querySelector('input') as HTMLInputElement - const url = input.value.trim() - - if (!url) return - - setIsAnalyzing(true) - setError(null) - - try { - const response = await fetch('/api/analyze', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ url }), - }) - - if (!response.ok) { - throw new Error('Failed to analyze website') - } - - const { analysis } = await response.json() - - // Add new report to the beginning of the list - setReports(prevReports => [{ - url, - analysis, - timestamp: Date.now() - }, ...prevReports]) - - } catch (err) { - setError('Failed to analyze the website. Please try again.') - } finally { - setIsAnalyzing(false) - } - } - - const handleDownload = (report: Report) => { - const blob = new Blob([report.analysis], { type: 'text/markdown' }) - const url = URL.createObjectURL(blob) - const a = document.createElement('a') - a.href = url - a.download = `analysis-report-${new Date(report.timestamp).toISOString().split('T')[0]}.md` - document.body.appendChild(a) - a.click() - document.body.removeChild(a) - URL.revokeObjectURL(url) - } - - const toggleReport = (timestamp: number) => { - setExpandedReports(prev => { - const newSet = new Set(prev) - if (newSet.has(timestamp)) { - newSet.delete(timestamp) - } else { - newSet.add(timestamp) - } - return newSet - }) - } - - const handleClose = (timestamp: number, e: React.MouseEvent) => { - e.stopPropagation() - setExpandedReports(prev => { - const newSet = new Set(prev) - newSet.delete(timestamp) - return newSet - }) - } +import { HeroSection } from '@/components/landing/hero-section' +import { FeaturesSection } from '@/components/landing/features-section' +import { CTASection } from '@/components/landing/cta-section' +import { Footer } from '@/components/landing/footer' +export default function LandingPage() { return ( - -
-
-

- Landing Page Content Analyzer -

-

- Get actionable insights to improve your landing page copywriting and layout -

-
- -
- - {isAnalyzing && ( -
- - Analyzing page... -
- )} - - {error && ( - - {error} - - )} -
- - {reports.length > 0 && ( -
-
-
- {reports.map((report) => { - const isExpanded = expandedReports.has(report.timestamp); - return ( -
toggleReport(report.timestamp)} - > -
-
-
-

- {report.url} -

-

- {formatDistanceToNow(report.timestamp, { addSuffix: true })} -

-
- {isExpanded && ( -
- - -
- )} -
-
- - {isExpanded && ( -
-
- -
-
- )} -
- ); - })} -
-
-
- )} -
-
+
+ + + +
+
) } \ No newline at end of file diff --git a/app/protected/analyzer/page.tsx b/app/protected/analyzer/page.tsx new file mode 100644 index 0000000..8af53bc --- /dev/null +++ b/app/protected/analyzer/page.tsx @@ -0,0 +1,210 @@ +'use client' + +import { AuroraBackground } from '@/components/ui/aurora-background' +import { PlaceholdersAndVanishInput } from '@/components/ui/placeholders-and-vanish-input' +import { useState } from 'react' +import { AnalysisResult } from '@/components/analysis-result' +import { Button } from '@/components/ui/button' +import { Download, Loader2, X } from 'lucide-react' +import { Alert, AlertDescription } from '@/components/ui/alert' +import { useLocalStorage } from 'usehooks-ts' +import { formatDistanceToNow } from 'date-fns' + +interface Report { + url: string + analysis: string + timestamp: number +} + +export default function AnalyzerPage() { + const [isAnalyzing, setIsAnalyzing] = useState(false) + const [error, setError] = useState(null) + const [reports, setReports] = useLocalStorage('webpage-reports', []) + const [expandedReports, setExpandedReports] = useState>(new Set()) + + const placeholders = [ + "Enter a website URL to analyze (e.g., https://example.com)", + "Let's analyze your website content", + "Get insights about your website's copywriting", + "Discover layout improvement suggestions", + "Find out how to enhance your website", + ] + + const handleChange = (e: React.ChangeEvent) => { + if (error) setError(null) + } + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + const form = e.target as HTMLFormElement + const input = form.querySelector('input') as HTMLInputElement + const url = input.value.trim() + + if (!url) return + + setIsAnalyzing(true) + setError(null) + + try { + const response = await fetch('/api/analyze', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ url }), + }) + + if (!response.ok) { + throw new Error('Failed to analyze website') + } + + const { analysis } = await response.json() + + // Add new report to the beginning of the list + setReports(prevReports => [{ + url, + analysis, + timestamp: Date.now() + }, ...prevReports]) + + } catch (err) { + setError('Failed to analyze the website. Please try again.') + } finally { + setIsAnalyzing(false) + } + } + + const handleDownload = (report: Report) => { + const blob = new Blob([report.analysis], { type: 'text/markdown' }) + const url = URL.createObjectURL(blob) + const a = document.createElement('a') + a.href = url + a.download = `analysis-report-${new Date(report.timestamp).toISOString().split('T')[0]}.md` + document.body.appendChild(a) + a.click() + document.body.removeChild(a) + URL.revokeObjectURL(url) + } + + const toggleReport = (timestamp: number) => { + setExpandedReports(prev => { + const newSet = new Set(prev) + if (newSet.has(timestamp)) { + newSet.delete(timestamp) + } else { + newSet.add(timestamp) + } + return newSet + }) + } + + const handleClose = (timestamp: number, e: React.MouseEvent) => { + e.stopPropagation() + setExpandedReports(prev => { + const newSet = new Set(prev) + newSet.delete(timestamp) + return newSet + }) + } + + return ( + +
+
+

+ Landing Page Content Analyzer +

+

+ Get actionable insights to improve your landing page copywriting and layout +

+
+ +
+ + {isAnalyzing && ( +
+ + Analyzing page... +
+ )} + + {error && ( + + {error} + + )} +
+ + {reports.length > 0 && ( +
+
+
+ {reports.map((report) => { + const isExpanded = expandedReports.has(report.timestamp); + return ( +
toggleReport(report.timestamp)} + > +
+
+
+

+ {report.url} +

+

+ {formatDistanceToNow(report.timestamp, { addSuffix: true })} +

+
+ {isExpanded && ( +
+ + +
+ )} +
+
+ + {isExpanded && ( +
+
+ +
+
+ )} +
+ ); + })} +
+
+
+ )} +
+
+ ) +} \ No newline at end of file diff --git a/app/protected/layout.tsx b/app/protected/layout.tsx new file mode 100644 index 0000000..7297a52 --- /dev/null +++ b/app/protected/layout.tsx @@ -0,0 +1,9 @@ +import { ClerkProvider } from '@clerk/nextjs' + +export default function ProtectedLayout({ + children, +}: { + children: React.ReactNode +}) { + return children +} \ No newline at end of file diff --git a/components/landing/cta-section.tsx b/components/landing/cta-section.tsx new file mode 100644 index 0000000..2c77866 --- /dev/null +++ b/components/landing/cta-section.tsx @@ -0,0 +1,170 @@ +'use client' + +import { motion } from 'framer-motion' +import { Button } from '@/components/ui/button' +import { SignInButton, SignUpButton, useAuth } from '@clerk/nextjs' +import { ArrowRight, Star, Check } from 'lucide-react' +import Link from 'next/link' + +const containerVariants = { + hidden: { opacity: 0 }, + visible: { + opacity: 1, + transition: { + staggerChildren: 0.1, + }, + }, +} + +const itemVariants = { + hidden: { opacity: 0, y: 20 }, + visible: { + opacity: 1, + y: 0, + transition: { + duration: 0.6, + ease: 'easeOut', + }, + }, +} + +const testimonials = [ + { + name: "Sarah Chen", + role: "Marketing Director", + company: "TechStart Inc.", + content: "This tool helped us increase our landing page conversion rate by 47% in just two weeks. The AI insights are incredibly actionable.", + rating: 5 + }, + { + name: "Marcus Johnson", + role: "Product Manager", + company: "GrowthLabs", + content: "Finally, an AI tool that actually understands landing page optimization. The recommendations are spot-on and easy to implement.", + rating: 5 + }, + { + name: "Emily Rodriguez", + role: "UX Designer", + company: "DesignFlow", + content: "The visual layout analysis caught issues we hadn't noticed. Our bounce rate dropped significantly after implementing the suggestions.", + rating: 5 + } +] + +export function CTASection() { + const { isSignedIn } = useAuth() + + return ( +
+
+ + +
+ {[...Array(5)].map((_, i) => ( + + ))} +
+

+ Trusted by 10,000+ marketers and developers +

+
+ + + Start Optimizing Your Landing Page Today + + + + Join thousands of professionals who use our AI-powered tool to create + high-converting landing pages. Get started in less than 30 seconds. + + + + {isSignedIn ? ( + + ) : ( + <> + + + + + + + + )} + + + +
+ + No credit card required +
+
+ + Instant setup +
+
+ + Cancel anytime +
+
+
+ + + {testimonials.map((testimonial, index) => ( + +
+
+ {[...Array(testimonial.rating)].map((_, i) => ( + + ))} +
+
+ "{testimonial.content}" +
+
+

{testimonial.name}

+

{testimonial.role} at {testimonial.company}

+
+
+
+ ))} +
+
+
+ ) +} \ No newline at end of file diff --git a/components/landing/features-section.tsx b/components/landing/features-section.tsx new file mode 100644 index 0000000..9f61e1d --- /dev/null +++ b/components/landing/features-section.tsx @@ -0,0 +1,165 @@ +'use client' + +import { motion } from 'framer-motion' +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' +import { Badge } from '@/components/ui/badge' +import { + FileText, + Eye, + BarChart3, + Users, + Smartphone, + Clock, + Download, + CheckCircle +} from 'lucide-react' + +const features = [ + { + icon: FileText, + title: 'Copywriting Analysis', + description: 'AI analyzes your landing page copy for clarity, persuasiveness, and conversion optimization.', + points: ['Headline effectiveness', 'CTA optimization', 'Tone and voice consistency'] + }, + { + icon: Eye, + title: 'Visual Layout Review', + description: 'Get insights on visual hierarchy, spacing, and design elements that impact user experience.', + points: ['Visual hierarchy', 'Whitespace usage', 'Color psychology'] + }, + { + icon: BarChart3, + title: 'Performance Metrics', + description: 'Track improvements with before/after comparisons and actionable performance metrics.', + points: ['Conversion predictions', 'Load time impact', 'SEO suggestions'] + }, + { + icon: Users, + title: 'User Experience Focus', + description: 'Understand how users interact with your page and identify friction points.', + points: ['Navigation flow', 'Mobile responsiveness', 'Accessibility checks'] + }, + { + icon: Smartphone, + title: 'Mobile Optimization', + description: 'Ensure your landing page performs perfectly on all devices with mobile-first insights.', + points: ['Responsive design', 'Touch targets', 'Loading optimization'] + }, + { + icon: Clock, + title: 'Instant Results', + description: 'Get comprehensive analysis results in seconds, not hours or days.', + points: ['Real-time analysis', 'Immediate feedback', 'Quick iterations'] + } +] + +const containerVariants = { + hidden: { opacity: 0 }, + visible: { + opacity: 1, + transition: { + staggerChildren: 0.1, + }, + }, +} + +const itemVariants = { + hidden: { opacity: 0, y: 20 }, + visible: { + opacity: 1, + y: 0, + transition: { + duration: 0.6, + ease: 'easeOut', + }, + }, +} + +export function FeaturesSection() { + return ( +
+
+ + + + Features + + + + + Everything You Need to Optimize Your Landing Page + + + + Comprehensive analysis tools that help you create high-converting landing pages + with actionable insights powered by AI. + + + + + {features.map((feature, index) => ( + + + +
+ +
+ {feature.title} + {feature.description} +
+ +
    + {feature.points.map((point, pointIndex) => ( +
  • + + {point} +
  • + ))} +
+
+
+
+ ))} +
+ + + + +
+
+
+ +
+
+
+

Ready to Get Started?

+

+ Join thousands of marketers and developers who use our tool to optimize their landing pages. +

+
+
+
+
+
+
+
+ ) +} \ No newline at end of file diff --git a/components/landing/footer.tsx b/components/landing/footer.tsx new file mode 100644 index 0000000..8438bd9 --- /dev/null +++ b/components/landing/footer.tsx @@ -0,0 +1,137 @@ +'use client' + +import { Github, Twitter, Linkedin, Mail } from 'lucide-react' +import Link from 'next/link' + +export function Footer() { + const currentYear = new Date().getFullYear() + + return ( +
+
+
+
+
+
+ Landing Page Analyzer +
+

+ AI-powered insights to optimize your landing pages and boost conversions. +

+
+ + + + + + + + + + + + +
+
+ +
+

Product

+
    +
  • + + Analyzer + +
  • +
  • + + Features + +
  • +
  • + + Pricing + +
  • +
  • + + Examples + +
  • +
+
+ +
+

Resources

+
    +
  • + + Documentation + +
  • +
  • + + Blog + +
  • +
  • + + Support + +
  • +
  • + + API Reference + +
  • +
+
+ +
+

Company

+
    +
  • + + About + +
  • +
  • + + Careers + +
  • +
  • + + Privacy + +
  • +
  • + + Terms + +
  • +
+
+
+ +
+
+

+ © {currentYear} Landing Page Analyzer. All rights reserved. +

+
+ + Privacy Policy + + + Terms of Service + + + Cookie Policy + +
+
+
+
+
+ ) +} \ No newline at end of file diff --git a/components/landing/hero-section.tsx b/components/landing/hero-section.tsx new file mode 100644 index 0000000..71f0f61 --- /dev/null +++ b/components/landing/hero-section.tsx @@ -0,0 +1,129 @@ +'use client' + +import { motion } from 'framer-motion' +import { Button } from '@/components/ui/button' +import { SignInButton, SignUpButton, useAuth } from '@clerk/nextjs' +import { ArrowRight, Sparkles, Zap, Target } from 'lucide-react' +import Link from 'next/link' + +const containerVariants = { + hidden: { opacity: 0 }, + visible: { + opacity: 1, + transition: { + staggerChildren: 0.1, + }, + }, +} + +const itemVariants = { + hidden: { opacity: 0, y: 20 }, + visible: { + opacity: 1, + y: 0, + transition: { + duration: 0.6, + ease: 'easeOut', + }, + }, +} + +export function HeroSection() { + const { isSignedIn } = useAuth() + + return ( +
+
+ +
+ + + + + AI-Powered Website Analysis + + + + + Transform Your Landing Page Into a +
+ Conversion Machine +
+ + + Get instant AI-powered insights to optimize your website's copywriting, + layout, and user experience. Boost conversions with data-driven recommendations. + + + + {isSignedIn ? ( + + ) : ( + <> + + + + + + + + )} + + + +
+
+ +
+

Lightning Fast

+

Get insights in seconds

+
+ +
+
+ +
+

Actionable Insights

+

Specific recommendations

+
+ +
+
+ +
+

AI-Powered

+

Latest AI technology

+
+
+
+
+
+ ) +} \ No newline at end of file diff --git a/documentation/app_flowchart.md b/documentation/app_flowchart.md new file mode 100644 index 0000000..1dcf26a --- /dev/null +++ b/documentation/app_flowchart.md @@ -0,0 +1,9 @@ +flowchart TD + A[User Opens App] --> B[Clerk Auth Gate] + B --> C[URL Submission Form] + C --> D[POST to api analyze] + D --> E[JinaAI Fetch Content] + E --> F[OpenAI Analyze Content] + F --> G[API Returns Markdown] + G --> H[Render AnalysisResult] + H --> I[Download Markdown Report] \ No newline at end of file diff --git a/documentation/backend_structure_document.md b/documentation/backend_structure_document.md new file mode 100644 index 0000000..f77b253 --- /dev/null +++ b/documentation/backend_structure_document.md @@ -0,0 +1,154 @@ +# Backend Structure Document + +This document outlines the backend setup of the Webpage Analyzer application. It describes the architecture, database management, APIs, hosting, infrastructure components, security, monitoring, and maintenance practices. The goal is to provide a clear, non-technical overview of how the backend works and why certain choices were made. + +## 1. Backend Architecture + +The backend is built using Next.js API Routes. This means we rely on Next.js both for serving pages and for handling server-side logic in dedicated API endpoints. + +• Frameworks and Patterns + - Next.js (App Router) for routing, server-side rendering (SSR), and API routes. + - Separation of concerns: API routes handle business logic, `lib/` modules contain core functions (e.g., content fetching, AI calls), and React components focus on UI. + - Environment variables (`.env`) store API keys and secrets, keeping them out of client code. + +• Scalability, Maintainability, Performance + - Serverless API Routes on Vercel automatically scale in response to traffic spikes. + - Modular code structure (pages, components, lib, utils) eases future feature additions and bug fixes. + - Third-party services (JinaAI, OpenAI) handle heavy processing, keeping our servers lightweight. + +## 2. Database Management + +Although the core analysis flow uses local browser storage for reports, we leverage Supabase (a hosted PostgreSQL service) for user-related data and future storage of analysis history. + +• Database Technology + - Type: SQL + - System: Supabase (managed PostgreSQL) + +• Data Handling + - User accounts and sessions are managed by Clerk, with Supabase storing user profiles and access records. + - In the current setup, analysis reports are saved locally in the browser. We plan to extend Supabase to store reports in the future. + - Supabase uses Row-Level Security (RLS) to ensure users can only access their own data. + +## 3. Database Schema + +Below is a human-readable overview of the proposed SQL schema for storing users and analysis reports. You can run these statements in PostgreSQL via Supabase. + +```sql +-- Table to store user profiles (supplied by Clerk integration) +CREATE TABLE profiles ( + id uuid PRIMARY KEY, + email text UNIQUE NOT NULL, + created_at timestamp with time zone DEFAULT now(), + updated_at timestamp with time zone DEFAULT now() +); + +-- Table to store analysis reports +CREATE TABLE analysis_reports ( + id uuid PRIMARY KEY DEFAULT gen_random_uuid(), + user_id uuid REFERENCES profiles(id) ON DELETE CASCADE, + url text NOT NULL, + fetched_content text NOT NULL, + analysis_markdown text NOT NULL, + created_at timestamp with time zone DEFAULT now(), + updated_at timestamp with time zone DEFAULT now() +); + +-- Index to quickly retrieve reports by user +CREATE INDEX ON analysis_reports (user_id); +``` + +## 4. API Design and Endpoints + +We use RESTful API routes built into Next.js to handle client-backend communication. + +• Main Endpoint + - `POST /api/analyze` + • Purpose: Receive a URL, fetch its content, analyze it via JinaAI and OpenAI, and return the analysis in Markdown format. + • Input: `{ url: string }` + • Output: `{ analysis: string }` (Markdown text) + • Logic: Calls `lib/analyze.ts` methods (`getWebsiteContent`, `analyzeContent`). + +• (Future) Report Management Endpoints + - `GET /api/reports` — List a user’s saved reports + - `POST /api/reports` — Save a new analysis report + - `GET /api/reports/{id}` — Retrieve a specific report + - `DELETE /api/reports/{id}` — Remove a report + +• Authentication + - Clerk middleware protects API routes, ensuring only signed-in users can call protected endpoints. + +## 5. Hosting Solutions + +• Application Hosting + - Vercel: Hosts the Next.js app and API routes. Provides automatic SSL, global CDN, and seamless deployments from the Git repository. + +• Database Hosting + - Supabase: Managed PostgreSQL database with built-in authentication, storage, and edge functions. + +• Authentication Service + - Clerk: Hosted user management service handling sign-up, sign-in, password resets, and session management. + +**Benefits** + - Reliability: Vercel and Supabase offer high uptime SLAs. + - Scalability: Serverless functions on Vercel scale automatically. Supabase scales vertically and horizontally as needed. + - Cost-Effectiveness: Pay-as-you-go model and generous free tiers for early-stage projects. + +## 6. Infrastructure Components + +• Load Balancing & CDN + - Vercel’s global CDN caches static assets and serverless responses close to users, reducing latency. + +• Caching Mechanisms + - Edge caching on Vercel for static assets and ISR (Incremental Static Regeneration) if adopted in future expansions. + +• Networking + - HTTPS enforced by default via Vercel’s SSL certificates. + +• Storage + - LocalStorage: Temporary client-side storage for analysis reports. + - Supabase Storage (optional): For storing larger files or logs in the future. + +## 7. Security Measures + +• Authentication & Authorization + - Clerk manages user identity, issuing secure JSON Web Tokens (JWT) for API access. + - API routes check tokens and enforce user-specific data access with Supabase Row-Level Security. + +• Data Encryption + - In transit: HTTPS/TLS for all network traffic. + - At rest: Supabase encrypts database storage by default. + +• Secrets Management + - API keys (OpenAI, JinaAI, Clerk, Supabase) kept in environment variables on Vercel, never exposed to the client. + +• Rate Limiting & Abuse Prevention (Future) + - Implement rate limiting on `/api/analyze` to avoid excessive AI calls. + +## 8. Monitoring and Maintenance + +• Logging + - Vercel logs serverless function invocations and errors. + - Supabase provides query and performance logs in its dashboard. + +• Metrics and Alerts + - Vercel Analytics: Tracks request volumes, latencies, and error rates. + - Supabase Metrics: Monitors database performance and usage. + +• Error Tracking (Recommended) + - Integrate Sentry or Logflare for centralized error monitoring and alerting. + +• Maintenance Practices + - Automated deployments on Git pushes (continuous deployment). + - Regular dependency updates and security scans. + - Scheduled backups of Supabase database. + +## 9. Conclusion and Overall Backend Summary + +The Webpage Analyzer’s backend leverages modern, serverless technologies to deliver scalable, secure, and maintainable services: + +• Next.js API Routes provide a unified framework for both frontend and backend logic, allowing rapid development and seamless deployment on Vercel. +• Supabase offers a robust PostgreSQL database with built-in authentication, ready to store user profiles and analysis history. +• Clerk handles user management, ensuring secure access to protected features. +• External AI services (JinaAI, OpenAI) perform content fetching and analysis, offloading heavy processing from our servers. + +Together, these components form a cohesive and future-proof backend foundation that aligns with the project’s goals of reliability, performance, and ease of use. As the application grows, additional endpoints, caching strategies, and monitoring tools can be added without major architectural changes, ensuring long-term success. \ No newline at end of file diff --git a/documentation/frontend_guidelines_document.md b/documentation/frontend_guidelines_document.md new file mode 100644 index 0000000..fe29339 --- /dev/null +++ b/documentation/frontend_guidelines_document.md @@ -0,0 +1,135 @@ +# Frontend Guidelines Document + +This document provides an overview of the frontend setup, architecture, design principles, and best practices for the Webpage Analyzer application. It is written in clear, everyday language so that anyone can understand how the frontend is built, maintained, and extended. + +## 1. Frontend Architecture + +### Frameworks and Libraries +- **Next.js 14 (App Router)**: Powers server-side rendering (SSR), routing, and API routes in a single framework. It keeps pages, components, and backend logic organized in one place. +- **React**: Builds interactive user interfaces through reusable components. +- **Tailwind CSS**: A utility-first CSS framework for rapid, consistent styling without leaving your HTML. +- **shadcn/ui + Radix UI**: A collection of accessible, prebuilt UI components layered on Tailwind, speeding up development while ensuring consistency. +- **Framer Motion**: Provides smooth, declarative animations to enhance user experience. +- **Lucide React**: Supplies a set of open-source icons for consistent visual cues. + +### How It Supports Scalability, Maintainability, and Performance +- **Server-Side Rendering** with Next.js ensures fast initial page loads and good SEO. +- **Component-Based Design** in React lets you build, test, and reuse small pieces of UI independently. +- **Utility CSS (Tailwind)** keeps your styles predictable and minimizes custom CSS. +- **Modular API Routes** (e.g., `/api/analyze`) secure API keys on the server, centralize business logic, and simplify client code. +- **Separation of Concerns**: UI components, business logic (in `lib/`), hooks, and utilities are each in their own folders, making it easy to find and update code. + +## 2. Design Principles + +### Key Principles +- **Usability**: Interfaces should be intuitive—forms guide users through URL input, analysis, and report download. +- **Accessibility**: Components follow ARIA best practices, and color choices meet contrast guidelines. +- **Responsiveness**: The layout adapts seamlessly from mobile to desktop using flexible utility classes in Tailwind. +- **Consistency**: Reusable components (buttons, inputs, cards) follow the same styling rules everywhere. + +### Applying the Principles +- Form fields show clear labels and inline validation messages. +- Focus states and keyboard navigation are supported by shadcn/ui and Radix defaults. +- Breakpoints in Tailwind ensure content reorganizes itself on small screens. +- Shared spacing, typography, and color rules keep the visual language unified. + +## 3. Styling and Theming + +### CSS Approach +- **Utility-First (Tailwind CSS)**: Apply small, single-purpose classes directly in JSX (e.g., `px-4 py-2 bg-indigo-600 text-white`). +- **Component Styles**: For complex patterns or theming variants, use Tailwind’s `@apply` directive in a central CSS file. + +### Theming +- A light and dark mode toggle is supported via a context provider. Tailwind’s `dark:` modifier switches colors automatically. +- Core color variables are defined in `tailwind.config.js` for easy theming adjustments. + +### Visual Style +- **Flat & Modern**: Clean surfaces, simple lines, and minimal shadows. +- **Subtle Glassmorphism**: Used sparingly for overlays or modal backgrounds to draw attention without distraction. + +### Color Palette +- **Primary**: Indigo (#4F46E5) +- **Secondary**: Emerald (#10B981) +- **Accent**: Amber (#F59E0B) +- **Neutral Light**: Gray-50 (#F9FAFB) +- **Neutral Dark**: Gray-900 (#111827) + +### Typography +- **Font Family**: Inter, with system-ui fallbacks (`font-family: 'Inter', system-ui, sans-serif`). +- **Sizes**: Scaled using Tailwind (`text-sm`, `text-base`, `text-lg`, `text-xl`). + +## 4. Component Structure + +### Organization +- **`components/`**: All reusable UI pieces live here. Subfolders: + - **`ui/`**: shadcn/ui components (buttons, cards, inputs). + - **`providers/`**: Context providers (e.g., Clerk client provider). +- **`app/`**: Page-level components and API routes in Next.js App Router. +- **`lib/`**: Business logic modules (`analyze.ts` for AI calls). +- **`hooks/`**: Custom React hooks (e.g., `useLocalStorage`). + +### Benefits of Component-Based Architecture +- **Reusability**: Build once, use everywhere (e.g., a Button component with consistent styling). +- **Maintainability**: Fix a bug in one place, and it updates everywhere. +- **Testability**: Isolated components are easier to test in isolation. + +## 5. State Management + +### Approach +- **Local Component State**: Managed with React’s `useState` for simple UI states (e.g., loading spinners). +- **Form State**: Handled by **React Hook Form** and validated with **Zod**, giving instant feedback. +- **Persistent State**: A `useLocalStorage` hook keeps analysis reports in browser storage so users can revisit past results. + +### Sharing State +- Context providers (e.g., Clerk for auth) wrap the app at the top level. +- Hooks and context keep state accessible but scoped to where it’s needed. + +## 6. Routing and Navigation + +### Routing Library +- **Next.js App Router** handles both page routes (in `app/`) and API routes (in `app/api/`). + +### Navigation Structure +- **Landing Page (`/`)**: Shows the URL input form and past reports. +- **Analysis API (`/api/analyze`)**: A backend endpoint that receives URLs, fetches content from JinaAI, sends it to OpenAI, and returns Markdown suggestions. + +### User Flow +1. User signs in (handled by Clerk). +2. User enters URL in `UrlAnalyzer` component. +3. Client posts to `/api/analyze`. +4. Server returns Markdown report. +5. `AnalysisResult` component renders the report and offers a download. + +## 7. Performance Optimization + +### Strategies +- **Code Splitting & Lazy Loading**: Next.js automatically splits code by route. For large components (e.g., Markdown renderer), use `dynamic()` imports. +- **Asset Optimization**: SVG icons from Lucide and optimized images in `public/`. +- **Minimal CSS**: Only load Tailwind utilities that are used, thanks to PurgeCSS built into Next.js. +- **Server-Side Rendering (SSR)**: Critical pages render on the server for faster first paint. + +### Impact on UX +- Faster page loads, smoother transitions. +- Reduced bundle sizes lead to less data transfer. +- Responsive animations without jank, thanks to Framer Motion. + +## 8. Testing and Quality Assurance + +### Unit Tests +- **React Testing Library**: For components like `UrlAnalyzer` and `AnalysisResult`. +- **Jest**: Runs fast, in-memory tests for functions in `lib/analyze.ts`. + +### Integration Tests +- **API Route Tests**: Mock JinaAI and OpenAI calls to ensure `/api/analyze` behaves as expected. + +### End-to-End (E2E) Tests +- **Cypress or Playwright**: Automate user flows—from signing in with Clerk to entering a URL and viewing a report. + +### Tooling +- **ESLint & Prettier**: Enforce code style and catch common errors. +- **TypeScript**: Ensures type safety throughout the codebase. +- **CI Pipeline**: Runs linters, tests, and builds on every push. + +## 9. Conclusion and Overall Frontend Summary + +This Frontend Guidelines Document outlines how the Webpage Analyzer app is built to be fast, scalable, and maintainable. We use Next.js 14 with React for a modern development experience, utility-first styling with Tailwind and shadcn/ui for consistency, and clear patterns for state, routing, and performance. Our design principles of usability, accessibility, and responsiveness ensure everyone has a smooth experience. Robust testing and quality tools keep our code reliable. By following these guidelines, new and existing team members can confidently develop, maintain, and extend the frontend with minimal friction. \ No newline at end of file diff --git a/documentation/project_requirements_document.md b/documentation/project_requirements_document.md new file mode 100644 index 0000000..cc27718 --- /dev/null +++ b/documentation/project_requirements_document.md @@ -0,0 +1,113 @@ +# Project Requirements Document (PRD) + +## 1. Project Overview + +**Paragraph 1:** +Webpage Analyzer is a web application that lets users enter any webpage URL and instantly get actionable copywriting and layout improvement suggestions. Under the hood, it fetches the raw HTML and text of the target site using JinaAI, sends that content to OpenAI for natural language analysis, and then presents a structured report in Markdown format. Users can read the feedback online or download the report for offline use. + +**Paragraph 2:** +This tool is being built to help marketers, copywriters, and designers quickly audit web pages without manual inspection. Key objectives include ease of use (single URL form), secure handling of API keys (all AI calls go through server-side Next.js API routes), and fast turnaround (aiming for report generation under 10 seconds). Success will be measured by user adoption, average response time, and the accuracy/relevance of suggestions as judged by early testers. + +--- + +## 2. In-Scope vs. Out-of-Scope + +**In-Scope (MVP):** +- User sign-up, sign-in, and session management (Clerk) +- Single-page interface with URL submission form (React Hook Form + Zod validation) +- Next.js API route (`/api/analyze`) that: + • Fetches content via JinaAI + • Analyzes text via OpenAI +- Markdown rendering of analysis results (`marked` library) +- Downloadable Markdown report +- Client-side local persistence of past reports (`useLocalStorage` hook) +- Responsive UI with Tailwind CSS, shadcn/ui, Framer Motion, Lucide icons +- Deployment on Vercel with environment-based API keys + +**Out-of-Scope (Phase 2+):** +- Team collaboration features (sharing, commenting) +- Multi-page project management or versioning +- In-app editing of page content +- Additional AI models (e.g., for layout mockups) +- Mobile native or desktop application +- Analytics dashboard with usage metrics +- Multi-language support beyond English + +--- + +## 3. User Flow + +**Paragraph 1:** +A new user lands on the homepage and is prompted to sign up or log in via Clerk’s authentication widgets. After authentication, they’re redirected to the main analyzer page, where they see a simple form at the top—an input field labeled "Enter webpage URL" and a submit button. Input is validated in real time: empty or invalid URLs trigger an inline error message. + +**Paragraph 2:** +When the user hits "Analyze," the form sends a `POST` request to the Next.js `/api/analyze` endpoint. The server fetches and analyzes content, then returns a Markdown report. The front end displays a loading spinner (Framer Motion) until the response arrives. Once ready, the Markdown is rendered in the main content area using the `marked` library. The user can read suggestions, click a "Download .md" button to save the report locally, or view past reports stored in localStorage below the current result. + +--- + +## 4. Core Features + +- **Authentication (Clerk):** Sign-up, login, session management, protected routes +- **URL Submission Form:** React Hook Form + Zod for real-time validation and error handling +- **Server-Side API Layer:** Next.js API route `/api/analyze` to keep AI keys secure +- **Content Fetching (JinaAI):** `getWebsiteContent(url)` helper in `lib/analyze.ts` +- **AI Analysis (OpenAI):** `analyzeContent(text)` helper in `lib/analyze.ts` +- **Markdown Rendering:** Use `marked` to convert Markdown to sanitized HTML +- **Report Download:** Client-side generation of `.md` file and download link +- **Local Persistence:** Custom `useLocalStorage` hook to store and retrieve past reports +- **Responsive UI:** Tailwind CSS + shadcn/ui for design, Framer Motion for animations, Lucide React for icons +- **Deployment Pipeline:** Vercel integration with environment variables for API keys +- **Basic Error Handling & Notifications:** Inline form errors, toast messages for network/AI failures + +--- + +## 5. Tech Stack & Tools + +- Frontend: Next.js 14 (App Router), React 18 +- Styling: Tailwind CSS, shadcn/ui components +- Animations: Framer Motion, Lucide React icons +- Forms & Validation: React Hook Form, Zod +- Auth & User Management: Clerk +- Backend/API: Next.js API Routes (`app/api/analyze/route.ts`) +- AI Services: JinaAI (content fetch), OpenAI (analysis) via `lib/analyze.ts` +- Persistence: Browser localStorage (custom hook), Supabase client setup (future DB integration) +- Markdown Parser: marked +- Deployment: Vercel +- IDE/Plugins (Optional): Cursor.ai, Windsurf for AI-assisted coding and navigation + +--- + +## 6. Non-Functional Requirements + +- **Performance:** 90th percentile response time ≤ 10s for analysis; initial page load ≤ 2s at 3G speeds +- **Security:** All AI API keys stored server-side; enforce HTTPS; sanitize Markdown output to prevent XSS +- **Scalability:** Rate limiting on `/api/analyze`; stateless serverless functions to scale with demand +- **Usability:** WCAG 2.1 AA accessibility; mobile-first responsive design; clear form error messages +- **Reliability:** 99.9% uptime on Vercel; retry logic for AI API calls (up to 2 retries with exponential backoff) +- **Maintainability:** TypeScript across codebase; modular folder structure; JSDoc on key functions + +--- + +## 7. Constraints & Assumptions + +- JinaAI and OpenAI API credentials are available and have sufficient quota +- The environment supports Next.js 14 serverless functions (Vercel) +- LocalStorage capacity (~5MB) is enough for storing text-only reports +- Users will only analyze publicly accessible URLs (no auth-protected pages) +- No on-premise hosting; relies on Vercel’s managed infrastructure +- Supabase is set up but only client initialization is in scope (no database schema changes yet) + +--- + +## 8. Known Issues & Potential Pitfalls + +- **API Rate Limits:** JinaAI/OpenAI quotas may be exhausted; implement monitoring and notify admins +- **Large Page Content:** Fetching very large websites could hit memory/time limits; consider chunking or summary first +- **Markdown Security:** Untrusted HTML injection via Markdown; use a sanitizer like DOMPurify +- **Network Failures:** Flaky connections can cause timeouts; implement retry/backoff logic and user messaging +- **LocalStorage Limits:** Users with many reports could exceed browser storage; warn or prune old entries +- **Edge Cases in URL Validation:** Some valid URLs may fail Zod checks; maintain a whitelist of URL patterns or fallback parsing logic + +--- + +*End of PRD* \ No newline at end of file diff --git a/documentation/security_guideline_document.md b/documentation/security_guideline_document.md new file mode 100644 index 0000000..fc76af2 --- /dev/null +++ b/documentation/security_guideline_document.md @@ -0,0 +1,97 @@ +# Security Guidelines for Webpage Analyzer + +This security guideline document outlines best practices and actionable recommendations to ensure the Webpage Analyzer application is built and operated securely. It is based on core security principles and tailored to the project’s architecture, technology stack, and workflows. + +## 1. Security by Design & Core Principles + +- **Embed Security Early:** Incorporate security considerations during design, development, and deployment phases; update continuously as features evolve. +- **Least Privilege:** Grant only the minimum permissions to users, API credentials, and services. For example, Supabase service roles should have limited access rights. +- **Defense in Depth:** Layer controls (network, API, application, data) so that a single failure does not compromise the system. +- **Fail Securely:** On errors—such as failed AI calls or network timeouts—return generic error messages without exposing stack traces or secrets. +- **Secure Defaults & Simplicity:** Opt for secure out-of-the-box configurations (e.g., HTTPS-only, secure cookies, strict CORS) and avoid complex custom security mechanisms. + +## 2. Authentication & Access Control + +- **Clerk Integration:** + - Enforce strong passwords, multi-factor authentication (MFA), and session timeouts. + - Use Clerk’s server-side sessions and validate them on every API call to `/api/analyze`. +- **Role-Based Access Control (RBAC):** + - Define roles (e.g., `user`, `admin`) in Clerk or Supabase policies. + - Check user roles server-side before initiating analysis or accessing stored reports. +- **Secure Session Management:** + - Configure cookies with `Secure`, `HttpOnly`, and `SameSite=Strict`. + - Regenerate session identifiers on login to prevent fixation. + +## 3. Input Handling & Processing + +- **Server-Side Validation:** + - Validate submitted URLs in `react-hook-form` via Zod and re-validate on the server to prevent open redirects or SSRF. + - Employ a URL allow-list or pattern check to restrict analysis to legitimate domains if needed. +- **Prevent Injection Attacks:** + - Use parameterized queries or Supabase’s prepared statements to avoid SQL injection. + - Sanitize any user-provided data before rendering in components or Markdown conversion. +- **Secure File Downloads:** + - When generating the Markdown report for download, ensure the filename is sanitized to prevent path traversal. + +## 4. Data Protection & Privacy + +- **Environment Variables & Secrets:** + - Store OpenAI, JinaAI, Clerk, and Supabase secrets in a secure vault (e.g., Vercel secrets, HashiCorp Vault) rather than plaintext `.env` files. + - Rotate keys periodically and after personnel changes. +- **Encryption in Transit & At Rest:** + - Enforce TLS 1.2+ for all frontend and API communications. + - Ensure Supabase database enforces encrypted connections. +- **PII Handling:** + - Do not log raw website content or user-submitted URLs in plain logs. + - Mask or redact sensitive data if logs are required for debugging. + +## 5. API & Service Security + +- **HTTPS Enforcement:** + - Redirect all HTTP traffic to HTTPS and set HSTS headers. +- **Rate Limiting & Throttling:** + - Implement rate limits on `/api/analyze` (e.g., 5 requests/minute per user) to prevent abuse and control API costs. +- **CORS Configuration:** + - Restrict origins to your application’s domain only. Avoid `*`. +- **Error Handling & Logging:** + - Return generic HTTP 4xx/5xx responses to clients. + - Log detailed errors (with context but no secrets) to a secure log store (e.g., Datadog, Logflare). + +## 6. Web Application Security Hygiene + +- **Security Headers:** + - `Content-Security-Policy`: Restrict sources for scripts, styles, and frames. + - `X-Content-Type-Options: nosniff` + - `X-Frame-Options: DENY` or `frame-ancestors 'none'` in CSP. + - `Referrer-Policy: strict-origin-when-cross-origin` +- **CSRF Protection:** + - Use Next.js built-in CSRF protection or anti-CSRF tokens for state-changing routes. +- **Secure Cookies:** + - For Clerk cookies: set `HttpOnly`, `Secure`, and `SameSite=Strict`. +- **Client-Side Storage:** + - Store analysis reports in `localStorage` only if they contain no PII or sensitive data. Consider user opt-in or encryption before storage. + +## 7. Infrastructure & Configuration Management + +- **Server Hardening:** + - Disable unused ports and services on deployment servers. + - Regularly apply OS and dependency patches. +- **CI/CD Pipeline:** + - Integrate vulnerability scanning (SCA) for dependencies. + - Fail builds on introduced high-severity CVEs. + - Use environment-specific configurations; disable debug logs in production. +- **TLS Configuration:** + - Use modern cipher suites only; disable SSLv3, TLS 1.0/1.1. + +## 8. Dependency Management + +- **Lockfiles & Audits:** + - Commit `package-lock.json` and run `npm audit` or `yarn audit` during CI. +- **Minimal Footprint:** + - Review and remove unused dependencies (e.g., check if `marked` can be replaced by a lighter Markdown parser). +- **Regular Updates:** + - Schedule periodic dependency upgrades and regression tests. + +--- + +By following these guidelines, the Webpage Analyzer application will maintain a strong security posture, protect user data, and reduce risk exposure throughout its lifecycle. \ No newline at end of file diff --git a/documentation/tasks/add-landing-page_2025-08-08_10-02-49-747Z.json b/documentation/tasks/add-landing-page_2025-08-08_10-02-49-747Z.json new file mode 100644 index 0000000..f1e9ba5 --- /dev/null +++ b/documentation/tasks/add-landing-page_2025-08-08_10-02-49-747Z.json @@ -0,0 +1,17 @@ +[ + { + "title": "Design and Implement Landing Page UI", + "description": "Create a responsive, accessible landing page for Webpage Analyzer that introduces the product and prompts users to sign up or log in via Clerk authentication.", + "details": "- Use Next.js 14 (App Router) and React 18 for page structure.\n- Style with Tailwind CSS, shadcn/ui components, and Lucide icons for visual appeal.\n- Ensure the landing page is mobile-first, responsive, and meets WCAG 2.1 AA accessibility standards.\n- Include a clear call-to-action (CTA) for sign-up/login, leveraging Clerk authentication widgets.\n- Add brief marketing copy describing the product’s value proposition.\n- Integrate Framer Motion for subtle entrance animations.\n- Ensure the landing page is the default route and redirects authenticated users to the analyzer page.\n- Sanitize and optimize all static content for performance (≤2s load at 3G speeds).", + "status": "pending", + "test_strategy": "- Manually verify landing page renders correctly on desktop and mobile devices.\n- Use Lighthouse to check accessibility and performance scores.\n- Confirm Clerk widgets display and function as expected.\n- Test responsive breakpoints and visual consistency across browsers.\n- Validate that authenticated users are redirected appropriately.", + "priority": "high", + "ordinal": 0, + "task_group_id": "6b1175d2-9d05-4be0-b8f9-615654d51c8f", + "parent_task_id": null, + "id": "13e6ed02-ac4b-4dae-9071-2dde74bdec2a", + "created_at": "2025-08-08T10:02:31.948642Z", + "user_id": "user_2qXKC3eZTjQJhRR30uDzhnVJfMe", + "subtasks": [] + } +] \ No newline at end of file diff --git a/middleware.ts b/middleware.ts index 494924a..d562a76 100644 --- a/middleware.ts +++ b/middleware.ts @@ -1,29 +1,27 @@ import { clerkMiddleware, createRouteMatcher } from "@clerk/nextjs/server" import { NextRequest, NextResponse } from "next/server" -// Default Next.js middleware to allow all requests -export function middleware(request: NextRequest) { - return NextResponse.next() -} - -/** - * Uncomment the following code to enable authentication with Clerk - */ - -// const isProtectedRoute = createRouteMatcher(['/protected']) +const isProtectedRoute = createRouteMatcher(['/protected(.*)']) -// export default clerkMiddleware(async (auth, req) => { -// if (isProtectedRoute(req)) { -// // Handle protected routes check here -// return NextResponse.redirect(req.nextUrl.origin) -// } - -// return NextResponse.next() -// }) +export default clerkMiddleware(async (auth, req) => { + const { userId } = await auth() + + // If user is signed in and trying to access root, redirect to analyzer + if (userId && req.nextpathname === '/') { + return NextResponse.redirect(new URL('/protected/analyzer', req.url)) + } + + // If user is not signed in and trying to access protected routes, redirect to landing + if (!userId && isProtectedRoute(req)) { + return NextResponse.redirect(new URL('/', req.url)) + } + + return NextResponse.next() +}) export const config = { matcher: [ // Skip Next.js internals and all static files, unless found in search params - "/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)|api/webhooks).*)", + "/((?!_next|[^?]*\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)|api/webhooks).*)", ], -} +} \ No newline at end of file