How to add Airtable as a database for content in Webflow Cloud

Learn how to serve Airtable records through a Next.js app on Webflow Cloud so editors keep one source of truth.

How to add Airtable as a database for content in Webflow Cloud

Ismail Ajagbe
Technical Author
View author profile
Ismail Ajagbe
Technical Author
View author profile
Table of contents

If your editors already live in Airtable, a Webflow Cloud app can read that base directly, so nobody has to copy rows into the CMS to publish them.

Marketing teams can keep running a partner directory or glossary from an Airtable base because the people who own that data live in Airtable all day. However, when someone has to copy rows into CMS items, the website can drift from the base.

Connecting Airtable directly to Webflow Cloud solves this sync issue. The Next.js 15 app runs on Webflow Cloud and uses a typed server-side helper to read Published records from Airtable. Its page renders those records at the mount path, while a Route Handler makes the same data available as JSON.

Airtable stays the place editors work, and the site reflects the base on the next request.

In this guide, we will walk through setting up the Airtable schema, configuring personal access tokens, and deploying a Next.js application on Webflow Cloud to serve live Airtable content seamlessly.

What do you need to add Airtable as a content database in Webflow?

You need an editable Airtable base, token permission, a local Node.js environment, a compatible Next.js project, and a Webflow site on Starter or higher (Premium is required for a custom-domain mount).

Gather these items before you configure the application:

  • Airtable base: Use a content table you can edit so you can add Status and read the base ID.
  • Token permission: Use an Airtable account that can create a scoped personal access token for the target base.
  • Webflow site: Start with any plan from Starter up; staging is free, while a custom-domain mount requires Premium or higher.
  • Local environment: Install Node.js locally with npm so you can run and test the Next.js project before deployment.
  • Next.js project: Use version 15 or higher, which is the floor Webflow Cloud lists for Next.js apps

With these five prerequisites ready, you can structure the Airtable source and build the application in deployment order.

6 steps to add Airtable as a content database in Webflow Cloud

These six steps produce a Next.js app that reads Published Airtable records on each request, renders them server-side, exposes matching JSON, and runs under a Webflow Cloud mount path.

The build moves from the Airtable schema and credentials through the server-side helper, Route Handler, page, and Webflow Cloud deployment.

1. Structure the Airtable table for publishing

Status gives editors control over which rows appear on the site. Add a single-select field named Status to the table that holds your content, with two options, Draft and Published, and set every row you want live to Published.

The filter in the fetch helper keys off that field, so changing the select value publishes or unpublishes a row while keeping it in the table.

I set Draft as the default for new rows so a half-written entry never reaches the site by accident. Keep the rest of the schema small and stable, because every field you rename later is a code change.

These are the fields the code expects:

Airtable field Field type What the app does with it
Title Single line text Heading for each item
Slug Single line text Stable identifier for URLs; falls back to the record ID
Body Long text Description shown under the heading
Status Single select (Draft, Published) Filter; only Published rows are fetched
Published At Date Sort order, newest first
Airtable field → Field type → What the app does with it
Title
Single line text
Heading for each item
Slug
Single line text
Stable identifier for URLs; falls back to the record ID
Body
Long text
Description shown under the heading
Status
Single select (Draft, Published)
Filter; only Published rows are fetched
Published At
Date
Sort order, newest first

Open the base's API documentation to read the base ID; it begins with app. Referencing the table by name works, and the AIRTABLE_TABLE variable holds that name, so renaming the table in Airtable means updating the variable too.

You now have a table where flipping Status to Published is the publish action, and a base ID ready to configure.

2. Create a scoped Airtable personal access token

The token needs exactly one scope, data.records:read, and access to only the target content base. Create it in Airtable's developer hub. A read-only token on one base limits the blast radius if it leaks: it allows reads from that base and blocks writes and access to your other bases.

Airtable shows the token value once at creation, so copy it into a password manager before you close the dialog.

The token is tied to the Airtable account that created it. On a client project, token ownership matters more than the scope. If the token sits on a contractor's account and that account is later removed from the workspace, the site stops reading content with no code change to explain why. Create it from an account the client controls.

You now have a token string beginning with pat that can list records from one base.

3. Prepare the Next.js app and add the Airtable variables to Webflow Cloud

Open the Next.js 15 project with the App Router and TypeScript prepared for this build, then add four variables to your Webflow Cloud environment.

Webflow Cloud's environment variables documentation states that "Both secret and non-secret environment variables are available to your application's build process and to the deployed application at runtime", and secret values are redacted from build logs, so the token can be stored as a secret and remain available to the build.

Use npm for this project, as Webflow Cloud requires. The project should have a package.json ready for the helper.

In the Webflow Cloud settings for your site, open the environment you will deploy to and add AIRTABLE_TOKEN as a secret, then AIRTABLE_BASE_ID, AIRTABLE_TABLE, and NEXT_PUBLIC_BASE_PATH as plain variables. Set NEXT_PUBLIC_BASE_PATH to the mount path you intend to use, such as /resources.

The deployed environment now contains the Airtable configuration while keeping the token redacted.

Mirror the names locally so next dev has the same shape:

# .env.local
AIRTABLE_TOKEN=your-personal-access-token
AIRTABLE_BASE_ID=your-base-id-starting-with-app
AIRTABLE_TABLE=Resources
# Leave empty locally: next dev serves at the root, Webflow Cloud serves at the mount path
NEXT_PUBLIC_BASE_PATH=

With both sets in place, the same code reads the token from process.env on your machine and on Webflow Cloud, and the token stays out of the repository.

4. Write the Airtable fetch helper

Airtable’s Web API returns records as a records array of { id, createdTime, fields } objects. It includes an offset string when more pages remain and accepts a filterByFormula query parameter written in Airtable formula syntax.

The server-only helper follows that pagination, fetches every Published record, and normalizes each record into a typed object the rest of the app can render.

Create lib/airtable.ts as the server-only module for that helper.

Two choices in that file are deliberate. The helper throws when a variable is missing, which produces a named configuration error in the logs. This avoids an empty list that looks like "no content yet".

The loop follows offset until Airtable stops returning one, so a table that outgrows a single page still renders in full. All requests run on the server; the token appears only in a server-side request header.

You now have a function that returns a typed, newest-first array of published items, or an error naming exactly what went wrong.

5. Expose the records through a Route Handler

The JSON endpoint lives at app/api/content/route.ts and gives browser-side clients access to the content.

This GET endpoint is intentionally unauthenticated because it serves public content. Every anonymous call can trigger an Airtable request and consume Airtable request quota and application resources. Before production, put a rate limit or cache in front of the route to control abuse and upstream request volume.

Create the handler so it calls listContent, returns the items as JSON, and handles upstream failures with a generic response. The handler returns a 502 with a generic message when Airtable or the configuration fails. It logs the real error server-side, so the token and the Airtable response body stay hidden from visitors.

Locally, npm run dev followed by a visit to http://localhost:3000/api/content returns { "items": [...] } containing your published rows.

6. Render the content server-side, then mount and deploy

Dynamic rendering ensures that each request reads Airtable instead of serving a snapshot taken during the build. The page calls the helper directly because the server component and helper share the same runtime. This avoids an extra HTTP request.

Create app/page.tsx as the server-rendered page that calls listContent and maps the returned items into the list. That page renders whatever the helper returns, with each item anchored by its slug.

Configure and deploy the app in Webflow Cloud. Set /resources as the mount path. Use the same value stored in NEXT_PUBLIC_BASE_PATH.

Open your site's staging domain followed by /resources. You should see the Published rows from Airtable as a list, and /resources/api/content should return the same records as JSON. Change a row's Status in Airtable and reload; the list updates without a deploy.

What causes Airtable content in Webflow Cloud to fail?

Build-time failures and request-time failures produce different symptoms. A build can reject a Next.js directive or freeze a page as static HTML, while individual requests can fail because of Airtable credentials or an incorrect browser path.

Each symptom below shows what you see and why it happens on Webflow Cloud specifically.

The build fails after you add export const runtime = 'edge' to a route

Cause: The OpenNext Cloudflare adapter that Webflow Cloud builds with rejects the Next.js edge runtime. Two different things share the word. Cloudflare Workers is an edge platform, while the Next.js runtime = 'edge' export is a separate compile target the adapter doesn't support.

Conflating the edge platform with the Next.js edge runtime target produces a broken build.

Fix: Delete the export const runtime line from every Route Handler and page, commit, and redeploy. Your handlers already execute on Workers. If you are unsure which files carry it, grep -r "runtime = 'edge'" app/ lists them in one pass. The build then completes, and /api/content answers at the mount path.

Airtable returns 401 or 403 on Webflow Cloud, but the same code works locally

Cause: One of two credential problems causes this symptom, and the log line tells you which one. If the deployed logs show Missing environment variable: AIRTABLE_TOKEN, the variable exists only in .env.local, which never leaves your machine, or it was added to a different Webflow Cloud environment than the one this deploy targets.

If the logs instead show Airtable responded with 401 or 403, the variable is present. Confirm that the target environment contains the read-only token created for the content base and that the pasted value has no trailing whitespace.

Fix: For the missing variable, open the environment your deploy uses, add AIRTABLE_TOKEN as a secret, and redeploy so both the build and the runtime pick it up. For a 401 or 403, create a fresh read-only token scoped to the target base, replace the secret's value, and redeploy.

Run npm run dev against the new token first; if it lists records locally, the remaining difference is the environment. After the redeploy, the route returns your items, and the error line stops appearing.

The page still shows content from the last deploy

Cause: The page was rendered once at build time and has been served as static HTML ever since. Webflow Cloud makes your environment variables available during the build and at runtime, so the build can reach Airtable, fetch every Published row successfully, and bake the result into the page.

The build succeeds, and the content remains as old as the last deploy. Any page under app/ that only awaits a server-side function, has no dynamic input, and lacks force-dynamic export is a candidate, and Next.js automatically renders it statically.

I diagnosed a published row that appeared stuck when a static page served exactly what it had built.

Fix: Restore export const dynamic = "force-dynamic" on the page, or move the read behind the Route Handler and fetch it from the client. The first option costs one Airtable request per page view; a high-traffic list deserves a cache in front of the helper that you invalidate when editors publish.

Either way, changing a row's Status to Published in Airtable should show on the next page load without a deploy.

A browser fetch to /api/content returns the Webflow site's 404 page

Cause: Your app is mounted at /resources, so the route actually lives at /resources/api/content, but the browser asked for /api/content at the site root, which the Webflow site answers with its own 404. Browser requests retain the URL supplied by client code.

The bring-your-own-app page says so directly: "Client-side fetch calls must manually include the base path." The issue appears when code running in the browser calls the route.

Fix: Prefix every client-side URL with process.env.NEXT_PUBLIC_BASE_PATH, set to the mount path in the Webflow Cloud environment and left empty in .env.local. Do not add basePath to next.config or import it from there to build URLs.

Webflow Cloud's current Next.js customization docs say "You don't need to add an adapter, a base path, or an output mode", and a hard-coded value in the config fights the one the platform injects. With the prefix in place, the browser request lands on /resources/api/content and the JSON comes back.

What you can build next with Airtable and Webflow

When the team that owns a dataset works in Airtable, the site should read that live dataset directly, and a Webflow Cloud app gives you that while the editors and marketing site stay where they are.

The same helper pattern extends to a write path: a form on the site posting to a Route Handler that creates records with a data.records:write token.

Because Webflow's CMS now carries expanded REST APIs, a Route Handler called by an Airtable automation can push rows into a CMS collection when Webflow's CMS should hold the content. I favor the mounted app when Airtable should remain the live source and use the CMS path when visual CMS control matters more.

For deeper customization beyond what a Route Handler handles natively, Webflow's developer docs cover the CMS APIs, environment variables, and the rest of the Webflow Cloud runtime.

Frequently asked questions

Can the Webflow Cloud app write records back to Airtable?

Yes. You can create a second personal access token with the data.records:write scope on the same base, store it as a separate secret, and add an authenticated POST Route Handler that forwards a validated records payload. Protect cookie-based authentication with CSRF controls, enforce authorization, and apply rate and abuse limits before accepting public traffic.

Can pages I built in the Designer show this Airtable content?

Yes. You can have a Designer page fetch the Route Handler's JSON endpoint, provided the browser URL includes the app's mount path. If you need visual, structured content management instead, an Airtable automation can call a Route Handler that pushes rows into a Webflow CMS collection through the CMS REST API.

What happens when Airtable returns more than one page of records?

Every published record is still returned. Airtable includes an offset when another page remains, and the server-only helper continues requesting pages until that value disappears. The helper then normalizes all returned records into one typed array and sorts them newest first, so the rendered list isn't limited to Airtable's first response page.

Who should own the Airtable personal access token?

Use an Airtable account the client controls to create the token. Personal access tokens remain tied to the creating account, so removing a contractor's account from the workspace can stop the site from reading content without any code change. A client-owned account keeps token administration with the organization that operates the site.

I'm on Next.js 16. Does middleware still work on Webflow Cloud?

Keep the file named middleware.ts. In Next.js 16, the renamed proxy.ts runs on the Node.js runtime and cannot opt into Edge. Webflow Cloud supports Edge runtime middleware on its Workers runtime, not Node.js runtime middleware, so retaining the middleware filename avoids producing a proxy file that the platform cannot run after deployment.


Last Updated
September 19, 2026
Category

Related articles


verifone logomonday.com logospotify logoted logogreenhouse logoclear logocheckout.com logosoundcloud logoreddit logothe new york times logoideo logoupwork logodiscord logo
verifone logomonday.com logospotify logoted logogreenhouse logoclear logocheckout.com logosoundcloud logoreddit logothe new york times logoideo logoupwork logodiscord logo

Get started for free

Try Webflow for as long as you like with our free Starter plan. Purchase a paid Site plan to publish, host, and unlock additional features.

Get started — it’s free
Watch demo

Try Webflow for as long as you like with our free Starter plan. Purchase a paid Site plan to publish, host, and unlock additional features.