diff --git a/apps/web/src/routes/_view/opensource.tsx b/apps/web/src/routes/_view/opensource.tsx index 7b05cb563f..a2fdeb103a 100644 --- a/apps/web/src/routes/_view/opensource.tsx +++ b/apps/web/src/routes/_view/opensource.tsx @@ -1,12 +1,21 @@ import { Icon } from "@iconify-icon/react"; -import { createFileRoute, Link } from "@tanstack/react-router"; +import { createFileRoute } from "@tanstack/react-router"; +import { AnimatePresence, motion } from "motion/react"; +import { Fragment, useRef, useState } from "react"; import { cn } from "@hypr/utils"; import { DownloadButton } from "@/components/download-button"; -import { GitHubOpenSource } from "@/components/github-open-source"; +import { Image } from "@/components/image"; import { SlashSeparator } from "@/components/slash-separator"; -import { Stargazer, useGitHubStargazers } from "@/queries"; +import { + GITHUB_LAST_SEEN_FORKS, + GITHUB_LAST_SEEN_STARS, + Stargazer, + useGitHubStargazers, + useGitHubStats, +} from "@/queries"; +import { CTASection } from "@/routes/_view/index"; export const Route = createFileRoute("/_view/opensource")({ component: Component, @@ -46,6 +55,8 @@ export const Route = createFileRoute("/_view/opensource")({ }); function Component() { + const heroInputRef = useRef(null); + return (
- + - + - + - + - + - +
); @@ -76,7 +87,7 @@ function StargazerAvatar({ stargazer }: { stargazer: Stargazer }) { href={`https://github.com/${stargazer.username}`} target="_blank" rel="noopener noreferrer" - className="block size-14 rounded-sm overflow-hidden border border-neutral-200/50 bg-neutral-100 shrink-0 hover:scale-110 hover:border-neutral-400 hover:opacity-100 transition-all" + className="block size-14 rounded-sm overflow-hidden border border-neutral-100/50 bg-neutral-100 shrink-0 hover:scale-110 hover:border-neutral-400 hover:opacity-100 transition-all" > 0 && }
-
+

Built in the open,
@@ -163,367 +174,714 @@ function HeroSection() { ); } -function WhyOpenSourceSection() { +function LetterSection() { return ( -
-

- Why open source matters -

-
-
- -

- Verifiable privacy -

-

- Don't just trust our privacy claims—verify them yourself. Every data - flow, every API call, every storage operation is visible in the - source code. -

-
-
- -

- Community driven -

-

- Features are shaped by real users, not just product managers. Report - bugs, suggest improvements, or contribute code directly to make - Hyprnote better for everyone. -

-
-
- -

- No vendor lock-in -

-

- Your data, your rules. Fork the project, self-host it, or modify it - to fit your exact needs. You're never trapped in a proprietary - ecosystem. -

-
-
- -

- Long-term sustainability -

-

- Open source projects outlive companies. Even if Hyprnote the company - disappears, the software lives on through the community. -

+
+
+
+ + A letter from our team +
-
-
- ); -} -function TransparencySection() { - return ( -
-

- Complete transparency -

-
-
-
- -

- Auditable codebase -

-

- Every function, every algorithm, every data handler is open for - inspection. Security researchers and privacy advocates can verify - our claims. +

+

+ Why Open Source is Inevitable +
+ in the Age of AI +

+ +
+

Hey friends,

+ +

+ We're watching software change faster than any of us expected. AI + isn't a concept anymore. It's in your meetings, it's inside your + documents, and it has context on things that used to live only in + your mind.

-
-
- -

- Public development -

-

- All development happens in the open. Watch features being built, - see how bugs are fixed, and understand the reasoning behind every - change. + +

+ When software listens to you, when it transcribes you, when it + summarizes your thinking, trust can't just be a marketing claim.

-
-
- -

Clear licensing

-

- GPL-3.0 ensures the code stays open. Any modifications must also - be open source, protecting the community's investment. + +

That's why open source is not a nice-to-have. It's mandatory.

+ +

+ If an AI tool captures your voice, your discussions, your + strategy, you should be able to see exactly what it does with that + information. Not a PDF saying "we care about privacy." Not a + privacy policy written by lawyers. Actual code.

-
-
-
-
- -
-

- No hidden data collection -

-

- Unlike closed-source alternatives, you can verify exactly what - data Hyprnote collects and where it goes. Our telemetry is - opt-in, minimal, and fully documented in the source code. -

- - - View analytics implementation - - +

+ Closed-source AI tools say "trust us." But you can't audit "trust + us." You can't fork it, stress-test it, or guarantee your own + compliance. +

+ +

In the age of AI, blind trust is basically an attack vector.

+ +

Open source flips the power dynamic:

+ +
    +
  • You can verify claims instead of believing them.
  • +
  • Security researchers can inspect, not speculate.
  • +
  • Teams can self-host, extend, or fork when needed.
  • +
  • The product outlives the company that built it.
  • +
+ +

That's why we built Hyprnote in the open.

+ +

+ We don't want you to trust us more. We want you to need to trust + us less. If you can inspect it, run it locally, modify it, or + audit it, the entire idea of trust changes. +

+ +

This isn't ideology. It's durability.

+ +

+ Companies die. Pricing changes. Terms change. Acquisitions happen. + Compliance requirements evolve. +

+ +

Open source survives all of that.

+ +

+ What AI is capable of today demands a different contract between + software and the people who rely on it. That contract should be + inspectable, forkable, and owned by its users, not hidden behind + opaque servers. +

+ +

+ If AI ends up shaping how we work, think, and communicate, then + the people using it deserve transparency—not promises. +

+ +
+
+ John Jeong + Yujong Lee +
+ +
+
+

With clarity,

+

John Jeong, Yujong Lee

+
+ +
+ Hyprnote Signature +
+
-
+
); } +const techStack = [ + { + category: "Languages", + items: [ + { + name: "Rust", + icon: "devicon:rust", + description: "Core language for audio processing and local AI", + url: "https://www.rust-lang.org/", + }, + { + name: "TypeScript", + icon: "devicon:typescript", + description: "Type-safe language for frontend development", + url: "https://www.typescriptlang.org/", + }, + ], + }, + { + category: "Desktop & UI", + items: [ + { + name: "Tauri", + icon: "devicon:tauri", + description: "Cross-platform desktop framework", + url: "https://tauri.app/", + }, + { + name: "React", + icon: "devicon:react", + description: "UI framework for building interfaces", + url: "https://react.dev/", + }, + { + name: "TanStack Start", + imageUrl: "https://avatars.githubusercontent.com/u/72518640?s=200&v=4", + description: "Full-stack React framework with type-safe routing", + url: "https://tanstack.com/start", + }, + ], + }, + { + category: "Build & Tooling", + items: [ + { + name: "Vite", + icon: "devicon:vitejs", + description: "Fast build tool and dev server", + url: "https://vite.dev/", + }, + { + name: "Turborepo", + icon: "vscode-icons:file-type-light-turbo", + description: "High-performance monorepo build system", + url: "https://turbo.build/repo", + }, + { + name: "pnpm", + icon: "devicon:pnpm", + description: "Fast, disk space efficient package manager", + url: "https://pnpm.io/", + }, + ], + }, + { + category: "AI & Data", + items: [ + { + name: "WhisperKit", + imageUrl: "https://avatars.githubusercontent.com/u/150409474?s=200&v=4", + description: "Local speech-to-text transcription", + url: "https://github.com/argmaxinc/WhisperKit", + }, + { + name: "llama.cpp", + imageUrl: "https://avatars.githubusercontent.com/u/134263123?s=200&v=4", + description: "Local LLM inference engine", + url: "https://github.com/ggerganov/llama.cpp", + }, + { + name: "TinyBase", + imageUrl: "https://avatars.githubusercontent.com/u/96894742?s=200&v=4", + description: "Reactive data store for local-first apps", + url: "https://tinybase.org/", + }, + { + name: "TanStack Query", + icon: "logos:react-query-icon", + description: "Powerful data synchronization for React", + url: "https://tanstack.com/query", + }, + ], + }, +]; + +const sponsors = [ + { + name: "Tauri", + icon: "devicon:tauri", + url: "https://github.com/tauri-apps", + description: "Desktop framework", + }, + { + name: "MrKai77", + imageUrl: "https://avatars.githubusercontent.com/u/68963405?v=4", + url: "https://github.com/MrKai77", + description: "Loop window manager", + }, + { + name: "James Pearce", + imageUrl: "https://avatars.githubusercontent.com/u/90942?v=4", + url: "https://github.com/jamesgpearce", + description: "Open source contributor", + }, +]; + function TechStackSection() { return ( -
-

- Built with modern technology -

-

- Hyprnote combines the best of systems programming and web technologies - to deliver a fast, secure, and cross-platform experience. -

- -
-
-
- -

Rust

-
-

- Memory-safe systems programming for the core audio processing, - transcription pipeline, and local AI inference. +

+
+
+

+ Our Tech Stack +

+

+ Built with modern, privacy-respecting technologies that run locally + on your device.

-
-
- -

Tauri

-
-

- Lightweight desktop framework that combines Rust backend with web - frontend for native performance. -

-
-
-
- -

React

-
-

- Modern UI framework powering the desktop app interface with TanStack - Router for navigation. -

-
-
-
- -

Whisper

-
-

- OpenAI's speech recognition model running locally for private, - accurate transcription in 100+ languages. -

-
-
-
- -

Local LLMs

-
-

- On-device language models for summarization and insights without - sending data to external servers. -

-
-
-
- -

SQLite

-
-

- Local-first database via libsql for fast, reliable storage with - optional cloud sync. -

-
-
-
- - - Explore the full architecture on GitHub - - +
+ {techStack.map((section) => { + return ( + +
+

+ {section.category} +

+
+ {section.items.map((tech, techIndex) => { + const itemCount = section.items.length; + const posInRow2 = techIndex % 2; + const posInRow3 = techIndex % 3; + const rowIn2Col = Math.floor(techIndex / 2); + const rowIn3Col = Math.floor(techIndex / 3); + const totalRows2Col = Math.ceil(itemCount / 2); + const totalRows3Col = Math.ceil(itemCount / 3); + const isLastItemMobile = techIndex === itemCount - 1; + const isLastRowSm = rowIn2Col === totalRows2Col - 1; + const isLastRowLg = rowIn3Col === totalRows3Col - 1; + + const hasBorderBMobile = !isLastItemMobile; + const hasBorderRSm = posInRow2 < 1; + const hasBorderRLg = posInRow3 < 2; + const hasBorderBSm = !isLastRowSm; + const hasBorderBLg = !isLastRowLg; + + return ( + +
+ {"imageUrl" in tech ? ( + {`${tech.name} + ) : ( + + )} +

+ {tech.name} +

+
+

+ {tech.description} +

+
+ ); + })} +
+ ); + })} +
); } -function ContributeSection() { +function SponsorsSection() { return ( -
-

- Join the community -

- -
-
-
- -

- Contribute code +
+
+
+

+ Paying It Forward +

+

+ We love giving back to the community that makes Hyprnote possible. + As we grow, we hope to sponsor even more projects and creators. +

+
+ +
+
+

+ Projects We Sponsor

-

- Whether it's fixing a bug, adding a feature, or improving - documentation, every contribution makes Hyprnote better. -

- - Read contributing guide - -
-
- -

- Report issues -

-

- Found a bug or have a feature request? Open an issue on GitHub and - help us prioritize what matters most to users. -

+ {sponsors.map((sponsor, index) => { + const hasBorderR = index < sponsors.length - 1; + + return ( + 0 && "border-t sm:border-t-0", + hasBorderR && "lg:border-r", + ])} + > +
+ {"imageUrl" in sponsor ? ( + {`${sponsor.name} + ) : ( + + )} +

+ {sponsor.name} +

+
+

+ {sponsor.description} +

+
+ ); + })} +
+
+

+ We Appreciate Your Support +

+

+ Your sponsorship keeps Hyprnote free, open source, and + independent for everyone. +

+
- View open issues - + + Sponsor on GitHub
+
+
+ ); +} -
- - -
-

GitHub

-

Star & fork

-
-
- - -
-

Discord

-

Join the chat

-
-
- ({ + id: i, + x: Math.random() * 100, + delay: Math.random() * 0.8, + duration: 0.6 + Math.random() * 0.8, + rotation: Math.random() * 720 - 360, + scale: 0.5 + Math.random() * 1, + xDrift: Math.random() * 60 - 30, + })); + + return ( +
+ + {icons.map((item) => ( + - -
-

Twitter

-

Follow updates

-
-
+ {imageUrl ? ( + + ) : icon ? ( + + ) : null} + + ))} + +
+ ); +} + +function StatCard({ + label, + value, + icon, + imageUrl, + color, + hasBorder, +}: { + label: string; + value: string; + icon?: string; + imageUrl?: string; + color: string; + hasBorder: boolean; +}) { + const [isHovered, setIsHovered] = useState(false); + + const confettiIcon = icon === "mdi:account-group" ? "mdi:account" : icon; + + return ( +
setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + > + {isHovered && (confettiIcon || imageUrl) && ( + + )} +
+ {imageUrl ? ( + {label} + ) : icon ? ( + + ) : null} +
+
+

{value}

+

{label}

+
+
+ ); +} + +function ProgressSection() { + const { data } = useGitHubStats(); + const stars = data?.stars; + const forks = data?.forks; + + const stats = [ + { + label: "GitHub Stars", + value: stars?.toLocaleString() ?? GITHUB_LAST_SEEN_STARS.toLocaleString(), + icon: "mdi:star", + color: "text-yellow-500", + }, + { + label: "Forks", + value: forks?.toLocaleString() ?? GITHUB_LAST_SEEN_FORKS.toLocaleString(), + icon: "mdi:source-fork", + color: "text-blue-500", + }, + { + label: "Contributors", + value: "17", + icon: "mdi:account-group", + color: "text-green-500", + }, + { + label: "Downloads", + value: "40k+", + imageUrl: "/api/images/hyprnote/icon.png", + color: "text-purple-500", + }, + { + label: "Discord Members", + value: "1k+", + icon: "logos:discord-icon", + color: "text-indigo-500", + }, + ]; + + return ( +
+
+
+

+ How We're Doing +

+

+ Our progress is measured by the community we're building together. +

+
+ +
+ {stats.map((stat, index) => ( + + ))}
); } -function CTASection() { +const contributions = [ + { + title: "Star Repository", + description: "Show your support and help others discover Hyprnote", + icon: "mdi:star", + link: "https://github.com/fastrepl/hyprnote", + linkText: "Star on GitHub", + }, + { + title: "Contribute Code", + description: "Fix bugs, add features, or improve documentation", + icon: "mdi:code-braces", + link: "https://github.com/fastrepl/hyprnote/contribute", + linkText: "View Issues", + }, + { + title: "Report Issues", + description: "Help us improve by reporting bugs and suggesting features", + icon: "mdi:bug", + link: "https://github.com/fastrepl/hyprnote/issues", + linkText: "Open Issue", + }, + { + title: "Help Translate", + description: "Make Hyprnote accessible in your language", + icon: "mdi:translate", + link: "https://github.com/fastrepl/hyprnote", + linkText: "Contribute Translations", + }, + { + title: "Spread the Word", + description: "Share Hyprnote with your network and community", + icon: "mdi:share-variant", + link: "https://twitter.com/intent/tweet?text=Check%20out%20Hyprnote%20-%20open%20source%20AI%20meeting%20notes%20that%20run%20locally!%20https://hyprnote.com", + linkText: "Share on X", + }, + { + title: "Join Community", + description: "Connect with other users and contributors", + icon: "mdi:forum", + link: "https://discord.gg/Hyprnote", + linkText: "Join Discord", + }, +]; + +function JoinMovementSection() { return ( -
-
-

- Privacy you can verify -

-

- Join thousands of users who trust Hyprnote because they can see - exactly how it works. Download the app or explore the source code - today. -

-
- - - Learn about Local AI - +
+
+
+

+ Be Part of the Movement +

+

+ Every contribution, no matter how small, helps build a more private + future for AI. +

+
+ +
+ {contributions.map((item, index) => { + const posInRow3 = index % 3; + const hasBorderR = posInRow3 < 2; + const hasBorderB = index < 3; + + return ( +
1 && "border-t sm:border-t-0 lg:border-t-0", + ])} + > +
+

+ {item.title} +

+

{item.description}

+
+ +
+ ); + })}