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

# Defining app settings

> How to define workspace-level settings for your app

<img className="dark:hidden" width="720" height="440" noZoom src="https://mintcdn.com/attio/jXl5_SFM_Le7vWWN/images/workspace-settings-guide.png?fit=max&auto=format&n=jXl5_SFM_Le7vWWN&q=85&s=b8fc2fa68d49d58f3f737e3cc02e54bc" data-path="images/workspace-settings-guide.png" />

<img className="hidden dark:block" width="720" height="440" noZoom src="https://mintcdn.com/attio/jXl5_SFM_Le7vWWN/images/workspace-settings-guide-dark.png?fit=max&auto=format&n=jXl5_SFM_Le7vWWN&q=85&s=cd34fc601b5bf96df6c367992074683a" data-path="images/workspace-settings-guide-dark.png" />

Apps may configure settings which let users customize the app at the workspace level.

Settings live in `src/app/settings/` and consist of a schema defined with [`Settings.defineWorkspaceSchema`](../settings/define-workspace-schema) and a page defined with [`Settings.defineWorkspacePage`](../settings/define-workspace-page), displayed with form components from [`Settings.useForm`](../settings/use-form).

Unlike regular forms in dialogs, workspace settings forms automatically save changes and don't require
a submit button or `onSubmit` handler. Each field saves individually:

* Text inputs and number inputs save `onBlur` (when the user leaves the field)
* Toggles, checkboxes, and comboboxes save `onChange` (immediately when changed)

<Note>
  Only workspace admins can edit workspace settings. However, all workspace members can view the
  settings.
</Note>

## Example: Basic workspace settings

First, define your settings schema as the default export of `src/app/settings/schema.ts`:

```ts src/app/settings/schema.ts theme={"system"}
import {Settings} from "attio"

export default Settings.defineWorkspaceSchema({
  team_name: Settings.Schema.string(),
  environment: Settings.Schema.string(),
  auto_sync_enabled: Settings.Schema.boolean(),
  sync_interval_minutes: Settings.Schema.number(),
})
```

Then, define your workspace settings page as the default export of `src/app/settings/page.tsx`:

```tsx src/app/settings/page.tsx theme={"system"}
import React from "react"
import {Settings} from "attio/client"

import schema from "./schema"

export default Settings.defineWorkspacePage(schema, () => {
  const {Form, Section, TextInput, Toggle, NumberInput} = Settings.useForm(schema)

  return (
    <Form>
      <Section title="General" description="Basic workspace settings.">
        <TextInput label="Team name" name="team_name" minLength={2} maxLength={50} />
        <TextInput label="Environment" name="environment" placeholder="production" />
      </Section>

      <Section title="Sync Settings" description="Control how data syncs.">
        <Toggle
          label="Enable automatic sync"
          name="auto_sync_enabled"
          description="Automatically sync data in the background."
        />
        <NumberInput
          label="Sync interval (minutes)"
          name="sync_interval_minutes"
          min={5}
          max={1440}
          placeholder="60"
        />
      </Section>
    </Form>
  )
})
```

The process to create workspace settings is:

1. Define a schema with [`Settings.defineWorkspaceSchema`](../settings/define-workspace-schema) at `src/app/settings/schema.ts`
2. Define a page with [`Settings.defineWorkspacePage`](../settings/define-workspace-page) at `src/app/settings/page.tsx`
3. Use [`Settings.useForm`](../settings/use-form) inside the page's render callback to get form components
4. Wrap your settings inputs in the `<Form/>` and organize with `<Section/>` components

## Validation

Unlike regular forms where validation is defined in the schema, workspace settings validation
is specified directly on the input components:

```tsx src/app/settings/page.tsx theme={"system"}
import React from "react"
import {Settings} from "attio/client"

import schema from "./schema"

export default Settings.defineWorkspacePage(schema, () => {
  const {Form, Section, TextInput, NumberInput} = Settings.useForm(schema)

  return (
    <Form>
      <Section title="Configuration">
        {/* String validation */}
        <TextInput
          label="Organization name"
          name="organization_name"
          minLength={2}
          maxLength={100}
        />

        {/* URL validation */}
        <TextInput label="Webhook URL" name="webhook_url" type="url" url />

        {/* Multiline text with character limit */}
        <TextInput label="Description" name="description" multiline maxLength={500} />

        {/* Number validation */}
        <NumberInput label="Timeout (seconds)" name="timeout_seconds" min={1} max={300} />
      </Section>
    </Form>
  )
})
```

## Available components

Workspace settings forms support the following components:

### Input components

* [`<TextInput />`](../components/workspace-settings/text-input) - String input with validation
* [`<NumberInput />`](../components/workspace-settings/number-input) - Numeric input with min/max
* [`<Toggle />`](../components/workspace-settings/toggle) - Boolean toggle switch
* [`<Checkbox />`](../components/workspace-settings/checkbox) - Boolean checkbox
* [`<Combobox />`](../components/workspace-settings/combobox) - Dropdown selection
* [`<AttioUserCombobox />`](../components/workspace-settings/attio-user-combobox) - Select workspace users
* [`<RichTextInput />`](../components/workspace-settings/rich-text-input) - Rich text input

### Layout components

* [`<Section />`](../components/workspace-settings/section) - Group settings into sections
* [`<InputGroup />`](../components/workspace-settings/input-group) - Group inputs horizontally

### Utility components

* [`<Button />`](../components/workspace-settings/button) - Action buttons for additional functionality
* [`<WithState />`](../components/workspace-settings/with-state) - Access form state for conditional rendering

## Accessing settings in your app

Once your workspace settings are configured, you can access them in different ways. Every setting value is `null` until it has been set.

### With real-time updates

In React components, use the [`Settings.useSettings`](../settings/use-settings) hook to get settings that automatically update when changed:

```tsx src/app/extensions/team-widget/team-widget-content.tsx theme={"system"}
import React from "react"
import {Settings, Widget} from "attio/client"

import schema from "../../settings/schema"

export const TeamWidgetContent = () => {
  const settings = Settings.useSettings(schema)

  // Access your settings with full type safety.
  // Automatically re-renders when settings change.
  return (
    <Widget.TextWidget>
      <Widget.Text.Primary>Team: {settings.team_name}</Widget.Text.Primary>
    </Widget.TextWidget>
  )
}
```

### Programmatically

Use [`Settings.getSettings`](../settings/get-settings) and [`Settings.setSettings`](../settings/set-settings) to read and write settings. They're available from both `attio/client` (for use in extensions, dialogs, etc.) and `attio/server` (for use in server functions, webhook handlers, and event handlers):

**In client code:**

```tsx src/app/extensions/sync-record/extension.tsx theme={"system"}
import {Extensions, Settings} from "attio/client"

import schema from "../../settings/schema"

export default Extensions.defineExtension({
  type: "record-action",
  id: "sync-record",
  label: "Sync Record",
  icon: "ArrowsRefresh",
  onTrigger: async ({recordId}) => {
    // Get all settings
    const settings = await Settings.getSettings(schema)

    // Or get a single setting
    const syncEnabled = await Settings.getSettings(schema, "auto_sync_enabled")

    // Update a setting
    await Settings.setSettings(schema, "auto_sync_enabled", true)
  },
})
```

**In server functions:**

```ts src/sync-data.server.ts theme={"system"}
import {Settings} from "attio/server"

import schema from "./app/settings/schema"

export default async function syncData() {
  // Get all settings
  const settings = await Settings.getSettings(schema)

  // Or get a single setting
  const syncEnabled = await Settings.getSettings(schema, "auto_sync_enabled")

  // Update a setting
  await Settings.setSettings(schema, "auto_sync_enabled", true)

  return {success: true}
}
```

## Related documentation

* [Workspace settings overview](../settings/overview)
* [`Settings.defineWorkspaceSchema()`](../settings/define-workspace-schema) - Define the structure and types of your settings
* [`Settings.defineWorkspacePage()`](../settings/define-workspace-page) - Define the settings page
* [`Settings.useForm()`](../settings/use-form) - Build the settings form
* [`Settings.useSettings()`](../settings/use-settings) - Hook for accessing settings in React components
* [`Settings.getSettings()`](../settings/get-settings) - Get settings in client or server code
* [`Settings.setSettings()`](../settings/set-settings) - Set a setting in client or server code
* [Settings Components](../components/workspace-settings/form)
