Skip to main content

Introduction

The table primitive lets you define database tables using XanoScript. Each table corresponds to a database table you could create in Xano’s visual builder — but expressed in code. Tables will typically:
  • Declare their name and description
  • Define a schema with fields and data types
  • Configure indexes for performance
  • Create views for data access patterns
  • Set authentication and security settings

Anatomy

Every XanoScript table follows a predictable structure. Here’s a quick visual overview of its main building blocks — from declaration at the top to settings at the bottom.

You can find more detail about each section by continuing below.

Declaration

Every table starts with a declarative header that specifies its type, name, and basic configuration.
XanoScript
table <table_name> {
description = "<what this table stores>"
auth = true
...
}
ElementRequiredDescription
tableDeclares a table primitive.
table_nameThe unique name for the table (e.g., user, product).
descriptionnoOptional human-readable description of the table’s purpose.
authnoWhen true, enables authentication features for this table.

Section 1: Schema

The schema block defines all fields (columns) in your table. Each field specifies its data type, constraints, and validation rules.
XanoScript
  schema {
    int id
    timestamp created_at?=now
    text name filters=trim
    email? email filters=trim|lower
    password? password filters=min:8|minAlpha:1|minDigit:1
    timestamp? last_login?
  }
For each field, you can:
  • Declare its type (int, text, email, password, etc.)
  • Mark it as optional (?) or nullable (?)
  • Set default values (?=default_value)
  • Apply filters for validation and transformation (filters=trim|lower)
Important: Your schema must begin with an ID field. You can choose one of two types:
int id
uuid id
Changing your primary key type after table creation is not supported.

Learn more about the available data types


Section 2: Indexes

The index block defines database indexes to improve query performance and enforce constraints.
XanoScript
  index = [
    {type: "primary", field: [{name: "id"}]}
    {type: "btree", field: [{name: "created_at", op: "desc"}]}
    {type: "btree|unique", field: [{name: "email", op: "asc"}]}
  ]
Index types include:
  • primary — Primary key constraint
  • btree — Standard B-tree index for fast lookups
  • gin — Generalized inverted index for complex queries
  • unique — Enforces uniqueness (use with | separator)
Each index can:
  • Target single or multiple fields
  • Specify sort order (asc, desc)
  • Enforce uniqueness constraints
  • Span multiple fields for composite queries

Section 3: Views

The views block defines database views that control how data is presented and accessed.
XanoScript
  views = [
    {
      name : "Basic Info"
      alias: "sanitized_user_info"
      hide : ["password", "id"]
      sort : [{name: "id", order: "asc"}]
      id   : "1dca1ee2-9997-4fed-9d03-276bd6d68593"
    }
  ]
Views can:
  • Hide sensitive fields like passwords from API responses
  • Create aliases for different access patterns
  • Set default sorting for consistent data ordering
  • Control data visibility for different use cases

Settings

Table primitives support optional settings for organization and categorization. These settings are defined at the root level of the table block.
SettingTypeRequiredDescription
tagsarray[string]noA list of tags used to categorize and organize the table in your workspace.

Field Types and Modifiers

Field Modifiers

Fields can be marked as required, nullable, and/or specify a default value:
OptionDescription
<field_name>Makes the field required and not nullable
Example: text name
<field_name>?Makes the field optional and not nullable
Example: text name?
?<field_name>?Makes the field required but nullable
Example: text ?name?
?<field_name>Makes the field required and nullable
Example: text ?name
<field_name>?=<value>Makes the field optional with a default value
Example: text name?=defaultValue

Filters

Filters can be applied to fields for validation and data transformation:
XanoScript
email ?email filters=trim|lower
password ?password filters=min:8|minAlpha:1|minDigit:1
Validation Filters
  • min:n — Enforces minimum length
  • max:n — Enforces maximum length
  • minAlpha:n — Requires minimum alphabetic characters
  • minDigit:n — Requires minimum digits
  • pattern:regex — Validates against regex pattern
Transformation Filters
  • trim — Removes whitespace
  • lower — Converts to lowercase
  • upper — Converts to uppercase
Character Filters
  • alphaOk — Whitelists alphabet characters (a-z, A-Z)
  • digitOk — Whitelists numerical characters (0-9)
  • ok:chars — Whitelists specific characters (e.g., ok:.-_)
Restriction Filters
  • startsWith:prefix — Enforces prefix
  • prevent:blacklist — Prevents blacklisted phrases

Field Properties

Fields can have additional properties defined within braces. These properties provide metadata and configuration for the field:
XanoScript
int[] users_photos? {
  table = "photo"
}
Common field properties include:
  • table — Specifies the related table for relationship fields
  • description — Human-readable description of the field’s purpose

Multi-field Indexes

Indexes can span multiple fields for complex querying and performance optimization:
XanoScript
{
  type : "btree"
  field: [{name: "name", op: "asc"}, {name: "email", op: "asc"}]
}
Multi-field indexes are useful for:
  • Composite queries — When you frequently query by multiple fields together
  • Performance optimization — Faster lookups for complex WHERE clauses
  • Sorting efficiency — Optimized ordering by multiple columns
Each field in a multi-field index can have its own sort order (asc or desc).

Detailed Example

Below, you’ll see a complete example of a typical user table.
XanoScript
table user {
  description = "Contains basic user account information"
  auth = true
  
  schema {
    int id
    timestamp created_at?=now
    text name filters=trim
    email? email filters=trim|lower
    password? password filters=min:8|minAlpha:1|minDigit:1
    timestamp? last_login?
    int[] users_photos? {
      table = "photo"
    }
  }

  index = [
    {type: "primary", field: [{name: "id"}]}
    {type: "btree", field: [{name: "created_at", op: "desc"}]}
    {type: "btree|unique", field: [{name: "email", op: "asc"}]}
    {
      type : "btree"
      field: [{name: "name", op: "asc"}, {name: "email", op: "asc"}]
    }
  ]

  views = [
    {
      name : "Basic Info"
      alias: "sanitized_user_info"
      hide : ["password", "id"]
      sort : [{name: "id", order: "asc"}]
      id   : "1dca1ee2-9997-4fed-9d03-276bd6d68593"
    }
  ]

  tags = ["user data"]
}

What’s Next

Now that you understand how to define tables in XanoScript, here are a few great next steps:

Learn about data types

Explore all the available field types and their specific properties.
https://mintlify.s3.us-west-1.amazonaws.com/xano-997cb9ee/images/vscode.svg

Try it out in VS Code

Use the XanoScript VS Code extension with Copilot to write XanoScript in your favorite IDE.

Learn about APIs

Create APIs that interact with your database tables to build complete backend functionality.
I