Getting Started

In this guide, you’ll create your first Data Client App to authorize with Webflow and make your first API request.

Prerequisites

To successfully follow along with this guide, please ensure you have the following:

  • A Webflow site for development and testing
  • A registered App on your Workspace. If you haven’t registered an App, follow along with our registration guide to create and register your first App with Webflow.
  • The sites:read scope enabled on your App
  • Node.js installed on your machine.
1

Clone the starter app

$git clone https://github.com/Webflow-Examples/webflow-app-starter-v2
>cd webflow-app-starter-v2
>npm install
2

Add your credentials to .env

Navigate to your Workspace settings in the Webflow dashboard and find your Client ID and Secret in the Apps & Integrations -> App Development section. Replace the placeholder values in the .env.example file with your own Client ID and Secret. Then save the file as .env.

1WEBFLOW_CLIENT_ID=your_client_id
2WEBFLOW_SECRET=your_client_secret
3

Start the server

$npm run dev
4

Create a tunnel to your local server

Create a tunnel to your local server using ngrok or localtunnel and update your Webflow App’s Redirect URL to point to your tunnel

1

Sign up for Ngrok

Sign up for a free Ngrok account

2

Install Ngrok

Install Ngrok via Homebrew by typing the following command in your terminal

$brew install Ngrok
3

Authenticate Ngrok

Authenticate Ngrok with your auth token by typing the following code in your terminal

$ngrok config add-authtoken <token>
4

Start a tunnel to the port of your choosing

Start a tunnel to the port of your choosing by typing the following code in your terminal. This should be the same port you set in your .env file.

$ngrok http 3000
5

Update App redirect URI

Copy the forwarding URI from the Ngrok session detail window.

Ngrok setup

  • Navigate to your App’s details in the App Development section of your Workspace Settings.
  • Click the “Edit App” button and navigate to the “Building Blocks” tab.
  • In the Data Client section, update the redirect URI to the Ngrok forwarding URL with /auth added to the end. For example: https://939c-136-33-253-184.Ngrok.io/auth
redirect uri
5

Visit your App

Visit http://localhost:3000 (or the port of your choice)and click “Connect with Webflow” to see your Webflow sites!

Webflow App Example

Understanding the example

This example is a simple Node.js app that handles authorization and makes a single request to the Webflow API.

Let’s review the code in server.jsto understand how the App works.

The App uses Fastify to create a lightweight server, Level as a database to store data, and the Webflow JavaScript SDK to authenticate with Webflow and make requests to the API. To keep things simple, the frontend of the App is built with vanilla JavaScript and CSS, with a simple HTML file served from the public directory.

In the beginning of server.js, we’re importing the necessary dependencies, loading our environment variables, and initializing the Fastify server. Here, we’ve also added security headers to the server to protect against common web vulnerabilities, as well as initializing the database for storing access tokens.

server.js
1import { WebflowClient } from "webflow-api";
2import Fastify from "fastify";
3import fastifyStatic from "@fastify/static";
4import path from "path";
5import url from "url";
6import { Level } from "level";
7import fs from "fs/promises";
8
9// Load environment variables from .env file
10const {
11WEBFLOW_CLIENT_ID,
12WEBFLOW_SECRET,
13PORT
14NODE_ENV = "development",
15} = process.env;
16
17// Validate required environment variables
18if (!WEBFLOW_CLIENT_ID || !WEBFLOW_SECRET) {
19console.error(
20 "Missing required environment variables. Please check your .env file:"
21);
22console.error("WEBFLOW_CLIENT_ID and WEBFLOW_SECRET are required");
23process.exit(1);
24}
25
26// Initialize our server with basic security headers
27const server = Fastify({
28logger: true,
29trustProxy: true, // Required for secure cookies behind a proxy
30});
31
32// Add security headers
33server.addHook("onSend", async (request, reply) => {
34reply.headers({
35 "X-Content-Type-Options": "nosniff", // Prevent MIME type sniffing
36 "X-Frame-Options": "DENY", // Prevent clickjacking
37 "Strict-Transport-Security": "max-age=31536000; includeSubDomains", // Enforce HTTPS
38});
39});
40
41// Initialize the database (Note: Use a proper database in production)
42const db = new Level("data", { valueEncoding: "json" });
43await db.open();

The App implements OAuth 2.0 authentication through a dedicated /auth route that handles both initiating the authorization flow and processing Webflow’s callback response. When a user clicks “Connect with Webflow”, this route first redirects them to Webflow’s authorization page. After the user grants permission, Webflow redirects back to this route with an authorization code that the App exchanges for an access token.

For a comprehensive walkthrough of implementing OAuth 2.0 authentication in your App, refer to our detailed OAuth 2.0 guide.

Start the OAuth 2.0 authorization flow

This route will check for a code query parameter. If the code is not present, we’ll redirect the user to the Webflow OAuth 2.0 authorization page using the authorizeURL method of the Webflow JavaScript SDK.

server.js
1// OAuth 2.0 authentication endpoint
2server.get("/auth", async (req, reply) => {
3 const { code, error, error_description } = req.query;
4
5 // If no code is provided, redirect to the authorization URL
6 if (!code) {
7 const installUrl = WebflowClient.authorizeURL({
8 scope: scopes,
9 clientId: WEBFLOW_CLIENT_ID,
10 // Optional: Add state parameter for CSRF protection
11 state: Math.random().toString(36).substring(7),
12 });
13 return reply.redirect(installUrl);
14 }
15});

Request an access token

If the code query parameter is present, we’ll use it to request an access token from Webflow using the getAccessToken method of the Webflow JavaScript SDK. We’ll also store the access token in the database and redirect the user to the root URL of the App.

server.js
1// OAuth 2.0 authentication endpoint
2server.get("/auth", async (req, reply) => {
3
4// Previous Code //
5
6 try {
7 // Exchange the code for an access token
8 const token = await WebflowClient.getAccessToken({
9 clientId: WEBFLOW_CLIENT_ID,
10 clientSecret: WEBFLOW_SECRET,
11 code: code,
12 });
13
14 // Store the token in the database
15 await db.put("token", token);
16
17 if (NODE_ENV === "development") {
18 console.log("\nAccess Token Received:", token, "\n");
19 }
20
21 return reply.redirect("/?authorized=true");
22 } catch (error) {
23 console.error("Auth Error:", error);
24 return reply.code(500).send({
25 error: "Authentication failed",
26 message: error.message,
27 });
28 }
29});

The example App stores and retrieves a single access token directly in the Level database. In a production app, you’ll want to implement proper user management and token storage, including:

  • Storing tokens securely per user/workspace
  • Encrypting sensitive data
  • Using secure session management

Consider using dedicated auth services or implementing these security measures using libraries like Passport.js, JWT tokens, and proper database encryption.

After the user has authorized the App, it can make requests to the REST API using the WebflowClient object. Here, the /sites route makes a request to the “List Sites” endpoint.

Before calling the API, the App retrieves the access token from the database and creates a new, authenticated WebflowClient object.

server.js
1// Example API endpoint
2server.get("/sites", async (req, reply) => {
3 try {
4 const accessToken = await db.get("token");
5
6 const webflow = new WebflowClient({ accessToken });
7
8 const sites = await webflow.sites.list();
9 return sites;
10
11 } catch (error) {
12 console.error("API Error:", error);
13
14 // Handle different types of errors
15 if (error.response?.status === 401) {
16 return reply.code(401).send({
17 error: "Invalid token",
18 message: "Please authenticate again",
19 });
20 }
21
22 return reply.code(500).send({
23 error: "Server error",
24 message: "Failed to fetch sites",
25 });
26 }
27});

Next Steps

Now that you have a working app, you can:

  1. Add More API Endpoints: Explore the API Reference and our Data Client Guides to add functionality
  2. Add Designer Extension capabilities: Learn how to add Designer Extension capabilities to your App.
  3. Authenticate a Hybrid App: Learn how to implement authentication for Apps using Data Client and Designer Extension capabilities.
  4. Prepare your Marketplace App: Learn how to prepare your App for submission to the Webflow Marketplace
Was this page helpful?
Built with