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

hylekit

v1.0.7

Published

Distributed BetterAuth library for SvelteKit and Next.js with Google OAuth and Turso

Readme

HyleKit

Distributed BetterAuth library for SvelteKit and Next.js with Google OAuth and Turso cloud database.

Note: HyleKit provides only the authentication database. You will need to provision your own separate database for storing application data.

Features

  • 🔐 Google OAuth - Simple Google login integration
  • 🌐 Distributed Auth - Each app runs auth locally, sharing a centralized Turso auth database
  • 📦 Framework Adapters - First-class support for SvelteKit and Next.js
  • 🗄️ Turso/LibSQL - Edge-friendly SQLite database for auth
  • 🔄 Session Management - Automatic session handling with cookies
  • 🚀 BFF Pattern - Built-in support for Backend-For-Frontend architecture with Express

Database Architecture

HyleKit uses a centralized authentication database that all your applications connect to. This database stores:

  • User accounts
  • Sessions
  • OAuth tokens
  • Verification tokens

You must provision two databases:

| Database | Purpose | Provided by | |----------|---------|-------------| | Hyle Auth Database | Stores users, sessions, and auth data | HyleKit (shared Turso instance) | | Your Application Database | Stores your app's business data | You (separate database) |

┌─────────────────────────────────────────────────────────────────┐
│  Your Application                                                │
├──────────────────────────────┬──────────────────────────────────┤
│  Hyle Auth Database          │  Your Application Database       │
│  (Turso - provided by Hyle)  │  (Postgres, MySQL, SQLite, etc.) │
│  ├── users                   │  ├── products                    │
│  ├── sessions                │  ├── orders                      │
│  ├── accounts                │  ├── posts                       │
│  └── verification            │  └── ... your data               │
└──────────────────────────────┴──────────────────────────────────┘

Important: Your application database can use any database technology you prefer. HyleKit does not manage or interact with your application data—only authentication.

Installation

npm install hylekit

Configuration

HyleKit uses a factory pattern - you pass configuration from your environment at initialization time. This design:

  • ✅ Keeps secrets out of client bundles
  • ✅ Throws runtime errors if factories are called on the client
  • ✅ Gives you full control over configuration

Required Environment Variables

# Turso Database
HYLE_DATABASE_URL=libsql://[db-name]-[org].turso.io
HYLE_DATABASE_AUTH_TOKEN=your-turso-token

# BetterAuth
BETTER_AUTH_URL=http://localhost:5173  # Your app's URL
BETTER_AUTH_SECRET=your-random-secret

# Google OAuth
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret

Quick Start (Recommended)

The simplest way to set up HyleKit is with the unified createHyleKit function. It automatically reads configuration from your environment variables:

// lib/auth.ts (server-side only!)
import { connectHylekit } from "hylekit";

// Next.js (automatically reads process.env)
export const { handler, getSession, isAuthenticated, getUser, makeAuthenticatedCall } = connectHylekit.nextJs();

// OR for SvelteKit (must pass env object explicitly)
// import { env } from "$env/dynamic/private";
// export const { handler, getSession, ... } = connectHylekit.svelteKit(env);

Then create your auth route handler:

// app/api/auth/[...auth]/route.ts (Next.js)
import { handler } from "@/lib/auth";

export const { GET, POST } = handler;

That's it! You now have authentication working.


Configuration

HyleKit looks for these environment variables by default:

# Database
HYLE_DATABASE_URL=...
HYLE_DATABASE_AUTH_TOKEN=...

# Auth
BETTER_AUTH_URL=...
BETTER_AUTH_SECRET=...

# Providers (Optional)
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...

To override any of these defaults, simply pass the config object to the connect function:

// Next.js
connectHylekit.nextJs({
    database: { url: "custom-url" }
});

// SvelteKit
connectHylekit.svelteKit(env, {
    database: { url: "custom-url" }
});

Advanced Setup (Granular Control)

If you need more control, you can use the individual factory functions:

// lib/auth.ts (server-side only!)
import { createDb, createAuth } from "hylekit";

export const db = createDb({
    url: process.env.HYLE_DATABASE_URL!,
    authToken: process.env.HYLE_DATABASE_AUTH_TOKEN,
});

export const auth = createAuth(db, {
    baseURL: process.env.BETTER_AUTH_URL!,
    secret: process.env.BETTER_AUTH_SECRET!,
    google: {
        clientId: process.env.GOOGLE_CLIENT_ID!,
        clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    },
});

⚠️ Security: createDb and createAuth will throw errors if called on the client side to prevent accidental secret exposure.

Architecture

HyleKit supports a BFF (Backend-For-Frontend) architecture:

┌─────────────────────────────────────────────────────────────────┐
│  Browser (Client FE)                                            │
│  └── Uses: hyle (from "hylekit/client")                         │
└─────────────────────────────────┬───────────────────────────────┘
                                  │
                                  ▼
┌─────────────────────────────────────────────────────────────────┐
│  Next.js / SvelteKit Backend (BFF)                              │
│  ├── Auth: hyle.server (getSession, handler, etc.)              │
│  └── Calls Express via: hyle.bff (BffClient)                    │
│      └── Attaches session as x-hyle-user/x-hyle-session headers │
└─────────────────────────────────┬───────────────────────────────┘
                                  │
                                  ▼
┌─────────────────────────────────────────────────────────────────┐
│  Express Backend                                                │
│  └── Uses: hyle.server.express.middleware()                     │
│      └── Parses headers → req.authUser, req.authSession         │
│      └── Optional: DB verification for service-to-service calls │
└─────────────────────────────────────────────────────────────────┘

SvelteKit Setup

1. Create Server Auth Module

Create your auth instance in a server-only module:

// src/lib/server/auth.ts
import { connectHylekit } from "hylekit";
import { env } from "$env/dynamic/private";

export const { handler, getSession, isAuthenticated, createHandle, makeAuthenticatedCall } = connectHylekit.svelteKit(env);

2. Create Auth Route Handler

// src/routes/api/auth/[...auth]/+server.ts
import { handler } from "$lib/server/auth";

export const { GET, POST } = handler;

3. Add Session Hook

// src/hooks.server.ts
import { createHandle } from "$lib/server/auth";

export const handle = createHandle();

4. Extend App.Locals Types

// src/app.d.ts
import type { SessionResult, UserInfo } from "hylekit";

declare global {
    namespace App {
        interface Locals {
            session: SessionResult;
            user: UserInfo | null;
        }
    }
}

export {};

5. Use in Pages

// src/routes/+page.server.ts
import type { PageServerLoad } from "./$types";

export const load: PageServerLoad = async ({ locals }) => {
    return { user: locals.user };
};
<!-- src/routes/+page.svelte -->
<script lang="ts">
    export let data;
</script>

{#if data.user}
    <p>Welcome, {data.user.name}!</p>
    <a href="/api/auth/sign-out">Sign out</a>
{:else}
    <a href="/api/auth/sign-in/google">Sign in with Google</a>
{/if}

Next.js Setup (App Router)

1. Create Server Auth Module

// lib/auth.ts (server-side only!)
import { connectHylekit } from "hylekit";

export const { handler, getSession, isAuthenticated, getUser, makeAuthenticatedCall } = connectHylekit.nextJs();

2. Create Auth Route Handler

// app/api/auth/[...auth]/route.ts
import { handler } from "@/lib/auth";

export const { GET, POST } = handler;

3. Use in Server Components

// app/page.tsx
import { getSession } from "@/lib/auth";

export default async function Page() {
    const session = await getSession();
    
    if (!session) {
        return <a href="/api/auth/sign-in/google">Sign in with Google</a>;
    }
    
    return (
        <div>
            <p>Welcome, {session.user.name}!</p>
            <a href="/api/auth/sign-out">Sign out</a>
        </div>
    );
}

4. Protected Routes

// app/dashboard/page.tsx
import { isAuthenticated, getUser } from "@/lib/auth";
import { redirect } from "next/navigation";

export default async function DashboardPage() {
    if (!(await isAuthenticated())) {
        redirect("/api/auth/sign-in/google");
    }
    
    const user = await getUser();
    return <p>Dashboard for {user?.name}</p>;
}

BFF Pattern with Express

1. Setup Express Middleware

// express-app/src/app.ts
import express from "express";
import { createDb, createExpressMiddleware } from "hylekit";

const app = express();

// Option 1: Trust headers from BFF (no DB needed)
app.use(createExpressMiddleware()({
    unauthenticatedRoutes: ["/health", "/public/*"],
}));

// Option 2: Verify sessions against DB (for service-to-service calls)
const db = createDb({
    url: process.env.HYLE_DATABASE_URL!,
    authToken: process.env.HYLE_DATABASE_AUTH_TOKEN,
});

app.use(createExpressMiddleware(db)({
    unauthenticatedRoutes: ["/health", "/public/*"],
    verifySession: true,  // Checks session in Turso DB
}));

2. Access Auth Context in Routes

Use req.authUser and req.authSession in your route handlers:

import type { AuthenticatedRequest } from "hylekit";

app.get("/api/profile", (req: AuthenticatedRequest, res) => {
    // authUser is always available on authenticated routes
    res.json({
        userId: req.authUser.id,
        email: req.authUser.email,
        name: req.authUser.name,
    });
});

app.post("/api/settings", (req: AuthenticatedRequest, res) => {
    // Access full session data
    console.log("Session expires:", req.authSession.expiresAt);
    
    // Your business logic here
    res.json({ success: true });
});

3. Using Helper Functions

import { isAuthenticated, getAuthContext } from "hylekit";

// Type guard for optional auth routes
app.get("/api/greeting", (req, res) => {
    if (isAuthenticated(req)) {
        res.json({ message: `Hello, ${req.authUser.name}!` });
    } else {
        res.json({ message: "Hello, guest!" });
    }
});

// Get auth context with error handling
app.post("/api/order", (req, res) => {
    try {
        const { user, session } = getAuthContext(req);
        // Proceed with authenticated user
    } catch (e) {
        res.status(401).json({ error: "Not authenticated" });
    }
});

4. Call Express from Next.js/SvelteKit

Use the BFF client to make authenticated calls from your frontend backend:

// Next.js: lib/bff.ts
import { createNextJsBff } from "hylekit";
import { auth } from "./auth";  // Your auth instance from step 1

export const bff = createNextJsBff(auth, process.env.EXPRESS_API_URL!);

// Usage in app/api/data/route.ts
import { bff } from "@/lib/bff";

export async function GET() {
    const data = await bff.get("/api/profile");
    return Response.json(data);
}
// SvelteKit: src/routes/api/data/+server.ts
import { createSvelteKitBff } from "hylekit";
import type { RequestHandler } from "./$types";

const bff = createSvelteKitBff(process.env.EXPRESS_API_URL!);

export const GET: RequestHandler = async (event) => {
    // Use .with(event) to bind the request context
    const data = await bff.with(event).get("/api/profile");
    return new Response(JSON.stringify(data));
};

Middleware Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | unauthenticatedRoutes | string[] | [] | Routes that skip authentication | | verifySession | boolean | false | Verify session against DB (for service-to-service) | | required | boolean | true | Return 401 for unauthenticated requests |

Route Pattern Examples

unauthenticatedRoutes: [
    "/health",           // Exact match
    "/public/*",         // Matches /public/anything (single level)
    "/api/webhooks/**",  // Matches /api/webhooks/a/b/c (deep)
]

Database Schema

HyleKit uses Drizzle ORM. You can import the schema definitions for use with Drizzle Kit or migration tools.

// Import all schema definitions
import hyle from "hylekit";

const { user, session, account, verification } = hyle.schema;

API Reference

The library exports a default hyle object containing:

hyle.server (Server-Only)

hylekit/sveltekit

  • handler: { GET, POST } route handlers.
  • createHandle(): Creates a SvelteKit handle hook.
  • getSession(event): Get session from request event.
  • isAuthenticated(event): Check if user is authenticated.
  • makeAuthenticatedCall(fn): Wrapper to ensure authentication.

hylekit/nextjs

  • handler: { GET, POST } route handlers.
  • getSession(): Get session from current request headers.
  • isAuthenticated(): Check if user is authenticated.
  • getUser(): Get current user object.
  • makeAuthenticatedCall(fn): Wrapper to ensure authentication.

hylekit/server/express (or hylekit)

  • middleware(options): Express middleware for session verification.
  • isAuthenticated(req): Type guard to check if request is authenticated.
  • getAuthContext(req): Get { user, session } from request (throws if not authenticated).

Client-Only (hylekit/client)

import hyle from "hylekit/client";

// Next.js
hyle.nextjs.useSession();
hyle.nextjs.signIn.social({ provider: "google" });

// SvelteKit
hyle.sveltekit.signIn.social({ provider: "google" });

hyle.sveltekit

  • login: Alias for signIn.
  • All better-auth/svelte client methods.

hyle.nextjs

  • login: Alias for signIn.
  • All better-auth/react client methods.

hyle.bff

hyle.bff.createNextJsBff(config)

Creates a BFF client for Next.js that automatically attaches session headers.

hyle.bff.createSvelteKitBff(config)

Creates a BFF client for SvelteKit that automatically attaches session headers.

Types

import type {
    SessionResult,
    SessionData,
    UserInfo,
    Session,
    User,
    BffClientConfig,
    RequestOptions,
    AuthenticatedRequest,
    MiddlewareOptions,
} from "hylekit";

License

ISC