# Your first table

> Add a working users table to an existing Laravel and Inertia application.

Source: https://docs.inertiax.dev/table/quick-start/

After [installation](https://docs.inertiax.dev/table/installation/), three steps add a users page. Two optional changes then show more of what a table can do. The example uses Laravel’s React starter kit, its `User` model and an account you can sign in with; in another app, keep your own page names and layout.

## 1. Define the table

**Laravel**

app/Http/Controllers/UserController.php

```php
<?php

namespace App\Http\Controllers;

use App\Models\User;
use Inertia\Inertia;
use Inertia\Response;
use InertiaX\Table\Columns\NumberColumn;
use InertiaX\Table\Columns\TextColumn;
use InertiaX\Table\Table;

class UserController
{
    public function index(): Response
    {
        return Inertia::render('users/index', [
            Table::make('users')
                ->data(User::class)
                ->addColumns([
                    NumberColumn::make('id')->numberCast('int')->visible(false),
                    TextColumn::make('name')->searchable()->sortable(),
                    TextColumn::make('email'),
                ]),
        ]);
    }
}
```

The `id` column identifies each row; `visible(false)` hides it.

## 2. Render the table

Create the page for `users/index`. The starter kit’s layout wraps it, and the highlighted lines are the InertiaX part:

**React**

resources/js/pages/users/index.tsx

```tsx
import { Head } from '@inertiajs/react';
import { AppTable } from '@/components/app-table';

export default function UsersIndex() {
    return (
        <>
            <Head title="Users" />
            <section className="m-4 rounded-xl border p-6">
                <h1 className="text-lg font-semibold">Users</h1>
                <p className="mb-4 text-sm text-muted-foreground">
                    Everyone who can sign in.
                </p>
                <AppTable prop="users" />
            </section>
        </>
    );
}
```

## 3. Add the route

Add it to the starter kit’s group for signed-in users:

**Laravel**

routes/web.php

```php
use App\Http\Controllers\UserController;

Route::middleware(['auth', 'verified'])->group(function () {
    // ...
    Route::get('users', [UserController::class, 'index'])->name('users.index');
});
```

## See it work

That’s the whole table. A new app may have only your own account, so add some users first:

```sh
php artisan tinker --execute="App\Models\User::factory(30)->create()"
```

Sign in and open `/users`: their names and email addresses appear in a styled table. Search for part of a name, click the **Name** heading to sort, and page through the rows.

## Try more (optional)

Each change below edits only `UserController`; the React page stays as it is.

### Add a filter

Make the email column filterable:

**Laravel**

```php
->addColumns([
    NumberColumn::make('id')->numberCast('int')->visible(false),
    TextColumn::make('name')->searchable()->sortable(),
    TextColumn::make('email')->filterable(),
]),
```

Automatic filters are on by default, so a filterable column gets a filter with comparisons for its type. Reload `/users` and click the new **Filter** button: choose **Email**, change **Equals** to **Ends With**, enter `example.org` and click **Add filter**. The rows narrow to those addresses, and the filter stays in the URL, so a reload or a shared link keeps it.

### Or let InertiaX infer the columns and filters

In `UserController`, replace the `return` statement in `index()` with this one, which infers the columns from the `User` model; the `NumberColumn` and `TextColumn` imports are then unused. Inferred columns aren’t searchable, sortable or filterable until the table turns that on:

**Laravel**

```php
return Inertia::render('users/index', [
    Table::make('users')
        ->data(User::class)
        ->autoColumns()
        ->searchableColumns()
        ->sortableColumns()
        ->filterableColumns(),
]);
```

Reload `/users`. If you searched or filtered earlier, the URL keeps it: clear the search box and click **Clear filters** to see every user. The table now shows every field the model serializes, such as **Email Verified At** and **Created At**, without `$hidden` fields such as the password. Text columns are searchable, and every column you see sorts and has a filter for its type.

A column that can be null also gets **Is empty**. The factory users are all verified, so add one that isn’t:

```sh
php artisan tinker --execute="App\Models\User::factory()->unverified()->create()"
```

Then filter **Email Verified At** by **Is empty** to find it.

Inference shows whatever the model serializes, so review those fields before you ship the page; see [Choose fields deliberately](https://docs.inertiax.dev/table/guide/security/#choose-fields-deliberately). To leave a field out or customize one, see [Infer columns from a model](https://docs.inertiax.dev/table/guide/columns/#infer-columns-from-a-model).

## Next steps

Choose what your page needs next:

- Show a related record’s field, such as an order’s customer name, or count related rows: [Show a related field](https://docs.inertiax.dev/table/guide/columns/#show-a-related-field).
- Use the same table on another page: [Reuse a table class](https://docs.inertiax.dev/table/guide/tables/#reuse-a-table-class).
- Link a cell to its record: [Link to a record](https://docs.inertiax.dev/table/guide/custom-columns/#link-to-a-record).
- Show the rows as cards: [Custom layouts](https://docs.inertiax.dev/table/guide/custom-layouts/#add-search-filters-sorting-and-pagination).
- Change colors and spacing: [Styling](https://docs.inertiax.dev/table/guide/styling/).

In production, pass a query scoped to your application’s authorization and access rules. See [Authorization & security](https://docs.inertiax.dev/table/guide/security/).
