Skip to content

Astro

This guide shows how to integrate gau with Astro 7, using GitHub as an example.


  1. Complete the Getting Started guide.

    Create your auth instance in src/server/auth.ts. For a persistent database, follow the Drizzle guide.

    For GitHub, set the callback URL to http://localhost:4321/api/auth/callback/github during development.

  2. Install an Astro server adapter so auth routes can run on each request. For example, with the Node adapter:

    astro.config.mjs
    import { defineConfig } from 'astro/config'
    import node from '@astrojs/node'
    export default defineConfig({
    output: 'server',
    adapter: node({ mode: 'standalone' }),
    session: false,
    })

    Gau does not require Astro’s session storage. Omit session: false if your app otherwise uses Astro.session.

  3. Export the Astro helpers alongside your auth instance:

    src/server/auth.ts
    import { AstroAuth } from '@rttnd/gau/astro'
    // After creating your auth instance:
    export const gau = AstroAuth(auth)

    Create a catch-all route for the auth endpoints.

    src/pages/api/auth/[...gau].ts
    import { gau } from '../../../server/auth'
    export const prerender = false
    export const { GET, POST, OPTIONS } = gau
  4. Add the Gau middleware to make sessions available in Astro.locals and refresh the session cookie when needed.

    src/middleware.ts
    import { gau } from './server/auth'
    export const onRequest = gau.onRequest

    Server code can now call Astro.locals.getSession(). Use getServerSession() only when you need account tokens on the server.

    Add the locals to src/env.d.ts for full type safety:

    src/env.d.ts
    import type { GauAstroLocals } from '@rttnd/gau/astro'
    import type { auth } from './server/auth'
    declare global {
    namespace App {
    interface Locals extends GauAstroLocals<typeof auth> {}
    }
    }
  5. Read the session in your page. Use a link to sign in and a form to sign out:

    src/pages/index.astro
    ---
    const { user } = await Astro.locals.getSession()
    ---
    {user ? (
    <>
    <p>Welcome, {user.name}!</p>
    <form method="post" action="/api/auth/signout?redirectTo=/" data-astro-reload>
    <button>Sign out</button>
    </form>
    </>
    ) : (
    <a href="/api/auth/github?redirectTo=/account" data-astro-reload>
    Sign in with GitHub
    </a>
    )}
  6. Check the session before rendering the page or loading private data.

    src/pages/account.astro
    ---
    export const prerender = false
    const { user } = await Astro.locals.getSession()
    if (!user)
    return Astro.redirect('/')
    ---
    <h1>Welcome, {user.name}!</h1>

    Check the session in each endpoint or action that accesses private data too. Keep personalized pages out of shared route caches.

    • Directorysrc
      • Directoryserver
        • auth.ts
      • Directorypages
        • Directoryapi
          • Directoryauth
            • […gau].ts
        • account.astro
        • index.astro
      • env.d.ts
      • middleware.ts
    • package.json
    • astro.config.mjs

A browser client is optional. Use the vanilla client in browser scripts, or a Gau Solid or Svelte provider inside a hydrated island.

Pass the session from Astro.locals.getSession() to the island to show the signed-in state immediately.

Separate islands do not share component context. To share updates, create one vanilla client in browser code and pass it through the providers’ client prop. Never share a mutable session client between server requests.

For a retained island, pass fresh server session props after navigation. A client-side sign-out only updates subscribed components; navigate afterward to update other server-rendered content.

A prerendered page cannot read a visitor’s session at build time. Use an on-demand page for private content, or a server island for a personalized section of a public page. Read the session inside the island’s own request.