The resource library lists titles on a public page. `GET /api/files` returns the files only after `requireAuth`.

Clone [starters/gatsby](https://github.com/authdog/samples/tree/main/starters/gatsby). SDK reference: [Gatsby](/docs/frameworks/gatsby).

`initAuthdog()` stores the browser token after a shape check. `requireAuth` is the identity gate. It does not grant a permission. Apply [authorization](/docs/concepts/authorization) inside the guarded function.

## What you need

| Requirement | Detail |
| --- | --- |
| Public key | `pk_...` from the [console](https://console.authdog.com) |
| Environment | Copy `.env.example` to `.env`. Set `PK_AUTHDOG` for Functions and `GATSBY_AUTHDOG_PUBLIC_KEY` for the browser |
| Secret key | Never put `sk_...` in client code |
| Return URL | Account portal back to this site. Local: `http://localhost:8000` |

## Run

```bash
npm install
npm run develop
```

Open http://localhost:8000. The page lists Q3 board pack and Runbook: payments. **Load files** calls `GET /api/files`. Without a session that returns 401. With a valid `authdog-session` cookie or `Authorization: Bearer` token, it returns those two files and the user from userinfo.

## Browser callback

```js
// gatsby-browser.js
import React, { useEffect } from "react"
import { initAuthdog } from "@authdog/gatsby/client"

function AuthdogBootstrap({ children }) {
  useEffect(() => {
    initAuthdog()
  }, [])
  return children
}

export const wrapRootElement = ({ element }) => {
  return <AuthdogBootstrap>{element}</AuthdogBootstrap>
}
```

## Files

```ts
// src/api/files.ts
import { createAuthdog } from "@authdog/gatsby/server"

const authdog = createAuthdog({ publicKey: process.env.PK_AUTHDOG! })

const FILES = [
  { id: "file_q3", title: "Q3 board pack", kind: "pdf" },
  { id: "file_run", title: "Runbook: payments", kind: "md" },
]

export default authdog.requireAuth(async (req, res) => {
  res.status(200).json({
    user: req.authdog?.user ?? null,
    files: FILES,
  })
})
```

Treat `requireAuth` as the security boundary. Pair logout with `clearAuthdogToken()` in the browser when the flow keeps a bearer in local storage.
