Webflow Cloud is a powerful tool to add nearly any kind of functionality imaginable to your Webflow site.
Developers can host and bind a Next.js or Astro app to their Webflow site, with the ability to pull Webflow design systems into their apps (thanks to the power of DevLink). They can also harness additional features from Webflow Cloud’s Cloudflare integration, including multiple options for data storage. In general, most people may consider using Webflow Cloud to build visual apps for their site visitors, but it can be used for purely “data centric” applications, as well. Today, I'm going to demonstrate one powerful example of this: creating an API wrapper.
When using remote APIs in client-side JavaScript code, you have to be careful to not expose API keys that can be stolen and used elsewhere. Creating a lightweight, server-side proxy makes this easier to prevent because the front-end code never contains the key. Even better, creating this proxy allows for:
- Data shaping: An API may return a lot of information you simply don't need. It may also return information in a way that's not helpful to the front-end code. Your server-side proxy can remove, add, and modify the result of the remote API. Additionally, you can shape both the output and the input.
- A remote API might support two arguments, but your proxy can hard-code one of them, permanently fixing its value. This gives you full control over not only how the remote API is called, but what it's allowed to return.
- Caching: By implementing a lightweight cache you can store and reuse the results of the API without having to hit the external resource. This can also reduce costs since many APIs will charge per request.
- Flexibility: In the most extreme case, you may need to completely switch to a new API provider. Since your front-end code is calling your Webflow Cloud app proxy, you can swap in the new provider, shape the response to match the previous one, and you’re done. You could even build a proxy that uses two or more API providers, switching between them as needed.
In this post, I'll demonstrate this in action, iterating over a few versions to show how an initial implementation can be improved.
Getting the weather: Pirate style
One of my favorite APIs is Pirate Weather, a replacement for the discontinued Dark Sky API. It provides really detailed weather information for a great price: free (there are limits and you can, and should, consider donating if you make use of the API). Using the API requires getting a key, and then perusing the docs. The simplest call looks like this:
https://api.pirateweather.net/forecast/YOUR_KEY/YOUR_LATITUDE,YOUR_LONGITUDEThis will return a huge amount of data for a specific location, including the general forecast, a daily forecast, an hourly forecast, and even weather alerts.
For our Webflow site, we want to make use of this API but have it proxied to an Astro Webflow Cloud app. Our proxy will also hard-code a location for Lafayette, Louisiana, which has this latitude and longitude: 30.471165, -91.147385.
I started off following our guide on initializing a Webflow Cloud site and selected Astro as my framework. I took the default page, index.astro, and renamed it to index.js to create a server endpoint. And with that, I got to hacking.
Version one: A new hope for APIs
The initial version was simply a wrapper and nothing more. It specifies a location and uses the exclude feature of the Pirate Weather API to help reduce the size of what's returned:
export const config = {
runtime: "edge",
};
async function getForecast(lat, lon, key) {
let req = await fetch(`https://api.pirateweather.net/forecast/${key}/${lat},${lon}?exclude=minutely,hourly,flags`);
let result = await req.json();
return result;
}
export async function GET({ request, locals }) {
const PIRATE_API_KEY = locals.runtime.env.PIRATE_API_KEY || process.env.PIRATE_API_KEY;
if(!PIRATE_API_KEY) {
throw('Missing env key');
}
let result = await getForecast(30.471165, -91.147385, PIRATE_API_KEY);
return new Response(
JSON.stringify(result),
{ headers: { 'Content-Type': 'application/json' } }
);
}As you can see, no input arguments are checked, this API route will just call the external remote API and return the data as is. This is the simplest and most direct way to accomplish what we need — adding a weather report (for one location, at least) to our Webflow site. You can run this yourself here.
Ok, that's good, but can we make it better?
Version two: The API strikes back
If you tried the URL above and saw the results, you could see it was quite intensive. Lots and lots of data. That's a great selling point for the Pirate Weather API (especially since it's free), but it includes way more data than we need. Let's address this by shaping the data. I added a new function, shapeData, to my code just for that purpose:
function shapeData(data) {
// We already know the location
delete data.latitude;
delete data.longitude;
// First, reduce daily forecast to 3 days
data.daily.data = data.daily.data.slice(0, 3);
// This is a list of keys we can remove from currently/daily data
const keysToRemove = ['time', 'apparentTemperatureMax', 'apparentTemperatureMaxTime', 'apparentTemperatureMin', 'apparentTemperatureMinTime','apparentTemperatureHigh', 'apparentTemperatureHighTime', 'apparentTemperatureLow', 'apparentTemperatureLowTime', 'cloudCover', 'icon', 'nearestStormBearing', 'apparentTemperature', 'dewPoint', 'pressure', 'uvIndex', 'ozone', 'visibility'];
for(let key of keysToRemove) {
delete data.currently[key];
for(let day of data.daily.data) {
delete day[key];
}
}
return data;
}The shapeData function does a few things. First, it removes a couple of top level items we don't need, like the location, which we literally had hard coded in the request. Next, it slims down the daily forecast to just three days. Finally, it removes a lot of data we don't need on our site. If you're curious about what they are (and the rest of the values we left alone), you can check out the response docs for details. But for now, I’ve removed the ones I didn't think were terribly important.
The last change is to simply call it:
let result = shapeData(await getForecast(30.471165, -91.147385, PIRATE_API_KEY));The net result is a lot less data that would have been wasted on our site anyway. You can hit this version here.
If you're curious about the savings: my devtools reported the first version at 3KB and this version at 1.8KB — a reduction of over a third in response payload size. The initial version is still really small, but you can imagine how this kind of trimming adds up with a larger or more complex API.
Version three: Return of the cache
For the third and final version, I made the ultimate upgrade: server-side caching. For this, I used the key value store feature of Webflow Cloud. After following the set up guide, my code had access to Cloudflare's KV system, which is super useful for caching.
Adding caching to the code involved two steps:
- Is the value in the cache? Return it!
- If it isn't, do the normal remote API call and cache it.
Here's the entirety of the change:
let result = await kv.get('forecast');
if(!result) {
console.log('forcast not in cache');
result = shapeData(await getForecast(30.471165, -91.147385, PIRATE_API_KEY));
// cache for ten minutes
await kv.put('forecast', JSON.stringify(result), { expirationTtl: 600 });
} else {
console.log('forecast from cache');
result = JSON.parse(result);
}As you can see, the code attempts to fetch the forecast from cache first. Cached items can expire, and the system handles that by itself — it just won't exist if it's expired. If the cache result isn't there, the code calls the API as usual and then stores the value in the cache for ten minutes. Note that I stringify the result first, and in the conditional block where the cache did exist, I parse the JSON string (the final result is stringified anyway, but this keeps it simpler).
Now if you hit the endpoint, you'll either get a cached or non-cached version depending on site traffic. In my quick test, I saw the response come in about half the time, but those savings will depend on the speed of the remote API, size of the data, and so forth.
If you want to see this for yourself, you can check out the repo here. The code for API wrappers are in the src/pages directory.
Next steps
Creating API proxies is not a new idea, but being able to use Webflow Cloud to host these proxies along with your site brings an additional level of cohesion and flexibility to what you can build on the Webflow platform. Give this a shot and let us know what you've built!



















Full-stack web apps hosted on Webflow
Extend the power of Webflow's platform by deploying full-stack web apps and dynamic, on-brand web experiences alongside your Webflow site.








