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

# Elysia

> Integrate Nile Auth with Elysia applications

This guide will help you get started with Nile Auth and ElysiaJS. This guide outlines the steps required to configure and integrate authentication in your
application.

<Note>
  If you have not done so yet, be sure you have [obtained credentials from the
  console](../getting-started/installation).
</Note>

<Steps>
  <Step title="Install packages">
    <CodeGroup>
      ```bash bun theme={null}
        bun add @niledatabase/server @niledatabase/elysia elysia
      ```
    </CodeGroup>
  </Step>

  <Step title="Configure the extension">
    The simplest way to use Nile with Elysia is to register the plugin. This will automatically mount Nile's default API routes ([authentication](/reference/api/auth), [tenant management](/reference/api/tenants), etc.) onto your Elysia application.

    ```typescript app.ts theme={null}
    import { Elysia } from 'elysia';
    import { Nile } from '@niledatabase/server';
    import { nilePlugin } from '@niledatabase/elysia';

    // Initialize the Nile Server
    const nile = Nile({
      debug: true,
      // ... configuration options
    });

    const app = new Elysia().use(nilePlugin(nile));

    // The plugin has now registered routes like:
    // POST /api/auth/signin
    // POST /api/auth/signup
    // GET  /api/auth/session
    // ...and more

    app.listen(3000);

    console.log(
      `🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`,
    );
    ```
  </Step>
</Steps>

## Accessing the Nile Instance

The `nilePlugin` automatically decorates the Elysia context with your `nile` server instance. This allows you to access it directly in your handlers for database queries or custom auth logic.

```typescript theme={null}
app.get('/my-data', async ({ nile, request, error }) => {
  // 1. You can access the configured nile instance directly
  const headers = new Headers(request.headers);
  const tenantId = request.headers.get('X-Tenant-Id') || undefined;

  // 2. Use nile.withContext to ensure isolation
  return await nile.withContext({ headers, tenantId }, async (nileCtx) => {
    // This query will automatically apply the tenantId for the tenant-aware table
    const result = await nileCtx.db.query('SELECT * FROM my_table');
    return result.rows;
  });
});
```

## Deriving the User

For a more idiomatic Elysia experience, you can create a derivation that extracts the authenticated user from the context.

```typescript theme={null}
const authApp = app.derive(async ({ nile, request }) => {
  const headers = new Headers(request.headers);
  // Use the decorated nile instance to fetch the session
  const user = await nile.withContext({ headers }, async (nileCtx) => {
    return await nileCtx.auth.getSession();
  });

  return { user };
});

authApp.get('/profile', ({ user, error }) => {
  if (!user) {
    return error(401, 'Not Authenticated');
  }
  return user;
});
```

## Custom Auth Helpers

You can extend the derivation pattern to expose helper methods that automatically handle context, making your handlers cleaner.

```typescript theme={null}
// Create a plugin that derives the user and auth helpers for every request
const authPlugin = (app: Elysia) =>
  app.derive(async ({ nile, request }) => {
    // 1. Create headers from the incoming request to propagate cookies/auth
    const headers = new Headers(request.headers);

    // 2. Use the decorated nile instance to get the session
    const user = await nile.withContext({ headers }, async (nileCtx) => {
      return await nileCtx.auth.getSession();
    });

    return {
      Auth: {
        user,
        // Wrap SDK methods to automatically provide context
        signUp: async (email: string, password: string) => {
          return nile.withContext({ headers }, (c) =>
            c.auth.signUp({ email, password }),
          );
        },
        signIn: async (email: string, password: string) => {
          return nile.withContext({ headers }, (c) =>
            c.auth.signIn('credentials', { email, password }),
          );
        },
      },
    };
  });
```

Now you can use the plugin in your application and access `Auth.user` and methods directly.

```typescript theme={null}
app
  .use(authPlugin)
  .get('/profile', ({ Auth: { user }, error }) => {
    if (!user) {
      return error(401, 'Not Authenticated');
    }
    return user;
  })
  .post('/register', async ({ Auth, body }) => {
    const { email, password } = body as any;
    return await Auth.signUp(email, password);
  });
```

## The Plugin

Under the hood, the elysia plugin does the following:

1. **Registers Routes**: Maps Nile's internal route handlers to Elysia's router (e.g. `app.get`, `app.post`), exposing the full API.
2. **Decorates Context**: Adds the `nile` server instance to the Elysia context (`ctx.nile`), making it available in all downstream handlers and plugins.
3. **Context Isolation**: For the routes it registers, it wraps execution in `nile.withContext` to ensure tenant isolation and proper authentication handling.

### Handlers and paths

The plugin iterates over the configured paths in the Nile Server SDK and registers them directly with your Elysia app instance. This ensures that all standard [authentication](/reference/api/auth) and [tenant management](/reference/api/tenants) routes are available without manual configuration.
