Add a Key Value Store to your app

Add a caching layer to your Webflow Cloud app using a Key Value Store
Beta

This guide will show you how to add a Key Value Store to your project and use it as a caching layer for third-party API data. You’ll learn how to store and serve data efficiently, helping your app perform better and reducing unnecessary external requests.

Key Value Store for Webflow Cloud is in Beta

To continue with this tutorial, you’ll need access to Key Value Store for Webflow Cloud. Apply for access here.

What you’ll learn:

  • How to add a Key Value Store to your Webflow Cloud project
  • How to use a Key Value Store as a caching layer for third-party API data
  • How to improve performance and reduce external requests

Prerequisites

Before you begin, make sure you have:

  • Access to the Webflow Cloud Storage Beta
  • A Webflow Cloud project linked to a GitHub repository
  • A Webflow Cloud environment set up
  • Node.js 20+ and npm 10+
  • Basic familiarity with JavaScript/TypeScript
New to Webflow Cloud?

If you haven’t already, follow the Quick Start guide to set up your project and environment.

Add a Key Value Store binding

Before you can use a Key Value Store in your Webflow Cloud app, you need to declare a binding in your project’s configuration. This binding tells your app how to connect to the storage resource.

Once the binding is declared, your app can use simple methods like .get(), .put(), and .delete() to read from and write to the Key Value Store directly in your code.

1

Update your project in Webflow Cloud (Optional)

If you created a Webflow Cloud prior to 7/16/2025, you’ll need to update your project in the Webflow Cloud dashboard to use Webflow Cloud’s new storage system.

  1. Go to your project in the Webflow Cloud dashboard.

  2. Select the ”…” icon in the “Actions” section of the menu.

  3. Select “Edit” (you don’t actually need to edit anything).

  4. Press “Save Changes” to update your project.

2

Open your project.

Launch your project in your preferred code editor.

3

Declare the Key Value Store binding.

In your project’s wrangler.json file, add a kv_namespaces array to define your Key Value Store binding:

wrangler.json
1"kv_namespaces": [
2 {
3 "binding": "WEATHER_CACHE",
4 "id": "1234567890", // Webflow Cloud will generate this for you once you deploy your app
5 }
6]
  • binding: The variable name you’ll use to access the database in your code. This must be a valid JavaScript variable name.
  • id: A unique identifier for your database (Webflow Cloud will generate this for you once you deploy your app).
4

Generate type definitions for your binding.

Update your project’s type definitions to enable autocomplete and type safety:

Terminal
$wrangler types

This ensures your code editor recognizes the Key Value Store binding.

Get weather data

Now that your Key Value Store binding is set up, you can use it to cache data in your app. In this section, you’ll build an API route that fetches weather information based on the user’s location. Each response will be stored in your Key Value Store for 10 minutes, so repeated requests are fast and reduce calls to the external weather API.

1

Create a new API route

Set up an API endpoint that will fetch weather data for your users.

  1. In your Astro project, go to the src/pages/api directory. If this directory doesn’t exist, create it.

  2. Inside this directory, create a new file called weather.ts.

  3. Add the following code into your new file:

src/pages/api/weather.ts
1import { APIRoute } from "astro";
2
3// Get api/weather
4export const GET: APIRoute = async ({ request, locals }) => {
5
6//... Implementation will be added in the next steps
7}
2

Get the Key Value Store binding

Access your Key Value Store binding in your API route so you can read from and write to the store.

In your weather.ts file, access the binding from the runtime environment:

src/pages/api/weather.ts
1import { APIRoute } from "astro";
2
3export const GET: APIRoute = async ({ request, locals }) => {
4
5 // Access the environment bindings
6 { env } = locals.runtime;
7 const weatherCache = env.WEATHER_CACHE;
8
9 //... continue with the next steps
10}
  • env.WEATHER_CACHE gives you access to the Key Value Store you declared in wrangler.json.
3

Get user's location

Extract the user’s location from the request headers. This information will be used to fetch location-specific weather data.

In your weather.ts file, add the following code to get the user’s latitude and longitude from the Cloudflare request headers:

src/pages/api/weather.ts
1import { APIRoute } from "astro";
2
3export const GET: APIRoute = async ({ request, locals }) => {
4
5 { env } = locals.runtime;
6 const weatherCache = env.WEATHER_CACHE;
7
8 // Get User's location from Cloudflare headers
9 if (!request.cf) {
10 return new Response("No Cloudflare headers found", { status: 400 });
11 }
12 const { latitude, longitude } = request.cf;
13
14
15 //... continue with the next steps
16}
  • request.cf contains the user’s location information.
  • If the headers are missing, return a 400 error.
4

Check for cached data

Before making an external API call, check if the weather data for the user’s location is already stored in your Key Value Store. If cached data exists, return it immediately to improve performance and reduce external requests.

Use the .get() method on the binding to check for cached data.

In your weather.ts file, add the following logic after retrieving the user’s location:

src/pages/api/weather.ts
1// ...previous code
2
3 // Create a cache key from latitude and longitude
4 const cacheKey = `${latitude}-${longitude}`;
5
6 try {
7 // Try to get the weather data from the cache
8 const cachedWeather = await weatherCache.get(cacheKey);
9
10 // If the cached data exists, return it
11 if (cachedWeather) {
12 return new Response(cachedWeather, {
13 status: 200,
14 headers: {
15 "Content-Type": "application/json",
16 "X-Cache-Status": "HIT"
17 },
18 });
19 }
20
21 //... continue with fetching weather data from the API if not cached
  • This creates a unique cache key for each location.
  • If data is found, return it with a X-Cache-Status: HIT header.
  • If not, continue to the next step to fetch and cache new data.
5

Fetch and cache fresh weather data

If no cached weather data is found, fetch fresh data from the Open-Meteo API, store it in your Key Value Store, and return it to the user.

Store the fresh data in your Key Value Store using the .put() method.

In your weather.ts file, add the following logic after checking for cached data:

src/pages/api/weather.ts
1// ...previous code
2
3// If NOT cached, fetch weather data from Open-Meteo API
4const weatherUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&current_weather=true&temperature_unit=fahrenheit`;
5const weatherData = await fetch(weatherUrl);
6
7// If error, return error message
8if (!weatherData.ok) {
9 throw new Error(`Weather API error: ${weatherData.status}`);
10}
11
12// Parse the weather data
13const weatherDataJson = await weatherData.json();
14
15// Cache the weather data for 10 minutes (600 seconds)
16await weatherCache.put(cacheKey, JSON.stringify(weatherDataJson), {
17 expirationTtl: 600,
18});
19
20// Return the weather data with a cache status header
21return new Response(JSON.stringify(weatherDataJson), {
22 status: 200,
23 headers: {
24 "Content-Type": "application/json",
25 "X-Cache-Status": "MISS"
26 },
27});
28
29// Add error handling
30} catch (error) {
31 console.error("Error fetching or caching weather data:", error);
32 return new Response(
33 JSON.stringify({ error: "Failed to fetch weather data" }),
34 {
35 status: 502,
36 headers: { "Content-Type": "application/json" },
37 }
38 );
39}
40};
  • Fetches weather data for the user’s location.
  • Stores the result in your Key Value Store for 10 minutes.
  • Returns the data with a X-Cache-Status: MISS header.
  • If error, return error message.
6

Test your weather API endpoint

Make sure your API route works as expected by sending a request from your terminal.

  1. In your terminal, start your dev server using Cloudflare’s context.

    $npm run preview
  2. In a new terminal, run:

    $curl http://localhost:<YOUR_PORT_NUMBER>/<YOUR_BASE_PATH>/api/weather
    • <YOUR_PORT_NUMBER> is the port number of your dev server.
    • <YOUR_BASE_PATH> is the base path of your project.
  3. Check the response headers:

    • The first request should include X-Cache-Status: MISS (data fetched from the API and cached).
    • Subsequent requests should include X-Cache-Status: HIT (data returned from the cache).

    If you see the expected headers and weather data in the response, your endpoint and caching are working!

Update your home page

Now that your API is returning weather data, let’s display it directly on your home page. In this section, you’ll add a weather widget that shows the current temperature and a matching weather icon for your user’s location. This gives users instant, dynamic feedback and demonstrates how to connect your frontend to your new API.

1

Add weather icons to your project

Add weather icons to your project so you can visually represent the current weather.

$npm install weather-icons
  • Run this command in your project’s root directory.
  • The weather-icons package provides a set of CSS classes for common weather conditions
2

Map weather codes to icon classes

Create a utility to translate weather codes from your API into icon classes for display.

  1. In your project’s src directory, create a utils folder if it doesn’t already exist.
  2. Inside utils, create a file named iconMap.ts.
  3. Copy and paste the following code into iconMap.ts:
src/utils/iconMap.ts
1 const ICON_MAP: { [key: number]: string } = {
2 0: "wi-day-sunny", // Clear
3 1: "wi-day-sunny-overcast", // Mostly Clear
4 2: "wi-day-cloudy", // Partly Cloudy
5 3: "wi-cloudy", // Overcast
6
7 45: "wi-fog", // Fog
8 48: "wi-fog", // Icy Fog
9
10 51: "wi-sprinkle", // Light Drizzle
11 53: "wi-showers", // Drizzle
12 55: "wi-rain", // Heavy Drizzle
13
14 56: "wi-rain-mix", // Light Freezing Drizzle
15 57: "wi-rain-mix", // Freezing Drizzle
16
17 61: "wi-raindrops", // Light Rain
18 63: "wi-rain", // Rain
19 65: "wi-rain-wind", // Heavy Rain
20
21 66: "wi-rain-mix", // Light Freezing Rain
22 67: "wi-rain-mix", // Freezing Rain
23
24 71: "wi-snow", // Light Snow
25 73: "wi-snow", // Snow
26 75: "wi-snow-wind", // Heavy Snow
27
28 77: "wi-snowflake-cold", // Snow Grains
29
30 80: "wi-raindrops", // Light Showers
31 81: "wi-rain", // Showers
32 82: "wi-rain-wind", // Heavy Showers
33
34 85: "wi-snow", // Light Snow Showers
35 86: "wi-snow-wind", // Snow Showers
36
37 95: "wi-thunderstorm", // Thunderstorm
38 96: "wi-storm-showers", // Light T-storm w/ Hail
39 99: "wi-storm-showers", // T-storm w/ Hail
40 };
41
42 export default ICON_MAP;
3

Call the weather API from your home page

Fetch the latest weather data from your API and display it on your home page, along with the appropriate weather icon.

  1. Open your home page file. (for example, src/pages/index.astro)

  2. Import the weather icons CSS and your icon map utility at the top of the file.

    src/pages/index.astro
    1import 'weather-icons/css/weather-icons.css';
    2import ICON_MAP from '../utils/iconMap.js';
  3. Fetch the weather data from your API and extract the temperature and weather code. Then, use the weather code to get the appropriate icon class from your icon map utility.

    src/pages/index.astro
    1// Get the base URL for your API
    2const url = Astro.url.origin + import.meta.env.BASE_URL;
    3
    4// Fetch weather data
    5const weather = await fetch(`${url}/api/weather`);
    6const weatherData = await weather.json();
    7const { temperature, weathercode } = weatherData?.current_weather;
    8
    9// Map the weather code to an icon class
    10const iconClass = ICON_MAP[weathercode];
    11---
  4. Display the weather data and icon in your page’s markup, below the welcome message:

    src/pages/index.astro
    1<h1 class="margin-bottom-24px">Welcome to Webflow Cloud</h1>
    2<p class="margin-bottom-24px">This is a simple test using Basic components with enhanced styling.</p>
    3<h2>{temperature}°F <i class={`wi ${iconClass}`}></i></h2>
    4<div>

See the full code example below:

src/pages/index.astro
1---
2import Layout from '../layouts/Layout.astro';
3import { Navbar } from '../../devlink/Navbar.jsx';
4import { Section, Container, Block, Link } from '../../devlink/_Builtin/Basic';
5import 'weather-icons/css/weather-icons.css';
6import ICON_MAP from '../utils/iconMap.js';
7
8// Get base url for API calls
9const url = Astro.url.origin + import.meta.env.BASE_URL;
10
11// Get weather data
12const weather = await fetch(`${url}/api/weather`);
13console.log(weather);
14const weatherData = await weather.json();
15const { temperature, weathercode }: { temperature: number; weathercode: number } = weatherData?.current_weather;
16
17const iconClass = ICON_MAP[weathercode];
18
19---
20
21<Layout>
22<Navbar
23/>
24<Section
25 client:load
26 tag="section"
27 className="margin-bottom-24px"
28 style={{
29 minHeight: '100vh',
30 display: 'flex',
31 alignItems: 'center',
32 justifyContent: 'center'
33 }}
34>
35 <Container>
36 <Block
37 tag="div"
38 className="hero-split"
39 style={{
40 textAlign: 'center',
41 maxWidth: '600px',
42 margin: '0 auto'
43 }}
44 >
45 <h1 class="margin-bottom-24px">Welcome to Webflow Cloud</h1>
46 <p class="margin-bottom-24px">This is a simple test using Basic components with enhanced styling.</p>
47 <h2>{temperature}°F <i class={`wi ${iconClass}`}></i></h2>
48 <div>
49 <Link
50 button={true}
51 options={{
52 href: "#"
53 }}
54 className="button-primary"
55 >
56 Get Started
57 </Link>
58 </div>
59 </Block>
60 </Container>
61</Section>
62</Layout>
63
64<style>
65h1 {
66 font-size: 2.5rem;
67 font-weight: 700;
68 background: linear-gradient(83.21deg, #3245ff 0%, #bc52ee 100%);
69 -webkit-background-clip: text;
70 -webkit-text-fill-color: transparent;
71 background-clip: text;
72}
73</style>

Test and deploy your app

Make sure your app is working as expected by running it locally and verifying the weather widget displays correctly.

1

Start your development server

Start your app in development mode with the Cloudflare context.

$npm run preview
2

Open your app in the browser

Visit your app in a web browser.

  • Go to http://<YOUR_PORT_NUMBER>/<YOUR_BASE_PATH> to see your app running locally.

    • <YOUR_PORT_NUMBER> is the port number of your dev server.
    • <YOUR_BASE_PATH> is the base path of your project.

    You should see your app running locally with the weather widget displaying the current temperature and weather icon.

3

Deploy your app

Deploy your app to Webflow Cloud. You can deploy your app in two ways:

  1. Use the Webflow CLI

    $webflow cloud deploy
  2. Commit and push your changes to your GitHub repository.

    $git add .
    >git commit -m "Deploying app to Webflow Cloud"
    >git push

Go to your environment in Webflow Cloud to see your app deployed. Once deployed, you can access your app at https://<YOUR_DOMAIN>/<YOUR_BASE_PATH>.

Next steps

Congratulations! You’ve successfully added a Key Value Store to your Webflow Cloud app, built a weather API with caching, and displayed live weather data on your home page.