# Welcome

Glad to have you on board!

## What is Jet Admin?

Jet Admin is an **app builder** that allows you to create **Client Portals**, **Business Apps**, and **Internal Tools** with your **existing data**, whether it's from databases, APIs, or Storages. You can build apps such as `Onboarding apps`, `Admin Panels`, `Vendor portals`, `CRMs`, and much more quickly and without code.

## Building a Business App?

This **2-min video** will explain what Jet Admin is and what you can build with it:

{% embed url="<https://youtu.be/ktkbSKQkQq8>" %}

1. [**Connect your data**](/user-guide/integrations): Connect Databases, business apps (Airtable, Stripe, Zendesk), Data Warehouses, Internal and external REST or GraphQL APIs, and File Storage.
2. [**Sync and Blend your data**](/user-guide/360-data-data-blending): Create a single source of truth (SSOT) that syncs to your multiple data sources (Stripe, Hubspot, Salesforce, ...).
3. [**Build App Interfaces**:](/user-guide/design-and-structure/components) Drag and drop UI components (Tables, Forms, Charts, Details Images) onto Layouts (Modals, Columns, Tavs) and connect them to your data sources.
4. [**Customize your app**](/component-designer): Design pixel-perfect components or use 50+ ready-to-use components from Marketplace.
5. [**Automate your workflow**](/user-guide/workflow): Create multi-sequence Automation with over 30+ automation blocks and trigger them by Webhook or Schedule jobs every minute, hour, day, or month.
6. [**Publish and share your app**](/user-guide/core-concept/sharing-your-app)

## Building a Portal?

This **5-min video** will walk you through the process of building a client portal from scratch:&#x20;

{% embed url="<https://www.youtube.com/watch?v=WpQ-PsAbmD8&ab_channel=JetAdmin>" %}

## Ready to Get Started?

This **Quickstart Guide** will walk you through the necessary steps for building your first app in Jet:

{% content-ref url="/pages/-Mik5XZlqUiijHffNwN1" %}
[Quickstart](/getting-started/quickstart-2)
{% endcontent-ref %}


# Academy

In Jet Academy, you'll be able to learn both the fundamentals of Jet Admin and more advanced topics through a series of **short tutorial videos**.

To navigate Academy, click on the topic in the menu on the left to open its contents, or get started with the most basic functions:

{% content-ref url="/pages/4Dl85uSaY1HCTfpZ9PQy" %}
[Connecting Data Sources](/videos/connecting-data-sources)
{% endcontent-ref %}

{% content-ref url="/pages/pwkvRQftiXL4NJGH5hCn" %}
[Data Editor](/videos/data-editor)
{% endcontent-ref %}

{% content-ref url="/pages/ZP3rWIJOxUKCi8bpvWtV" %}
[App Builder](/videos/app-builder)
{% endcontent-ref %}


# Getting Started

In this Crash Course, we'll learn **the fundamentals** of Jet Admin so you can start building your app today.

We'll also dive deeper into **advanced concepts** to help you get the maximum juice for the squeeze.

Finally, we'll **build some of the most popular kinds of apps together**, guiding you step by step from the square one to production-ready.

{% embed url="<https://www.youtube.com/watch?time_continue=1&v=lsYvasJo820&ab_channel=JetAdmin>" %}


# Connecting Data Sources

In this section, you'll learn how to connect your Data to Jet Admin.

You can connect **as many data sources** as you need to create a centralized place for all your operations. You can integrate with anything using native integrations or custom APIs.

Use the submenu to navigate to a particular topic or start with the first one:&#x20;

{% content-ref url="/pages/IeOBSLKBUnkQ8fuspeze" %}
[Jet Database](/videos/connecting-data-sources/jet-database)
{% endcontent-ref %}


# Jet Database

{% embed url="<https://www.youtube.com/watch?v=2rdWPCUiGd4&ab_channel=JetAdmin>" %}


# Google Sheet

{% embed url="<https://www.youtube.com/watch?v=SWAmJMD8H38&ab_channel=JetAdmin>" %}


# Airtable

In this article, we'll review the integration with Airtable, and its characteristics and will go through the steps necessary to connect it to Jet Admin

{% embed url="<https://www.youtube.com/watch?v=HOiRAbCOcss&list=PLSkzi9eq0vBnUGMnwXrRRVo9TXUjZ7uSj&index=19&ab_channel=JetAdmin>" %}

###

{% hint style="info" %}
**API keys are deprecated by the end of January 2024.**&#x20;

Airtable's API keys stopped working and you will have to migrate to **personal access tokens**. **Personal access tokens** allow you to more securely grant API access to Airtable data.
{% endhint %}

### Connecting Airtable

You can connect to Airtable from the data tab on the left menu bar or from the data section within a UI component. You'll need to enter a valid personal access token, and choose a base.

### Obtaining a personal access tokens

To obtain your personal access token on [Airtable's Developer Hub](https://airtable.com/create/tokens), follow the steps below:

1. Go to Airtable's [developer hub](https://airtable.com/create/tokens) page
2. Click on 'Create token'
3. Create a new token
4. Copy and save the token in a safe place.

{% hint style="info" %}
When creating a new 'personal access token', please make sure you choose the 'data.records:write' scope if you need to view, add, edit, and delete records on Jetadmin's side.
{% endhint %}

<div data-full-width="false"><figure><img src="/files/vcGOd69YYtXYGviyreNJ" alt=""><figcaption></figcaption></figure></div>

### Connect Airtable to Jetadmin&#x20;

1. On Jetadmin's builder side, click 'Add Resource' from the data section on the left-side menu
2. Choose Airtable
3. Click on 'Sign In to Airtable' button
4. Click on 'Add a base'&#x20;
5. Choose the needed base or workspace
6. Click 'Grant access'
7. Choose the base needed
8. Click the 'Choose tables' button
9. Select/unselect the needed tables and choose a **view** for each table
10. Click the 'Add Resource' button.

{% @arcade/embed flowId="hsHDJdkTBCT823AUWCtD" url="<https://app.arcade.software/share/hsHDJdkTBCT823AUWCtD>" %}

### Choosing connection mode&#x20;

After that, you need to choose how you'd like your Airtable to be integrated with Jet Admin. You can either connect directly or **sync it** with Jet's internal database to get extended functionality.&#x20;

If you want to be able to **combine your Airtable data** with data from other data sources, such as Firebase, Google Sheets, or even REST API within the same tables, you should choose the **"Sync" connection** for Google Sheets. You can learn more about it here:

![](/files/0emn93ciJ7PfSgdIlQmA)

After having connected your Airtable, you'll be prompted to choose pages you want Jet Admin to generate **an admin panel (CRUD pages)** for.&#x20;

### Airtable Views

On Airtable side, you can create different views for each table. Each view allows you to filter and sort records. In Jetadmin you can choose to use only one view for each table when creating the resource. To view all records in each table, choose the main view 'All'.

The image below will show you the differences between the main view and the filtered views:

<figure><img src="/files/rRLpbmyqvNsviOL4Ni7P" alt=""><figcaption></figcaption></figure>

### Switch Airtable's Views

To switch to other views for each table, follow the steps below:

1. Click 'Edit resource' from the resource's settings menu
2. Click on 'Choose tables'
3. Select the needed views for each table
4. Click 'Update resource'.

<figure><img src="/files/a1Ot4cBSrtUln8vxREYV" alt=""><figcaption></figcaption></figure>


# Custom API Action (Zapier)

{% hint style="warning" %}
This video might be **partially outdated** due to product changes - we'll replace it with the fresh one soon. However, you still can use the concepts from it and apply them to the current version
{% endhint %}

{% embed url="<https://www.youtube.com/watch?v=mry1qfKIhZ0&ab_channel=JetAdmin>" %}


# Firebase

{% embed url="<https://www.youtube.com/watch?v=5TTXZhHHP0I>" %}


# Firebase FAQ

In this section you can find about Frequently Asked Questions about Firebase


# Data Editor

**Data Editor** is a key part of the Jet Admin App Builder. Typically you end up in Data Editor right after you connect your data source(s).

In Data Editor you can **audit, edit, and refine** your data before using it in the App Builder.

{% embed url="<https://youtu.be/G-3GIF_28ZM>" %}


# Data Editor Interface

This short video will help you understand how to **get around Data Editor** and start working with your data more quickly.

{% embed url="<https://youtu.be/0nRHFy6oPmw>" %}


# Data Source Settings

Once you've connected your Data Source to Jet, you can specify its **settings**, specify the **sync intervals**, see **audit logs**, **manage collections (tables)**, and more:

{% embed url="<https://youtu.be/RqtphcWBDnk>" %}


# Prepare & Organize Data

Before you start working with your data, it makes sense to organize it so you can easily **access the relevant parts**.

This video covers the basics of sorting, filtering, working with columns, and more.

{% embed url="<https://youtu.be/UfN2JYWSrD0>" %}


# Edit Data

In this video, we'll learn how to **edit your data** in Data Editor:

* Edit particular fields&#x20;
* Add and delete records
* Upload and download data

{% embed url="<https://youtu.be/nKwapk29m-A>" %}


# Field Types

This video explains **how to change field types** so that you can make sure your data is rendered in the correct format.&#x20;

{% embed url="<https://youtu.be/-VnJL0KbiXc>" %}


# Related Data

In this video, we'll learn about the **related data** – what this means and why relational databases are such a great concept. We'll also learn how to work with related data in Jet, how to set relations, and what to do with these related data sets later on.

{% embed url="<https://www.loom.com/share/125c9affac474a34901ab96489324648>" %}


# Lookups & Rollups

In this video, we'll learn about the very powerful field types **Rollups and Lookups**. We'll also go over an example of how to use them to "look into" the related table and get the information you need from there.

{% embed url="<https://youtu.be/HBrF6wAMghA>" %}


# Files & Storages

This is the overview video on **how to work with files** in Jet, whether that means connecting an Airtable with files attached to records, connecting a dedicated storage such as Firebase, or using another data source.

{% embed url="<https://youtu.be/FtR0a40ufRU>" %}


# Data Blending Intro

In this video, we'll look behind the "no-code" curtain and explore how you can **consolidate data** from **multiple data sources** (Non-SQL included) using custom SQL queries.

{% embed url="<https://youtu.be/l1jrrwlj0eU>" %}


# App Builder

In this Crash Course section, we'll learn the fundamentals of the App builder.

**App builder** is a core part of Jet Admin. It allows you to assemble your UI, and layout as well as bind and transform data to create custom user flows for your app. All this is done through an intuitive Drag & Drop and Point & Click interface.

Go into the submenu to navigate to a particular topic or start with the first one:

{% content-ref url="/pages/OpOTKO4Hs55RkqAs5GGO" %}
[Builder and User Modes](/videos/app-builder/builder-and-user-modes)
{% endcontent-ref %}


# Builder and User Modes

Any app you'll create with Jet will be built in the **Builder mode** so it's important to understand what it is and how it interacts with the user mode where your end users will be using the app

{% embed url="<https://youtu.be/IzoNmMnZ_kE>" %}


# Pages and Overlays

Before diving into the features of the builder, it's important to understand the fundamental structural elements of any app you build with Jet: **Pages and Overlays**.

{% embed url="<https://www.youtube.com/watch?v=7382TbvzzRs&ab_channel=JetAdmin>" %}


# UI Builder

**UI builder** is a part of the App builder and allows you to assemble the UI components on the page using pre-made Drag & Drop UI components

{% embed url="<https://youtu.be/ZuKlkslvZSs>" %}


# Bind Data to UI

To build any app you'll need two things: your UI and the data. But how to **link or connect** the two in Jet Admin? Learn in this video

{% embed url="<https://youtu.be/jV9LiBbyWYQ>" %}


# Bind Filter to Table

In this and the following videos, we'll cover how to bind data and components **in various situations**. In this video, in particular, we'll learn about the **Filter-Table binding use-case**: you have a filter component and you want all the inputs in it to be passed over into the Table and used to filter it.&#x20;

{% embed url="<https://youtu.be/zZxiLuhdiGI>" %}


# Bind Input Field to Table

In this video, we'll learn about the **Field-Table binding use-case**: you have an input field component and you want a value from a specific column from in a selected row of a Table to be fetched into this field&#x20;

{% embed url="<https://youtu.be/0wBmO3yNCBY>" %}


# Bind Form to Table

In this video, we'll learn about the **Form-Table binding use-case**:&#x20;

* You have a Form and you want this form to dynamically receive the values from a selected row (a record) of a Table into the fields of this form

{% embed url="<https://youtu.be/rdM-p_fgi-k>" %}


# Bind Related Tables

Slowly ramping up the complexity of the use-cases, now we'll look at the **Table-Table binding**:

* You have two related tables and want, in the second Table, to dynamically show the records related to the selected (clicked) record in the first Table

{% embed url="<https://youtu.be/m6PvvR05xRI>" %}


# Bind across Pages

In this video, we'll cover binding **UI elements from separate pages**:&#x20;

* You have a Table on Page 1 and an input field on Page 2 and you want, when you click on the specific row in the table to drill down into Page 2. Additionally, as you drill down, you want to "pass" a specific value from a selected record in the Table into the input field on Page 2

{% embed url="<https://youtu.be/5wjRkGZMJwI>" %}


# Bind from Page to Modal

In this video, we'll cover binding a **UI element in the Modal to the UI component on the Page**:&#x20;

* You have a Table on a Page and an input in a Modal and you want, when you click on the specific row in the table to open up the Modal. Additionally, as the Modal opens up, you want to "pass" a specific value from a selected record in the Table into the input field in the Modal

{% embed url="<https://youtu.be/t-93auOdrno>" %}


# Calculcation & Formulas

{% hint style="warning" %}
This video might be **partially outdated** due to product changes - we'll replace it with the fresh one soon. However, you still can use the concepts from it and apply them to the current version
{% endhint %}

{% embed url="<https://www.youtube.com/watch?v=r0yL_CQh9J8>" %}


# Team & Users Permissions

{% hint style="warning" %}
This video might be **partially outdated** due to product changes - we'll replace it with the fresh one soon. However, you still can use the concepts from it and apply them to the current version
{% endhint %}

{% embed url="<https://www.youtube.com/watch?v=lUv_wfNfKR8&ab_channel=JetAdmin>" %}


# Automations

{% embed url="<https://www.youtube.com/watch?v=_mbNeLJDqpU>" %}


# Environments

{% embed url="<https://www.youtube.com/watch?v=E3z8j3tBlbI&ab_channel=JetAdmin>" %}


# Custom API Collection

{% hint style="warning" %}
This video might be **partially outdated** due to product changes - we'll replace it with the fresh one soon. However, you still can use the concepts from it and apply them to the current version
{% endhint %}

{% embed url="<https://www.youtube.com/watch?v=ajqCp3uTb-o&ab_channel=JetAdmin>" %}


# Nested Filters

Filters for related collections

Nested filters allow you to go through the layers of relations between collections and filter by ANY field from ANY collection (table), that's related to the original one.

{% embed url="<https://youtu.be/GBviXPUJT24>" %}


# Built-in Approval Flow

{% embed url="<https://www.youtube.com/watch?v=-DMkubFxhDs&t=2s&ab_channel=JetAdmin>" %}


# Create Multi-Step Forms

{% embed url="<https://www.youtube.com/watch?v=gCWxPG-jTME>" %}


# Component Designer

{% embed url="<https://www.youtube.com/watch?v=-u6X4gpCWj8&t=16s&ab_channel=JetAdmin>" %}


# Build Apps Together

In this section, we'll go over **specific apps**, building each use-case from scratch to the point when it's up and running.

Go to a specific one in the submenu or start from the first one:

{% content-ref url="/pages/t0xavOmYDzCTzDOmBbBy" %}
[Custom CRM](/videos/build-apps-together/custom-crm)
{% endcontent-ref %}


# Custom CRM

{% hint style="warning" %}
This video might be **partially outdated** due to product changes - we'll replace it with the fresh one soon. However, you still can use the concepts from it and apply them to the current version
{% endhint %}

{% embed url="<https://youtu.be/miw10SJlkBk>" %}


# Internal Tool

{% hint style="warning" %}
This video might be **partially outdated** due to product changes - we'll replace it with the fresh one soon. However, you still can use the concepts from it and apply them to the current version
{% endhint %}

{% embed url="<https://youtu.be/lj93KBKlpYk>" %}


# Customer portal

{% hint style="warning" %}
This video might be **partially outdated** due to product changes - we'll replace it with the fresh one soon. However, you still can use the concepts from it and apply them to the current version
{% endhint %}

{% embed url="<https://youtu.be/WpQ-PsAbmD8>" %}


# Supabase CRM

{% embed url="<https://www.youtube.com/watch?v=aZ0oPbFGVBU>" %}


# Import Figma design to Jet

{% embed url="<https://www.youtube.com/watch?v=F5RYVPibse8>" %}


# Authentication


# Supabase Auth

{% embed url="<https://www.youtube.com/watch?v=4Tfjl1hQVEE>" %}


# Firebase Auth

{% embed url="<https://youtu.be/FGXkthvlUbA>" %}


# Xano Auth

{% embed url="<https://www.youtube.com/watch?v=KY24zB7yn2A>" %}


# Data Privacy & Security

### **Where is my data stored, and is it secure?**

Yes, your data is secure and is always stored by you, whether that be with your chosen data resources or on your own servers. We provide Jet Bridge that makes our architecture secure. Jet Bridge is a free and ope&#x6E;**-**&#x73;ource app that **generates an API** and proxies the requests to databases and business apps. **We don’t collect, copy, or host your private data on our side. Jet follows best practices to ensure that important data is only accessed by you and your users.** Jet encrypts all data and credentials that go through our servers using an HTTPS connection.\
\
Jet Admin offers you the ability to [use Jet Tables](https://docs.jetadmin.io/user-guide/integrations/jet-tables), which is a PostgreSQL database hosted by Jet. Jet Tables, like other top-tier PostgreSQL databases, uses best practices to keep your data secure.  Using Jet Tables is the only case in which your data would be stored on Jet servers, but there is no difference between the way Jet Admin allows you to access data in Jet Tables and the way that Jet allows you to access your data in other PostgreSQL databases, so your data remains secure, regardless of which databases you choose to use. You can learn more about Jet Tables [here.](https://docs.jetadmin.io/user-guide/integrations/jet-tables)

{% content-ref url="/pages/-M9bZLSZDt2NNw3KARyl" %}
[Cloud](/jet-bridge-deployment/cloud)
{% endcontent-ref %}

Host Jet Bridge on your servers. You can place it behind your VPN, in your own VPC. We won’t get access to your data, however, you will still receive interfaces updates normally.

{% content-ref url="/pages/-M9bZJlOdxwMpIvszDG6" %}
[Self-hosted Jet Bridge](/jet-bridge-deployment/jet-admin)
{% endcontent-ref %}

If your infrastructure doesn't have access to the internet, you can use on-premise on your own servers and block all network connections. You can place it behind your VPN, in your own VPC.

{% content-ref url="/pages/-MGJse9bZXdY1l2qxYy-" %}
[On-premise](/jet-bridge-deployment/on-premise)
{% endcontent-ref %}

## Built-in Security-Grade Features <a href="#built-in-security-grade-features" id="built-in-security-grade-features"></a>

![](/files/-MGOTQCiboON-jtHpvcw)

### Incident Recovery <a href="#incident-recovery" id="incident-recovery"></a>

To prevent bad consequences for your business, Jet Admin automatically creates a backup of your interface, so you can always restore it in case of an incident. Simply push the “Recover” button at the top right corner of your screen and select what you would like to backup.

![](https://gblobscdn.gitbook.com/assets%2F-LQ08RFAKZvFADEiXKFy%2F-MGOKqrFcjeSkw6nnATM%2F-MGOUO-nRbXuxE22JoX4%2Frecover-dark%402x.png?alt=media\&token=0e3f32a9-fb29-4994-90ca-a59867b59763)

### DMZ <a href="#dmz" id="dmz"></a>

Since Jet Admin doesn’t require access to your data, you are free to host your admin’s API under DMZ or VPN network. Once you do that, your admin panel will be separated from your public network, leaving no chance for malicious attacks or remote rooting. This might be on a checklist for some large healthcare and financial companies that can be held liable for clients’ personal information. In most cases though, it is not a necessity.

![](https://gblobscdn.gitbook.com/assets%2F-LQ08RFAKZvFADEiXKFy%2F-LqpSrnI1pd1VctEG1LG%2F-LqpT2hOOG5k1OjEq6wb%2Fhow-it-works-dmz%402x.png?alt=media\&token=95609ba5-139e-4fe6-96e5-d04f0bfc51be)


# Join the Community

**Join the community here →** [**https://community.jetadmin.io/**](https://community.jetadmin.io/)

The community is where you can meet, get help & support, share resources and discuss what you're working on. The community is filled with thousands of kind and friendly users – many of them experts – who are willing to help each other out.&#x20;

We have only a few simple guidelines:

* Be polite and kind to other members
* Use the search bar to see if your topic has been discussed before
* Check out the community’s different [categories](https://community.jetadmin.io/)
* When posting questions, try to be clear and concise and write descriptive titles. If you need help with many different things, try posting them as separate topics.
* Where possible, provide links (e.g. to your app), screenshots or even videos that help explain the point you are trying to make
* Please be aware that everything you post in the forums is public
* If you have questions that others could benefit from – try to post publicly and not privately message other members. Some of our experts and staff get a lot of DMs – bear in mind that there are many other people in the forum that may be able to help you.&#x20;


# FAQ and Troubleshooting

In this section, you'll be able to find answers to common questions as well as more advanced troubleshooting.

To navigate FAQ & Troubleshooting, click on the topic on the left menu to open its contents.


# A data resource is failing to sync

After editing in the structure of the database in the third-party integration source, such as Airtable, Firebase, Xano, Supabase, postgreSQL … etc, the sync with Jetadmin might fail sometimes.

To fix this you need to Recreate Scheme.

1- In Jetadmin, open the resource that is failing to sync;

2- Click on the 3 dots button on top-left near the resource name;

3- Choose ‘recreate scheme’ from the menu;

4- Click the ‘recreate structure’ red button;

5- Wait a few seconds till the data is being imported, then click the ‘Start working with …’ blue button.

<div align="left"><figure><img src="https://downloads.intercomcdn.com/i/o/813558823/903e27e98e3b741a0f9fa582/image.png" alt=""><figcaption></figcaption></figure></div>

Now your resource should be synced and working fine.&#x20;


# Data is not loading

If your data is not loading, there might be many potential causes for this. This might as well render differently in the UI component: the infinite load, or the error.

In this article, we'll review the most common causes of this issue and help you identify and fix the problem.

#### Case 1 - VPN

A user supposedly hasn't changed anything but started to get this error:&#x20;

<figure><img src="/files/9UqS3o01kqsq56HPsR9t" alt=""><figcaption></figcaption></figure>

**Solution:** Disabling VPN solved the problem - this is the most common reason for such an error. After disabling it, reload the page.&#x20;

Case 2 - SQL query filters

In this case, a user wanted to display a filtered collection from a custom SQL query but got the "Nothing found" message

<figure><img src="/files/ZhVJ5vlVLKJp687G1Hfx" alt=""><figcaption></figcaption></figure>

Even though the query was correct, it didn't account for the fact that Jet handles filtering automatically, so you **should not** add the `WHERE` clause.

<figure><img src="/files/3ZXNRE3iHSOGaNBjaqrq" alt=""><figcaption></figcaption></figure>

**Solution:** omit `WHERE` and only set up the inputs and reference them in the query.


# How to clone the whole app?

If you want to duplicate your app, you can save your progress as a backup to a file, create a new app, and restore your app from a backup. Please be aware that created actions won’t be copied, you will need to add them manually.

Go to MyApp in upper right corner -> Environment -> Settings -> Download backup

<figure><img src="/files/Mg6LzM5qwA2xuL2t5XZm" alt=""><figcaption></figcaption></figure>

After that, create a new app and go to the Environment -> Settings to restore your backup.

{% hint style="info" %}
Please note that Actions from your original app won’t be copied
{% endhint %}


# Why new SQL tables are not showing?

If you've added new SQL tables to your database, you will need to manually select new tables to load into JetAdmin.

Go to Data -> *Your Resource Name* -> Three dots -> Edit resource

<figure><img src="/files/Ksw4UajIJ9AdOUaUyZkU" alt=""><figcaption></figcaption></figure>

Scroll down and click on "Choose Tables"

<figure><img src="/files/DAnXARLNssT6qF0Qm1nh" alt=""><figcaption></figcaption></figure>

You will see a list of your tables there. You’ll need to click on checkboxes of tables that you want to add and then click on "Update resource".

<br>


# How to restrict input in a text field?

If you want to allow an input to only receive a certain number or text format, you can use regular expressions.

For example, let's say that you want your input to receive an ID number that is structured like this: “010.124.501-55”. If you don’t know how to write regular expressions, you can simply ask any AI bot to do this for you, [ChatGPT](https://chat.openai.com/) for example:

<figure><img src="/files/sjsnCQjoes6hy54DBKv5" alt=""><figcaption></figcaption></figure>

After you get your regular expression, you can input it in the validation field of your component. Click on the component in builder -> Display tab -> Validate -> Use Regular expression

<figure><img src="/files/ihXmhUwLXJ3NjF4LOrW8" alt=""><figcaption></figcaption></figure>

You can also mention your field format in the custom validation error field for easier understanding.<br>


# Troubleshooting Django integration

If you are having trouble connecting Django to JetAdmin, you will need to check a few things:

* Make sure there are no network restrictions.
* Check whether your Jet Bridge is the latest version.
* Check your CORS policies in Django.

If your network with Django is okay, and you are using the latest Jet Bridge version but still getting errors like this:

<figure><img src="/files/VQLooDLPjHHcvGHKyZfQ" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/8WkE3LmBreNxglkQ0DO4" alt=""><figcaption></figcaption></figure>

That means that you need to check your CORS policies in Django.

By default, there is a parameter in Jet Bridge for Django that contains CORS in settings.py called "JET\_CORS\_HEADERS".

It is enabled by default and filled automatically, but if your Django already has an app called “corsheaders” then it turns off. You can configure your CORS settings in the "corsheaders" app instead.

Alternatively, you can try to force "JET\_CORS\_HEADERS" to be set to True, but it can lead to strange effects, so we would advise trying it only as a last resort.

\ <br>


# How to Connect to Slack Channel

Learn how to join our Slack workspace and access your dedicated channel.

Our Slack channels are available for Pro and Enterprise plan users, including:

* Internal Tool Pro
* Internal Tool Enterprise
* Customer Portal Pro
* Customer Portal Enterprise

Joining our workspace gives you direct access to our team. You can ask any questions related to your app in your dedicated channel.

### How to Join Slack

#### Step 1: Join the Workspace

1. Click the **blue question mark** button in the bottom-right corner.
2. Select **Slack Channel** from the support options.
3. Follow the instructions to join the workspace.

#### Step 2: Access Your Channel

1. Your Slack email may differ from your registered email; you can enter a different email if needed.
2. The default channel name is `jetadmin_`, but you can change it.
3. Once completed, you’ll be added to your specific Slack channel.

### Need Help?

If you have any issues joining, reach out via live chat or email us at **<support@jetadmin.io>**.


# Quickstart

👉Before we jump into the thick of it, there is one thing that needs to be **clarified**:

### Internal Tools vs Customer Portals

Both **Client Portals** and the **Internal Tools** are the same in their essence - they are just web or mobile apps built on Jet Admin. However, they differ from the usage perspective: `end-users` of the Portal are **external users**, e.g. Vendors, Partners, Merchants, or Individuals, whereas `end-users` of the Internal App are **internal users**, i.e. your organization's employees. They also differ in [pricing](https://www.jetadmin.io/pricing/).

Typical use-cases for the Client Portal and for the Internal Tool also differ, that's why we've created two **separate quickstart journeys** based on the common use-cases:

{% content-ref url="/pages/-MAWMT75HEiZPsSqA8Jk" %}
[Building an Internal Tool](/getting-started/quickstart)
{% endcontent-ref %}

{% content-ref url="/pages/-Mik5nzjodLgLMp3obSd" %}
[Creating a Customer Portal](/getting-started/creating-a-customer-portal)
{% endcontent-ref %}

If you want to save time building your app, you can apply one of the **templates** that you can find on the dashboard. You can preview the templates [**here**](https://www.jetadmin.io/templates).

![](/files/jfDbIOtRZqqKuGFcno1b)

{% hint style="danger" %}
For the template to become a functional app, It's crucial to **correctly bind** your own data and **set relations** between to UI components composing a template. Learn more about it in the [**Values**](/user-guide/binding-and-values/parameters) section.
{% endhint %}


# Building an Internal Tool

Get your first internal app up and running in under 10 minutes

### Custom CRM in 10 mins 🚀

To familiarize yourself with how Jet works, let's build a simple CRM that will allow us to `View` and `Edit` the Customers:

<figure><img src="/files/KP7n2Y7uAIW9VcYNPlIp" alt=""><figcaption></figcaption></figure>

We'll go through the whole **process of creation** step by step. Let's start with our data:

{% content-ref url="/pages/-MF\_MK6Y3Yi1OB0EB0TP" %}
[Connect your Data](/getting-started/quickstart/connect-your-data)
{% endcontent-ref %}


# Connect your Data

Jet allows you to connect and sync with 50+ data sources: business apps (Airtable, Stripe, Zendesk), Data Warehouses, Internal and external REST or GraphQL APIs, and File Storage. Once a [data source](/user-guide/integrations) is set up, you can utilize your data to create apps.

This guide focuses on using [Jet Table](/user-guide/integrations/jet-tables) as the data source. Jet Table offers a quick and secure method for storing and modifying data specifically for Jet applications. It integrates the robustness of a PostgreSQL database with the user-friendly aspect of a spreadsheet interface, enabling efficient data management.

To insert test data into the Jet Database, first download the following provided CSV files:

* [Deals](https://res.cloudinary.com/djpvkoh3s/raw/upload/v1699769136/csv%20samples/lzhlxcnvtyvsu6jrl5mx.csv)
* [Companies](https://res.cloudinary.com/djpvkoh3s/raw/upload/v1699769136/csv%20samples/jrhpf9oosuuozugee4rn.csv)

Once you have downloaded the CSV files, follow the steps:

1. Log in to Jet Admin and create a new project. If you don't have an account, [sign up](https://app.jetadmin.io/register) for free.
2. Create a new project and add Jet Table as your data source, or if you have an existing project, integrate Jet Table by navigating to **Data** > **Add Resource**.
3. Click **Import CSV**&#x20;
4. Select the **Companies** CSV you downloaded
5. Click **Import file**

{% @arcade/embed flowId="mecpHbmAMz6gVq1gjYiH" url="<https://app.arcade.software/share/mecpHbmAMz6gVq1gjYiH>" %}

6. Follow the same process to import **Deals: Data** > **Jet Tables > Add or Import.**

{% @arcade/embed flowId="OcDA6NlTW7qooOE72OIg" url="<https://app.arcade.software/share/OcDA6NlTW7qooOE72OIg>" %}

{% content-ref url="/pages/UsgTz7o4vPeieqeQtyvh" %}
[Configure Data](/getting-started/quickstart/configure-data)
{% endcontent-ref %}


# Configure Data

In Data, you can set up field types (Number, Text, Select, Date, Rating), define [Relations](/user-guide/computed-columns/relations) between tables, [pull record contents](/user-guide/computed-columns/lookup-column) from one linked record into another, [perform a calculation on Relation](/user-guide/computed-columns/rollup-column), or [calculate the values](/user-guide/computed-columns/formulas).

Next, let's set up the field type for the **Priority** field. We will configure it as a **Select** type with predefined options: `High`, `Medium`, and `Low`.

1. Click on **Priority** header in your table to access its settings
2. Choose **Edit field** to modify the field's properties.
3. Select the field type as **Select**. This allows you to create a dropdown menu with predefined options.
4. Click on **Display** to proceed with the visual setup.
5. Add predefined options for the 'Priority' field: `High`, `Medium`, and `Low`.

{% @arcade/embed flowId="wVznrrHS98pka8fvLcPp" url="<https://app.arcade.software/share/wVznrrHS98pka8fvLcPp>" %}

Use the Link to **Record** field type to establish a relationship between Deals and Companies. This will enable you to link these two tables, effectively associating specific deals with respective companies.

1. Click on **Company id** column in your table to access its settings.
2. Choose **Edit field** to modify the field's properties.
3. Select the field type as **Link to record**. This option allows you to create a link between the current record and another table.
4. Specify the related table by selecting **Company**.

{% @arcade/embed flowId="f9bvhXrjPJarXzwB1bsq" url="<https://app.arcade.software/share/f9bvhXrjPJarXzwB1bsq>" %}

Once you've established a Relation using the **Link to Record** field type, you can pull record contents from one linked record into another, and you can perform calculations on this Relation, enabling more complex data manipulations and analyses based on the interconnected data.

Next, we will focus on extracting and inserting the **Company logo** into the **Deals** table.

1. Click **+ New Column** on the right-top
2. Select **Lookup related field**
3. Select **Company\_id** > **Logo**
4. Save

{% @arcade/embed flowId="bfEhFWmRJsRH59Mk0jLj" url="<https://app.arcade.software/share/bfEhFWmRJsRH59Mk0jLj>" %}

{% content-ref url="/pages/-MA\_QWCxubYeYxxHu3jN" %}
[Build UI](/getting-started/quickstart/set-the-layout)
{% endcontent-ref %}


# Build UI

Discover how to utilize components to build your app's user interface

Components are prebuilt UI elements your users engage in, such as `Tables`, `Forms`, `Buttons`. In this example, only a limited number of components are used; you can explore 50+ Components in the UI Component Library. Drag-and-drop components within **Layout** `Columns`, `Tabs`, and `Modals`, facilitating the building of your app.

You'll be building an app that enables the creation and updating of **Deals** data. To enable this functionality, you'll add `Table`, `Forms`, and `Modals`. Learn more about [Jet UI Concept](/user-guide/core-concept/jet-ui) in our documentation. Additionally, if you want to implement this functionality swiftly (Create, Update, Delete flow), you can generate it in seconds using [Page Templates](/getting-started/ui-in-seconds).

### 1. Set the Layout

`Columns` are used to set the horizontal component of the layout. You can add multiple columns and resize them.&#x20;

{% @arcade/embed flowId="qqlSdR0LVUOSNZRMPOO4" url="<https://app.arcade.software/share/qqlSdR0LVUOSNZRMPOO4>" %}

### 2. Display Deals

When you select the **Table** component, the right panel automatically updates to display the properties of the component. Components come with a wide range of properties that you can configure. Properties are accessible from other components and queries, allowing for a more integrated and dynamic user interface experience.&#x20;

Click **Data Source** – **Jet Tables** and the **Deals** collection that you've created.

{% @arcade/embed flowId="jU26kc5IVQRR4HeOLBMj" url="<https://app.arcade.software/share/jU26kc5IVQRR4HeOLBMj>" %}

Modify the **Logo** column to have a circular frame and position it as the first column.

{% @arcade/embed flowId="2SmD0N6RcbanMEkUyAed" url="<https://app.arcade.software/share/2SmD0N6RcbanMEkUyAed>" %}

### 3. Bind your components

**Component Binding** allows the passing of values between components. In this case, we will bind the `Table` and `Filter` components, enabling users to filter Deals by criteria such as `Name`, `Priority`, and `Amount`.

{% @arcade/embed flowId="WeYMccrK3MnPjQeVxhCk" url="<https://app.arcade.software/share/WeYMccrK3MnPjQeVxhCk>" %}

### 4. Update Deal with a Form component <a href="#id-3-add-user-management-options-with-a-split-button-component" id="id-3-add-user-management-options-with-a-split-button-component"></a>

The final component to add is a Form component. This component will allow you to generate [Forms](/user-guide/design-and-structure/components/form) automatically based on your Collections fields.

{% @arcade/embed flowId="CSycxxwLOkyFXhQrqax6" url="<https://app.arcade.software/share/CSycxxwLOkyFXhQrqax6>" %}

Every field in the Form is individually configurable: you can add or remove fields from the Form, alter the field type, rearrange the order of the fields, and change appearance.

{% @arcade/embed flowId="mEmk4at1wRPLQJIEsc7p" url="<https://app.arcade.software/share/mEmk4at1wRPLQJIEsc7p>" %}

To update a deal, the user must select the corresponding row in the Table. You can configure the first row to be selected by default in a `Table`. To do this, go to the Display tab in the `Table` properties and choose **Select the first row by default.**

{% @arcade/embed flowId="A9bZJki3hDolQGhFqDZu" url="<https://app.arcade.software/share/A9bZJki3hDolQGhFqDZu>" %}

{% content-ref url="/pages/nhWBWmKblyqZ86cq7ImS" %}
[Run Actions](/getting-started/quickstart/run-actions)
{% endcontent-ref %}


# Run Actions

Add actions that users can trigger

A helpful way to think about apps is through how users interact. Two elementary levels of interaction are viewing and editing data, which we built on the previous steps. But often, apps need to be able to perform custom actions with specific workflow.

Initiating a **Form** is a form of action. Actions such as **Open Link** and **Show notification** are native functionalities within Jet, triggering specific processes within your app.

In this tutorial, we'll set up a system to automatically send notifications to the user via email and Slack when a deal is marked as **Closed Won**.

1. Initiate the workflow when the **Deal** is updated, which occurs when the associated form is successfully submitted.

{% @arcade/embed flowId="xwy9H9O3HZpT5S9hShmp" url="<https://app.arcade.software/share/xwy9H9O3HZpT5S9hShmp>" %}

2. Add a conditional step in the workflow that checks whether the deal stage is set to **Closed Won.** For the conditional step, employ the 'Equals' operation using the [Formula](/user-guide/computed-columns/formulas) `EQ({deal_stage}, 'Closed Won')` to verify if the deal stage matches the **Closed Won** status. The value for {deal\_stage} is selected from Formula.

{% @arcade/embed flowId="0oY95MDbyTrkHCRLTqzX" url="<https://app.arcade.software/share/0oY95MDbyTrkHCRLTqzX>" fullWidth="false" %}

3. **Send email**. Add actions to send an email with the content formatted as: `"Deal {0} is Closed Won"`. Here, `{deal_name}` should be dynamically inserted into the email content, and its value can be selected using a formula that references the `{deal_name}` field from the data source.

{% @arcade/embed flowId="i1idRrbrtOyTqGYgPNFK" url="<https://app.arcade.software/share/i1idRrbrtOyTqGYgPNFK>" %}

4. **Show notifications**. Use the same logic to implement notifications.

{% @arcade/embed flowId="efqZNcKZhvcZqqyfucne" url="<https://app.arcade.software/share/efqZNcKZhvcZqqyfucne>" %}

{% content-ref url="/pages/m0UauKOnm5mlSC8KyQjf" %}
[App Customization](/getting-started/quickstart/app-customization)
{% endcontent-ref %}


# App Customization

Branding, color, typographic and menu

This tutorial will show how to customize the app's primary colors, typography, and menus.

{% @arcade/embed flowId="LKK6brg6hPA58MWFfmcC" url="<https://app.arcade.software/share/LKK6brg6hPA58MWFfmcC>" %}

The menu is a great component when you would like to implement navigation between pages.

{% @arcade/embed flowId="Nw4ELeDJtHzDswUJENac" url="<https://app.arcade.software/share/Nw4ELeDJtHzDswUJENac>" %}

{% content-ref url="/pages/-MGI\_FJRHxlJpnWcHKCr" %}
[Publish your App](/getting-started/quickstart/publish-your-app)
{% endcontent-ref %}


# Publish your App

After you've made the changes to your app, you can **preview it** to test and, if everything's right, **publish it**. To preview your app, click on the `Preview` button at the top.

{% @arcade/embed flowId="SIYzbQhcM4L01WTEBpYS" url="<https://app.arcade.software/share/SIYzbQhcM4L01WTEBpYS>" %}

Great! Now that we're done with the Basics, we can get to the **advanced functionality** of Jet Admin:

{% content-ref url="/pages/-MF\_6uRs2tS12EZ0g8Pk" %}
[ Deep dives](/getting-started/part-2-intermediate)
{% endcontent-ref %}


# Creating a Customer Portal

In this section you will learn how to create a customer portal

### PM Portal in 5 mins 🚀

As an example, we'll build a Portal for a Consultancy agency's corporate clients where they can `View` their **Projects**, `Edit` the related **Tasks**, and `Update` their **Profile:**

![](/files/-MjTW8WTERm1JPMglR1J)

To build the portal, we start with **preparing the data**:

{% content-ref url="/pages/-MizqcCIcY9GQAcQiYMy" %}
[Prepare your Data](/getting-started/creating-a-customer-portal/prepare-your-data)
{% endcontent-ref %}


# Prepare your Data

In this section you will learn how to prepare your data for creating a customer portal

You can build Portals with data from pretty much **Any Data Source**: `Firebase, Sheets`, `Airtable`, `Stripe`, `REST API`, and so on. We'll use **Airtable** in our example.

In our case, we will use two tables: Projects and Tasks. **The projects** table has the `Link to Tasks` column and the **Tasks** have the `Project` column in it.

**Projects Table:**

![](/files/-Mj-Bg-HPEyaeOMcP1V0)

**Tasks Table:**

![](/files/-Mj-BmpQEDNYIpgdLvxU)

Next, we **generate the app**:

{% content-ref url="/pages/-Mizqw2Kj8Hu3vyq-0ba" %}
[Generate the App](/getting-started/creating-a-customer-portal/generate-the-ui)
{% endcontent-ref %}


# Generate the App

In this section you will learn how to generate the app for creating a customer portal

### Connect your Data Source

After creating a project, you'll be prompted to start with the Blank app or your Data. Select your chosen Data Source, fill in the credentials, and finish the process.

1. Click on the `Data Source` icon
2. Click on the `Add Resource` icon
3. Choose **Airtable**

{% @arcade/embed flowId="JP2Q7Vs9Of2LQ4rYdTey" url="<https://app.arcade.software/share/JP2Q7Vs9Of2LQ4rYdTey>" %}

### Choose the Page

You can **navigate through** pages and **create new** ones in the top left tab. Now,  let's pick another page:

1. Click on the Pages icon
2. Choose and Navigate to the Page

{% @arcade/embed flowId="b2ownQCQUDzU1CFsdcNx" url="<https://app.arcade.software/share/b2ownQCQUDzU1CFsdcNx>" %}

{% hint style="info" %}
When you connect a Database, Jet Admin automatically **generates an app** based on the pages you selected in the previous step
{% endhint %}

Now let's **test** how it works by&#x20;

1. Clicking on the `Table` to select it
2. Clicking on a `Row` to drill down to the record view

![](/files/-Mj-Td2lG6dOI_ywDYUJ)

Next, let's set up **the Layout**:

{% content-ref url="/pages/-Mizqghl0EdvkHXzRHd7" %}
[Set the Layout](/getting-started/creating-a-customer-portal/set-the-layout)
{% endcontent-ref %}


# Set the Layout

In this section you will learn how to set the layout for creating a customer portal

Jet Admin provides a library of pre-built **UI components**, such as `Table`, `Map`, `Gallery`, or `Charts` that you can **drag and drop** to display your data. As well as the `Layout` components that are used to assemble other components on the page.

### Set the Layout

`Columns` are used to set the horizontal component of the layout. You can add multiple columns and resize them.&#x20;

To add columns, follow the steps:

1. From the Layout menu, drag and drop **Columns**
2. **Drag and Drop** the Tasks Table in the **Right Column**
3. **Drag and Drop** a Form in the **Left Column**

{% @arcade/embed flowId="6Nwgc22eZgdQzUN8KFfA" url="<https://app.arcade.software/share/6Nwgc22eZgdQzUN8KFfA>" %}

We also can change the position of the individual fields in the record view. For that, drill down into the record and drag and drop the fields you want to reassemble:

{% @arcade/embed flowId="I3gyu8LesPigQCpUxvxk" url="<https://app.arcade.software/share/I3gyu8LesPigQCpUxvxk>" %}

Now, let's add our `Project` table and link it to the `Tasks` table:

{% content-ref url="/pages/-Mizrl8MaWUqHSs9-LOJ" %}
[Link Related Tables](/getting-started/creating-a-customer-portal/link-related-table)
{% endcontent-ref %}


# Link Related Tables

In this section you will learn how to link related tables for creating a customer portal

You can **link different tables** as long as there's a common field in both of them. In our case, we'll link by the `Unit name` field.

{% hint style="info" %}
In Jet Admin you can link tables from **different Bases**
{% endhint %}

### Display the Projects

Drag the `Table` component and change the mock data to your own. Select the data source you've connected and the page you want to display:

1. Drag and Drop the Table Component to the page
2. Choose the Resource and the Collection

{% @arcade/embed flowId="7q2aksuonDvNDmR9Ybem" url="<https://app.arcade.software/share/7q2aksuonDvNDmR9Ybem>" %}

### Link the Tables

Each `Unit` has many `Tasks` and we want to see the list of `Tasks` for a given `Unit`. To create this flow, follow the steps:

1. Click on the T**able**
2. Click on the `Filter` icon
3. Choose **Unit ID -> ID equals**
4. Click on the `Formula` icon&#x20;
5. Choose **Units -> Selected Row -> ID**

{% @arcade/embed flowId="hdBNu4urzBykb3PXvuFR" url="<https://app.arcade.software/share/hdBNu4urzBykb3PXvuFR>" %}

Now, let's **customize** our Portal:

{% content-ref url="/pages/-MizrV\_hN23IC0H\_ZFRM" %}
[Customize your Portal](/getting-started/creating-a-customer-portal/customize-your-portal)
{% endcontent-ref %}


# Customize your Portal

In this section you will learn how to customize your customer portal

In Jet Admin, you can **customize the appearance** of your Portal for better usability. Let's start with the `Units` table.

**Let's disable** unnecessary columns and **rearrange** the order.

1. Click on the **Units Table**
2. Disable the unnecessary columns

{% @arcade/embed flowId="LYaHo5hSztGepkgqLi60" url="<https://app.arcade.software/share/LYaHo5hSztGepkgqLi60>" %}

{% hint style="info" %}
In Airtable, field types are detected automatically, but for other data sources you might need to configure them by clicking on the **column icon**
{% endhint %}

Let's now set the number of **displayed rows** to **5**, and make the first row selected by default. To do that, follow the steps:

1. Go to the **Display Tab**
2. Set 5 in the **Rows Per Table** section
3. Enable the **Select First Row By Default** option

{% @arcade/embed flowId="2mIZsLJCVfTuoCwaQcKw" url="<https://app.arcade.software/share/2mIZsLJCVfTuoCwaQcKw>" %}

You can change the **field types** to render different fields differently and customize their appearance. To do so,

1. Click on the **Priority** field
2. Choose **Low Option**
3. Click on the **Color** field
4. Choose the Color

{% @arcade/embed flowId="O0wzcnLu1EGHcL2st20X" url="<https://app.arcade.software/share/O0wzcnLu1EGHcL2st20X>" %}

In Jet Admin, you can configure and customize **any component individually on any page**. Let's make our record fields non-editable so that the users will be able to change them.

1. Click on the **Unit ID** field
2. From the menu on the right, change it to **Editable**
3. Click on the Assign To ID field
4. From the menu on the right, change it to **View-Only**

{% @arcade/embed flowId="tgWMjNELHaMSoJv0JBGc" url="<https://app.arcade.software/share/tgWMjNELHaMSoJv0JBGc>" %}

Applying similar edits to the `Tasks` table and we're done with the UI customization.

<figure><img src="/files/uKELl1gdU40mBqIgrzO8" alt=""><figcaption></figcaption></figure>

Now, let's invite external users and make them interact **only with their data:**

{% content-ref url="/pages/-MizsTUT7xryLnA\_fV2W" %}
[Users & Permissions](/getting-started/creating-a-customer-portal/invite-users)
{% endcontent-ref %}


# Users & Permissions

In this section you will learn how to link set Users and Permissions for creating a customer portal

The key functionality of any Portal is that any user or group of users see and interact **only with their data**. In this step, we'll invite our users and set permissions to turn our Airtable app into a **secure portal**.

### Invite Users

Click `Share` and add the email of a user. Then we can invite this user to the existing team or create a New Team by clicking `Add a new Team`. In our example, we build a portal for corporate clients, so we'll create separate teams for every company we work with.

1. Click on the `Share` button
2. Paste the **Email** you want to send an invite to
3. Click on the `Team` Icon
4. Choose `Add a New` Team
5. Write the **Name** of the **New Team**
6. Click on the `Create` button

{% @arcade/embed flowId="4S1c4rKJWzVxvot6V2Rq" url="<https://app.arcade.software/share/4S1c4rKJWzVxvot6V2Rq>" %}

{% hint style="info" %}
In Jet Admin, **Teams** are the groups of users with the same permissions
{% endhint %}

Then **send invites** to the users.&#x20;

{% @arcade/embed flowId="WdxQ2HoaddaIOJMPRjKS" url="<https://app.arcade.software/share/WdxQ2HoaddaIOJMPRjKS>" %}

### Set the Data Separation

**Team Properties** and **User Properties** are used to set the data separation in Jet Admin. For each team or user, we add a `Property` that uniquely identifies a company or a client, such as `domain` or `email`. In our case, we use the company name:

1. Click on the **Add Property**
2. **Choose the Name of the Property**
3. Click on the `Create` button
4. Set the property of the team

{% @arcade/embed flowId="1vVYyB8kUeFeCEFYvDDe" url="<https://app.arcade.software/share/1vVYyB8kUeFeCEFYvDDe>" %}

{% hint style="info" %}
To be able to separate data, we need to have the property value in our data
{% endhint %}

Next, we need to **filter** our Portal's data by the property. Select the component you want to separate data for, proceed to filters, and set them `Client field` to match `Client property` what we've created.

1. Choose the **Table**
2. Click on the `Filter` icon
3. Choose **Client -> Client equals**
4. Click on the `Formula` icon
5. Choose **Team Properties -> Client**

{% @arcade/embed flowId="xtNGUpI44uaOZz1tBtxl" url="<https://app.arcade.software/share/xtNGUpI44uaOZz1tBtxl>" %}

### Set Permissions

Additionally, we want our Coffee Beans employees to interact only with the portal page we've created. For this, go to the **Teams** and set page-level permissions to allow access to the `Tasks` , `Tasks-edit` and the `Tasks-create` pages:

![](/files/-Mj3LexdUBBsS4z0z_D7)

Now, let's check how that works: the Beans Coffee employee that we've invited can see **only their company's projects**:

![](/files/-Mj3Qy5_4OXYQ_zT7yw8)


# &#x20;Deep dives

In depth tutorials covering multiple topics

This part focuses on advanced Jet features such as **custom HTTP**, **SQL** queries, **conditional visibilit**y, and **related fields** (e.g. single relation). Let's start with the latter:

{% content-ref url="/pages/-MF\_Kmi3lE\_fay--eOUm" %}
[Single relations](/getting-started/part-2-intermediate/single-relations)
{% endcontent-ref %}

{% content-ref url="/pages/-MF\_L60P9tcQ6\_jLuDva" %}
[Reading data from SQL](/getting-started/part-2-intermediate/reading-data-from-sql-1)
{% endcontent-ref %}

{% content-ref url="/pages/-MF\_KzQK3Uy2IpjboDR5" %}
[Reading data from API](/getting-started/part-2-intermediate/perform-api-requests)
{% endcontent-ref %}


# Single relations

**Single relations** help you fetch data from the **related collections**.&#x20;

To illustrate how it works, let's imagine we have the `Transactions` table that doesn't contain a **customer's email** and the `Users` table that contains the customer information including the email:

![](/files/-MkNPkf61ukzo95Sex7S)

And we want to **display the email** in the `Transactions` list:

![](/files/-MkNSOI-p4c83n5VXJT5)

First of all, we identify how our tables are **related**: for each user, there are several transactions that are related to the users list by the **ID** and **Customer ID fields:**

![](/files/-MkNN1Zfv7MgU1uT4A6a)

Now, let's create a new **custom column** in the `Transactions` table:

![](/files/-MkNTfKtz24SDPcnPcsU)

Then change the **column type** to `Link to record`

![](/files/-MkNUgvW4-UXL5u_HPQL)

Now, we need to select where we'll get the user email from (a related `Users` table), what field in the `Users` table is used to set relations with the `Transactions` table (the `ID` field), and what field from the `Users` table we'd like to display (the `Email` field):

![](/files/-MkNWT6xG9xGbSQ0OZDQ)

And the **final step** is to get our custom field value from the `Transactions` table field that sets relations to the `Users` table (the `Customer ID` field):

![](/files/-MkNXnKZh7yXZuEOwA7k)

Now, let's make UI components **dynamically visible** based on a rule:

{% content-ref url="/pages/-Mkg6VpZJSj1ZRY0u6Qf" %}
[Conditional Visibility](/getting-started/part-2-intermediate/conditional-visibility)
{% endcontent-ref %}


# Conditional Visibility

In Jet Admin, you can make certain components visible or invisible depending on the values or combination of values from your data or user attributes.&#x20;

Say, we want to show two different status change `buttons` depending on the status value of the selected row of the `users` table:

![](/files/-MkgFhSXlnt5fbAjvCz0)

{% hint style="info" %}
If standard permissions are not enough and you may want to **restrict access** on the level of **individual UI components**, use [user properties](/user-guide/security-and-privacy/user-and-team-properties) in the visibility logical expression
{% endhint %}

To achieve that, let's first drop **two buttons**: one that changes the status of a user to "active" and the other that changes it to "inactive":

![](/files/-MkgHjYYjBz2TurTvxpq)

Then, we proceed to the "Activate" button's settings to the **"Visible" section**:

![](/files/-MkgIeg9WfYt8QbOJPlC)

Next, we type in the condition: `IF` the `status` value from the selected row equals "inactive", then return `true`, otherwise, return `false`. Returned `true` will make the component visible and `false` will make it invisible:

![](/files/-MkgKklxhgu8c3b0s1JQ)

Here's the expression: `=IF(EQ(elements.users["0"].selected_item.Status, "inactive"), 1, 0)`

Then we do the same for the "Deactivate" button, grabbing the "active" value from the selected row:

`=IF(EQ(elements.users["0"].selected_item.Status, "active"), 1, 0)`

And we get our buttons being **dynamically hidden** based on the status value from the selected row:

![](/files/-MkgFhSXlnt5fbAjvCz0)


# Reading data from API

If you need to make your own API request, simply select **"Make an HTTP request"** as the operation. This allows you to connect to any external API and display the response data using available components, such as tables or charts. Just configure the request method, URL, headers, and any necessary parameters based on your API.

### Make an API request using API Builder

1\. Go to the Component Settings then `Add Data Resource`

2\. Select a resource then choose collection as `Make an HTTP request`

{% @arcade/embed flowId="YsnZSlIwPuBdUzzsLNRz" url="<https://app.arcade.software/share/YsnZSlIwPuBdUzzsLNRz>" %}

### Pass API parameters

Now you are in API Query Builder. Specify `endpoint` and add any new parameter.

<figure><img src="/files/J0ACQYmePvJ0L6NVy4X4" alt=""><figcaption></figcaption></figure>

### Use tokens on your API request

If you need to pass tokens or other important headers, simply navigate to the **Headers** section and add the required key-value pairs. For example: `Authorization`, `Content-Type`, or any custom token headers.

<figure><img src="/files/5hYiv5dN8p8MwGp3LPyC" alt=""><figcaption></figcaption></figure>

### Transform your response

To transform the response, use the `Transform` feature to specify the result of your request:

<figure><img src="/files/TX9ubfqLmeo6YdJGDt4E" alt=""><figcaption></figcaption></figure>

### Paginate by pages

If you need pagination, simply navigate to the **Pagination** section and choose your preferred type — such as **Client-side** or **Server-side** (Page, Offset, or Cursor Pagination).

* For **Client-side** pagination, filters, sorting, and pagination are applied automatically — no additional configuration needed.
* For **Server-side** pagination, select the appropriate type (Page, Offset, or Cursor) and configure the necessary parameters based on your API’s structure. You can also use a transformer to adjust the response format if needed.<br>

<figure><img src="/files/B30kMK19CxWiNIiwhrc0" alt=""><figcaption></figcaption></figure>

### Run your request

Simply click `Test Request` button to run your request

<figure><img src="/files/7B4ucvCf8kGzWlfzueJn" alt=""><figcaption></figcaption></figure>

{% content-ref url="/pages/-MAARNCnpjDL0xKCL8Pp" %}
[Making API requests](/user-guide/data/make-an-http-request)
{% endcontent-ref %}


# Reading data from SQL

The SQL Query Builder lets you create, edit, and run queries easily. You can write SQL manually, insert tables and columns, or let AI generate queries and transformations for you.

### Writing and Generating Queries

You can type SQL directly in the editor or click **Ask AI** to describe what you need in plain language. AI will generate the SQL for you—for example, *“show tickets created in 2019 with low priority.”*

```sql
SELECT *
FROM Tickets
WHERE "Opened date" BETWEEN '2018-01-01' AND '2024-12-31';
```

{% @arcade/embed flowId="B1cUtKdZJcMZRr2xFKuv" url="<https://app.arcade.software/share/B1cUtKdZJcMZRr2xFKuv>" %}

Or consider using AI to refine or write your SQL query for enhanced accuracy and efficiency.

{% @arcade/embed flowId="NvrLmzZbiySNDqwW11WS" url="<https://app.arcade.software/share/NvrLmzZbiySNDqwW11WS>" %}

### Inserting Tables and Columns

On the right-hand panel, you will see a list of all available tables and their columns. By clicking on any table or column, it is automatically inserted into your SQL editor. This eliminates the need to manually type table names or remember exact column names, reducing errors and making query construction much faster.

<figure><img src="/files/5CEtCArtOijjR1tCUFPF" alt=""><figcaption></figcaption></figure>

### Inserting Custom Inputs

The Query Builder also allows you to add dynamic parameters using the **Insert Input** option below the editor. Inputs act as placeholders for values that can change, so you can reuse the same query multiple times with different filters. This is particularly handy when running similar queries across different date ranges or user IDs without rewriting SQL each time.

<figure><img src="/files/hfFAxBqUyEW3Yn37kD04" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}

### Prettify SQL

Click **Prettify SQL** to automatically format your query, making it more readable and easier to debug.
{% endhint %}

### Transforming Query Results

After running a query, use the **Transform** feature to adjust results. Choose from dropdown options or write custom JavaScript. AI can also generate transformation code to rename fields, restructure data, or filter results.

{% @arcade/embed flowId="NMcY31rHAKf7igivIPLV" url="<https://app.arcade.software/share/NMcY31rHAKf7igivIPLV>" %}

### Testing, Previewing, and Saving

Click **Test Request** to run your query and check the results in the **Preview panel**. Once everything looks correct, click **Save** to reuse the query later—ideal for recurring reports or analysis.

{% hint style="info" %}

### Best Practices

To get the most out of the SQL Query Builder, it’s a good idea to prettify queries regularly for readability, and make frequent use of AI assistance for complex SQL generation. Inputs should be used whenever possible to create dynamic, reusable queries. Transformations are a powerful way to adjust your results without altering the base SQL, and testing queries before saving ensures accuracy. Finally, previewing results after execution helps confirm that your query meets the intended goals.
{% endhint %}


# Reading data from SQL

Let's say, we need to display order total amount on `Customer` table for each customer. All Orders we stored in the separate `Orders` table in the SQL database.&#x20;

The result`Customers`table contains: `customer_id`, `photo`, `name`, `total_amount`columns of data for each customer.

### Build SQL query using SQL Builder

1\. Go to the Component Settings then `Add Data Resource`

![](/files/-MGaGGH4oL0pnZ2iIv5V)

2\. Select a resource (SQL database) then choose collection as `Make an SQL request`

![](/files/-MGbbiVX1PFrzeIhkAtx)

### Write SQL query

Let's write a SQL query that returns customers includes the total amount column:

```sql
select 
(select sum(amount) from orders where customer_id = customerscrm.id) as total_amount,
id,
photo,
name
from 
customerscrm
```

![](/files/-MGbcucSNZUlfpiVBir7)

### Tips

Here is a list of your available tables, you can see the table columns. You can use them while writing SQL, just click on the table name and the name will be automatically added.

![](/files/-MGbdbnDARXgDvu6TbTh)

### Run your SQL query

Simply click `Update Result` button to run your SQL command.

![](/files/-MGbe8JDvVonoeXxltFU)

### Customize table

Just close SQL Query Builder to start to customize the result table.

![](/files/-MGbehytc7zFuHma4cMT)

{% content-ref url="/pages/-MACAp62Ew2HNnkoMkrb" %}
[Making SQL queries](/user-guide/data/make-a-sql-query)
{% endcontent-ref %}


# Generate Invoice or Document


# Document

Create documents from your data right in Jet Admin

<figure><img src="/files/9klj86OMrBYXTvKsYFjR" alt=""><figcaption></figcaption></figure>

Generate documents for your Jet Admin applications with the Documint.

{% embed url="<https://www.loom.com/share/1d0ad685efe348b3a5ce144e359aa5b9?from_recorder=1&focus_title=1>" %}


# Send Emails

Send emails from a Jet app

Jet Email allows you to send emails via Action or Workflow/Automations. All emails will be sent through **<no-reply@jetadmin.app>** (unless you have set up a custom *From* email address in App Settings).

Use the following guide to set up emails, and specify the next operation:

1. Choose operation -> App built-ins
2. Action -> Send email

![](/files/ht0qCqtvd100tCvKpSfd)

3\. Specify inputs:

* to – receiver email (allows only email's format)
* subject – text field to specify the email subject
* text – text field without markups
* text (HTML) – text field with markups

![](/files/F867LGB1TcAvxM5G1bw8)

{% hint style="info" %}
The maximum limit number of emails to be sent is 10 emails per 1 minute.
{% endhint %}


# Pixel Perfect App

Design your first custom component from scratch using Component Designer

To familiarize yourself with how `Customize with Designer` works, let's build a simple design:

{% embed url="<https://www.youtube.com/watch?v=-u6X4gpCWj8&t=16s&ab_channel=JetAdmin>" %}

<figure><img src="/files/KvFv2XgaunA4UAvAfxr1" alt=""><figcaption></figcaption></figure>

We'll go through the whole **process of creation** step-by-step.&#x20;

### **1. Design your component**&#x20;

**1.1 Choose Component Type**

Identify the type of component you want to create, whether a button, card or any other UI element.

{% @arcade/embed flowId="e986hg2hXRjuOfMN1uGx" url="<https://app.arcade.software/share/e986hg2hXRjuOfMN1uGx>" %}

**1.2 Customization with Designer**

**Step 1: How to add shapes**

Select the shape you want to utilize from the menu on the top left. In the example, we will use Rectangle and Ellipse shapes.

{% @arcade/embed flowId="tHEIVQEXp7tmHjPOqRY9" url="<https://app.arcade.software/share/tHEIVQEXp7tmHjPOqRY9>" %}

**Step 2: How to add parameters**

To add a parameter to the card, you need to use the menu on the top left. After adding a parameter you need to specify type and test value.

{% @arcade/embed flowId="K4g9WpLVlMqNcnv0XFvS" url="<https://app.arcade.software/share/K4g9WpLVlMqNcnv0XFvS>" %}

**Step 3: How to add borders**

You can add borders to the shapes or reshape them. To add borders or reshape, choose the shape and use the menu on the right.

{% @arcade/embed flowId="tJuH1P3DuoWr1KGhdUR5" url="<https://app.arcade.software/share/tJuH1P3DuoWr1KGhdUR5>" %}

\
**Step 4: How to locate fields**

Use the tutorial below to locate the fields for the parameters.

{% @arcade/embed flowId="xLtlwzXqhNBYs88MUNh0" url="<https://app.arcade.software/share/xLtlwzXqhNBYs88MUNh0>" %}

### **2. Pass and bind data with elements.**

After creating the design, you need to bind it with the table data.&#x20;

{% @arcade/embed flowId="W1tBfHOyhfPBZvQ6y3GW" url="<https://app.arcade.software/share/W1tBfHOyhfPBZvQ6y3GW>" %}

### **3. Conditional visibility (Component Visibility, Conditional Fills)**

For changing the visibility of a component please follow the steps as shown below.

{% @arcade/embed flowId="6ya9Zo2mBFCpaLEhofSA" url="<https://app.arcade.software/share/6ya9Zo2mBFCpaLEhofSA>" %}

### **4. Responsiveness**

To check how your design will respond to different screen sizes, please follow the steps shown below. Ensure that it maintains its integrity and functionality across various devices.

{% @arcade/embed flowId="hIz9gNH1QAh9z5gLziPW" url="<https://app.arcade.software/share/hIz9gNH1QAh9z5gLziPW>" %}


# Designing your component

Discover how to custmize Cards in Gallery

To customize Cards in the Gallery, follow the steps:&#x20;

1. Click on the **Gallery**
2. Click on the **Property card** button in the right panel
3. From the dropdown menu, choose **Customize with Designer**

{% @arcade/embed flowId="ez1HHLwTqX296dN72JLb" url="<https://app.arcade.software/share/ez1HHLwTqX296dN72JLb>" %}


# Adding Images

Explore how to customize background

To add shapes, follow the steps:

1. Click on the `Shape` icon in the Toolbar at the top-left.
2. Select `Rectangle` as a **Shape**
3. Drag-and-drop `Rectangle` to the Canvas

{% @arcade/embed flowId="tHEIVQEXp7tmHjPOqRY9" url="<https://app.arcade.software/share/tHEIVQEXp7tmHjPOqRY9>" %}

Customize (resize, reshape, position,...) the `Rectangle shape` using the **Right sidebar**:

1. Click on `Rectangle`&#x20;
2. Update the positioning of `Rectangle`

{% @arcade/embed flowId="DMXaFN212kTMC2GiSTxi" url="<https://app.arcade.software/share/DMXaFN212kTMC2GiSTxi>" %}

3. Update the corner radius of `Rectangle`

{% @arcade/embed flowId="bLW6ri0wNTktVtIDkZpP" url="<https://app.arcade.software/share/bLW6ri0wNTktVtIDkZpP>" %}


# Apply Frame to Image

Explore how to set up Frame for Image

To set up Frame for **Image** – add `Border` to the `Rectangle`:

1. Select `Ellipse`
2. Click on the `Add Border` button on the **Right sidebar**
3. Set the color of the border
4. Set the thickness of the border

{% @arcade/embed flowId="tJuH1P3DuoWr1KGhdUR5" url="<https://app.arcade.software/share/tJuH1P3DuoWr1KGhdUR5>" %}


# Pass values to Image

Explore how to data from Visual Builder to Component Designer

To pass data of type **Image** from Visual Builder to Component Designer, use the Parameters:

1. Click on `Parameters` in **Toolbar**
2. Click on `Add Parameter` in the `Parameter sidebar`
3. Click on `Edit` button to rename the **Parameter**
4. Change the type of the parameter to **Image**
5. Drop a test value for the **Parameter**
6. Save the test value

{% @arcade/embed flowId="deNQopC4ShJdvrInLtlH" url="<https://app.arcade.software/share/deNQopC4ShJdvrInLtlH>" %}

To show an image in the design, follow the steps:

1. Click on the shape you want to add an image to.
2. Go to the fills on the **Right Sidebar.**
3. Click on the `Image` button.
4. Click on the `Set up with Formula` button.
5. Specify the formula.
6. Select the corresponding parameter.

{% @arcade/embed flowId="QlNVvWochLAnZdzdOCUI" url="<https://app.arcade.software/share/QlNVvWochLAnZdzdOCUI>" %}


# Pass values to Text Field

Discover how to pass values to Designer

To add text to your design, follow the steps:

1. From the menu on the top left, click on the `Text` button.
2. Locate the field in your design.
3. Add a test value to the field and save it.

{% @arcade/embed flowId="gtgwUVxPslSwPiA7wbjW" url="<https://app.arcade.software/share/gtgwUVxPslSwPiA7wbjW>" %}

To connect the text field to the parameter using the **formula,** follow the steps:

1. Click on the field you want to connect a parameter to.
2. Click on the `Function` button.
3. Click on the `Function` button inside the field to specify the parameter.
4. Choose the parameter you want to connect.

{% @arcade/embed flowId="UqsvudiiW8V80TEmJEsa" url="<https://app.arcade.software/share/UqsvudiiW8V80TEmJEsa>" %}


# Binding data

Discover how to pass and bind the data with elements

To pass and bind simple data with the elements, follow the steps:

1. Click on the **Gallery**
2. Click on the `Property card`
3. Click on the `Change Data Binding`
4. Pass the corresponding **Data** for each of the **Custom Componen**ts.&#x20;
5. Click `Use Selected Binding` for saving.

{% @arcade/embed flowId="W1tBfHOyhfPBZvQ6y3GW" url="<https://app.arcade.software/share/W1tBfHOyhfPBZvQ6y3GW>" %}

To pass and bind data with the elements using **Functions**, follow the steps:

1. Click on the **Gallery**
2. Click on the `Property card`
3. Click on the `Change Data Binding`
4. Click on the `Set up with Formula` button
5. Click to search for the **formula** – `CONCAT`
6. Choose the fields: `first_name` and `last_name` – you want to concatenate: CONCAT(`first_name``, last_name`)
7. Click on the `Use selected binding` for saving it

{% @arcade/embed flowId="A60qQRej2ZicsofcqrDI" url="<https://app.arcade.software/share/A60qQRej2ZicsofcqrDI>" %}


# Hide elements

Discover how to hide elements with Conditional Visibility

Hiding elements is useful for optimization, such as concealing large navigation menus on smaller screens. Conditional visibility improves user experience by showing only relevant content.

Hide elements in Component Designer using Conditional Visibility:

1. Click on the **element** you want to **set conditional visibility** to.
2. Go to the **Right Sidebar**.
3. Click on the `Conditional Visibility` button.
4. Scroll and choose the option that fits the best for your requirements.

{% @arcade/embed flowId="6ya9Zo2mBFCpaLEhofSA" url="<https://app.arcade.software/share/6ya9Zo2mBFCpaLEhofSA>" %}

Dynamically change elements in Component Designer using Conditional Fill:

1. Click on the **element** you want to **set the conditional fill** to.
2. Go to the **Right Sidebar**.
3. Go to the `Fill` section.
4. Click on the `More` button to see more options.
5. Scroll and choose the option that fits the best for your requirements.

{% @arcade/embed flowId="lXwalnXKIGa3TonER8z6" url="<https://app.arcade.software/share/lXwalnXKIGa3TonER8z6>" %}


# Support multi-screens

Explore how to do your components responsive

Responsiveness and support of multi-screens refers to the ability of a design to adapt and display optimally across various devices and screen sizes. It ensures a seamless user experience by adjusting layout and content to accommodate different resolutions, promoting accessibility and usability.

To fit your component to different screen sizes, follow the steps:

1. Click to fix the width for the text component.
2. Go to the resizing section in the **Right Sidebar**.
3. Fix the borders for the text.

{% @arcade/embed flowId="hIz9gNH1QAh9z5gLziPW" url="<https://app.arcade.software/share/hIz9gNH1QAh9z5gLziPW>" %}


# UI in seconds

Learn how to generate CRUD interface in seconds

Jet can automatically generate a user interface when creating a new page. There are several use cases that you can cover:

1. **Record Review**: allows you to view the details of a record selected from a list.
2. **Record Update**: update the data of a record chosen from the list.
3. **Record Create**: create new records using a form layout.
4. **Dashboard**: visual display of your data, incorporating KPIs and charts for a comprehensive overview.

{% @arcade/embed flowId="AnJguxPnG54dbDUH89JG" url="<https://app.arcade.software/share/AnJguxPnG54dbDUH89JG>" %}


# Figma design into a web app

From MVPs to web apps, Jet helps you to deliver pixel-perfect apps that users will love.

{% embed url="<https://www.youtube.com/watch?v=F5RYVPibse8>" %}

{% embed url="<https://youtu.be/C6M-6CjAc5c?si=wA2IU0pHqd-yZyi1>" %}


# Token Usage


# Agents

Learn how to use Jetadmin Agents to automate tasks using natural language and LLMs, no coding or complex logic required.

### What Are Agents?

Agents in JetAdmin are AI components that can understand a task, decide what actions to take, and execute them using available tools. They don’t rely on fixed steps instead, they determine the best way to complete a task based on your instructions and context.

### Key Characteristics

* **Decision-based**: choose actions instead of following fixed logic
* **Action-oriented**: use tools, workflows, and data to get things done
* **Interactive**: can be triggered through chat or other inputs
* **Contextual:** use instructions and past input to guide behavior

### Creating Your First Agent

{% stepper %}
{% step %}

#### Add an Agent

Add an agent to your app in JetAdmin using one of the following:

* Add it as a **component** from the components panel
* Create it inside a **workflow** using a trigger or step
* Use the **Agents section** from the left sidebar

{% content-ref url="/pages/7zqyEDQEsPbYt7fWYSq6" %}
[Add an Agent](/agents/add-an-agent)
{% endcontent-ref %}
{% endstep %}

{% step %}

#### Add Tools

Connect the tools your agent will use to perform actions.

This can include:

* **Data sources** (e.g. Airtable, Supabase, internal tables)
* **Integrations** (e.g. APIs, external services)
  {% endstep %}

{% step %}

#### Write Instructions

Define how the agent should behave and what it should do. Keep instructions clear and specific to get better results.

Example (Data Manager Agent):

```
You're a data management assistant responsible for working with application data.

Your responsibilities:
1. Retrieve and display data based on user requests
2. Create new records when instructed
3. Update existing records with clear confirmation
4. Delete records only after explicit user approval
5. Analyze data and provide insights when requested

Guidelines:
- Always confirm before making changes that affect data
- Ensure accuracy when reading or modifying records
- Clearly explain any updates or actions performed
- If the request is unclear or incomplete, ask for clarification
```

{% endstep %}

{% step %}

#### Test Thoroughly

Run the agent with different inputs to make sure it:

* Understands the task
* Uses the correct tools
* Produces reliable results
  {% endstep %}
  {% endstepper %}

### How Agents Work

Agents in JetAdmin combine instructions, tools, and built-in decision logic to figure out the best way to complete a task, one step at a time.

{% @arcade/embed flowId="shdqfKBJ6wLtfV5WnaLm" url="<https://app.arcade.software/share/shdqfKBJ6wLtfV5WnaLm>" %}

{% hint style="info" %}

### Agents vs Workflows

* **Agents:** dynamic, decide the next step
* **Workflows:** predefined, execute fixed steps

Agents can use workflows when structured execution is needed.
{% endhint %}


# Add an Agent

Choose how to add a Jetadmin agent to your app

You can set up agents in several ways:

* Use Jetadmin triggers by selecting “Agent” as the action when setting one up.

{% content-ref url="/pages/qmG6B8DT5DDHSkQXDhhM" %}
[Triggers](/user-guide/workflow/triggers)
{% endcontent-ref %}

{% @arcade/embed flowId="qM5YHy90gQHp6vJewhG5" url="<https://app.arcade.software/share/qM5YHy90gQHp6vJewhG5>" %}

* **Choose from the component list:** Type “Agent Chat” in the search box and drag it onto your page

{% @arcade/embed flowId="dzyDUvcYhYQSoDLzku7K" url="<https://app.arcade.software/share/dzyDUvcYhYQSoDLzku7K>" %}

* **Left menu:** Click **Agents** → **Add Agent**.\
  Then choose to **create an agent from scratch** or **use a built-in template**.

{% @arcade/embed flowId="v5wuQBO1pEK3iuS5n3sy" url="<https://app.arcade.software/share/v5wuQBO1pEK3iuS5n3sy>" %}

{% hint style="info" %}

### When to Use Agents

Agents are useful when you need more than simple automation rules. They are best for:

* **Complex workflows** where steps depend on reasoning or context.
* **Customer-facing chatbots** that can pull data from multiple sources.
* **Task delegation** when actions may involve multiple systems or tools.
* **Dynamic decisions** that go beyond pre-defined logic.

If your task is straightforward and always follows the same pattern, a regular workflow or automation may be enough. If it requires flexibility and decision-making, an agent is the better choice.
{% endhint %}


# Agent Tools

Agents in JetAdmin use tools to interact with data, perform actions, and extend their capabilities.

Instead of defining logic manually, you can enable tools that allow the agent to fetch information, take actions, and process results.

### Tool Capabilities

#### Data Access & Operations

Connect data sources and MCP integrations to let the agent:

* Read and query records
* Create new entries
* Update existing data
* Delete records when needed

This is essential for building agents that work with your application data.

<figure><img src="/files/rmElW5GuW7bcKhn7gTMO" alt=""><figcaption></figcaption></figure>

#### Internal Actions

Use built-in tools to perform actions inside your app, such as:

* Sending emails
* Accessing user or team data
* Triggering internal processes

{% @arcade/embed flowId="xhd7W8vJqxK2EMzQImry" url="<https://app.arcade.software/share/xhd7W8vJqxK2EMzQImry>" %}

#### External Information

Enable tools that allow the agent to retrieve information from outside your system:

* **Internet Search:** find up-to-date information
* **Fetch URL Content:** read and analyze specific web pages

<figure><img src="/files/GZEAYYyMrQ6N4MgXUw45" alt=""><figcaption></figcaption></figure>

#### Content Generation

Allow the agent to generate new content:

* **Image generation:** create visuals from prompts
* **Code execution:** process data, run logic, or perform calculations

<figure><img src="/files/ROC7HOjtTo7YhJRYNZNr" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}

#### Best Practice

Focus on enabling only the tools required for your use case.\
Fewer tools lead to more predictable behavior and better performance.
{% endhint %}


# Agent Skills

Skills allow you to extend agent behavior with reusable instructions and capabilities.

A skill can contain custom instructions, knowledge, or specialized behaviors that agents can use when responding to users.

Skills can be attached to multiple agents and managed centrally.

### Add a Skill

To add a skill:

1. Open your agent settings
2. In the right-side **Skills** section, click **Add Skill**

{% @arcade/embed flowId="fBapfj7IiEbENYYrxIl0" url="<https://app.arcade.software/share/fBapfj7IiEbENYYrxIl0>" %}

{% hint style="info" %}
There are two ways to create a skill:

* Upload a skill file
* Write skill instructions manually
  {% endhint %}

### Upload a Skill

To upload an existing skill:

1. Click **Upload Skill**
2. Select the skill file from your device

The skill will be uploaded and added to the agent.

<figure><img src="/files/sYP2LxpBQntWk4DgbecM" alt=""><figcaption></figcaption></figure>

### Write Skill Instructions

You can also create a skill manually.

Fill in the following fields:

| Field        | Description                                      |
| ------------ | ------------------------------------------------ |
| Skill Name   | Name of the skill                                |
| Description  | Short description of what the skill does         |
| Instructions | Detailed instructions and behavior for the skill |

After completing the fields, click **Create Skill**.

<figure><img src="/files/8vyrPEj89IkgRRuJgoMH" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}

## Managing Skills

After creating a skill, you can:

* Add it to multiple agents
* Edit the skill
* Download the skill
* Replace the skill file
* Delete the skill
  {% endhint %}

### Using Skills in Agent Instructions

After attaching a skill to an agent, you should define in the agent instructions:

* When the skill should be used
* How the skill should be used
* Which types of requests should trigger the skill

This helps the agent understand when to apply the connected skill during conversations.

> **Best Practice**
>
> Keep skill instructions focused and specific.\
> Clearly describing when a skill should be used improves agent reliability and response quality.




---

[Next Page](/llms-full.txt/1)

