diff --git a/apps/web/src/components/mock-window.tsx b/apps/web/src/components/mock-window.tsx index e394a04e77..e374021481 100644 --- a/apps/web/src/components/mock-window.tsx +++ b/apps/web/src/components/mock-window.tsx @@ -4,10 +4,12 @@ import { cn } from "@hypr/utils"; export function MockWindow({ showAudioIndicator, variant = "desktop", + className, children, }: { showAudioIndicator?: boolean; variant?: "desktop" | "mobile"; + className?: string; children: React.ReactNode; }) { const isMobile = variant === "mobile"; @@ -17,6 +19,7 @@ export function MockWindow({ className={cn([ "bg-white shadow-lg border border-neutral-200 border-b-0 overflow-hidden", isMobile ? "rounded-t-lg" : "w-full max-w-lg rounded-t-xl", + className, ])} >
diff --git a/apps/web/src/routes/_view/index.tsx b/apps/web/src/routes/_view/index.tsx index aba28619d7..5b3fb70ebb 100644 --- a/apps/web/src/routes/_view/index.tsx +++ b/apps/web/src/routes/_view/index.tsx @@ -797,7 +797,16 @@ function HowItWorksSection() { setEnhancedLines(3); setTimeout(() => { setEnhancedLines(4); - setTimeout(() => runAnimation(), 1000); + setTimeout(() => { + setEnhancedLines(5); + setTimeout(() => { + setEnhancedLines(6); + setTimeout(() => { + setEnhancedLines(7); + setTimeout(() => runAnimation(), 1000); + }, 800); + }, 800); + }, 800); }, 800); }, 800); }, 800); @@ -876,7 +885,7 @@ function HowItWorksSection() {
  • = 1 ? "opacity-100" : "opacity-0", + enhancedLines >= 2 ? "opacity-100" : "opacity-0", )} > Sarah presented the new mobile UI update, which includes a @@ -886,7 +895,7 @@ function HowItWorksSection() {
  • = 2 ? "opacity-100" : "opacity-0", + enhancedLines >= 3 ? "opacity-100" : "opacity-0", ])} > Ben confirmed that API adjustments are needed to support @@ -896,7 +905,7 @@ function HowItWorksSection() {
  • = 3 ? "opacity-100" : "opacity-0", + enhancedLines >= 4 ? "opacity-100" : "opacity-0", ])} > The UI update will be implemented in phases, starting with @@ -909,7 +918,7 @@ function HowItWorksSection() {

    = 4 ? "opacity-100" : "opacity-0", + enhancedLines >= 5 ? "opacity-100" : "opacity-0", ])} > New Dashboard – Urgent Priority @@ -918,7 +927,7 @@ function HowItWorksSection() {
  • = 4 ? "opacity-100" : "opacity-0", + enhancedLines >= 6 ? "opacity-100" : "opacity-0", ])} > Alice emphasized that the new analytics dashboard must be @@ -927,7 +936,7 @@ function HowItWorksSection() {
  • = 5 ? "opacity-100" : "opacity-0", + enhancedLines >= 7 ? "opacity-100" : "opacity-0", ])} > The new dashboard will feature real-time user engagement diff --git a/apps/web/src/routes/_view/product/ai-notetaking.tsx b/apps/web/src/routes/_view/product/ai-notetaking.tsx index 7500fff8ae..aa6f305d35 100644 --- a/apps/web/src/routes/_view/product/ai-notetaking.tsx +++ b/apps/web/src/routes/_view/product/ai-notetaking.tsx @@ -212,31 +212,27 @@ function EditorSection() { function AudioTranscriptionDemo() { const [progress, setProgress] = useState(0); - // Words with their position along the timeline (0 to 1) - // Positioning accounts for approximate text width to prevent overlap const words = [ - { position: 0.02, text: "Welcome" }, // ~7 chars - { position: 0.15, text: "to" }, // ~2 chars - { position: 0.2, text: "today's" }, // ~7 chars - { position: 0.33, text: "meeting" }, // ~7 chars - { position: 0.48, text: "Let's" }, // ~5 chars - { position: 0.59, text: "discuss" }, // ~7 chars - { position: 0.73, text: "the" }, // ~3 chars - { position: 0.79, text: "Q4" }, // ~2 chars - { position: 0.86, text: "roadmap" }, // ~7 chars + { position: 0.02, text: "Welcome" }, + { position: 0.15, text: "to" }, + { position: 0.2, text: "today's" }, + { position: 0.33, text: "meeting" }, + { position: 0.48, text: "Let's" }, + { position: 0.59, text: "discuss" }, + { position: 0.73, text: "the" }, + { position: 0.79, text: "Q4" }, + { position: 0.86, text: "roadmap" }, ]; - // Generate static audio bars with varying heights (memoized to prevent regeneration) const audioBarHeights = useState(() => { const audioBarCount = 60; return Array.from({ length: audioBarCount }, () => { - // Random heights between 20% and 100% return Math.random() * 0.8 + 0.2; }); })[0]; useEffect(() => { - const duration = 8000; // 8 seconds for full cycle + const duration = 8000; const startTime = Date.now(); const animate = () => { @@ -257,7 +253,6 @@ function AudioTranscriptionDemo() { className="relative w-full bg-white flex flex-col items-center justify-center p-8 gap-6" style={{ aspectRatio: "52/39" }} > - {/* Audio bars - taking up more vertical space */}
    {audioBarHeights.map((height, i) => { const isTranscribed = i / audioBarHeights.length <= progress; @@ -275,7 +270,6 @@ function AudioTranscriptionDemo() { })}
    - {/* Subtitle display - words appear along timeline */}
    {words.map((word, i) => { const isVisible = progress >= word.position; @@ -318,7 +312,6 @@ function AnimatedMarkdownDemo({ isMobile = false }: { isMobile?: boolean }) { useEffect(() => { if (currentLineIndex >= lines.length) { - // Reset animation after a pause const timeout = setTimeout(() => { setCompletedLines([]); setCurrentLineIndex(0); @@ -338,7 +331,6 @@ function AnimatedMarkdownDemo({ isMobile = false }: { isMobile?: boolean }) { setTypingText(newText); charIndex++; - // Check if we just typed the trigger characters const shouldTransform = (currentLine.type === "heading" && newText === "# ") || (currentLine.type === "bullet" && newText === "- ") || @@ -350,15 +342,12 @@ function AnimatedMarkdownDemo({ isMobile = false }: { isMobile?: boolean }) { timeout = setTimeout(typeCharacter, 60); } else { - // Finished typing this line timeout = setTimeout(() => { - // Add the completed line const completedElement = renderCompletedLine(currentLine, isMobile); if (completedElement) { setCompletedLines((prev) => [...prev, completedElement]); } - // Reset for next line setTypingText(""); setIsTransformed(false); setCurrentLineIndex((prev) => prev + 1); @@ -494,7 +483,6 @@ function AnimatedMarkdownDemo({ isMobile = false }: { isMobile?: boolean }) { ); } - // Show raw text before transformation return (
    { setEnhancedLines(4); - setTimeout(() => runAnimation(), 1000); + setTimeout(() => { + setEnhancedLines(5); + setTimeout(() => { + setEnhancedLines(6); + setTimeout(() => { + setEnhancedLines(7); + setTimeout(() => runAnimation(), 1000); + }, 800); + }, 800); + }, 800); }, 800); }, 800); }, 800); @@ -745,7 +742,7 @@ function SummariesSection() {
  • = 1 ? "opacity-100" : "opacity-0", + enhancedLines >= 2 ? "opacity-100" : "opacity-0", ])} > Sarah presented the new mobile UI update, which includes @@ -755,7 +752,7 @@ function SummariesSection() {
  • = 2 ? "opacity-100" : "opacity-0", + enhancedLines >= 3 ? "opacity-100" : "opacity-0", ])} > Ben confirmed that API adjustments are needed to support @@ -765,7 +762,7 @@ function SummariesSection() {
  • = 3 ? "opacity-100" : "opacity-0", + enhancedLines >= 4 ? "opacity-100" : "opacity-0", ])} > The UI update will be implemented in phases, starting @@ -778,7 +775,7 @@ function SummariesSection() {

    = 4 ? "opacity-100" : "opacity-0", + enhancedLines >= 5 ? "opacity-100" : "opacity-0", ])} > New Dashboard – Urgent Priority @@ -787,7 +784,7 @@ function SummariesSection() {
  • = 4 ? "opacity-100" : "opacity-0", + enhancedLines >= 6 ? "opacity-100" : "opacity-0", ])} > Alice emphasized that the new analytics dashboard must @@ -796,7 +793,7 @@ function SummariesSection() {
  • = 5 ? "opacity-100" : "opacity-0", + enhancedLines >= 7 ? "opacity-100" : "opacity-0", ])} > The new dashboard will feature real-time user engagement diff --git a/apps/web/src/routes/_view/product/notepad.tsx b/apps/web/src/routes/_view/product/notepad.tsx index 3251571337..0cced616fc 100644 --- a/apps/web/src/routes/_view/product/notepad.tsx +++ b/apps/web/src/routes/_view/product/notepad.tsx @@ -1,9 +1,10 @@ -import { Icon } from "@iconify-icon/react"; import { createFileRoute, Link } from "@tanstack/react-router"; +import { useEffect, useState } from "react"; import { cn } from "@hypr/utils"; -import { SlashSeparator } from "@/components/slash-separator"; +import { MockWindow } from "@/components/mock-window"; +import { usePlatform } from "@/hooks/use-platform"; export const Route = createFileRoute("/_view/product/notepad")({ component: Component, @@ -20,600 +21,260 @@ export const Route = createFileRoute("/_view/product/notepad")({ }); function Component() { + const platform = usePlatform(); + + const getPrimaryCTA = () => { + if (platform === "mac") { + return { + labelFull: "Download for Mac", + labelShort: "Download", + href: "/download/apple-silicon", + isDownload: true, + }; + } + return { + labelFull: platform === "mobile" ? "Remind Me" : "Join Waitlist", + labelShort: platform === "mobile" ? "Remind Me" : "Join Waitlist", + href: "/", + isDownload: false, + }; + }; + + const primaryCTA = getPrimaryCTA(); + return (
    -
    -
    -
    -

    - Your private notepad. No bots. Local-first. +
    + {/* Hero content */} +
    +
    +

    + Your private notepad.
    + No bots. Local-first.

    -

    - Record meetings without bots and process everything locally for - complete privacy +

    + Hyprnote takes your memos and transcripts{" "} +
    + to make crazy good notes

    -
    - + +
    + {primaryCTA.isDownload ? ( + + + {primaryCTA.labelFull} + + {primaryCTA.labelShort} + + ) : ( + + + {primaryCTA.labelFull} + + {primaryCTA.labelShort} + + )} + - Download for free - + Learn More +
    -

    +
    +
    +
  • + ); +} - - -
    -
    -
    -
    -

    - No Bots -

    -

    - Record directly from your device without intrusive meeting - bots. -

    -
    -
    -

    - Local-First -

    -

    - All AI processing happens on your device, nothing sent to - cloud. -

    -
    -
    -

    - Fully Private -

    -

    - Your conversations stay yours, complete data ownership. -

    -
    -
    -
    - -
    -

    - Why Hyprnote Notepad -

    -
    -
    - -

    - No bots, no interruptions -

    -

    - Unlike other AI notetakers, Hyprnote doesn't send bots to join - your meetings. Record directly from your device for seamless, - unobtrusive capture. -

    -
      -
    • - - Stay under the radar -
    • -
    • - - No awkward "bot has joined" notifications -
    • -
    • - - Works everywhere - Zoom, Meet, Teams, Discord -
    • -
    • - - No host permissions needed -
    • -
    -
    -
    - -

    - Local-first AI processing -

    -

    - All your data stays on your device. AI processes recordings - locally with no cloud uploads or third-party servers. -

    -
      -
    • - - - Complete privacy - data never leaves your computer - -
    • -
    • - - Lightning fast - no network delays -
    • -
    • - - Works offline completely -
    • -
    • - - Unlimited processing - no API costs -
    • -
    -
    -
    -
    - - - -
    -

    - Hyprnote vs. Bot-based services -

    -
    -
    -
    - -

    - Bot-based Services -

    -
    -
      -
    • - - Bot announces itself when joining -
    • -
    • - - Makes participants self-conscious -
    • -
    • - - Audio uploaded to company servers -
    • -
    • - - Requires internet connection -
    • -
    • - - Processing delays from uploads -
    • -
    • - - Monthly usage limits -
    • -
    • - - Only works with supported platforms -
    • -
    -
    -
    -
    - -

    - Hyprnote Notepad -

    -
    -
      -
    • - - Silent background recording -
    • -
    • - - Natural conversations flow freely -
    • -
    • - - All processing on your device -
    • -
    • - - Works completely offline -
    • -
    • - - Instant processing, no uploads -
    • -
    • - - Unlimited recordings -
    • -
    • - - Works with any application -
    • -
    -
    -
    -
    +function AnimatedNotesDemo() { + const [typedText1, setTypedText1] = useState(""); + const [typedText2, setTypedText2] = useState(""); + const [showEnhanced, setShowEnhanced] = useState(false); + const [enhancedLines, setEnhancedLines] = useState(0); - + const text1 = "metrisc w/ john"; + const text2 = "stakehlder mtg"; -
    -

    - Built for privacy and compliance -

    -
    -
    - -
    -

    - Compliance-ready -

    -

    - Meet GDPR, HIPAA, and other data protection requirements by - keeping sensitive conversations entirely local on your - device. -

    -
    -
    -
    - -
    -

    - Zero data leaks -

    -

    - Eliminate the risk of data breaches, unauthorized access, or - third-party data mining. Your data never leaves your - computer. -

    -
    -
    -
    - -
    -

    - Full data ownership -

    -

    - Maintain complete ownership and control. Export, backup, or - delete your data anytime without requesting access from a - service provider. -

    -
    -
    -
    - -
    -

    - No vendor lock-in -

    -

    - Your data isn't trapped in a proprietary cloud system. It's - stored in standard formats on your device. -

    -
    -
    -
    -
    + useEffect(() => { + const runAnimation = () => { + setTypedText1(""); + setTypedText2(""); + setShowEnhanced(false); + setEnhancedLines(0); - + let currentIndex1 = 0; + setTimeout(() => { + const interval1 = setInterval(() => { + if (currentIndex1 < text1.length) { + setTypedText1(text1.slice(0, currentIndex1 + 1)); + currentIndex1++; + } else { + clearInterval(interval1); -
    -

    - Perfect for sensitive meetings -

    -
    -
    - -

    - Confidential discussions -

    -

    - Keep sensitive business conversations private without - third-party bots listening in. -

    -
    -
    - -

    - Legal consultations -

    -

    - Record attorney-client conversations without privacy concerns - or compliance issues. -

    -
    -
    - -

    - Healthcare meetings -

    -

    - Maintain HIPAA compliance by keeping all recordings local and - private. -

    -
    -
    - -

    - HR discussions -

    -

    - Document performance reviews and sensitive HR matters - discreetly. -

    -
    -
    - -

    - Client calls -

    -

    - Take notes without making clients uncomfortable about bots - joining. -

    -
    -
    - -

    - Creative sessions -

    -

    - Let ideas flow naturally without the self-consciousness of - visible recording. -

    -
    -
    -
    + let currentIndex2 = 0; + const interval2 = setInterval(() => { + if (currentIndex2 < text2.length) { + setTypedText2(text2.slice(0, currentIndex2 + 1)); + currentIndex2++; + } else { + clearInterval(interval2); + setTimeout(() => { + setShowEnhanced(true); + setTimeout(() => { + setEnhancedLines(1); + setTimeout(() => { + setEnhancedLines(2); + setTimeout(() => { + setEnhancedLines(3); + setTimeout(() => { + setEnhancedLines(4); + setTimeout(() => { + setEnhancedLines(5); + setTimeout(() => { + setEnhancedLines(6); + setTimeout(() => runAnimation(), 2000); + }, 800); + }, 800); + }, 800); + }, 800); + }, 800); + }, 500); + }, 1000); + } + }, 50); + } + }, 50); + }, 500); + }; - + runAnimation(); + }, []); -
    -

    - Powerful local AI capabilities -

    -
    -
    - -

    - Transcription -

    -

    - High-quality speech-to-text powered by local Whisper models. -

    -
    -
    - -

    - Summarization -

    -

    - AI-generated summaries with key points and action items. -

    -
    -
    - -

    - Classification -

    -

    - Automatic categorization and tagging of conversations. -

    -
    -
    - -

    - Semantic search -

    -

    - Find information across all meetings using natural language. -

    -
    -
    - -

    - Key insights -

    -

    - Extract decisions, questions, and important moments - automatically. -

    -
    -
    - -

    - Speaker detection -

    -

    - Identify different speakers and attribute quotes accurately. -

    -
    -
    -
    -
    - - - -
    -
    -
    - Hyprnote -
    -

    - The privacy-first notepad -

    -

    - Experience professional AI notetaking without bots, cloud uploads, - or privacy compromises. Your data stays yours -

    -
    - +
    + + Ben confirmed that API adjustments are needed to support dynamic + UI changes, particularly for fetching personalized user data + more efficiently. + +
  • = 4 ? "opacity-100" : "opacity-0", + ])} + > + The UI update will be implemented in phases, starting with core + navigation improvements. Ben will ensure API modifications are + completed before development begins. +
  • + +
    +
    +

    = 5 ? "opacity-100" : "opacity-0", + ])} + > + New Dashboard – Urgent Priority +

    +
      +
    • = 6 ? "opacity-100" : "opacity-0", + ])} + > + Alice emphasized that the new analytics dashboard must be + prioritized due to increasing stakeholder demand. +
    • +
    -
    + + + ); + } + + return ( + +
    +
    ui update - mobile
    +
    api
    +
    new dash - urgent
    +
    a/b test next wk
    +
    + {typedText1} + {typedText1 && typedText1.length < text1.length && ( + | + )} +
    +
    + {typedText2} + {typedText2 && typedText2.length < text2.length && ( + | + )} +
    - +
    ); }