# Front-End Frameworks Used in Karakeep: Next.js 16, React Native, and Expo

> Explore the front-end frameworks powering Karakeep: Next.js 16 for web, React Native with Expo for mobile, and React 19 for browser extensions. Discover our unified tech stack.

- Repository: [Karakeep App/karakeep](https://github.com/karakeep-app/karakeep)
- Tags: architecture
- Published: 2026-07-07

---

**Karakeep uses Next.js 16 for the web application, React Native with Expo for mobile devices, and React 19 for the browser extension, all unified by a shared React component library built on Tailwind CSS, Shadcn UI, and Radix UI primitives.**

The open-source bookmarking application **Karakeep** (formerly Hoarder) maintains a consistent React-centric architecture across all client platforms. Understanding the front-end frameworks used in Karakeep reveals how the project delivers a unified experience across web, mobile, and browser extension environments while maximizing code reuse through the `@karakeep/shared-react` package.

## Web Application: Next.js 16 with React 19

The Karakeep web client resides in `apps/web/` and runs on **Next.js 16**, a React-based server-rendered framework. According to [`apps/web/package.json`](https://github.com/karakeep-app/karakeep/blob/main/apps/web/package.json), the project declares `next`, `react`, and `react-dom` as core dependencies, confirming the Next.js architecture alongside **React 19**.

The implementation uses the **Pages Router** convention, as evidenced by file paths like [`apps/web/pages/index.tsx`](https://github.com/karakeep-app/karakeep/blob/main/apps/web/pages/index.tsx). The stack includes **Tailwind CSS** for styling, **Shadcn UI** for pre-built components, and **Radix UI** for accessible primitives. Data fetching relies on a **tRPC client** paired with **React Query** for type-safe server communication.

```tsx
// apps/web/pages/index.tsx
import { NextPage } from "next";
import Head from "next/head";

const Home: NextPage = () => (
  <main className="flex min-h-screen flex-col items-center justify-center bg-gray-50">
    <Head>
      <title>Karakeep – Read‑it‑later</title>
    </Head>
    <h1 className="text-4xl font-bold">Welcome to Karakeep</h1>
    <p className="mt-4 text-lg">Your bookmarks, everywhere.</p>
  </main>
);

export default Home;

```

This entry point demonstrates the Next.js Pages Router pattern, React component structure, and Tailwind utility classes (`className`) that define the styling system.

## Mobile Application: React Native with Expo

For iOS and Android, Karakeep leverages **React Native** running inside the **Expo** ecosystem. The [`apps/mobile/package.json`](https://github.com/karakeep-app/karakeep/blob/main/apps/mobile/package.json) manifest lists `react-native`, `expo`, and `expo-router` as primary dependencies, establishing the standard React Native + Expo stack.

The mobile app uses **NativeWind** to bring Tailwind CSS classes to React Native components, allowing shared styling logic with the web platform. Navigation relies on **Expo Router** using file-based routing in `apps/mobile/app/`, while UI primitives come from **Radix UI** via the `@rn-primitives` package.

```tsx
// apps/mobile/app/(home)/index.tsx
import { Text, View } from "react-native";
import { Link } from "expo-router";
import { cn } from "@karakeep/shared-react/utils"; // Tailwind merge helper

export default function HomeScreen() {
  return (
    <View className={cn("flex-1 items-center justify-center bg-white")}>
      <Text className="text-2xl font-bold">Karakeep Mobile</Text>
      <Link href="/bookmarks" className="mt-4 text-blue-600">
        View Bookmarks
      </Link>
    </View>
  );
}

```

This screen uses React Native core components (`View`, `Text`), Expo Router's `Link` component for navigation, and the `cn` utility from the shared package to handle Tailwind class merging via NativeWind.

## Browser Extension: React 19 with Vite

The browser extension located in `apps/browser-extension/` uses **React 19** bundled with **Vite** (or webpack). Unlike the web app, it does not use Next.js, but it imports the same **Shadcn UI** and **Radix UI** components from the shared library, ensuring visual consistency with the main web application.

## Shared UI Architecture: Tailwind, Shadcn UI, and Radix

Both web and mobile applications import components from `@karakeep/shared-react`, a centralized package that houses the design system. This package integrates **Tailwind CSS** (via `tailwind-merge`), **Shadcn UI** components, and **Radix UI** primitives.

The [`apps/web/components.json`](https://github.com/karakeep-app/karakeep/blob/main/apps/web/components.json) file confirms the Shadcn UI configuration schema, while [`packages/shared-react/components/ui/button.tsx`](https://github.com/karakeep-app/karakeep/blob/main/packages/shared-react/components/ui/button.tsx) demonstrates how base components wrap Radix primitives with Tailwind styling.

```tsx
// packages/shared-react/components/ui/button.tsx
import * as React from "react";
import * as ButtonPrimitive from "@radix-ui/react-button";
import { cn } from "@/utils";

export const Button = React.forwardRef<
  React.ElementRef<typeof ButtonPrimitive.Root>,
  React.ComponentPropsWithoutRef<typeof ButtonPrimitive.Root>
>(({ className, ...props }, ref) => (
  <ButtonPrimitive.Root
    ref={ref}
    className={cn("inline-flex items-center rounded-md px-4 py-2", className)}
    {...props}
  />
));
Button.displayName = "Button";

```

Both the Next.js web app and React Native mobile app consume this component, gaining a consistent look-and-feel across platforms while the implementation details remain framework-agnostic.

## Summary

- **Next.js 16** powers the web application in `apps/web/`, using React 19 and the Pages Router structure.
- **React Native with Expo** drives the mobile experience in `apps/mobile/`, utilizing Expo Router for navigation.
- **React 19** runs the browser extension via Vite, sharing UI components with the web platform.
- A shared `@karakeep/shared-react` package provides **Tailwind CSS**, **Shadcn UI**, and **Radix UI** components across all front-ends.
- **NativeWind** enables Tailwind-style utility classes in the React Native mobile environment.

## Frequently Asked Questions

### Does Karakeep use Next.js App Router or Pages Router?

Based on the source code structure, Karakeep uses the **Pages Router** convention, as evidenced by the `apps/web/pages/` directory structure. The example entry point at [`apps/web/pages/index.tsx`](https://github.com/karakeep-app/karakeep/blob/main/apps/web/pages/index.tsx) follows the traditional Next.js pages pattern rather than the newer app directory structure.

### How does Karakeep share UI components between web and mobile platforms?

Karakeep maintains a **shared component library** in `packages/shared-react/` that exports UI primitives built on React and Tailwind CSS. Both the Next.js web app and the React Native mobile app import these components, with the mobile layer using NativeWind to interpret Tailwind classes in the native environment.

### What is the role of Expo in the Karakeep mobile app?

**Expo** provides the build tooling, development environment, and runtime services for the React Native application. Specifically, `expo-router` handles navigation using file-based routing in `apps/mobile/app/`, while the Expo SDK supplies native modules for device capabilities. The [`apps/mobile/package.json`](https://github.com/karakeep-app/karakeep/blob/main/apps/mobile/package.json) confirms this dependency stack.

### Is the browser extension built with Next.js?

No, the browser extension uses **React 19** directly, bundled with Vite or webpack rather than Next.js. However, it imports the same **Shadcn UI** and **Radix UI** components from the shared package, ensuring UI consistency with the main web application without the overhead of the Next.js framework.