diff --git a/PRODUCT_OVERVIEW.md b/PRODUCT_OVERVIEW.md new file mode 100644 index 0000000..fd406fd --- /dev/null +++ b/PRODUCT_OVERVIEW.md @@ -0,0 +1,385 @@ +# FocusMode v3.0 — Comprehensive Product Overview + +> This document is a complete reference for generating an SEO-optimized landing page update for focusmode.app. + +--- + +## 1. Product Identity + +- **Name**: FocusMode +- **Tagline**: "Stay focused, be present" +- **Version**: 3.0 (complete rewrite from v2.x) +- **Category**: Browser Extension / Digital Wellness / Productivity +- **Platform**: Chrome (Manifest V3), built with WXT Framework + React + TypeScript +- **Pricing**: Free tier + PRO at **$20.99 one-time lifetime purchase** (via Polar.sh) +- **Website**: https://focusmode.app (Next.js) +- **Chrome Web Store**: 15,000+ users, 4.7/5 star rating +- **Purchase link**: https://polar.sh/focusmode + +--- + +## 2. Core Value Proposition + +FocusMode is a **mindfulness-first website blocker** that reduces mindless browsing through intelligent, friction-based interventions — not brute-force blocking. + +**Key differentiators:** +- 4 unique intervention types that use psychological friction (hold, watch, wait) instead of hard blocks +- Calm, zen-inspired aesthetic that feels like self-care, not punishment +- Break management with flexible durations (5/10/15/30 min) that respects user autonomy +- Progressive escalation that adapts to behavior without being punitive +- Built-in analytics and mindfulness streak tracking for accountability +- Group-based organization for nuanced control over different site categories + +**One-liner**: "A mindful website intervention tool that helps you browse with intention — not a blocker that locks you out." + +**Claim**: "Reduce mindless browsing by 10x" (existing hero headline) + +--- + +## 3. Target Audience & Pain Points + +### Primary Audiences +1. **Knowledge workers & remote workers** — Losing 2-3 hours/day to distracting websites during work +2. **Students** — Struggling to focus during study sessions, reflexively opening social media +3. **Digital wellness seekers** — Anyone wanting to be more intentional with screen time +4. **People who tried other blockers** — Found them too harsh, too easy to bypass, or too ugly + +### Pain Points Addressed +- Guilt after mindless scrolling sessions +- Broken flow states from "just checking" social media +- Missed deadlines due to YouTube/Reddit rabbit holes +- Feeling controlled or punished by traditional blockers +- Blocker fatigue (habituation to the same block screen) +- All-or-nothing blocking that doesn't allow for legitimate use + +### Emotional Outcome +Users feel **in control, calm, and self-aware** — not restricted. The extension is a "personal focus coach" in the browser. + +--- + +## 4. Complete Feature Set (v3.0) + +### A. Group-Based Website Blocking +- Organize blocked sites into logical groups: "Social Media", "News", "Video", "Shopping", etc. +- Each group has its own intervention settings, break limits, and trigger rules +- Advanced URL pattern matching: + - Wildcards: `*.example.com`, `example.com/reels/*` + - Exclusions: `!allowed.example.com` + - Path-based: `example.com/feed` (block feed but not homepage) + - Comments: Lines starting with `#` are ignored + - Auto-includes www: `example.com` also blocks `www.example.com` +- **Free**: 1 group | **PRO**: Unlimited groups + +### B. 4 Intervention Types (Core Differentiator) + +Each intervention is designed around a different psychological approach to prevent habituation: + +1. **Instant Block** — "A moment of stillness" + - Calm, immediate pause with a leaf icon and pulsing animation + - Zero-friction reflection point before choosing to continue + - Encouraging copy: "Continue mindfully" or "Return to focus" + +2. **Hold to Complete** — "Cultivate patience" + - Press and hold a circular button for 3-15 seconds (configurable) + - SVG circular progress indicator with green-to-teal gradient + - Real-time countdown: "X seconds remaining" + - Tactile feedback: button scales when pressed + +3. **Slide to Continue** — "Flow with intention" + - Full-screen gradient animation slides across the screen + - Duration: 3-15 seconds (configurable) + - Mix-blend-difference effect creates dynamic visual + - Meditative, passive observation experience + +4. **Pixel Garden** — "Watch the garden grow" + - 400 pixels bloom across the screen in randomized order (Fisher-Yates shuffle) + - 20x20 grid with gradient colors from primary to accent + - Duration: 3-15 seconds (configurable) + - Creates organic "garden growth" visual effect + +**All interventions feature:** +- Customizable duration per group (3-15 seconds, doubling under escalation up to 30s) +- Custom messages per intervention type per group +- Visual editor for full appearance customization (opens in dedicated tab) +- Shadow DOM isolation — works on ANY website without style conflicts (even YouTube) +- Dark/light mode detection + +### C. Smart Triggering (3 Modes) + +1. **Always On** — Block whenever a listed site is visited +2. **On Schedule** — Block only during configured time windows (e.g., 9 AM–5 PM weekdays) + - Multiple schedules per group + - Schedule manager UI with day/time picker +3. **After Usage** — Block only after daily time limit is exceeded + - Configurable daily limit in minutes (e.g., 30 min of Reddit before blocking starts) + - Tracks seconds spent on group sites in real-time + +### D. Break Management System + +- **Daily break limits** per group (configurable, e.g., 3 breaks/day for Social Media) +- **Flexible break durations**: 5, 10, 15, or 30 minutes (Free: 5 min only, PRO: all durations) +- **Badge countdown** showing remaining break time in the extension icon +- **Break selector UI** with visual card interface and checkmark animation +- **Automatic break end** when duration expires — sites block again immediately +- **Smart tracking**: If daily time limit is exceeded during a break, the break ends automatically + +### E. Progressive Escalation System + +When users exceed their daily break limit or usage limits, the extension can optionally: +- **Double intervention duration** (5s → 10s, max 30s) — make users wait longer +- **Remove Instant Block** — force harder intervention types only (hold/slide/pixel) +- **Show streak warning banner** — orange motivational warning about breaking their streak + +Escalation is: +- Opt-in per group (users choose "Keep breaks easy" vs "Increase friction") +- Each escalation behavior is individually toggleable +- Designed to be firm but encouraging, not punitive + +### F. Mindfulness Streak Tracking + +- **Current streak**: Consecutive days staying within break/usage limits +- **Longest streak**: Personal best record +- **Growth Calendar**: Visual 7/30/90-day calendar showing mindful vs missed days + - Green leaf icons for maintained days + - Dashed circles for missed days + - Ring highlight for today +- **Total blocks prevented**: Running counter of how many times the extension intervened +- Gamification that encourages consistency through visible progress + +### G. Analytics Dashboard (PRO) + +- **Website Usage Chart**: Top 10 domains by time spent, with horizontal bar chart + - Gradient bars from primary to accent color + - Shows hours/minutes per domain + - Percentage breakdown +- **Key Metrics**: Current streak, longest streak, total blocks prevented +- **Date Range Filters**: 7D, 30D, 90D views +- **"Time in Garden"** — zen-inspired section title for usage data + +### H. Additional Features + +- **Right-click context menu**: "Add to FocusMode Group" → shows all groups + "Create New Group" +- **Theme**: Light / Dark / System (auto-detects OS preference) +- **Data export/import**: JSON backup of all settings, groups, and analytics +- **Overlay mode**: Show interventions as overlays vs full-page +- **Show stats on interventions**: Optionally display usage chart during intervention +- **Offline-first**: Works without internet, PRO license cached for 24 hours +- **Privacy-respecting**: No external tracking, all data stored locally + +--- + +## 5. Free vs PRO Comparison + +| Feature | Free | PRO ($20.99 lifetime) | +|---|---|---| +| Focus groups | 1 | Unlimited | +| Intervention types | All 4 | All 4 | +| Break durations | 5 min only | 5 / 10 / 15 / 30 min | +| Schedule-based triggering | Yes | Yes | +| Usage-based triggering | Yes | Yes | +| Escalation system | Yes | Yes | +| Streak tracking | Yes | Yes | +| Analytics dashboard | Basic | Full (usage charts, date ranges) | +| Website usage charts | — | Top 10 domains breakdown | +| Data export/import | — | Full backup & restore | +| Context menu | Yes | Yes | +| Dark mode | Yes | Yes | +| Custom intervention messages | Yes | Yes | +| Intervention editor | Yes | Yes | + +**PRO purchase**: One-time $20.99 via Polar.sh — no subscription, no recurring fees. + +--- + +## 6. Competitive Positioning + +### vs Freedom ($8.99/mo or $39.99/yr) +- FocusMode is **free to start** with a one-time PRO upgrade +- FocusMode uses **mindful interventions** instead of hard blocks +- FocusMode has **built-in analytics and streak tracking** +- Freedom requires a subscription; FocusMode is pay-once + +### vs Cold Turkey (free basic, $39 lifetime) +- FocusMode offers **4 unique intervention types** vs simple blocking +- FocusMode has a **calm, zen aesthetic** vs Cold Turkey's utilitarian UI +- FocusMode includes **break management** with flexible durations +- FocusMode is **$20.99** vs Cold Turkey's **$39** + +### vs LeechBlock (free) +- FocusMode has a **modern, beautiful UI** vs LeechBlock's dated interface +- FocusMode offers **escalation and streak tracking** beyond basic scheduling +- FocusMode has **4 intervention types** vs LeechBlock's simple block page +- FocusMode provides **analytics** for tracking progress + +### vs Forest ($3.99) +- FocusMode is **group-based** (not just a single focus timer) +- FocusMode offers **granular per-site and per-path controls** +- FocusMode has **4 intervention types** vs Forest's tree-growing mechanic +- FocusMode costs **$20.99 one-time** vs Forest's per-device pricing + +### vs StayFocusd (free) +- FocusMode has **modern UI** vs StayFocusd's basic interface +- FocusMode offers **4 intervention types** vs simple time-based blocking +- FocusMode has **break management, escalation, and streaks** +- FocusMode includes **analytics dashboard** + +### vs BlockSite ($10.99/mo) +- FocusMode is **$20.99 one-time** vs BlockSite's **$131.88/yr subscription** +- FocusMode uses **mindful interventions** vs hard blocks +- FocusMode has **no ads or upselling** in the free tier +- FocusMode is **privacy-respecting** (no data collection) + +--- + +## 7. SEO Keyword Strategy + +### Primary Keywords +- focus mode extension +- website blocker chrome +- website blocker extension +- digital wellness chrome extension +- mindful browsing extension + +### Secondary Keywords +- block distracting websites chrome +- reduce screen time chrome extension +- productivity extension chrome +- focus app for chrome +- website intervention tool +- mindless browsing blocker + +### Long-tail Keywords +- how to stop mindless scrolling on chrome +- chrome extension to block social media during work hours +- website blocker with breaks and timer +- best website blocker that doesn't fully block sites +- chrome extension for digital wellness and focus +- how to reduce time on distracting websites +- website blocker with analytics and tracking +- gentle website blocker with interventions + +### Comparison Keywords +- focusmode vs freedom app +- focusmode vs cold turkey +- focusmode vs leechblock +- focusmode vs forest app +- best website blocker chrome 2026 +- website blocker alternatives +- freedom app alternative free + +### Feature-Specific Keywords +- website blocker with break timer +- website blocker with streak tracking +- website blocker with analytics +- website blocker with schedule +- mindful browsing chrome extension +- zen website blocker + +--- + +## 8. Social Proof + +### Chrome Web Store Stats +- 15,000+ active users +- 4.7 out of 5 stars rating + +### Testimonial Themes (from existing landing page) +- Easy to use and set up +- Beautiful, aesthetic design (zen/calming) +- Actually effective at preventing procrastination +- Love the gamification features +- Scheduled blocking is a game-changer +- Feels encouraging, not restrictive + +--- + +## 9. Design & Brand Language + +### Visual Identity +- **Primary color**: Sage green (#4A9075) — calm, natural +- **Accent**: Teal (#6AABB0) — fresh, balanced +- **Background**: Warm off-white (#FAF9F6) — paper-like, zen +- **Typography**: Nunito (body, clean) + Fraunces (headings, elegant serif) +- **Iconography**: Leaf motif throughout (growth, nature, mindfulness) + +### Brand Voice +- Calm, encouraging, never punitive +- Uses nature metaphors: "zen garden", "growth calendar", "watch the garden grow" +- Active language: "cultivate patience", "flow with intention", "find your calm" +- Empowering: "continue mindfully", "resume focus", "take control" +- Avoids: urgency language, fear-based copy, aggressive blocking terminology + +### UX Philosophy +- Self-care over self-control +- Friction over blocking +- Encouragement over punishment +- Awareness over restriction +- Flexibility over rigidity + +--- + +## 10. Current Landing Page Audit (focusmode.app) + +### What Exists +- Hero: "Reduce Mindless Browsing By 10x" with 15k+ users / 4.7 rating badge +- Value prop section: "We know what you're thinking" +- 3 feature cards: Structured Breaks, Personalized Prompts, Automatic Scheduling +- 5 testimonials carousel +- Meta tags: title, description, OG tags, Twitter cards +- CTA: "Install Now" → Chrome Web Store + +### What's Missing / Outdated +1. **No v3.0 features**: Groups, 4 intervention types, escalation, streak calendar, analytics +2. **No schema markup**: Missing SoftwareApplication, FAQPage, Organization schemas +3. **No FAQ section**: Huge opportunity for featured snippets +4. **No pricing section**: Free vs PRO breakdown not shown +5. **No comparison content**: Missing "vs" pages for competitors +6. **Feature descriptions are thin**: Only 3 features listed, briefly described +7. **No demo video**: Video placeholder exists but is empty +8. **No internal linking**: No blog, resources, or sub-pages +9. **No how-it-works section**: Flow diagram of intervention → break → resume +10. **No stats/numbers section**: Could showcase "X blocks prevented across all users" + +### Technical SEO Gaps +- Missing JSON-LD structured data +- No sitemap reference found +- No FAQ schema for rich snippets +- OG image exists but page content doesn't reflect v3.0 +- Meta description doesn't mention key v3.0 features + +--- + +## 11. Recommended Landing Page Structure + +1. **Hero** — Updated headline + v3.0 value prop + social proof badge + CTA +2. **How It Works** — 3-step visual flow: Visit → Intervention → Break → Resume +3. **4 Intervention Types** — Individual showcase cards with animations/screenshots +4. **Feature Deep Dive** — Groups, scheduling, break management, escalation +5. **Analytics & Streaks** — Dashboard preview screenshots +6. **Pricing** — Free vs PRO comparison table +7. **Testimonials** — Existing + request new ones highlighting v3.0 features +8. **FAQ** — Common questions with schema markup +9. **Competitors Comparison** — Brief "Why FocusMode" section +10. **Final CTA** — Install button + PRO purchase link + +--- + +## 12. Content for Schema Markup + +### SoftwareApplication Schema +- Name: FocusMode +- Application Category: BrowserApplication +- Operating System: Chrome +- Offers: Free / $20.99 (one-time) +- Aggregate Rating: 4.7/5 (15,000+ users) +- Description: "A mindful website intervention tool for Chrome that reduces mindless browsing through intelligent, friction-based interventions." + +### FAQ Items for Schema +1. "What is FocusMode?" — A Chrome extension that reduces mindless browsing through calming interventions instead of hard blocks. +2. "Is FocusMode free?" — Yes, FocusMode has a free tier with 1 group and all 4 intervention types. PRO is a one-time $20.99 for unlimited groups and analytics. +3. "How is FocusMode different from other website blockers?" — FocusMode uses 4 unique mindfulness-based interventions (hold, slide, pixel, instant) instead of simply blocking sites. It respects user autonomy with flexible breaks and progressive escalation. +4. "Does FocusMode work on all websites?" — Yes, FocusMode uses Shadow DOM isolation to work on any website without style conflicts. +5. "Can I use FocusMode during work hours only?" — Yes, schedule-based triggering lets you activate blocking during specific time windows. +6. "What happens when I exceed my break limit?" — Optional escalation increases intervention duration, removes easy interventions, and shows streak warnings. +7. "Does FocusMode collect my data?" — No, all data is stored locally in your browser. FocusMode is privacy-respecting with no external tracking. +8. "Can I block specific pages instead of entire websites?" — Yes, FocusMode supports path-based blocking (e.g., block youtube.com/shorts but allow youtube.com). diff --git a/SEO_REPORT.md b/SEO_REPORT.md new file mode 100644 index 0000000..9dc8e0a --- /dev/null +++ b/SEO_REPORT.md @@ -0,0 +1,443 @@ +# FocusMode SEO Analysis & Landing Page Optimization Report + +> Generated: 2026-02-18 | Site: https://focusmode.app | Product: FocusMode v3.0 + +--- + +## SEO Health Score: 28/100 + +| Category | Weight | Score | Status | +|----------|--------|-------|--------| +| Technical SEO | 25% | 35/100 | Missing sitemap, robots.txt, schema | +| Content Quality | 25% | 20/100 | Thin (~850 words), outdated v2.x content | +| On-Page SEO | 20% | 15/100 | ZERO target keywords on page | +| Schema / Structured Data | 10% | 0/100 | Completely absent | +| Performance (CWV) | 10% | 60/100 | Next.js, decent load time | +| Images | 5% | 40/100 | Broken video, missing alt text | +| AI Search Readiness | 5% | 10/100 | No structured content for AI citation | + +--- + +## CRITICAL FINDINGS + +### 1. Zero Target Keywords on Page + +The page contains **none** of the target keywords anywhere — not in the title, meta description, headings, or body text. The words "Chrome extension," "website blocker," "screen time," and "digital wellness" do not appear at all. + +| Target Keyword | In Title | Meta Desc | H1 | Headings | Body | +|---|---|---|---|---|---| +| website blocker chrome | No | No | No | No | No | +| focus mode extension | No | No | No | No | No | +| digital wellness chrome extension | No | No | No | No | No | +| mindful browsing extension | No | No | No | No | Partial | +| block distracting websites | No | No | No | No | Partial | +| reduce screen time chrome | No | No | No | No | No | + +### 2. No Structured Data / Schema Markup + +Zero JSON-LD, Microdata, or RDFa detected. Missing out on rich results (star ratings, pricing, FAQ snippets). + +### 3. Missing sitemap.xml and robots.txt + +Both return 404. Google can still crawl but cannot efficiently discover pages. + +### 4. Broken Hero Video + +The demo video shows "Media Error" on both desktop and mobile. This occupies ~50% of above-the-fold visual weight and severely damages first impressions. + +### 5. Content Reflects v2.x, Not v3.0 + +Major v3.0 features entirely absent from the page: +- 4 intervention types (hold, slide, pixel, instant) +- Group-based blocking +- Break management with escalation +- Streak tracking & growth calendar +- Analytics dashboard + +--- + +## RECOMMENDED META TAGS + +### Title Tag (57 chars) +``` +FocusMode - Website Blocker & Focus Mode Chrome Extension +``` + +### Meta Description (155 chars) +``` +Block distracting websites mindfully with FocusMode. 4 intervention types, break management, streak tracking & analytics. Free Chrome extension used by 15k+ people. +``` + +### Open Graph +```html + + +``` + +--- + +## SCHEMA MARKUP (Ready to Implement) + +### Block 1: Organization +```json +{ + "@context": "https://schema.org", + "@type": "Organization", + "@id": "https://focusmode.app/#organization", + "name": "FocusMode", + "url": "https://focusmode.app", + "logo": { + "@type": "ImageObject", + "url": "https://focusmode.app/focusmode-logo.png", + "width": 32, + "height": 32 + }, + "image": "https://focusmode.app/public/focusmode-og-img.png", + "email": "focusmode.app@gmail.com", + "sameAs": [ + "https://chromewebstore.google.com/detail/focus-mode-stay-focused-b/ollmdedpknmlcdmpehclmgbogpifahdc" + ] +} +``` + +### Block 2: WebSite +```json +{ + "@context": "https://schema.org", + "@type": "WebSite", + "@id": "https://focusmode.app/#website", + "name": "FocusMode", + "url": "https://focusmode.app", + "publisher": { "@id": "https://focusmode.app/#organization" }, + "description": "Reduce mindless browsing with gentle interventions. A Chrome extension for mindful, intentional browsing.", + "inLanguage": "en-US" +} +``` + +### Block 3: SoftwareApplication +```json +{ + "@context": "https://schema.org", + "@type": "SoftwareApplication", + "@id": "https://focusmode.app/#software", + "name": "FocusMode", + "description": "A Chrome extension that reduces mindless browsing through calming interventions instead of hard blocks. 4 intervention types, break management, streak tracking, and analytics.", + "url": "https://focusmode.app", + "applicationCategory": "BrowserApplication", + "operatingSystem": "Chrome", + "browserRequirements": "Requires Google Chrome", + "softwareVersion": "3.0", + "installUrl": "https://chromewebstore.google.com/detail/focus-mode-stay-focused-b/ollmdedpknmlcdmpehclmgbogpifahdc", + "author": { "@id": "https://focusmode.app/#organization" }, + "aggregateRating": { + "@type": "AggregateRating", + "ratingValue": "4.7", + "bestRating": "5", + "worstRating": "1", + "ratingCount": "15000" + }, + "offers": [ + { + "@type": "Offer", + "name": "Free", + "price": "0", + "priceCurrency": "USD", + "description": "1 group, all 4 intervention types, 5-min breaks", + "availability": "https://schema.org/InStock" + }, + { + "@type": "Offer", + "name": "PRO Lifetime", + "price": "20.99", + "priceCurrency": "USD", + "description": "Unlimited groups, all break durations, full analytics, data export", + "availability": "https://schema.org/InStock", + "url": "https://focusmode.app/pro/" + } + ], + "featureList": [ + "4 mindful intervention types", + "Group-based website blocking", + "Schedule-based triggering", + "Usage-based triggering", + "Break management with escalation", + "Mindfulness streak tracking", + "Analytics dashboard", + "Path-based blocking with wildcards", + "Shadow DOM isolation", + "Privacy-respecting local storage" + ] +} +``` + +### Block 4: BreadcrumbList +```json +{ + "@context": "https://schema.org", + "@type": "BreadcrumbList", + "itemListElement": [ + { "@type": "ListItem", "position": 1, "name": "Home", "item": "https://focusmode.app/" }, + { "@type": "ListItem", "position": 2, "name": "PRO Version", "item": "https://focusmode.app/pro/" }, + { "@type": "ListItem", "position": 3, "name": "Changelog", "item": "https://focusmode.app/changelog/" }, + { "@type": "ListItem", "position": 4, "name": "Privacy Policy", "item": "https://focusmode.app/privacy-policy/" } + ] +} +``` + +### Block 5: FAQPage +```json +{ + "@context": "https://schema.org", + "@type": "FAQPage", + "mainEntity": [ + { + "@type": "Question", + "name": "What is FocusMode?", + "acceptedAnswer": { + "@type": "Answer", + "text": "FocusMode is a Chrome extension that reduces mindless browsing through calming interventions instead of hard blocks. Rather than simply preventing access to websites, it uses 4 unique mindfulness-based approaches to help you make conscious decisions about your browsing habits." + } + }, + { + "@type": "Question", + "name": "Is FocusMode free?", + "acceptedAnswer": { + "@type": "Answer", + "text": "Yes, FocusMode has a free tier that includes 1 group and all 4 intervention types (hold, slide, pixel, and instant). The PRO version is a one-time payment of $20.99 that unlocks unlimited groups, full analytics, flexible break durations, and data export. No subscription required." + } + }, + { + "@type": "Question", + "name": "How is FocusMode different from other website blockers?", + "acceptedAnswer": { + "@type": "Answer", + "text": "FocusMode uses 4 unique mindfulness-based interventions (hold, slide, pixel, and instant) instead of simply blocking sites. It respects user autonomy with flexible breaks and progressive escalation, encouraging mindful browsing rather than rigid restriction." + } + }, + { + "@type": "Question", + "name": "Does FocusMode work on all websites?", + "acceptedAnswer": { + "@type": "Answer", + "text": "Yes, FocusMode uses Shadow DOM isolation to work on any website without style conflicts. This ensures the intervention overlays display correctly regardless of a website's existing CSS or JavaScript." + } + }, + { + "@type": "Question", + "name": "Can I use FocusMode during work hours only?", + "acceptedAnswer": { + "@type": "Answer", + "text": "Yes, schedule-based triggering lets you activate blocking during specific time windows. You can configure FocusMode to only intervene during your work hours or study sessions, and browse freely outside those windows." + } + }, + { + "@type": "Question", + "name": "What happens when I exceed my break limit?", + "acceptedAnswer": { + "@type": "Answer", + "text": "Optional escalation increases intervention duration, removes easy interventions, and shows streak warnings. This progressive approach helps reinforce mindful browsing habits without being overly punitive. You control what escalation behaviors are enabled per group." + } + }, + { + "@type": "Question", + "name": "Does FocusMode collect my data?", + "acceptedAnswer": { + "@type": "Answer", + "text": "No, all data is stored locally in your browser. FocusMode is privacy-respecting with no external tracking. Your browsing data never leaves your device." + } + }, + { + "@type": "Question", + "name": "Can I block specific pages instead of entire websites?", + "acceptedAnswer": { + "@type": "Answer", + "text": "Yes, FocusMode supports path-based blocking with wildcards. For example, you can block youtube.com/shorts while still allowing access to youtube.com for other content. You can also use exclusion patterns like !allowed.example.com." + } + } + ] +} +``` + +--- + +## RECOMMENDED PAGE STRUCTURE + +### Updated Landing Page Sections + +1. **Hero** — "Block Distracting Websites Mindfully" + - Subtitle: "The Chrome extension that helps you reduce screen time without going cold turkey. Used by 15,000+ people." + - CTA: "Install Free" + Chrome logo + - Social proof: 15k+ users, 4.7/5 rating badge + - Fix or replace broken video with static screenshots + +2. **How It Works** — 3-step visual flow + - Visit blocked site → See calming intervention → Choose break or return to focus + - Target keyword: "block distracting websites" + +3. **4 Intervention Types** — Individual showcase cards + - Instant Block, Hold to Complete, Slide to Continue, Pixel Garden + - Screenshots/animations of each + - Target keyword: "mindful browsing extension" + +4. **Feature Deep Dive** — Group blocking, scheduling, break management + - Target keywords: "website blocker chrome", "digital wellness chrome extension" + +5. **Analytics & Streaks** — Dashboard preview + - Growth calendar, usage charts, blocks prevented + - Target keyword: "screen time tracker chrome" + +6. **Pricing** — Free vs PRO comparison table + - Emphasize: "$20.99 once, not $8.99/month" + - Target keyword: "free website blocker chrome" + +7. **Testimonials** — Existing reviews (fix truncation) + +8. **FAQ** — 8 questions with schema markup + - Target: Long-tail keywords and featured snippets + +9. **Final CTA** — Install + PRO purchase link + +### Content Target +- Expand from ~850 words to **1,500-2,000 words** +- Every section should naturally include at least one target keyword + +--- + +## VISUAL & MOBILE FIXES + +| Priority | Issue | Fix | +|----------|-------|-----| +| P0 | Broken hero video ("Media Error") | Add poster image fallback, test codec compatibility, provide multiple `` formats | +| P1 | Mobile nav overlap (375px) | Add hamburger menu or simplify mobile nav | +| P1 | Touch targets too small on mobile | Increase button padding to meet 48x48px minimum | +| P2 | Review cards clipped on right edge | Add proper container padding or overflow handling | +| P2 | "4.7 / 5" line break on mobile | Use `white-space: nowrap` | +| P3 | Subtitle text contrast | Darken from `rgb(113,113,122)` to at least `rgb(82,82,91)` | +| P3 | Tab labels lack context | Add "Intervention Styles" label above tabs | + +--- + +## TECHNICAL SEO CHECKLIST + +### Immediate (Week 1) +- [ ] Create `robots.txt` allowing all crawlers + AI bots (GPTBot, ClaudeBot, PerplexityBot) +- [ ] Create `sitemap.xml` with all pages +- [ ] Add 5 JSON-LD schema blocks (Organization, WebSite, SoftwareApplication, BreadcrumbList, FAQPage) +- [ ] Fix title tag: `FocusMode - Website Blocker & Focus Mode Chrome Extension` +- [ ] Fix meta description with target keywords +- [ ] Fix OG/Twitter title from lowercase "focusmode" to proper casing +- [ ] Add `twitter:description` meta tag +- [ ] Update changelog link from v2.7.4 to v3.0 +- [ ] Fix broken hero video or add poster fallback +- [ ] Submit sitemap to Google Search Console + +### Short-term (Weeks 2-4) +- [ ] Update all page content to reflect v3.0 features +- [ ] Add FAQ section with schema markup +- [ ] Add "How It Works" section +- [ ] Add pricing comparison table (Free vs PRO) +- [ ] Expand content to 1,500-2,000 words +- [ ] Add target keywords to H1, H2s, and body text naturally +- [ ] Fix mobile nav and touch target issues + +### Medium-term (Weeks 4-8) +- [ ] Create `/pricing` page +- [ ] Create `/features/` hub + 4 feature sub-pages +- [ ] Create top 3 comparison pages (`/compare/freedom`, `/compare/cold-turkey`, `/compare/blocksite`) +- [ ] Create standalone `/faq` page +- [ ] Implement internal linking across all pages + +### Long-term (Weeks 8-16) +- [ ] Launch `/blog` with 8 articles targeting informational keywords +- [ ] Build remaining comparison pages (LeechBlock, StayFocusd) +- [ ] Product Hunt launch for v3.0 +- [ ] Chrome Web Store listing optimization +- [ ] Monthly blog cadence (2 posts/month) +- [ ] Link building outreach + +--- + +## SITE ARCHITECTURE (Target State) + +``` +focusmode.app/ +├── / ← enhanced homepage +├── /features/ ← feature overview hub +│ ├── /features/interventions ← 4 intervention types +│ ├── /features/analytics ← usage tracking +│ ├── /features/scheduling ← time-based blocking +│ └── /features/groups ← site group management +├── /pricing ← Free vs PRO +├── /compare/ ← comparison hub +│ ├── /compare/freedom +│ ├── /compare/cold-turkey +│ ├── /compare/blocksite +│ ├── /compare/leechblock +│ └── /compare/stayfocusd +├── /faq ← standalone FAQ +├── /blog/ ← content hub +├── /changelog ← v3.0 release notes +├── /privacy-policy +├── /robots.txt +└── /sitemap.xml +``` + +--- + +## KEYWORD-TO-PAGE MAPPING + +| Page | Primary Keyword | Secondary Keywords | +|------|----------------|-------------------| +| `/` | website blocker chrome | focus mode extension, digital wellness chrome extension | +| `/features/interventions` | mindful browsing extension | gentle website blocker, website intervention tool | +| `/features/analytics` | screen time tracker chrome | browsing analytics extension | +| `/features/scheduling` | schedule website blocker | block websites during work hours | +| `/features/groups` | block social media chrome | website blocker categories | +| `/pricing` | focusmode pricing | free website blocker, one-time website blocker | +| `/compare/freedom` | focusmode vs freedom | freedom alternative free | +| `/compare/cold-turkey` | focusmode vs cold turkey | cold turkey alternative | +| `/compare/blocksite` | focusmode vs blocksite | blocksite alternative no subscription | +| `/faq` | focusmode faq | how does focusmode work | +| `/blog/*` | informational long-tail keywords | how to stop mindless scrolling, etc. | + +--- + +## AI SEARCH OPTIMIZATION + +### robots.txt — Allow AI Crawlers +``` +User-agent: * +Allow: / +Sitemap: https://focusmode.app/sitemap.xml + +User-agent: GPTBot +Allow: / +User-agent: ChatGPT-User +Allow: / +User-agent: Google-Extended +Allow: / +User-agent: PerplexityBot +Allow: / +User-agent: ClaudeBot +Allow: / +``` + +### Content Structure for AI Citation +- Use question-as-heading format for FAQ content +- Provide concise definitions in the first paragraph of each section +- Use comparison tables that AI can extract and cite +- Structure feature descriptions as lists with clear labels + +--- + +## NEXT STEPS + +This report + `PRODUCT_OVERVIEW.md` together provide everything needed for another agent to: +1. Update the existing Next.js landing page with SEO-optimized content +2. Implement the 5 JSON-LD schema blocks +3. Create new pages (pricing, features, comparisons) +4. Write blog content targeting the keyword strategy + +Both files are at the project root: +- `/PRODUCT_OVERVIEW.md` — comprehensive product details +- `/SEO_REPORT.md` — this file (SEO analysis + action plan) diff --git a/amplify.yml b/amplify.yml index 7fbca6a..d24972f 100644 --- a/amplify.yml +++ b/amplify.yml @@ -7,6 +7,17 @@ frontend: - npx prisma generate build: commands: + - echo "GOOGLE_CLIENT_ID=$GOOGLE_CLIENT_ID" >> .env + - echo "GOOGLE_CLIENT_SECRET=$GOOGLE_CLIENT_SECRET" >> .env + - echo "NEXTAUTH_SECRET=$NEXTAUTH_SECRET" >> .env + - echo "NEXTAUTH_URL=$NEXTAUTH_URL" >> .env + - echo "STRIPE_SECRET_KEY=$STRIPE_SECRET_KEY" >> .env + - echo "STRIPE_WEBHOOK_SECRET=$STRIPE_WEBHOOK_SECRET" >> .env + - echo "NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=$NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY" >> .env + - echo "NEXT_PUBLIC_WEBSITE_URL=$NEXT_PUBLIC_WEBSITE_URL" >> .env + - echo "DATABASE_URL=$DATABASE_URL" >> .env + - echo "MUX_TOKEN_ID=$MUX_TOKEN_ID" >> .env + - echo "MUX_TOKEN_SECRET=$MUX_TOKEN_SECRET" >> .env - npm run build artifacts: baseDirectory: .next @@ -16,3 +27,41 @@ frontend: paths: - node_modules/**/* - .next/cache/**/* + customHeaders: + - pattern: '/api/webhook' + headers: + - key: 'Cache-Control' + value: 'no-store, no-cache, must-revalidate' + - key: 'Pragma' + value: 'no-cache' + - pattern: '/api/**/*' + headers: + - key: 'Cache-Control' + value: 'no-store' + - pattern: '**/*' + headers: + - key: 'Strict-Transport-Security' + value: 'max-age=31536000; includeSubDomains' + - key: 'X-Frame-Options' + value: 'SAMEORIGIN' + - key: 'X-XSS-Protection' + value: '1; mode=block' + - key: 'X-Content-Type-Options' + value: 'nosniff' + customRules: + - pattern: '/api/webhook' + target: '/api/webhook' + status: '200' + condition: 'if(method == "POST" || method == "OPTIONS")' + - pattern: 'ALL' + target: '/index.html' + status: '404-200' + condition: > + if( + !path.matches("\\.well-known(/.*)?") && + !path.matches("^/.*/static/.*") && + !path.matches("^/static/.*") && + !path.matches("^/api/.*") && + !path.matches("^/_next/.*") && + !path.matches("^/.*\\.(js|css|png|jpg|jpeg|gif|svg|ico|json)") + ) diff --git a/next.config.mjs b/next.config.mjs index 166c03b..a9bdecb 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,12 +1,10 @@ -import { withNextVideo } from "next-video/process"; - /** @type {import('next').NextConfig} */ const nextConfig = { typescript: { ignoreBuildErrors: true, }, images: { - unoptimized: true, // Required for Amplify deployment + unoptimized: true, remotePatterns: [ { protocol: "https", @@ -22,9 +20,48 @@ const nextConfig = { }, optimizeFonts: true, output: "standalone", + trailingSlash: true, experimental: { + esmExternals: "loose", serverComponentsExternalPackages: ["@prisma/client", "bcrypt"], }, + async headers() { + return [ + { + source: '/api/:path*', + headers: [ + { + key: 'Access-Control-Allow-Origin', + value: '*', + }, + { + key: 'Access-Control-Allow-Methods', + value: 'GET, POST, PUT, DELETE, OPTIONS', + }, + { + key: 'Access-Control-Allow-Headers', + value: 'Content-Type, stripe-signature', + }, + ], + }, + ]; + }, + async rewrites() { + return { + beforeFiles: [ + { + source: '/api/webhook', + destination: '/api/webhook', + has: [ + { + type: 'header', + key: 'stripe-signature', + }, + ], + }, + ], + }; + }, }; -export default withNextVideo(nextConfig); +export default nextConfig; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index efdba26..84a7a44 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1,5 +1,6 @@ generator client { - provider = "prisma-client-js" + provider = "prisma-client-js" + binaryTargets = ["native", "rhel-openssl-1.0.x"] } datasource db { @@ -39,18 +40,18 @@ model Session { } model User { - id String @id @default(cuid()) - name String? - email String? @unique - emailVerified DateTime? @map("email_verified") - image String? - stripeCustomerId String? @unique - isSubscribed Boolean @default(false) - hasUsedFreeTrial Boolean @default(false) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - accounts Account[] - sessions Session[] + id String @id @default(cuid()) + name String? + email String? @unique + emailVerified DateTime? @map("email_verified") + image String? + stripeCustomerId String? @unique + isSubscribed Boolean @default(false) + hasUsedFreeTrial Boolean @default(false) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + accounts Account[] + sessions Session[] @@map("users") } diff --git a/public/changelog/advanced-list.webp b/public/changelog/advanced-list.webp new file mode 100644 index 0000000..ea900ec Binary files /dev/null and b/public/changelog/advanced-list.webp differ diff --git a/public/changelog/alert.webp b/public/changelog/alert.webp new file mode 100644 index 0000000..cf2d71c Binary files /dev/null and b/public/changelog/alert.webp differ diff --git a/public/changelog/breathing-intervetion.webp b/public/changelog/breathing-intervetion.webp new file mode 100644 index 0000000..ef383a6 Binary files /dev/null and b/public/changelog/breathing-intervetion.webp differ diff --git a/public/changelog/breathing-setting.webp b/public/changelog/breathing-setting.webp new file mode 100644 index 0000000..f9e950e Binary files /dev/null and b/public/changelog/breathing-setting.webp differ diff --git a/public/changelog/chart-dark.webp b/public/changelog/chart-dark.webp new file mode 100644 index 0000000..74cbe65 Binary files /dev/null and b/public/changelog/chart-dark.webp differ diff --git a/public/changelog/confirmation-prompt.webp b/public/changelog/confirmation-prompt.webp new file mode 100644 index 0000000..0a884f6 Binary files /dev/null and b/public/changelog/confirmation-prompt.webp differ diff --git a/public/changelog/confirmation.webp b/public/changelog/confirmation.webp new file mode 100644 index 0000000..e3d960f Binary files /dev/null and b/public/changelog/confirmation.webp differ diff --git a/public/changelog/dark.webp b/public/changelog/dark.webp new file mode 100644 index 0000000..f67cacc Binary files /dev/null and b/public/changelog/dark.webp differ diff --git a/public/changelog/pin.webp b/public/changelog/pin.webp new file mode 100644 index 0000000..baebe84 Binary files /dev/null and b/public/changelog/pin.webp differ diff --git a/public/changelog/pro.webp b/public/changelog/pro.webp new file mode 100644 index 0000000..29a736d Binary files /dev/null and b/public/changelog/pro.webp differ diff --git a/public/changelog/theme.webp b/public/changelog/theme.webp new file mode 100644 index 0000000..1d0cd23 Binary files /dev/null and b/public/changelog/theme.webp differ diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..2fdb3b6 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,14 @@ +User-agent: * +Allow: / +Sitemap: https://focusmode.app/sitemap.xml + +User-agent: GPTBot +Allow: / +User-agent: ChatGPT-User +Allow: / +User-agent: Google-Extended +Allow: / +User-agent: PerplexityBot +Allow: / +User-agent: ClaudeBot +Allow: / diff --git a/rewrites.json b/rewrites.json new file mode 100644 index 0000000..50654d0 --- /dev/null +++ b/rewrites.json @@ -0,0 +1,8 @@ +{ + "rewrites": [ + { + "source": "/api/<*>", + "destination": "/api/<*>" + } + ] +} diff --git a/src/app/api/auth/[...nextauth]/route.ts b/src/app/api/auth/[...nextauth]/route.ts index 149fdb2..3922ffc 100644 --- a/src/app/api/auth/[...nextauth]/route.ts +++ b/src/app/api/auth/[...nextauth]/route.ts @@ -16,23 +16,43 @@ export const authOptions: NextAuthOptions = { ], session: { strategy: "jwt", + maxAge: 30 * 24 * 60 * 60, // 30 days + }, + cookies: { + sessionToken: { + name: + process.env.NODE_ENV === "production" + ? `__Secure-next-auth.session-token` + : `next-auth.session-token`, + options: { + httpOnly: true, + sameSite: "lax", + path: "/", + secure: process.env.NODE_ENV === "production", + domain: + process.env.NODE_ENV === "production" ? ".focusmode.app" : undefined, + }, + }, }, callbacks: { async jwt({ token, user }) { if (user) { token.id = user.id; - // Fetch the latest user data from the database + } + + // For lifetime subscription: only check DB if not yet subscribed + // Once true, it stays true forever - no need to re-check + if (token.id && !token.isSubscribed) { const dbUser = await prisma.user.findUnique({ - where: { id: user.id }, + where: { id: token.id as string }, select: { stripeCustomerId: true, isSubscribed: true }, }); if (dbUser) { token.stripeCustomerId = dbUser.stripeCustomerId ?? undefined; token.isSubscribed = dbUser.isSubscribed; - } else { - token.isSubscribed = false; } } + return token; }, async session({ session, token }) { diff --git a/src/app/api/user/route.ts b/src/app/api/user/route.ts index 18239cd..c5117ef 100644 --- a/src/app/api/user/route.ts +++ b/src/app/api/user/route.ts @@ -1,20 +1,48 @@ import { NextRequest, NextResponse } from "next/server"; import { getServerSession } from "next-auth/next"; +import { decode } from "next-auth/jwt"; import { prisma } from "@/lib/prisma"; import { authOptions } from "../auth/[...nextauth]/route"; export { PATCH as PATCH } from "./free-trial"; export async function GET(req: NextRequest) { + let userId: string | null = null; + + // Try cookie-based auth first (for web app) const session = await getServerSession(authOptions); + if (session?.user?.id) { + userId = session.user.id; + } + + // Fallback to Bearer token auth (for Chrome extension) + if (!userId) { + const authHeader = req.headers.get("authorization"); + if (authHeader?.startsWith("Bearer ")) { + const token = authHeader.slice(7); + try { + const decoded = await decode({ + token, + secret: process.env.NEXTAUTH_SECRET!, + }); + + if (decoded?.id) { + userId = decoded.id as string; + } + } catch (error) { + console.error("JWT decode failed:", error); + return NextResponse.json({ error: "Invalid token" }, { status: 401 }); + } + } + } - if (!session || !session.user) { + if (!userId) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } try { const user = await prisma.user.findUnique({ - where: { id: session.user.id }, + where: { id: userId }, select: { id: true, name: true, @@ -27,10 +55,21 @@ export async function GET(req: NextRequest) { }); if (!user) { - return NextResponse.json({ error: "User not found" }, { status: 404 }); + return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } - return NextResponse.json({ user }, { status: 200 }); + return NextResponse.json( + { user }, + { + status: 200, + headers: { + "Cache-Control": + "no-store, no-cache, must-revalidate, proxy-revalidate", + Pragma: "no-cache", + Expires: "0", + }, + } + ); } catch (error) { console.error("Error fetching user:", error); return NextResponse.json( diff --git a/src/app/api/webhook/route.ts b/src/app/api/webhook/route.ts index 5901cb9..c1857a8 100644 --- a/src/app/api/webhook/route.ts +++ b/src/app/api/webhook/route.ts @@ -6,10 +6,17 @@ import { stripe } from "@/lib/stripe"; const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET; export async function POST(req: NextRequest) { + console.log("Webhook received:", req.url); + console.log( + "Headers:", + JSON.stringify(Object.fromEntries(req.headers.entries()), null, 2) + ); + const body = await req.text(); const sig = req.headers.get("stripe-signature"); if (!sig || !webhookSecret) { + console.error("Missing signature or webhook secret"); return NextResponse.json( { error: "Missing signature or webhook secret" }, { status: 400 } @@ -20,6 +27,7 @@ export async function POST(req: NextRequest) { try { event = stripe.webhooks.constructEvent(body, sig, webhookSecret); + console.log("Event constructed successfully:", event.type); } catch (err: unknown) { const error = err as Stripe.errors.StripeError; console.error(`Webhook Error: ${error.message}`); diff --git a/src/app/changelog/page.tsx b/src/app/changelog/page.tsx new file mode 100644 index 0000000..cec694c --- /dev/null +++ b/src/app/changelog/page.tsx @@ -0,0 +1,263 @@ +import { Metadata } from "next"; +import Image from "next/image"; + +export const metadata: Metadata = { + title: "Changelog | FocusMode", + description: "Latest updates and improvements to FocusMode", +}; + +export default function Changelog() { + const changes = [ + { + date: "November 2025", + updates: [ + { + version: "2.7.4", + title: "Breathing intervetions is here for PRO users!", + imageSrc: [ + "/changelog/breathing-intervetion.webp", + "/changelog/breathing-setting.webp", + ], + description: [ + "4 different breathing intervention is now available for PRO users. Try it in the intervetion options.", + ], + }, + ], + }, + { + date: "April 2025", + updates: [ + { + version: "2.7.3", + title: "Bug Fixed for Dark Mode", + imageSrc: [], + description: ["Dark mode theme in certain websites is now fixed"], + }, + { + version: "2.7.2", + title: "Bug Fixed and Improvements", + imageSrc: [], + description: [ + "Confirmation prompt before toggle FocusMode OFF is now working fine", + "Other minor improvements", + ], + }, + ], + }, + { + date: "March 2025", + updates: [ + { + version: "2.7.1", + title: + "Dark Mode for PRO users, Confirmation Prompt Toggle & Bug Fixed and Improvements", + imageSrc: [ + "/changelog/dark.webp", + "/changelog/confirmation-prompt.webp", + "/changelog/chart-dark.webp", + "/changelog/theme.webp", + ], + description: [ + "Dark mode theme is now available exclusively for PRO users", + "Added option to toggle confirmation dialog when disabling FocusMode", + "Theme colors for charts. More charts are coming to PRO users.", + "Resolved an issue with Advanced List website blocking functionality", + "Fixed a bug preventing websites from being unblocked when FocusMode is disabled", + "Restored missing website usage statistics", + "Save the charts setting", + ], + }, + { + version: "2.7.0", + title: + "FREE PRO Interventions, PIN Protection, Confirmation Before Turning OFF and Schedule limit", + imageSrc: [ + "/changelog/pro.webp", + "/changelog/confirmation.webp", + "/changelog/pin.webp", + "/changelog/alert.webp", + ], + description: [ + "PRO interventions are now FREE for all users! Enjoy advanced interventions like Slide In Out, Hold to Complete and Pixelated.", + "PIN Protection is now available for all users. Try it in the Settings.", + "Confirmation dialog added when turning off FocusMode. When confirmed, FocusMode will stay off eventhough the scheduled is ON.", + "Schedule feature is now limited to 3 days (Sun, Mon, Tue) per week for free users. Upgrade to PRO for unlimited scheduling.", + // "More features are coming! Promo code 'BF2025' for 30% OFF will expired soon", + ], + }, + ], + }, + { + date: "February 2025", + updates: [ + { + version: "2.6.7", + title: "Advanced List (BETA) for Power Users ", + description: [ + "Introducing the advanced list for power users. User can now filter website with advanced rules to block websites with pattern matching", + ], + imageSrc: ["/changelog/advanced-list.webp"], + }, + ], + }, + ]; + + return ( +
+
+

+ 🎉 What's New + + FocusMode Changelog + +

+

+ Keep track of updates and improvements to FocusMode +

+ +
+
+ + + + + +
+

+ Black Friday Special - Breathing intervetion is here for PRO + users! +

+
+
+
+

+ More features are coming! Promo code{" "} + + BF2025 + {" "} + for $24 OFF will + expire soon +

+
+
+
+
+
+
+
+ +
+ {changes.map((period, idx) => ( +
+
+

+ {period.date} +

+
+
+ {period.updates.map((update, index) => ( +
+
+ +

+ {update.version} +

+ {index === 0 && idx === 0 && ( + + NEW + + )} +
+
+

+ {update.title} +

+ +
    + {update.description.map((desc, i) => { + return ( +
  • + {desc} +
  • + ); + })} +
+ {update.imageSrc && update.imageSrc.length > 0 && ( +
+ {Array.isArray(update.imageSrc) ? ( +
+ {update.imageSrc.map((src, i) => ( +
+ {`${update.title} +
+ ))} +
+ ) : ( +
+ {update.title} +
+ )} +
+ )} +
+
+
+ ))} +
+
+ ))} +
+
+ ); +} diff --git a/src/app/faq/page.tsx b/src/app/faq/page.tsx new file mode 100644 index 0000000..c8b7738 --- /dev/null +++ b/src/app/faq/page.tsx @@ -0,0 +1,24 @@ +import { Metadata } from "next/types"; +import { FaqSection } from "@/components/v3/faq-section"; +import { JsonLdSchemas } from "@/components/v3/json-ld-schemas"; +import { Footer } from "@/components/footer"; + +export const metadata: Metadata = { + title: "FAQ", + description: + "Frequently asked questions about FocusMode — the mindful website blocker Chrome extension. Learn about intervention types, pricing, privacy, and more.", +}; + +export default function FaqPage() { + return ( + <> + +
+
+ +
+
+
+ + ); +} diff --git a/src/app/globals.css b/src/app/globals.css index 3f14815..77161f2 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -4,65 +4,65 @@ @layer base { :root { - --background: 0 0% 100%; - --foreground: 240 10% 3.9%; + --background: 40 33% 97%; + --foreground: 150 15% 20%; --card: 0 0% 100%; - --card-foreground: 240 10% 3.9%; + --card-foreground: 150 15% 20%; --popover: 0 0% 100%; - --popover-foreground: 240 10% 3.9%; + --popover-foreground: 150 15% 20%; - --primary: 240 5.9% 10%; - --primary-foreground: 0 0% 98%; + --primary: 153 32% 43%; + --primary-foreground: 0 0% 100%; - --secondary: 240 4.8% 95.9%; - --secondary-foreground: 240 5.9% 10%; + --secondary: 160 15% 92%; + --secondary-foreground: 150 15% 20%; - --muted: 240 4.8% 95.9%; - --muted-foreground: 240 3.8% 46.1%; + --muted: 140 10% 93%; + --muted-foreground: 150 10% 45%; - --accent: 240 4.8% 95.9%; - --accent-foreground: 240 5.9% 10%; + --accent: 184 30% 55%; + --accent-foreground: 0 0% 100%; --destructive: 0 84.2% 60.2%; --destructive-foreground: 0 0% 98%; - --border: 240 5.9% 90%; - --input: 240 5.9% 90%; - --ring: 240 10% 3.9%; + --border: 140 10% 88%; + --input: 140 10% 88%; + --ring: 153 32% 43%; --radius: 0.5rem; } .dark { - --background: 240 10% 3.9%; - --foreground: 0 0% 98%; + --background: 160 15% 8%; + --foreground: 140 10% 90%; - --card: 240 10% 3.9%; - --card-foreground: 0 0% 98%; + --card: 160 12% 12%; + --card-foreground: 140 10% 90%; - --popover: 240 10% 3.9%; - --popover-foreground: 0 0% 98%; + --popover: 160 12% 12%; + --popover-foreground: 140 10% 90%; - --primary: 0 0% 98%; - --primary-foreground: 240 5.9% 10%; + --primary: 153 32% 50%; + --primary-foreground: 0 0% 100%; - --secondary: 240 3.7% 15.9%; - --secondary-foreground: 0 0% 98%; + --secondary: 160 12% 18%; + --secondary-foreground: 140 10% 90%; - --muted: 240 3.7% 15.9%; - --muted-foreground: 240 5% 64.9%; + --muted: 160 10% 16%; + --muted-foreground: 140 8% 60%; - --accent: 240 3.7% 15.9%; - --accent-foreground: 0 0% 98%; + --accent: 184 30% 45%; + --accent-foreground: 0 0% 100%; --destructive: 0 62.8% 30.6%; --destructive-foreground: 0 0% 98%; - --border: 240 3.7% 15.9%; - --input: 240 3.7% 15.9%; - --ring: 240 4.9% 83.9%; + --border: 160 10% 20%; + --input: 160 10% 20%; + --ring: 153 32% 50%; } } @@ -74,18 +74,3 @@ @apply bg-background text-foreground; } } -.video-container { - position: relative; - padding-bottom: 56.25%; /* 16:9 aspect ratio */ - height: 0; - overflow: hidden; - max-width: 100%; -} - -.video-container iframe { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; -} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 9e132af..901598c 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,38 +1,38 @@ import type { Metadata } from "next/types"; -import { Inter } from "next/font/google"; +import { Nunito, Fraunces } from "next/font/google"; import "./globals.css"; -import localFont from "next/font/local"; import Providers from "@/components/providers"; -import { Navbar } from "@/components/navbar"; import { Header } from "@/components/header"; -// import { eudoxusSans } from "@/lib/font"; -const CalSans = localFont({ - src: "../../public/fonts/CalSans-SemiBold.otf", - variable: "--font-cal-sans", +const nunito = Nunito({ + subsets: ["latin"], + variable: "--font-body", }); -const inter = Inter({ subsets: ["latin"] }); +const fraunces = Fraunces({ + subsets: ["latin"], + variable: "--font-heading", +}); export const metadata: Metadata = { metadataBase: new URL("https://focusmode.app"), title: { - default: "FocusMode - Stay focused, be present", + default: "FocusMode - Website Blocker & Focus Mode Chrome Extension", template: "%s | FocusMode", }, description: - "Reclaim 2-3 hours daily with FocusMode. Our app helps you reduce mindless browsing and make informed decisions about distracting websites. Try it now!", + "Block distracting websites mindfully with FocusMode. 4 intervention types, break management, streak tracking & analytics. Free Chrome extension used by 15k+ people.", openGraph: { - title: "focusmode", + title: "FocusMode — Mindful Website Blocker for Chrome", description: - "Reclaim 2-3 hours daily with FocusMode. Our app helps you reduce mindless browsing and make informed decisions about distracting websites. Try it now!", + "Gentle interventions that help you stay focused. Not a blunt blocker — a mindful browsing companion. Free with optional $20.99 PRO.", url: "https://focusmode.app", - siteName: "focusmode", + siteName: "FocusMode", locale: "en_US", type: "website", images: [ { - url: "/public/focusmode-og-img.png", + url: "/focusmode-og-img.png", width: 1200, height: 630, }, @@ -50,8 +50,11 @@ export const metadata: Metadata = { }, }, twitter: { - title: "focusmode", + title: "FocusMode — Mindful Website Blocker for Chrome", + description: + "Block distracting websites mindfully with FocusMode. 4 intervention types, break management, streak tracking & analytics. Free Chrome extension.", card: "summary_large_image", + images: ["/focusmode-og-img.png"], }, }; @@ -62,33 +65,31 @@ export default function RootLayout({ }>) { return ( - - - - - - - - - - {/* */} - + + + + + + + + + +
{children} - ); } diff --git a/src/app/page.tsx b/src/app/page.tsx index 97d1891..2a9b06d 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,102 +1,35 @@ -import SEOHead from "@/components/SEOhead"; -import { CtaSection } from "@/components/cta-section"; -import { Features } from "@/components/features"; -import { Footer } from "@/components/footer"; -import { Header } from "@/components/header"; -import { HeroSection } from "@/components/hero-section"; -import { Objections } from "@/components/objections"; +import { HeroSection } from "@/components/v3/hero-section"; +import { HowItWorks } from "@/components/v3/how-it-works"; +import { InterventionTypes } from "@/components/v3/intervention-types"; +import { FeatureDeepDive } from "@/components/v3/feature-deep-dive"; +import { AnalyticsStreaks } from "@/components/v3/analytics-streaks"; +import { PricingSection } from "@/components/v3/pricing-section"; import { Testimonials } from "@/components/testimonials"; +import { FaqSection } from "@/components/v3/faq-section"; +import { CompetitorsSection } from "@/components/v3/competitors-section"; +import { CtaSection } from "@/components/v3/cta-section"; +import { JsonLdSchemas } from "@/components/v3/json-ld-schemas"; +import { Footer } from "@/components/footer"; export default function Home() { return ( -
-
- - - - - -
-
-
- ); -} - -function GithubIcon(props: { className: string }) { - return ( - - - - - ); -} - -function LinkedinIcon(props: { className: string }) { - return ( - - - - - - ); -} - -function MountainIcon(props: { className: string }) { - return ( - - - - ); -} - -function TwitterIcon(props: { className: string }) { - return ( - - - + <> + +
+
+ + + + + + + + + + +
+
+
+ ); } diff --git a/src/app/pricing/page.tsx b/src/app/pricing/page.tsx new file mode 100644 index 0000000..99d9f6b --- /dev/null +++ b/src/app/pricing/page.tsx @@ -0,0 +1,22 @@ +import { Metadata } from "next/types"; +import { PricingSection } from "@/components/v3/pricing-section"; +import { FaqSection } from "@/components/v3/faq-section"; +import { Footer } from "@/components/footer"; + +export const metadata: Metadata = { + title: "Pricing", + description: + "FocusMode pricing — free forever with 1 group and all 4 intervention types. PRO is a one-time $20.99 for unlimited groups, analytics, and flexible break durations.", +}; + +export default function PricingPage() { + return ( +
+
+ + +
+
+
+ ); +} diff --git a/src/app/privacy-policy/page.tsx b/src/app/privacy-policy/page.tsx index cb7fc0e..becfdbb 100644 --- a/src/app/privacy-policy/page.tsx +++ b/src/app/privacy-policy/page.tsx @@ -4,7 +4,6 @@ import { Footer } from "@/components/footer"; export default function PrivacyPolicy() { return (
-

Privacy Policy

@@ -13,7 +12,7 @@ export default function PrivacyPolicy() { 1. Information We Collect

- Our Chrome extension collects and uses the following information: + Our browser extension collects and uses the following information:

  • @@ -88,11 +87,13 @@ export default function PrivacyPolicy() {

    7. Contact Us

    If you have any questions about this Privacy Policy, please - contact us at focusmode.app@gmail.com. + contact us at focusmode.app@gmail.com

-

Last updated: 24 Jul 2024

+

+ Last updated: 16 April 2025 +

diff --git a/src/app/pro/page.tsx b/src/app/pro/page.tsx index 98169e1..e9761e6 100644 --- a/src/app/pro/page.tsx +++ b/src/app/pro/page.tsx @@ -19,20 +19,27 @@ import Link from "next/link"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { LandingSocialProof } from "@/components/social-proof/landing-social-proof"; -import { avatarItems } from "@/components/hero-section"; +import { PopiconsCircleCheckLine } from "@popicons/react"; + +const avatarItems = [ + { imageSrc: "/users/6.png", name: "Khang Nguyen Duy" }, + { imageSrc: "/users/3.png", name: "Stan Olery" }, + { imageSrc: "/users/4.jpeg", name: "Julio Santirachi" }, + { imageSrc: "/users/8.jpeg", name: "Cristian Andrei Grigore" }, +]; export default function ProVersionPage() { const [isHovered, setIsHovered] = useState(false); const features = [ - "3 PRO interventions", - "Customizable interventions", + "Breathing intervention", "Ad-free experience", "Browsing analytics", "Muti-device Sync", "Lifetime updates", "Priority support", "Support Indie Developer", + "Advanced Customization (Coming Soon)", ]; const { data: session } = useSession(); const [promoCode, setPromoCode] = useState("LAUNCH30"); @@ -101,8 +108,8 @@ export default function ProVersionPage() { className="flex flex-col lg:flex-row items-center justify-between gap-20 w-full" >
-

- Buy Once, Use Forever +

+ Buy Once, Use Forever!

@@ -113,11 +120,11 @@ export default function ProVersionPage() { onMouseLeave={() => setIsHovered(false)} > -
+
LIFETIME
- FocusMode Pro + FocusMode PRO Stop mindless browsing for good. @@ -147,7 +154,7 @@ export default function ProVersionPage() { transition={{ duration: 0.3, delay: index * 0.1 }} className="flex items-center" > - + {feature} ))} @@ -175,7 +182,10 @@ export default function ProVersionPage() { ) : ( - @@ -185,7 +195,7 @@ export default function ProVersionPage() { -
- + */} Have questions?{" "} Contact our sales team diff --git a/src/app/sitemap.ts b/src/app/sitemap.ts new file mode 100644 index 0000000..257cdb3 --- /dev/null +++ b/src/app/sitemap.ts @@ -0,0 +1,38 @@ +import { MetadataRoute } from "next"; + +export default function sitemap(): MetadataRoute.Sitemap { + const baseUrl = "https://focusmode.app"; + + return [ + { + url: baseUrl, + lastModified: new Date(), + changeFrequency: "weekly", + priority: 1, + }, + { + url: `${baseUrl}/pricing`, + lastModified: new Date(), + changeFrequency: "monthly", + priority: 0.8, + }, + { + url: `${baseUrl}/faq`, + lastModified: new Date(), + changeFrequency: "monthly", + priority: 0.7, + }, + { + url: `${baseUrl}/changelog`, + lastModified: new Date(), + changeFrequency: "monthly", + priority: 0.5, + }, + { + url: `${baseUrl}/privacy-policy`, + lastModified: new Date(), + changeFrequency: "yearly", + priority: 0.3, + }, + ]; +} diff --git a/src/components/SEOhead.tsx b/src/components/SEOhead.tsx deleted file mode 100644 index b2489c6..0000000 --- a/src/components/SEOhead.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import Head from "next/head"; - -function SEOHead({ - title, - description, - path, - ogPath = "/og.png", -}: { - title: string; - description: string; - path: string; - ogPath: string; -}) { - return ( - - {title} - - - - - - - - - - - - - {/* Facebook Meta Tags */} - - - - - - - - {/* Twitter Meta Tags */} - - - - - - - - - - ); -} - -export default SEOHead; diff --git a/src/components/cta-section.tsx b/src/components/cta-section.tsx deleted file mode 100644 index 2954979..0000000 --- a/src/components/cta-section.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { InfiniteMovingCards } from "@/components/ui/infinite-moving-cards"; -import { Button } from "./ui/button"; -import Link from "next/link"; -import { ArrowBigRight, MoveRightIcon } from "lucide-react"; - -export let CtaSection = () => { - return ( -
-
-
-

- Try focusmode Now -

-

- Reclaim Your Focus, Be More Present -

-
-
- - -
- ); -}; diff --git a/src/components/features-bento.tsx b/src/components/features-bento.tsx deleted file mode 100644 index 41b9954..0000000 --- a/src/components/features-bento.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import React from "react"; -import { BentoGrid, BentoGridItem } from "./ui/bento-grid"; -import { PopiconsHomeLine } from "@popicons/react"; -// import { -// IconClipboardCopy, -// IconFileBroken, -// IconSignature, -// IconTableColumn, -// } from "@tabler/icons-react"; - -export let FeaturesBento = () => { - return ( - - {items.map((item, i) => ( - - ))} - - ); -}; -const Skeleton = () => ( -
-); -const items = [ - { - title: "Structured Breaks", - description: - "When you visit a distracting site, focusmode presents a calming intervention. Breathe, stretch, and decide mindfully how long you want to spend there.", - header: , - className: "md:col-span-2", - // icon: , - }, - { - title: "Personalized Prompts", - description: - "Create your own intervention messages that resonate with you. Choose break durations that fit your workflow. FocusMode adapts to you.", - header: , - className: "md:col-span-1", - // icon: , - }, - { - title: "Automatic Scheduling", - description: - "Set focusmode to activate during your most productive hours, and turn off when it's time to unwind. Strike the perfect balance effortlessly.", - header: , - className: "md:col-span-1", - // icon: , - }, - { - title: "The Power of Communication", - description: - "Understand the impact of effective communication in our lives.", - header: , - className: "md:col-span-2", - // icon: , - }, -]; diff --git a/src/components/features.tsx b/src/components/features.tsx deleted file mode 100644 index b56569c..0000000 --- a/src/components/features.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { FeaturesBento } from "./features-bento"; -import { - PopiconsHomeLine, - PopiconsUserCheckDuotone, - PopiconsCirclePauseDuotone, - PopiconsCalendarTimeDuotone, -} from "@popicons/react"; - -const items = [ - { - title: "Structured Breaks", - description: - "When you visit a distracting site, focusmode presents a calming intervention. Breathe, stretch, and decide mindfully how long you want to spend there.", - header: , - }, - { - title: "Personalized Prompts", - description: - "Create your own intervention messages that resonate with you. Choose break durations that fit your workflow. focusmode adapts to you.", - header: , - }, - { - title: "Automatic Scheduling", - description: - "Set focusmode to activate during your most productive hours, and turn off when it's time to unwind. Strike the perfect balance effortlessly.", - header: , - }, -]; - -export let Features = () => { - return ( -
-
-
-
-
- Features -
-

- Take Control of Your Time -

-

- Stop mindless browsing and stay mindful. Access distracting - websites with well-informed intention. -

-
-
- {/* */} -
- {items.map(({ title, description, header }) => { - return ( -
-
-
-
- {header} -
-

{title}

-
-

- {description} -

-
-
- ); - })} -
-
-
- ); -}; diff --git a/src/components/footer.tsx b/src/components/footer.tsx index 729f930..5d096d7 100644 --- a/src/components/footer.tsx +++ b/src/components/footer.tsx @@ -1,14 +1,97 @@ import Link from "next/link"; +import Image from "next/image"; -export let Footer = () => { +const CHROME_STORE_URL = + "https://chromewebstore.google.com/detail/focus-mode-stay-focused-b/ollmdedpknmlcdmpehclmgbogpifahdc"; + +export function Footer() { return ( -