npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@appwrite.io/react

v0.1.0-rc.3

Published

[![Discord](https://img.shields.io/discord/564160730845151244?label=discord&style=flat-square)](https://appwrite.io/discord)

Readme

Appwrite React SDK

Discord

Appwrite is an open-source backend as a service that abstracts common application features behind simple APIs. The Appwrite React SDK provides React hooks and framework adapters for Appwrite authentication in client-rendered and server-rendered React apps.

Appwrite

Features

  • React provider and hooks for sign-up, sign-in, sign-out, OAuth, and current user state
  • Client-side auth for Vite and other non-SSR React apps
  • SSR auth handlers for Next.js and TanStack Start
  • Server helpers for reading the current user/session from HTTP-only cookies
  • Server-context session clients and admin clients

Installation

For client-rendered React apps:

pnpm add @appwrite.io/react appwrite @tanstack/react-query

For SSR apps that use the server handlers or admin client, also install node-appwrite:

pnpm add @appwrite.io/react appwrite node-appwrite @tanstack/react-query

Framework packages such as next, @tanstack/react-start, react, and react-dom should come from your app scaffold.

Non-SSR React Apps

Use this setup for Vite or any app where auth is handled directly in the browser.

import { AppwriteProvider } from "@appwrite.io/react";

export function Root() {
  return (
    <AppwriteProvider
      endpoint={import.meta.env.VITE_APPWRITE_ENDPOINT}
      projectId={import.meta.env.VITE_APPWRITE_PROJECT_ID}
    >
      <App />
    </AppwriteProvider>
  );
}

Then, for authentication:

import { useAuth } from "@appwrite.io/react";

export function AuthPanel() {
  const { user, isLoading, signIn, signUp, signOut } = useAuth();

  if (isLoading) return <p>Loading...</p>;

  if (!user) {
    return (
      <>
        <button
          onClick={() =>
            signIn.emailPassword({
              email: "[email protected]",
              password: "password123",
            })
          }
        >
          Sign in
        </button>
        <button
          onClick={() =>
            signUp.emailPassword({
              email: "[email protected]",
              password: "password123",
              name: "Jane Doe",
            })
          }
        >
          Sign up
        </button>
      </>
    );
  }

  return (
    <>
      <p>Signed in as {user.email}</p>
      <button onClick={() => signOut.signOut()}>Sign out</button>
    </>
  );
}

Next.js App Router SSR

Set public Appwrite values and keep only the API key private:

NEXT_PUBLIC_APPWRITE_ENDPOINT=https://fra.cloud.appwrite.io/v1
NEXT_PUBLIC_APPWRITE_PROJECT_ID=PROJECT_ID
APPWRITE_API_KEY=SERVER_ONLY_API_KEY

Create the Appwrite auth handler route:

// app/api/appwrite/[...appwrite]/route.ts
import { createAppwriteHandlers } from "@appwrite.io/react/handlers/next";

export const { GET, POST } = createAppwriteHandlers({
  endpoint: process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!,
  projectId: process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!,
  apiKey: process.env.APPWRITE_API_KEY!,
  basePath: "/api/appwrite",
});

Pass the server session into the client provider:

// app/providers.tsx
"use client";

import { AppwriteProvider } from "@appwrite.io/react";

export function Providers({
  session,
  children,
}: {
  session?: string | null;
  children: React.ReactNode;
}) {
  return (
    <AppwriteProvider
      endpoint={process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!}
      projectId={process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!}
      ssr={{ session, basePath: "/api/appwrite" }}
    >
      {children}
    </AppwriteProvider>
  );
}
// app/layout.tsx
import { createNextServerHelpers } from "@appwrite.io/react/server/next";
import { Providers } from "./providers";

const appwrite = {
  endpoint: process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!,
  projectId: process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!,
};

export default async function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const helpers = createNextServerHelpers(appwrite);
  const session = await helpers.readSessionCookie();

  return (
    <html lang="en">
      <body>
        <Providers session={session}>{children}</Providers>
      </body>
    </html>
  );
}

Read SSR auth state and create server-context clients:

// app/page.tsx
import { createNextServerHelpers } from "@appwrite.io/react/server/next";

const appwrite = {
  endpoint: process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!,
  projectId: process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!,
  apiKey: process.env.APPWRITE_API_KEY!,
};

export default async function Page() {
  const helpers = createNextServerHelpers(appwrite);

  const user = await helpers.getLoggedInUser();
  const sessionClient = await helpers.createSessionClient();
  const adminClient = helpers.createAdminClient();
  const users = await adminClient.users.list({ total: false });

  return (
    <main>
      <p>SSR user: {user?.email ?? "signed out"}</p>
      <p>Session client: {sessionClient ? "available" : "none"}</p>
      <p>Admin users loaded: {users.users.length}</p>
    </main>
  );
}

In client components, use the same hooks. Refresh the router after auth mutations when server-rendered state should update.

// app/auth-panel.tsx
"use client";

import { useAuth } from "@appwrite.io/react";
import { useRouter } from "next/navigation";

export function AuthPanel() {
  const { user, isLoading, signIn, signOut } = useAuth();
  const router = useRouter();

  if (isLoading) return <p>Loading...</p>;

  if (!user) {
    return (
      <button
        onClick={() =>
          signIn.emailPassword({
            email: "[email protected]",
            password: "password123",
            onSuccess: () => router.refresh(),
          })
        }
      >
        Sign in
      </button>
    );
  }

  return (
    <button
      onClick={() => signOut.signOut({ onSuccess: () => router.refresh() })}
    >
      Sign out
    </button>
  );
}

TanStack Start SSR

Set public Appwrite values and keep only the API key private:

VITE_APPWRITE_ENDPOINT=https://fra.cloud.appwrite.io/v1
VITE_APPWRITE_PROJECT_ID=PROJECT_ID
APPWRITE_API_KEY=SERVER_ONLY_API_KEY

Create the Appwrite auth handler route:

// src/routes/api/appwrite/$.ts
import { createFileRoute } from "@tanstack/react-router";
import { createAppwriteHandlers } from "@appwrite.io/react/handlers/tanstack";

export const Route = createFileRoute("/api/appwrite/$")({
  server: {
    handlers: createAppwriteHandlers({
      endpoint: import.meta.env.VITE_APPWRITE_ENDPOINT,
      projectId: import.meta.env.VITE_APPWRITE_PROJECT_ID,
      apiKey: process.env.APPWRITE_API_KEY!,
      basePath: "/api/appwrite",
    }),
  },
});

Read SSR auth state in a server function and pass the session into the provider:

// src/routes/index.tsx
import { createFileRoute, useRouter } from "@tanstack/react-router";
import { createServerFn } from "@tanstack/react-start";
import { AppwriteProvider, useAuth } from "@appwrite.io/react";
import { createTanStackServerHelpers } from "@appwrite.io/react/server/tanstack";

const getAuthSnapshot = createServerFn({ method: "GET" }).handler(async () => {
  const appwrite = {
    endpoint: import.meta.env.VITE_APPWRITE_ENDPOINT,
    projectId: import.meta.env.VITE_APPWRITE_PROJECT_ID,
    apiKey: process.env.APPWRITE_API_KEY!,
  };

  const helpers = createTanStackServerHelpers(appwrite);
  const user = await helpers.getLoggedInUser();
  const sessionClient = await helpers.createSessionClient();
  const adminClient = helpers.createAdminClient();
  const users = await adminClient.users.list({ total: false });

  return {
    session: helpers.readSessionCookie() ?? null,
    user,
    hasSessionClient: Boolean(sessionClient),
    adminUserCount: users.users.length,
  };
});

export const Route = createFileRoute("/")({
  loader: () => getAuthSnapshot(),
  component: Page,
});

function Page() {
  const { session, user, hasSessionClient, adminUserCount } = Route.useLoaderData();

  return (
    <AppwriteProvider
      endpoint={import.meta.env.VITE_APPWRITE_ENDPOINT}
      projectId={import.meta.env.VITE_APPWRITE_PROJECT_ID}
      ssr={{ session, basePath: "/api/appwrite" }}
    >
      <main>
        <p>SSR user: {user?.email ?? "signed out"}</p>
        <p>Session client: {hasSessionClient ? "available" : "none"}</p>
        <p>Admin users loaded: {adminUserCount}</p>
        <AuthPanel />
      </main>
    </AppwriteProvider>
  );
}

function AuthPanel() {
  const { user, isLoading, signIn, signOut } = useAuth();
  const router = useRouter();

  if (isLoading) return <p>Loading...</p>;

  if (!user) {
    return (
      <button
        onClick={() =>
          signIn.emailPassword({
            email: "[email protected]",
            password: "password123",
            onSuccess: () => router.invalidate(),
          })
        }
      >
        Sign in
      </button>
    );
  }

  return (
    <button
      onClick={() => signOut.signOut({ onSuccess: () => router.invalidate() })}
    >
      Sign out
    </button>
  );
}

API Overview

Client entrypoint:

import {
  AppwriteProvider,
  OAuthProvider,
  useAuth,
  useSignIn,
  useSignOut,
  useSignUp,
  useUser,
} from "@appwrite.io/react";

Server entrypoints:

import { createAppwriteHandlers as createNextAppwriteHandlers } from "@appwrite.io/react/handlers/next";
import { createAppwriteHandlers as createTanStackAppwriteHandlers } from "@appwrite.io/react/handlers/tanstack";

import {
  createAdminClient,
  createSessionClient,
} from "@appwrite.io/react/server";
import { createNextServerHelpers } from "@appwrite.io/react/server/next";
import { createTanStackServerHelpers } from "@appwrite.io/react/server/tanstack";

Do not import server entrypoints from client components or browser-only code.

Learn More

License

Please see the MIT license file for more information.