> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nuabase.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Frontend Integration

> Securely call LLMs directly from your browser application

Nuabase is designed to let your frontend application call LLMs directly, without routing every request through your own backend API. This reduces latency and server load while keeping your API keys secure.

## Architecture

Instead of exposing your `API_KEY` to the browser (which is insecure), you use a **Short-lived Access Token**.

1. **Login**: User logs into your app as usual.
2. **Token Request**: Your frontend requests a Nuabase Token from your backend.
3. **Sign**: Your backend uses your **Signing Key Secret** to generate a JWT for that specific user.
4. **Call**: Your frontend uses this token to initialize the Nuabase SDK and make requests.

## Step 1: Backend - Generate Tokens

You need to expose an endpoint (e.g., `POST /api/nuabase-token`) that returns a token for the currently authenticated user.

<CodeGroup>
  ```ruby Ruby (Rails) theme={null}
  # Gemfile
  # gem 'nuabase'

  class NuabaseController < ApplicationController
    before_action :authenticate_user!

    def token
      # Initialize the generator with your secret and the user's ID
      generator = Nuabase::NuaTokenGenerator.new(
        signing_key_secret: ENV['NUABASE_SIGNING_KEY_SECRET'],
        user_id: current_user.id.to_s
      )

      # Generate the token (valid for 3 minutes by default)
      render json: generator.generate
    end
  end
  ```

  ```typescript TypeScript (Node.js) theme={null}
  // Using nuabase-server-sdk (pseudocode example)
  import { NuaTokenGenerator } from 'nuabase-server';

  app.post('/api/nuabase-token', requireAuth, async (req, res) => {
    const generator = new NuaTokenGenerator({
      signingKeySecret: process.env.NUABASE_SIGNING_KEY_SECRET,
      userId: req.user.id
    });

    const token = await generator.generate();
    res.json(token);
  });
  ```
</CodeGroup>

<Warning>
  Never expose your `NUABASE_SIGNING_KEY_SECRET` to the client. It must only be used on your server.
</Warning>

## Step 2: Frontend - Initialize SDK

In your frontend application, you initialize the `Nua` client by providing a `fetchToken` function. This function is called automatically whenever the SDK needs a fresh token.

```typescript theme={null}
import { Nua } from 'nuabase';
import { z } from 'zod';

const nua = new Nua({
  // The SDK calls this to get a valid token
  fetchToken: async () => {
    const response = await fetch('/api/nuabase-token', {
      method: 'POST',
      // Include your app's auth headers if needed
      headers: { 'Content-Type': 'application/json' }
    });
    
    if (!response.ok) throw new Error('Failed to fetch token');
    
    const data = await response.json();
    return data.access_token;
  }
});
```

## Step 3: Make Requests

Once initialized, you can define and call functions just like in the server-side workflow.

```typescript theme={null}
const SuggestReply = z.object({
  text: z.string(),
  tone: z.enum(['Professional', 'Casual'])
});

const suggestReply = nua.createFn({
  prompt: "Draft a reply to this email.",
  output: { name: "reply", schema: SuggestReply }
});

// Usage in a Component
async function handleReply() {
  const result = await suggestReply(emailContent);
  if (result.isSuccess) {
    setDraft(result.data.text);
  }
}
```

## Security & abuse prevention

Since requests come directly from the client, Nuabase uses the `userId` embedded in the token to enforce limits.

* **Budgets**: Set a maximum monthly spend per user.
* **Rate Limits**: Limit the number of requests per minute per user.

You can configure these limits in the [Nuabase Console](https://console.nuabase.com).
