
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title><![CDATA[ The Cloudflare Blog ]]></title>
        <description><![CDATA[ Get the latest news on how products at Cloudflare are built, technologies used, and join the teams helping to build a better Internet. ]]></description>
        <link>https://blog.cloudflare.com</link>
        <atom:link href="https://blog.cloudflare.com/" rel="self" type="application/rss+xml"/>
        <language>en-us</language>
        <image>
            <url>https://blog.cloudflare.com/favicon.png</url>
            <title>The Cloudflare Blog</title>
            <link>https://blog.cloudflare.com</link>
        </image>
        <lastBuildDate>Fri, 03 Apr 2026 18:28:10 GMT</lastBuildDate>
        <item>
            <title><![CDATA[Your frontend, backend, and database — now in one Cloudflare Worker]]></title>
            <link>https://blog.cloudflare.com/full-stack-development-on-cloudflare-workers/</link>
            <pubDate>Tue, 08 Apr 2025 14:05:00 GMT</pubDate>
            <description><![CDATA[ You can now deploy static sites and full-stack applications on Cloudflare Workers. Framework support for React Router v7, Astro, Vue and more are generally available today and Cloudflare Vite plugin.  ]]></description>
            <content:encoded><![CDATA[ <p><a href="https://blog.cloudflare.com/builder-day-2024-announcements/#static-asset-hosting"><u>In September 2024</u></a>, we introduced beta support for <a href="https://www.cloudflare.com/developer-platform/solutions/hosting/">hosting</a>, storing, and serving <a href="https://developers.cloudflare.com/workers/static-assets/"><u>static assets</u></a> for free on <a href="https://www.cloudflare.com/developer-platform/products/workers/">Cloudflare Workers</a> — something that was previously only possible on <a href="https://blog.cloudflare.com/cloudflare-pages/"><u>Cloudflare Pages</u></a>. Being able to host these assets — your client-side JavaScript, HTML, CSS, fonts, and images — was a critical missing piece for developers looking to build a full-stack application within a <b>single Worker</b>. </p><p>Today we’re announcing ten big improvements to building apps on Cloudflare. All together, these new additions allow you to build and host projects ranging from simple static sites to full-stack applications, all on Cloudflare Workers:</p><ul><li><p>Cloudflare Workers now provides production ready, <b>generally available</b> (GA) support for <a href="https://developers.cloudflare.com/workers/frameworks/framework-guides/remix/"><u>React Router v7 (Remix)</u></a>, <a href="https://developers.cloudflare.com/workers/frameworks/framework-guides/astro/"><u>Astro</u></a>, <a href="https://developers.cloudflare.com/workers/frameworks/framework-guides/hono/"><u>Hono</u></a>, <a href="https://developers.cloudflare.com/workers/frameworks/framework-guides/vue/"><u>Vue.js</u></a>, <a href="https://developers.cloudflare.com/workers/frameworks/framework-guides/nuxt/"><u>Nuxt</u></a>, <a href="https://developers.cloudflare.com/workers/frameworks/framework-guides/svelte/"><u>Svelte (SvelteKit)</u></a>, and <a href="https://developers.cloudflare.com/workers/frameworks/"><u>more</u></a>, with GA support for more frameworks including <a href="https://developers.cloudflare.com/workers/frameworks/framework-guides/nextjs/"><u>Next.js</u></a>, <a href="https://developers.cloudflare.com/workers/frameworks/framework-guides/angular/"><u>Angular</u></a>, and <a href="https://developers.cloudflare.com/workers/frameworks/framework-guides/solid/"><u>SolidJS</u></a> (SolidStart) to follow in Q2 2025. </p></li><li><p>You can build complete full-stack apps on Workers without a framework: you can “<a href="https://blog.cloudflare.com/introducing-the-cloudflare-vite-plugin/"><u>just use Vite</u></a>" and React together, and build a backend API in the same Worker. See our <a href="https://github.com/cloudflare/templates/tree/staging/vite-react-template"><u>Vite + React template</u></a> for an example.</p></li><li><p>The adapter for Next.js — <a href="https://opennext.js.org/cloudflare"><u>@opennextjs/cloudflare</u></a>, introduced in September 2024 as an early alpha, <a href="https://blog.cloudflare.com/deploying-nextjs-apps-to-cloudflare-workers-with-the-opennext-adapter"><u>is now v1.0-beta</u></a>, and will be GA in the coming weeks. Those using the OpenNext adapter will also be able to easily upgrade to the <a href="https://github.com/vercel/next.js/discussions/77740"><u>recently announced Next.js Deployments API</u></a>. </p></li><li><p>The <a href="https://blog.cloudflare.com/introducing-the-cloudflare-vite-plugin"><u>Cloudflare Vite plugin</u></a> is now v1.0 and generally available. The Vite plugin allows you to run Vite’s development server in the Workers runtime (<code>workerd</code>), meaning you get all the benefits of Vite, including <a href="https://vite.dev/guide/features.html#hot-module-replacement"><u>Hot Module Replacement</u></a>, while still being able to use features that are exclusive to Workers (like Durable Objects).</p></li><li><p>You can now use static <a href="https://developers.cloudflare.com/workers/static-assets/headers/"><u>_headers</u></a> and <a href="https://developers.cloudflare.com/workers/static-assets/redirects/"><u>_redirects</u></a> configuration files for your applications on Workers, something that was previously only available on Pages. These files allow you to add simple headers and configure redirects without executing any Worker code. </p></li><li><p>In addition to <a href="https://developers.cloudflare.com/hyperdrive/configuration/connect-to-postgres/"><u>PostgreSQL</u></a>, you can now connect to <a href="https://blog.cloudflare.com/building-global-mysql-apps-with-cloudflare-workers-and-hyperdrive"><u>MySQL databases in addition from Cloudflare Workers, via Hyperdrive</u></a>. Bring your existing Planetscale, AWS, GCP, Azure, or other MySQL database, and Hyperdrive will take care of pooling connections to your database and eliminating unnecessary roundtrips by caching queries.</p></li><li><p><a href="#node-js-compatibility"><u>More Node.js APIs are available</u></a> in the Workers Runtime — including APIs from the <code>crypto</code>, <code>tls</code>, <code>net</code>, and <code>dns </code>modules. We’ve also increased the maximum CPU time for a Workers request from 30 seconds to 5 minutes.</p></li><li><p>You can now <a href="https://blog.cloudflare.com/deploy-workers-applications-in-seconds"><u>bring any repository from GitHub or GitLab that contains a Worker application</u></a>, and <a href="https://developers.cloudflare.com/workers/ci-cd/builds/"><u>Workers Builds</u></a> will take care of deploying the app as a new Worker on your account. <a href="#workers-builds"><u>Workers Builds is also starting much more quickly</u></a> (by up to 6 seconds for every build). </p></li><li><p>You can now set up Workers Builds to <a href="https://developers.cloudflare.com/workers/ci-cd/builds/build-branches/#configure-non-production-branch-builds"><u>run on non-production branches</u></a>, and preview URLs will be <a href="https://developers.cloudflare.com/workers/ci-cd/builds/git-integration/github-integration/#pull-request-comment"><u>posted back to GitHub as a comment</u></a>. </p></li><li><p>The <a href="https://developers.cloudflare.com/images/transform-images/bindings/"><u>Images binding in Workers</u></a> is generally available, allowing you to build more flexible, programmatic workflows. </p></li></ul><p>These improvements allow you to build both simple static sites and more complex server-side rendered applications. Like <a href="https://www.cloudflare.com/developer-platform/products/pages/">Pages</a>, you only get charged when your Worker code runs, meaning you can host and serve static sites for free. When you want to do any rendering on the server or need to build an API, simply add a Worker to handle your backend. And when you need to read or write data in your app, you can connect to an existing database with <a href="https://developers.cloudflare.com/hyperdrive/"><u>Hyperdrive</u></a>, or use any of our storage solutions: <a href="https://developers.cloudflare.com/kv/"><u>Workers KV</u></a>, <a href="https://developers.cloudflare.com/r2/"><u>R2</u></a>, <a href="https://developers.cloudflare.com/durable-objects/"><u>Durable Objects</u></a>, or <a href="https://developers.cloudflare.com/d1/"><u>D1</u></a>. </p><p>If you'd like to dive straight into code, you can deploy a single-page application built with Vite and React, with the option to connect to a hosted database with Hyperdrive, by clicking this “Deploy to Cloudflare” button: </p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/templates/tree/main/react-postgres-fullstack-template"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/56hrgUpOebvOdzbI8j6liw/bc9e7d01dde8cb6a8a4623aec3abc883/1.jpg" />
          </figure>
    <div>
      <h2>Start with Workers</h2>
      <a href="#start-with-workers">
        
      </a>
    </div>
    <p>Previously, you needed to choose between building on Cloudflare Pages or Workers (or use Pages for one part of your app, and Workers for another) just to get started. This meant figuring out what your app needed from the start, and hoping that if your project evolved, you wouldn’t be stuck with the wrong platform and architecture. Workers was designed to be a flexible platform, allowing developers to evolve projects as needed — and so, we’ve <a href="https://blog.cloudflare.com/pages-and-workers-are-converging-into-one-experience/"><u>worked to bring pieces of Pages into Workers</u></a> over the years.  </p><p>Now that Workers supports both serving static assets <b>and </b>server-side rendering, you should <b>start with Workers</b>. Cloudflare Pages will continue to be supported, but, going forward, all of our investment, optimizations, and feature work will be dedicated to improving Workers. We aim to make Workers the best platform for building full-stack apps, building upon your feedback of what went well with Pages and what we could improve. </p><p>Before, building an app on Pages meant you got a really easy, opinionated on-ramp, but you’d eventually hit a wall if your application got more complex. If you wanted to use Durable Objects to manage state, you would need to set up an entirely separate Worker to do so, ending up with a complicated deployment and more overhead. You also were limited to real-time logs, and could only roll out changes all in one go. </p><p>When you build on Workers, you can immediately bind to any other Developer Platform service (including <a href="https://developers.cloudflare.com/durable-objects/"><u>Durable Objects</u></a>, <a href="https://developers.cloudflare.com/email-routing/email-workers/"><u>Email Workers</u></a>, and more), and manage both your front end and back end in a single project — all with a single deployment. You also get the whole suite of <a href="https://developers.cloudflare.com/workers/observability/"><u>Workers observability</u></a> tooling built into the platform, such as <a href="https://developers.cloudflare.com/workers/observability/logs/workers-logs/"><u>Workers Logs</u></a>. And if you want to rollout changes to only a certain percentage of traffic, you can do so with <a href="https://developers.cloudflare.com/workers/configuration/versions-and-deployments/gradual-deployments/"><u>Gradual Deployments</u></a>.  </p><p>These latest improvements are part of our goal to bring the best parts of Pages into Workers. For example, we now support static  <a href="https://developers.cloudflare.com/workers/static-assets/headers/"><u>_headers</u></a> and <a href="https://developers.cloudflare.com/workers/static-assets/redirects/"><u>_redirects</u></a> config files, so that you can easily take an existing project from Pages (or another platform) and move it over to Workers, without needing to change your project. We also directly integrate with GitHub and GitLab with <a href="https://developers.cloudflare.com/workers/ci-cd/builds/"><u>Workers Builds</u></a>, providing automatic builds and deployments. And starting today, <a href="https://developers.cloudflare.com/workers/configuration/previews/"><u>Preview URLs</u></a> are <a href="https://developers.cloudflare.com/workers/ci-cd/builds/git-integration/github-integration/#pull-request-comment"><u>posted back to your repository as a comment</u></a>, with feature branch aliases and environments coming soon. </p><p>To learn how to migrate an existing project from Pages to Workers, read our <a href="https://developers.cloudflare.com/workers/static-assets/migrate-from-pages/"><u>migration guide</u></a>. </p><p>Next, let’s talk about how you can build applications with different rendering modes on Workers.  </p>
    <div>
      <h2>Building static sites, SPAs, and SSR on Workers</h2>
      <a href="#building-static-sites-spas-and-ssr-on-workers">
        
      </a>
    </div>
    <p>As a quick primer, here are all the architectures and rendering modes we’ll be discussing that are supported on Workers: </p><ul><li><p><b>Static sites</b>: When you visit a static site, the server immediately returns pre-built static assets — HTML, CSS, JavaScript, images, and fonts. There’s no dynamic rendering happening on the server at request-time. Static assets are typically generated at build-time and served directly from a <a href="https://www.cloudflare.com/learning/cdn/what-is-a-cdn/"><u>CDN</u></a>, making static sites fast and easily cacheable. This approach works well for sites with content that rarely changes. </p></li><li><p><b>Single-Page Applications (SPAs)</b>:  When you load an SPA, the server initially sends a minimal HTML shell and a JavaScript bundle (served as static assets). Your browser downloads this JavaScript, which then takes over to render the entire user interface client-side. After the initial load, all navigation occurs without full-page refreshes, typically via client-side routing. This creates a fast, app-like experience. </p></li><li><p><b>Server-Side Rendered (SSR) applications</b>: When you first visit a site that uses SSR, the server generates a fully-rendered HTML page on-demand for that request. Your browser immediately displays this complete HTML, resulting in a fast first page load. Once loaded, JavaScript "<a href="https://en.wikipedia.org/wiki/Hydration_(web_development)"><u>hydrates</u></a>" the page, adding interactivity. Subsequent navigations can either trigger new server-rendered pages or, in many modern frameworks, transition into client-side rendering similar to an SPA.</p></li></ul><p>Next, we’ll dive into how you can build these kinds of applications on Workers, starting with setting up your development environment. </p>
    <div>
      <h3>Setup: build and dev</h3>
      <a href="#setup-build-and-dev">
        
      </a>
    </div>
    <p>Before uploading your application, you need to bundle all of your client-side code into a directory of <b>static assets</b>. Wrangler bundles and builds your code when you run <code>wrangler dev</code>, but we also now support Vite with our <a href="https://www.npmjs.com/package/@cloudflare/vite-plugin"><u>new Vite plugin</u></a>. This is a great option for those already using Vite’s build tooling and development server — you can continue developing (and testing with <a href="https://developers.cloudflare.com/workers/testing/vitest-integration/"><u>Vitest</u></a>) using Vite’s development server, all using the Workers runtime. </p><p>To get started using the Cloudflare Vite plugin, you can scaffold a React application using Vite and our plugin, by running: </p>
            <pre><code>npm create cloudflare@latest my-react-app -- --framework=react</code></pre>
            <p>When you open the project, you should see a directory structure like this: </p>
            <pre><code>...
├── api
│   └── index.ts
├── public
│   └── ...
├── src
│   └── ...
...
├── index.html
├── package.json
├── vite.config.ts
└── wrangler.jsonc</code></pre>
            <p>If you run <code>npm run build</code>, you’ll see a new folder appear, named <code>/dist</code>. </p>
            <pre><code>...
├── api
│   └── index.ts
├── dist
│   └── ...
├── public
│   └── ...
├── src
│   └── ...
...
├── index.html
├── package.json
├── vite.config.ts
└── wrangler.jsonc</code></pre>
            <p>The Vite plugin informs Wrangler that this <code>/dist</code> directory contains the project’s built static assets — which, in this case, includes client-side code, some CSS files, and images. </p><p>Once deployed, this single-page application (SPA) architecture will look something like this: </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6syBGxC8udJi8wlsqvLTXW/526d05095a953cb6d29526abfd4f4b3a/2.jpg" />
          </figure><p>When a request comes in, Cloudflare looks at the pathname and automatically serves any static assets that match that pathname. For example, if your static assets directory includes a <code>blog.html</code> file, requests for <code>example.com/blog</code> get that file. </p>
    <div>
      <h3>Static sites</h3>
      <a href="#static-sites">
        
      </a>
    </div>
    <p>If you have a static site created by a static site generator (SSG) like <a href="https://docs.astro.build/en/concepts/why-astro/"><u>Astro</u></a>, all you need to do is create a <code>wrangler.jsonc</code> file (or <code>wrangler.toml</code>) and tell Cloudflare where to find your built assets: </p>
            <pre><code>// wrangler.jsonc 

{
  "name": "my-static-site",
  "compatibility_date": "2025-04-01",
  "assets": {
    "directory": "./dist",
  }
}</code></pre>
            <p>Once you’ve added this configuration, you can simply build your project and run wrangler deploy.  Your entire site will then be uploaded and ready for traffic on Workers. Once deployed and requests start flowing in, your static site will be <a href="https://developers.cloudflare.com/workers/static-assets/#caching-behavior"><u>cached across Cloudflare’s network</u></a>.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/OaFnoUfvhzfjwv537fh5S/763524c2ed3b2beb61304576723667ea/3.jpg" />
          </figure><p>You can try starting a fresh Astro project on Workers today by running:</p>
            <pre><code>npm create cloudflare@latest my-astro-app -- --framework=astro</code></pre>
            <p>You can see our other supported Frameworks and how to get started in our <a href="https://developers.cloudflare.com/workers/frameworks/"><u>framework guides</u></a>. </p>
    <div>
      <h3>Single-page applications (SPAs) </h3>
      <a href="#single-page-applications-spas">
        
      </a>
    </div>
    <p>If you have a single-page application, you can explicitly enable <code>single-page-application</code> mode in your Wrangler configuration: </p>
            <pre><code>{
 "name": "example-spa-worker-hyperdrive",
 "main": "api/index.js",
 "compatibility_flags": ["nodejs_compat"],
 "compatibility_date": "2025-04-01",
 },
 "assets": {
   "directory": "./dist",
   "binding": "ASSETS",
   "not_found_handling": "single-page-application"
 },
 "hyperdrive": [
   {
     "binding": "HYPERDRIVE",
     "id": "d9c9cfb2587f44ee9b0730baa692ffec",
     "localConnectionString": "postgresql://myuser:mypassword@localhost:5432/mydatabase"
   }
 ],
 "placement": {
   "mode": "smart"
 }
}</code></pre>
            <p>By enabling this, the platform assumes that any navigation request (requests which include a <code>Sec-Fetch-Mode: navigate</code> header) are intended for static assets and will serve up <code>index.html</code> whenever a matching static asset match cannot be found. For non-navigation requests (such as requests for data) that don't match a static asset, Cloudflare will invoke the Worker script. With this setup, you can render the frontend with React, use a Worker to handle back-end operations, and use Vite to help stitch the two together. This is a great option for porting over older SPAs built with <code>create-react-app</code>, <a href="https://react.dev/blog/2025/02/14/sunsetting-create-react-app"><u>which was recently sunset</u></a>. </p><p>Another thing to note in this Wrangler configuration file: we’ve defined a Hyperdrive binding and enabled <a href="https://developers.cloudflare.com/workers/configuration/smart-placement/"><u>Smart Placement</u></a>. Hyperdrive lets us use an existing database<i> and</i> handles connection pooling. This solves a long-standing challenge of connecting Workers (which run in a highly distributed, serverless environment) directly to traditional databases. By design, Workers operate in lightweight V8 isolates with no persistent TCP sockets and a strict CPU/memory limit. This isolation is great for security and speed, but it makes it difficult to hold open database connections. Hyperdrive addresses these constraints by acting as a “bridge” between Cloudflare’s network and your database, taking care of the heavy lifting of maintaining stable connections or pools so that Workers can reuse them.  By turning on Smart Placement, we also ensure that if requests to our Worker originate far from the database (causing latency), Cloudflare can choose to relocate both the Worker—which handles the database connection—and the Hyperdrive “bridge” to a location closer to the database, ​​reducing round-trip times. </p>
    <div>
      <h4>SPA example: Worker code</h4>
      <a href="#spa-example-worker-code">
        
      </a>
    </div>
    <p>Let’s look at the <a href="https://github.com/korinne/example-spa-worker"><u>“Deploy to Cloudflare” example</u></a> at the top of this blog. In <code>api/index.js</code>, we’ve defined an API (using Hono) which connects to a hosted database through Hyperdrive. </p>
            <pre><code>import { Hono } from "hono";
import postgres from "postgres";
import booksRouter from "./routes/books";
import bookRelatedRouter from "./routes/book-related";

const app = new Hono();

// Setup SQL client middleware
app.use("*", async (c, next) =&gt; {
 // Create SQL client
 const sql = postgres(c.env.HYPERDRIVE.connectionString, {
   max: 5,
   fetch_types: false,
 });

 c.env.SQL = sql;

 // Process the request
 await next();

 // Close the SQL connection after the response is sent
 c.executionCtx.waitUntil(sql.end());
});

app.route("/api/books", booksRouter);
app.route("/api/books/:id/related", bookRelatedRouter);


export default {
 fetch: app.fetch,
};</code></pre>
            <p>When deployed, our app’s architecture looks something like this: </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/56hrgUpOebvOdzbI8j6liw/bc9e7d01dde8cb6a8a4623aec3abc883/1.jpg" />
          </figure><p>If Smart Placement moves the placement of my Worker to run closer to my database, it could look like this: </p><div>
  
</div>
<p></p>
    <div>
      <h3>Server-Side Rendering (SSR)</h3>
      <a href="#server-side-rendering-ssr">
        
      </a>
    </div>
    <p>If you want to handle rendering on the server, we support a number of popular full-stack <a href="https://developers.cloudflare.com/workers/frameworks/"><u>frameworks</u></a>. </p><p>Here’s a version of our previous example, now using React Router v7’s server-side rendering:</p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/templates/tree/main/react-router-postgres-ssr-template"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>You could also use Next.js with the <a href="https://opennext.js.org/cloudflare"><u>OpenNext adapter</u></a>, or any other <a href="https://developers.cloudflare.com/workers/frameworks/"><u>framework listed in our framework guides</u></a>. </p>
    <div>
      <h2>Deploy to Workers, with as few changes as possible</h2>
      <a href="#deploy-to-workers-with-as-few-changes-as-possible">
        
      </a>
    </div>
    
    <div>
      <h3>Node.js compatibility</h3>
      <a href="#node-js-compatibility">
        
      </a>
    </div>
    <p>We’ve also continued to make progress supporting Node.js APIs, recently adding support for the <code>crypto</code>, <code>tls</code>, <code>net</code>, and <code>dns</code> modules. This allows existing applications and libraries that rely on these Node.js modules to run on Workers. Let’s take a look at an example:</p><p>Previously, if you tried to use the <code>mongodb</code> package, you encountered the following error:</p>
            <pre><code>Error: [unenv] dns.resolveTxt is not implemented yet!</code></pre>
            <p>This occurred when <code>mongodb</code> used the <code>node:dns</code> module to do a DNS lookup of a hostname. Even if you avoided that issue, you would have encountered another error when <code>mongodb</code> tried to use <code>node:tls</code> to securely connect to a database.</p><p>Now, you can use <code>mongodb</code> as expected because <code>node:dns</code> and <code>node:tls</code> are supported. The same can be said for libraries relying on <code>node:crypto</code> and <code>node:net</code>.</p><p>Additionally, Workers <a href="https://developers.cloudflare.com/changelog/2025-03-11-process-env-support/"><u>now expose environment variables and secrets on the process.env object</u></a> when the <code>nodejs_compat</code> compatibility flag is on and the compatibility date is set to <code>2025-04-01</code> or beyond. Some libraries (and developers) assume that this object will be populated with variables, and rely on it for top-level configuration. Without the tweak, libraries may have previously broken unexpectedly and developers had to write additional logic to handle variables on Cloudflare Workers.</p><p>Now, you can just access your variables as you would in Node.js.</p>
            <pre><code>const LOG_LEVEL = process.env.LOG_LEVEL || "info";</code></pre>
            
    <div>
      <h3>Additional Worker CPU time</h3>
      <a href="#additional-worker-cpu-time">
        
      </a>
    </div>
    <p>We have also <a href="https://developers.cloudflare.com/changelog/2025-03-25-higher-cpu-limits/"><u>raised the maximum CPU time per Worker request</u></a> from 30 seconds to 5 minutes. This allows for compute-intensive operations to run for longer without timing out. Say you want to use the newly supported <code>node:crypto</code> module to hash a very large file, you can now do this on Workers without having to rely on external compute for CPU-intensive operations.</p>
    <div>
      <h3>Workers Builds </h3>
      <a href="#workers-builds">
        
      </a>
    </div>
    <p>We’ve also made improvements to <a href="https://developers.cloudflare.com/workers/ci-cd/builds/"><u>Workers Builds</u></a>, which allows you to connect a Git repository to your Worker, so that you can have automatic builds and deployments on every pushed change. Workers Builds was introduced during <a href="https://blog.cloudflare.com/builder-day-2024-announcements/#continuous-integration-and-delivery"><u>Builder Day 2024</u></a>, and initially only allowed you to connect a repository to an existing Worker. Now, you can bring a repository and <a href="https://blog.cloudflare.com/deploy-workers-applications-in-seconds/"><u>immediately deploy it as a new Worker</u></a>, reducing the amount of setup and button clicking needed to bring a project over. We’ve improved the performance of Workers Builds by reducing the latency of build starts by <b>6 seconds</b> — they now start within <b>10 seconds</b> on average. We also boosted API responsiveness, achieving a <b>7x </b>latency improvement thanks to Smart Placement. </p><ul><li><p><b>Note</b>: On April 2, 2025, Workers Builds transitioned to a new pricing model, as announced during <a href="https://blog.cloudflare.com/builder-day-2024-announcements/"><u>Builder Day 2024</u></a>. Free plan users are now capped at 3,000 minutes of build time, and Workers Paid subscription users will have a new usage-based model with 6,000 free minutes included and $0.005 per build minute pricing after. To better support concurrent builds, Paid plans will also now get six (6) concurrent builds, making it easier to work across multiple projects and monorepos. For more information on pricing, see the <a href="https://developers.cloudflare.com/workers/ci-cd/builds/limits-and-pricing/"><u>documentation</u></a>.</p></li></ul><p>You can also set up Workers Builds to <a href="https://developers.cloudflare.com/workers/ci-cd/builds/build-branches/#configure-non-production-branch-builds"><u>run on non-production branches</u></a>, and preview URLs will be <a href="https://developers.cloudflare.com/workers/ci-cd/builds/git-integration/github-integration/#pull-request-comment"><u>posted back to GitHub as a comment</u></a>. </p>
    <div>
      <h3>Bind the Images API to your Worker</h3>
      <a href="#bind-the-images-api-to-your-worker">
        
      </a>
    </div>
    <p>Last week, we wrote a <a href="https://blog.cloudflare.com/improve-your-media-pipelines-with-the-images-binding-for-cloudflare-workers/"><u>blog post</u></a> that covers how the Images binding enables more flexible, programmatic workflows for image optimization.</p><p>Previously, you could access image optimization features by calling <code>fetch()</code> in your Worker. This method requires the original image to be retrievable by URL. However, you may have cases where images aren’t accessible from a URL, like when you want to compress user-uploaded images before they are uploaded to your storage. With the Images binding, you can directly optimize an image by operating on its body as a stream of bytes.</p><p>To learn more, read our guide on <a href="https://developers.cloudflare.com/images/tutorials/optimize-user-uploaded-image"><u>transforming an image before it gets uploaded to R2</u></a>.</p>
    <div>
      <h2>Start building today</h2>
      <a href="#start-building-today">
        
      </a>
    </div>
    <p>We’re excited to see what you’ll build, and are focused on new features and improvements to make it  easier to create any application on Workers. Much of this work was made even better by community feedback, and we encourage everyone to <a href="https://discord.com/invite/cloudflaredev"><u>join our Discord</u></a> to participate in the discussion. </p><p><b>Helpful resources to get you started:</b></p><ul><li><p><a href="https://developers.cloudflare.com/workers/frameworks/"><u>Framework guides</u></a> </p></li><li><p><a href="https://developers.cloudflare.com/workers/static-assets/migrate-from-pages/"><u>Migration guide</u></a> </p></li><li><p><a href="https://developers.cloudflare.com/workers/static-assets/"><u>Static assets documentation</u></a> </p></li><li><p><a href="https://developers.cloudflare.com/workers/vite-plugin"><u>Cloudflare Vite plugin documentation</u></a></p></li></ul><p></p> ]]></content:encoded>
            <category><![CDATA[Developer Week]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Front End]]></category>
            <category><![CDATA[Full Stack]]></category>
            <category><![CDATA[General Availability]]></category>
            <category><![CDATA[Cloudflare Pages]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[MySQL]]></category>
            <category><![CDATA[Hyperdrive]]></category>
            <guid isPermaLink="false">67CgcpMED2Rw0BozjKbdUz</guid>
            <dc:creator>Korinne Alpers</dc:creator>
        </item>
        <item>
            <title><![CDATA[Blazing fast development with full-stack frameworks and Cloudflare]]></title>
            <link>https://blog.cloudflare.com/blazing-fast-development-with-full-stack-frameworks-and-cloudflare/</link>
            <pubDate>Fri, 05 Apr 2024 13:00:44 GMT</pubDate>
            <description><![CDATA[ You can now use your framework’s development server while accessing D1 databases, R2 object stores, AI models, and more. Iterate locally in milliseconds to build sophisticated web apps that run on Cloudflare ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Hello web developers! <a href="/making-cloudflare-for-web">Last year we released</a> a slew of improvements that made deploying web applications on Cloudflare much easier, and in response we’ve seen a large growth of Astro, Next.js, Nuxt, Qwik, Remix, SolidStart, SvelteKit, and other web apps hosted on Cloudflare. Today we are announcing major improvements to our integration with these web frameworks that makes it easier to develop sophisticated applications that use our <a href="https://www.cloudflare.com/developer-platform/products/d1/">D1 SQL database</a>, <a href="https://developers.cloudflare.com/r2/">R2</a> object store, <a href="https://developers.cloudflare.com/ai/">AI</a> models, and other powerful features of <a href="https://www.cloudflare.com/developer-platform/">Cloudflare’s developer platform.</a></p><p>In the past, if you wanted to develop a web framework-powered application with D1 and run it locally, you’d have to build a production build of your application, and then run it locally using `wrangler pages dev`. While this worked, each of your code iterations would take seconds, or tens of seconds for big applications. Iterating using production builds is simply too slow, pulls you out of the <a href="https://en.wikipedia.org/wiki/Flow_(psychology)">flow</a>, and doesn’t allow you to take advantage of all the DX optimizations that framework authors have put a lot of hard work into. This is changing today!</p><p>Our goal is to integrate with web frameworks in the most natural way possible, without developers having to learn and adopt significant workflow changes or custom APIs when deploying their app to Cloudflare. Whether you are a Next.js developer, a Nuxt developer, or prefer another framework, you can now keep on using the blazing fast local development workflow familiar to you, and ship your application on Cloudflare.</p><p>All full-stack web frameworks come with a local development server (dev server) that is custom tailored to the framework and often provides an excellent development experience, with only one exception — they don't natively support some important features of Cloudflare’s development platform, especially our <a href="https://www.cloudflare.com/developer-platform/products/#storage">storage solutions</a>.</p><p>So up until recently, you had to make a tough choice. You could use the framework-specific dev server to develop your application, but forgo access to many of Cloudflare’s features. Alternatively, you could take full advantage of Cloudflare’s platform including various resources like D1 or R2<a href="https://developers.cloudflare.com/workers/configuration/bindings/">, but you would have to give up using the framework specific developer tooling. In that case, your iteration cycle would slow down, and it would take seconds rather than milliseconds for you to see results of your code changes in the browser.</a> But not anymore! Let’s take a look.</p>
    <div>
      <h3>Let’s build an application</h3>
      <a href="#lets-build-an-application">
        
      </a>
    </div>
    <p>Let’s create a new application using <a href="https://developers.cloudflare.com/pages/get-started/c3/">C3</a> — our create-cloudflare CLI. We could use any npm client of our choice (pnpm anyone?!?), but to keep things simple in this post, we’ll stick with the default npm client. To get started, just run:</p><p><code>$ npm create cloudflare@latest</code></p><p>Provide a name for your app, or stick with the randomly generated one. Then select the “Website or web app” category, and pick a full-stack framework of your choice. We support many: <a href="https://astro.build/">Astro</a>, <a href="https://nextjs.org/">Next.js</a>, <a href="https://nuxt.com/">Nuxt</a>, <a href="https://qwik.dev/">Qwik</a>, <a href="https://remix.run/">Remix</a>, <a href="https://start.solidjs.com/getting-started/what-is-solidstart">SolidStart</a>, and <a href="https://kit.svelte.dev/">SvelteKit</a>.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/pa9natISsY3icyIUpu9Ul/cd6aa0baebe85d1b0a85eaba684d66e6/Screenshot-2024-03-28-at-7.25.10-AM.png" />
            
            </figure><p>Since C3 delegates the application scaffolding to the latest version of the framework-specific CLI, you will scaffold the application exactly as the framework authors intended without missing out on any of the framework features or options. C3 then adds to your application everything necessary for integrating and deploying to Cloudflare so that you don’t have to configure it yourself.</p><p>With our application scaffolded, let’s get it to display a list of products stored in a database with just a few steps. First, we add the configuration for our database to our <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#d1-databases">wrangler.toml</a> config file:</p>
            <pre><code>[[d1_databases]]
binding = "DB"
database_name = "blog-products-db"
database_id = "XXXXXXXXXXXXXXXX"</code></pre>
            <p>Yes, that’s right! You can now configure your <a href="https://developers.cloudflare.com/workers/configuration/bindings/">bound resources</a> via the <a href="https://developers.cloudflare.com/pages/functions/wrangler-configuration/">wrangler.toml file</a>, even for full-stack apps deployed to Pages. We’ll share much more about configuration enhancements to Pages in a <a href="/browser-rendering-api-ga-rolling-out-cloudflare-snippets-swr-and-bringing-workers-for-platforms-to-our-paygo-plans/">dedicated announcement</a>.</p><p>Now let’s create a simple schema.sql file representing our database schema:</p>
            <pre><code>CREATE TABLE products(product_id INTEGER PRIMARY KEY, name TEXT, price INTEGER);
INSERT INTO products (product_id, name, price) VALUES (1, 'Apple', 250), (2, 'Banana', 100), (3, 'Cherry', 375);</code></pre>
            <p>And initialize our database:</p><p><code>$ npx wrangler d1 execute blog-products-db --local --file schema.sql</code></p><p>Notice that we used the <code>–local</code> flag of <a href="https://developers.cloudflare.com/workers/wrangler/commands/#execute"><code>wrangler d1 execute</code></a> to apply the changes to our local D1 database. This is the database that our dev server will connect to.</p><p>Next, if you use TypeScript, let TypeScript know about your database by running:</p><p><code>$ npm run build-cf-types</code></p><p>This command is preconfigured for all full-stack applications created via C3 and executes <a href="https://developers.cloudflare.com/workers/wrangler/commands/#types"><code>wrangler types</code></a> to update the interface of Cloudflare’s environment containing all configured bindings.</p><p>We can now start the dev server provided by your framework via a handy shortcut:</p><p><code>$ npm run dev</code></p><p>This shortcut will start your framework’s dev server, whether it’s powered by <a href="https://nextjs.org/docs/app/api-reference/next-cli#development">next dev</a>, <a href="https://nitro.unjs.io/">nitro</a>, or <a href="https://vitejs.dev/">vite</a>.</p><p>Now to access our database and list the products, we can now use a framework specific approach. For example, in a Next.js application that uses the App router, we could update <code>app/api/hello/route.ts</code> with the following:</p>
            <pre><code>const db = getRequestContext().env.DB;
 const productsResults = await db.prepare('SELECT * FROM products').all();
 return Response.json(productsResults.results);</code></pre>
            <p>Or in a Nuxt application, we can create a <code>server/api/hello.ts</code> file and populate it with:</p>
            <pre><code>export default defineEventHandler(async ({ context }) =&gt; {
   const db = context.cloudflare.env.DB;
   const productsResults = await db.prepare('SELECT * FROM products').all();
   return productsResults.results;
 });</code></pre>
            <p>Assuming that the framework dev server is running on port 3000, you can test the new API route in either framework by navigating to <a href="http://localhost:3000/api/hello">http://localhost:3000/api/hello</a>. For simplicity, we picked API routes in these examples, but the same applies to any UI-generating routes as well.</p><p>Each web framework has its own way to define routes and pass contextual information about the request throughout the application, so how you access your databases, object stores, and other resources will depend on your framework. You can read our updated full-stack framework guides to learn more:</p><ul><li><p><a href="https://developers.cloudflare.com/pages/framework-guides/deploy-an-astro-site/">Astro guide</a></p></li><li><p><a href="https://developers.cloudflare.com/pages/framework-guides/nextjs/deploy-a-nextjs-site/">Next.js guide</a></p></li><li><p><a href="https://developers.cloudflare.com/pages/framework-guides/deploy-a-nuxt-site/">Nuxt guide</a></p></li><li><p><a href="https://developers.cloudflare.com/pages/framework-guides/deploy-a-qwik-site/">Qwik guide</a></p></li><li><p><a href="https://developers.cloudflare.com/pages/framework-guides/deploy-a-remix-site/">Remix guide</a></p></li><li><p><a href="https://developers.cloudflare.com/pages/framework-guides/deploy-a-solid-site/">SolidStart guide</a></p></li><li><p><a href="https://developers.cloudflare.com/pages/framework-guides/deploy-a-svelte-site/">SvelteKit guide</a></p></li></ul><p>Now that you know how to access Cloudflare’s resources in the framework of your choice, everything else you know about your framework remains the same. You can now develop your application locally, using the development server optimized for your framework, which often includes support for hot module replacement (HMR), custom dev tools, enhanced debugging support and more, all while still benefiting from Cloudflare-specific APIs and features. Win-win!</p>
    <div>
      <h3>What has actually changed to enable these development workflows?</h3>
      <a href="#what-has-actually-changed-to-enable-these-development-workflows">
        
      </a>
    </div>
    <p>To decrease the development latency and preserve the custom framework-specific experiences, we needed to enable web frameworks and their dev servers to integrate with wrangler and miniflare in a seamless, almost invisible way.</p><p><a href="https://miniflare.dev/">Miniflare</a> is a key component in this puzzle. It is our local simulator for Cloudflare-specific resources, which is powered by <a href="https://github.com/cloudflare/workerd">workerd</a>, our JavaScript (JS) runtime. By relying on workerd, we ensure that Cloudflare’s JavaScript APIs run locally in a way that faithfully simulates our production environment. The trouble is that framework dev servers already rely on Node.js to run the application, so bringing another JS runtime into the mix breaks many assumptions in how these dev servers have been architected.</p><p>Our team however came up with an interesting approach to bridging the gap between these two JS runtimes. We call it the <a href="https://developers.cloudflare.com/workers/wrangler/api/#getplatformproxy">getPlatformProxy()</a> API, which is now part of wrangler and is super-powered by <a href="https://github.com/cloudflare/miniflare/pull/639">miniflare’s magic proxy</a>. This API exposes a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy">JS proxy object</a> that behaves just like the usual <a href="https://developers.cloudflare.com/workers/runtime-apis/handlers/fetch/#parameters">Workers env object</a> containing all bound resources. The proxy object enables code from Node.js to transparently invoke JavaScript code running in workerd, as well access Cloudflare-specific runtime APIs.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1MPXvdyK3eYsY3YKnOC8co/480cdd00d7a921ecb65eb738caf17ff2/pasted-image-0--6-.png" />
            
            </figure><p>With this bridge between the Node.js and workerd runtimes, your application can now access Cloudflare simulators for D1, R2, KV and other storage solutions directly while running in a dev server powered by Node.js. Or you could even write an Node.js script to do the same:</p>
            <pre><code> import {getPlatformProxy} from 'wrangler';


 const {env} = getPlatformProxy();
 console.dir(env);
 const db = env.DB;


 // Now let’s execute a DB query that runs in a local D1 db
 // powered by miniflare/workerd and access the result from Node.js
 const productsResults = await db.prepare('SELECT * FROM products').all();
 console.log(productsResults.results);</code></pre>
            <p>With the <code>getPlatformProxy()</code> API available, the remaining work was all about updating all framework adapters, plugins, and in some cases frameworks themselves to make use of this API. We are grateful for the support we received from framework teams on this journey, especially <a href="https://github.com/alexanderniebuhr">Alex</a> from Astro, <a href="https://github.com/pi0">pi0</a> from Nuxt, <a href="https://github.com/pcattori">Pedro</a> from Remix, <a href="https://github.com/ryansolid">Ryan</a> from Solid, <a href="https://github.com/benmccann">Ben</a> and <a href="https://github.com/Rich-Harris">Rich</a> from Svelte, and our collaborator on the <a href="https://github.com/cloudflare/next-on-pages">next-on-pages</a> project, <a href="https://github.com/james-elicx">James Anderson</a>.</p>
    <div>
      <h3>Future improvements to development workflows with Vite</h3>
      <a href="#future-improvements-to-development-workflows-with-vite">
        
      </a>
    </div>
    <p>While the <a href="https://developers.cloudflare.com/workers/wrangler/api/#getplatformproxy"><code>getPlatformProxy()</code></a> API is a good solution for many scenarios, we can do better. If we could run the entire application in our JS runtime rather than Node.js, we could even more faithfully simulate the production environment and reduce developer friction and production surprises.</p><p>In the ideal world, we’d like you to develop against the same runtime that you deploy to in production, and this can only be achieved by integrating workerd directly into the dev servers of all frameworks, which is not a small feat considering the number of frameworks out there and the differences between them.</p><p>We however got a bit lucky. As we kicked off this effort, we quickly realized that <a href="https://vitejs.dev/">Vite</a>, a popular dev server used by many full-stack frameworks, was gaining increasingly greater adoption. In fact, Remix switched over to <a href="https://remix.run/blog/remix-vite-stable">Vite just recently</a> and confirmed the popularity of Vite as the common foundation for web development today.</p><p>If Vite had first-class support for running a full-stack application in an alternative JavaScript runtime, we could enable anyone using Vite to develop their applications locally with complete access to the Cloudflare developer platform. No more framework specific custom integrations and workarounds — all the features of a full-stack framework, Vite, and Cloudflare accessible to all developers.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3hj4Tb9Ex2NnwrnqZ5z6M2/e049e4300b188381259f60bc69ad054c/pasted-image-0--7-.png" />
            
            </figure><p>Sounds too good to be true? Maybe. We are very stoked to be working with the Vite team on the <a href="https://github.com/vitejs/vite/pull/16089">Vite environments</a> proposal, which could enable just that. This proposal is still evolving, so stay tuned for updates.</p>
    <div>
      <h3>What will you build today?</h3>
      <a href="#what-will-you-build-today">
        
      </a>
    </div>
    <p>We aim to make Cloudflare the best development platform for web developers. Making it quick and easy to develop your application with frameworks and tools you are already familiar with is a big part of our story. Start your journey with us by running a single command:</p><p><code>$ npm create cloudflare@latest</code></p> ]]></content:encoded>
            <category><![CDATA[Developer Week]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Full Stack]]></category>
            <category><![CDATA[Wrangler]]></category>
            <category><![CDATA[Miniflare]]></category>
            <guid isPermaLink="false">14PqvEOUknz9TI2FQGbZT3</guid>
            <dc:creator>Igor Minar</dc:creator>
            <dc:creator>Dario Piotrowicz</dc:creator>
            <dc:creator>James Culveyhouse</dc:creator>
            <dc:creator>Peter Bacon Darwin</dc:creator>
        </item>
        <item>
            <title><![CDATA[Spice up your sites on Cloudflare Pages with Pages Functions General Availability]]></title>
            <link>https://blog.cloudflare.com/pages-function-goes-ga/</link>
            <pubDate>Thu, 17 Nov 2022 14:05:00 GMT</pubDate>
            <description><![CDATA[ Pages is officially a full stack platform with Pages Functions now Generally Available. Pages is harnessing the power and scalability of Workers and specializing them to align with the Pages developer experience. ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4Qt2PNf7dtFOmbvvzhQvnn/03e6c9de323ee7a011607e61c5443610/image2-37.png" />
            
            </figure><p>Before we launched Pages back in April 2021, we knew it would be the start of something magical – an experience that felt “just right”. We envisioned an experience so simple yet so smooth that <b><i>any developer</i></b> could ship a website in seconds and add more to it by using the rest of our Cloudflare ecosystem.</p><p>A few months later, when we announced that Pages was a full stack platform in November 2021, that vision became a reality. Creating a development platform for just static sites was not the end of our Pages story, and with Cloudflare Workers already a part of our ecosystem, we knew we were sitting on untapped potential. With the introduction of Pages Functions, we empowered developers to take any static site and easily add in dynamic content with the power of Cloudflare Workers.</p><p>In the last year since Functions has been in open beta, we dove into an exploration on what kinds of full stack capabilities developers are looking for on their projects – and set out to fine tune the Functions experience into what it is today.</p><p><b>We’re thrilled to announce that Pages Functions is now generally available!</b></p>
    <div>
      <h2>Functions recap</h2>
      <a href="#functions-recap">
        
      </a>
    </div>
    <p>Though called “Functions” in the context of Pages, these functions running on our Cloudflare network are Cloudflare Workers in “disguise”. Pages harnesses the power and scalability of Workers and specializes them to align with the Pages experience our users know and love.</p><p>With Functions you can dream up the possibilities of dynamic functionality to add to your site – integrate with storage solutions, connect to third party services, use server side rendering with your favorite full stack frameworks and more. As Pages Functions opens its doors to production traffic, let’s explore some of the exciting features we’ve improved and added on this release.</p>
    <div>
      <h2>The experience</h2>
      <a href="#the-experience">
        
      </a>
    </div>
    
    <div>
      <h3>Deploy with Git</h3>
      <a href="#deploy-with-git">
        
      </a>
    </div>
    <p>Love to code? We’ll handle the infrastructure, and leave you to it.</p><p>Simply write a JavaScript/Typescript Function and drop it into a <b>functions</b> directory by committing your code to your Git provider. Our lightning fast CI system will build your code and deploy it alongside your static assets.</p>
    <div>
      <h3>Directly upload your Functions</h3>
      <a href="#directly-upload-your-functions">
        
      </a>
    </div>
    <p>Prefer to handle the build yourself? Have a special git provider not yet supported on Pages? No problem! After dropping your Function in your <b>functions</b> folder, you can build with your preferred CI tooling and then upload your project to Pages to be deployed.</p>
    <div>
      <h3>Debug your Functions</h3>
      <a href="#debug-your-functions">
        
      </a>
    </div>
    <p>While in beta, we learned that you and your teams value visibility above all. As on Cloudflare Workers, we’ve built a simple way for you to watch your functions as it processes requests – the faster you can understand an issue the faster you can react.</p><p>You can now easily view logs for your Functions by “tailing” your logs. For basic information like outcome and request IP, you can navigate to the Pages dashboard to obtain relevant logs.</p><div></div><p>For more specific filters, you can use</p>
            <pre><code>wrangler pages deployment tail</code></pre>
            <p>to receive a live feed of console and exception logs for each request your Function receives.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1Bc7Zz0wMrVCuLV3Ll8RFN/e581f4cb24dc8c78f28346195d0cd789/image1-52.png" />
            
            </figure>
    <div>
      <h3>Get real time Functions metrics</h3>
      <a href="#get-real-time-functions-metrics">
        
      </a>
    </div>
    <p>In the dashboard, Pages aggregates data for your Functions in the form of request successes/error metrics and invocation status. You can refer to your metrics dashboard not only to better understand your usage on a per-project basis but also to get a pulse check on the health of your Functions by catching success/error volumes.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/20rgwkkI2erSSmySgkpdzV/8d1aba3bb5081816d1de891e28efb7eb/image4-20.png" />
            
            </figure>
    <div>
      <h3>Quickly integrate with the Cloudflare ecosystem</h3>
      <a href="#quickly-integrate-with-the-cloudflare-ecosystem">
        
      </a>
    </div>
    
    <div>
      <h4><b>Storage bindings</b></h4>
      <a href="#storage-bindings">
        
      </a>
    </div>
    <p>Want to go truly full stack? We know finding a storage solution that fits your needs and fits your ecosystem is not an easy task – but it doesn’t have to be!</p><p>With Functions, you can take advantage of our broad range of storage products including Workers KV, Durable Objects, R2, D1 and – very soon – <a href="https://developers.cloudflare.com/queues/">Queues</a> and <a href="https://developers.cloudflare.com/analytics/analytics-engine/">Workers Analytics Engine</a>! Simply create your namespace, bucket or database and add your binding in the Pages dashboard to get your full stack site up and running in just a few clicks.</p><p>From dropping in a quick comment system to rolling your own authentication to creating database-backed <a href="https://www.cloudflare.com/ecommerce/">eCommerce sites</a>, integrating with existing products in our developer platform unlocks an exponential set of use cases for your site.</p>
    <div>
      <h4><b>Secret bindings</b></h4>
      <a href="#secret-bindings">
        
      </a>
    </div>
    <p>In addition to adding environment variables that are available to your project at both build-time and runtime, you can now also add “secrets” to your project. These are encrypted environment variables which cannot be viewed by any dashboard interfaces, and are a great home for sensitive data like API tokens or passwords.</p>
    <div>
      <h3>Integrate with 3rd party services</h3>
      <a href="#integrate-with-3rd-party-services">
        
      </a>
    </div>
    <p>Our goal with Pages is always to meet you where you are when it comes to the tools you love to use. During this beta period we also noticed some consistent patterns in how you were employing Functions to integrate with common third party services. <a href="https://developers.cloudflare.com/pages/platform/functions/plugins/">Pages Plugins</a> – our ready-made snippets of code – offers a plug and play experience for you to build the ecosystem of your choice around your application.</p><p>In essence, a Pages Plugin is a reusable – and customizable – chunk of runtime code that can be incorporated anywhere within your Pages application. It’s a “composable” Pages Function, granting Plugins the full power of Functions (i.e. Workers), including the ability to set up middleware, parameterized routes, and static assets.</p><p>With Pages Plugins you can integrate with a plethora of 3rd party applications – including officially supported <a href="https://developers.cloudflare.com/pages/platform/functions/plugins/sentry/">Sentry</a>, <a href="https://developers.cloudflare.com/pages/platform/functions/plugins/honeycomb/">Honeycomb</a>, <a href="https://developers.cloudflare.com/pages/platform/functions/plugins/stytch/">Stytch</a>, <a href="https://developers.cloudflare.com/pages/platform/functions/plugins/mailchannels/">MailChannels</a> and more.</p>
    <div>
      <h3>Use your favorite full stack frameworks</h3>
      <a href="#use-your-favorite-full-stack-frameworks">
        
      </a>
    </div>
    <p>In the spirit of meeting developers where they are at, this sentiment also comes in the form of Javascript frameworks. As a big supporter of not only widely adopted frameworks but up and coming frameworks, our team works with a plethora of framework authors to create opportunities for you to play with their new tech and deploy on Pages right out of the box.</p>
    <div>
      <h4>Now compatible with Next.js 13 and more!</h4>
      <a href="#now-compatible-with-next-js-13-and-more">
        
      </a>
    </div>
    <p>Recently, we announced our <a href="/next-on-pages/">support for Next.js applications</a> which opt in to the Edge Runtime. Today we’re excited to announce we are now compatible with Next.js 13. Next.js 13 brings some most-requested modern paradigms to the Next.js framework, including nested routing, React 18's Server Components and streaming.</p><p>Have a different preference of framework? No problem.</p><p>Go full stack on Pages to take advantage of server side rendering (SSR) with one of many other officially supported frameworks like <a href="https://remix.run/">Remix</a>, <a href="https://kit.svelte.dev/">SvelteKit</a>, <a href="https://qwik.builder.io/qwikcity/overview/">QwikCity,</a> <a href="https://start.solidjs.com/getting-started/what-is-solidstart">SolidStart</a>, <a href="https://astro.build/">Astro</a> and <a href="https://nuxtjs.org/">Nuxt</a>. You can <a href="/pages-full-stack-frameworks">check out our blog post on SSR support on Pages</a> and how to get started with some of these frameworks.</p>
    <div>
      <h3>Go fast in advanced mode</h3>
      <a href="#go-fast-in-advanced-mode">
        
      </a>
    </div>
    <p>While Pages Functions are powered by Workers, we understand that at face-value they are not exactly the same. Nevertheless, for existing users who are perhaps using Workers and are keen on trying Cloudflare Pages, we’ve <a href="https://developers.cloudflare.com/pages/platform/functions/advanced-mode/">got a direct path</a> to get you started quickly.</p><p>If you already have a single Worker and want an easy way to go full stack on Pages, you can use Pages Function’s “advanced mode”. Generate an <a href="https://developers.cloudflare.com/workers/runtime-apis/fetch-event/#syntax-module-worker">ES module Worker</a> called <code>_worker.js</code> in the output directory of your project and deploy!This can be especially helpful if you’re a framework author or perhaps have a more complex use case that does not fit into our file-based router.</p>
    <div>
      <h2>Scaling without limits</h2>
      <a href="#scaling-without-limits">
        
      </a>
    </div>
    <p>So today, as we announce Functions as generally available we are thrilled to allow your traffic to scale. During the Open Beta period, we imposed a daily limit of 100,000 free requests per day as a way to let you try out the feature. While 100,000 requests per day remains the free limit today, you can now pay to truly go unlimited.</p><p>Since Functions are just “special” Workers, with this announcement you will begin to see your Functions usage reflected on your bill under the Workers Paid subscription or via your Workers Enterprise contract. Like Workers, when on a paid plan, you have the option to choose between our two usage models – Bundled and Unbound – and will be billed accordingly.</p><p>Keeping Pages on brand as Cloudflare’s “gift to the Internet”, you will get unlimited free static asset requests and will be billed primarily on dynamic requests. You can <a href="https://developers.cloudflare.com/pages/platform/functions/pricing/">read more</a> about how billing with Functions works in our documentation.</p>
    <div>
      <h2>Get started today</h2>
      <a href="#get-started-today">
        
      </a>
    </div>
    <p>To start jamming, head over to the <a href="https://developers.cloudflare.com/pages/platform/functions/">Pages Functions docs</a> and <a href="/pages-full-stack-frameworks">check out our blog</a> on some of the best frameworks to use to deploy your first full stack application. As you begin building out your projects be sure to let us know in the <a href="https://discord.com/channels/595317990191398933/910978223968518144">#functions channel</a> under Pages of our <a href="https://discord.gg/cloudflaredev">Cloudflare Developers Discord</a>. Happy building!</p> ]]></content:encoded>
            <category><![CDATA[Developer Week]]></category>
            <category><![CDATA[Cloudflare Pages]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Serverless]]></category>
            <category><![CDATA[Full Stack]]></category>
            <category><![CDATA[JAMstack]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">0qAOpwZHFx8u2Lq0PKf8c</guid>
            <dc:creator>Nevi Shah</dc:creator>
        </item>
        <item>
            <title><![CDATA[And here's another one: the Next.js Edge Runtime becomes the fourth full-stack framework supported by Cloudflare Pages]]></title>
            <link>https://blog.cloudflare.com/next-on-pages/</link>
            <pubDate>Mon, 24 Oct 2022 13:00:00 GMT</pubDate>
            <description><![CDATA[ You can now deploy SSR Next.js applications to the Cloudflare Pages platform ⚡️ ]]></description>
            <content:encoded><![CDATA[ <p></p><p>You can now deploy <a href="https://nextjs.org/">Next.js</a> applications which opt in to the <a href="https://nextjs.org/docs/api-reference/edge-runtime">Edge Runtime</a> on Cloudflare Pages. Next.js is the fourth full-stack web framework that the Pages platform officially supports, and it is <a href="https://almanac.httparchive.org/en/2022/jamstack">one of the most popular in the 'Jamstack-y' space</a>.</p><p>Cloudflare Pages started its journey as a platform for static websites, but with <a href="/cloudflare-pages-goes-full-stack/">last year's addition of Pages Functions</a> powered by Cloudflare Workers, the platform has progressed to support an even more diverse range of use cases. Pages Functions allows developers to sprinkle in small pieces of server-side code with its simple file-based routing, or, as we've seen with the adoption from other frameworks (namely <a href="https://developers.cloudflare.com/pages/framework-guides/deploy-a-svelte-site/">SvelteKit</a>, <a href="https://developers.cloudflare.com/pages/framework-guides/remix/">Remix</a> and <a href="https://developers.cloudflare.com/pages/framework-guides/deploy-a-qwik-site/">Qwik</a>), Pages Functions can be used to power your entire full-stack app. The folks behind <a href="/remix-on-cloudflare-pages/">Remix previously talked about the advantages of adopting open standards</a>, and we've seen this again with Next.js' Edge Runtime.</p>
    <div>
      <h2>Next.js' Edge Runtime</h2>
      <a href="#next-js-edge-runtime">
        
      </a>
    </div>
    <p><a href="https://nextjs.org/docs/api-reference/edge-runtime">Next.js' Edge Runtime</a> is an experimental mode that developers can opt into which results in a different type of application being built. Previously, Next.js applications which relied on server-side rendering (SSR) functionality had to be deployed on a Node.js server. Running a Node.js server has significant overhead, and our Cloudflare Workers platform was fundamentally built on a different technology, <a href="https://developers.cloudflare.com/workers/learning/how-workers-works/">V8</a>.</p><p>However, when Next.js <a href="https://vercel.com/blog/introducing-the-edge-runtime">introduced the Edge Runtime mode</a> in June 2022, we saw the opportunity to bring this widely used framework to our platform. We're very excited that this is being developed in coordination with the <a href="/introducing-the-wintercg/">WinterCG</a> standards to ensure interoperability across the various web platforms and to ensure that developers have the choice on where they run their business, without fearing any significant vendor lock-in.</p><p>It’s important to note that some existing Next.js apps built for Node.js won't immediately work on Pages. If your application relies on any Node.js built-ins or long-running processes, then Pages may not support your app with today’s announcement as we're working on <a href="/node-js-support-cloudflare-workers/">expanding our support for Node.js</a>.</p><p>However, we see the migration to the Edge Runtime as an effort that's worthy of investment, to run your applications, well, on the edge! These applications are cheaper to run, respond faster to users and have the latest features that full-stack frameworks offer. We're seeing increased interest in third-party npm packages and libraries that support standardized runtimes, and in combination with Cloudflare's data products (e.g. <a href="https://www.cloudflare.com/products/workers-kv/">KV</a>, <a href="https://www.cloudflare.com/products/durable-objects/">Durable Objects</a> and <a href="/whats-new-with-d1/">D1</a>), we're confident that the edge is going to be the first place that people will want to deploy applications going forward.</p>
    <div>
      <h2>Deploy your Next.js app to Cloudflare Pages</h2>
      <a href="#deploy-your-next-js-app-to-cloudflare-pages">
        
      </a>
    </div>
    <p>Let’s walk through an example, creating a new Next.js application that opts into this Edge Runtime and deploying it to Cloudflare Pages.</p>
            <pre><code>npx create-next-app@latest my-app</code></pre>
            <p>This will create a new Next.js app in the <code>my-app</code> folder. The default template comes with a traditional Node.js powered API route, so let's update that to instead use the Edge Runtime.</p>
            <pre><code>// pages/api/hello.js

// Next.js Edge API Routes: https://nextjs.org/docs/api-routes/edge-api-routes

export const config = {
  runtime: 'experimental-edge',
}

export default async function (req) {
  return new Response(
    JSON.stringify({ name: 'John Doe' }),
    {
      status: 200,
      headers: {
        'Content-Type': 'application/json'
      }
    }
  )
}</code></pre>
            <p>Thanks to the Edge Runtime adopting the Web API standards, if you've ever written a Cloudflare Worker before, this might look familiar.</p><p>Next, we can update the global <code>next.config.js</code> configuration file to use the Edge Runtime. This will enable us to use <a href="https://nextjs.org/docs/api-reference/data-fetching/get-server-side-props">the <code>getServerSideProps()</code> API</a> and server-side render (SSR) our webpages.</p>
            <pre><code>// next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    runtime: 'experimental-edge',
  },
  reactStrictMode: true,
  swcMinify: true,
}
module.exports = nextConfig</code></pre>
            <p>Finally, we're ready to deploy the project. Publish it to a GitHub or GitLab repository, create a new Pages project, and select "Next.js" from the list of framework presets. This will configure your project to use <a href="https://github.com/cloudflare/next-on-pages">the <code>@cloudflare/next-on-pages</code> CLI</a> which builds and transforms your project into something we can deploy on Pages. Navigate to the project settings and add an environment variable, <code>NODE_VERSION</code> set to <code>14</code> or greater, as well as the following compatibility flags: <code>streams_enable_constructors</code> and <code>transformstream_enable_standard_constructor</code>. You should now be able to deploy your Next.js application. If you want to read more, you can find a detailed guide in <a href="https://developers.cloudflare.com/pages/framework-guides/deploy-a-nextjs-site/">our documentation</a>.</p>
    <div>
      <h2>How it runs on Cloudflare Pages</h2>
      <a href="#how-it-runs-on-cloudflare-pages">
        
      </a>
    </div>
    
    <div>
      <h3>Compatibility Dates and Compatibility Flags</h3>
      <a href="#compatibility-dates-and-compatibility-flags">
        
      </a>
    </div>
    <p>Cloudflare Workers has solved the versioning problem by <a href="/backwards-compatibility-in-cloudflare-workers/">introducing compatibility dates and compatibility flags</a>. While it has been in beta, Pages Functions has always defaulted to using the oldest version of the Workers runtime. We've now introduced controls to allow developers to set these dates and flags on their Pages projects environments.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1qm1x1OaVxhfm80IgIBhYd/e7bff63f0f14ee4a08ea82b14f3c8a53/image2-12.png" />
            
            </figure><p>By keeping this date recent, you are able to opt in to the latest features and bug fixes that the Cloudflare Workers runtime offers, but equally, you're completely free to keep the date on whatever works for you today, and we'll continue to support the functionality at that point in time, forever. We also allow you to set these dates for your production and preview environments independently which will let you test these changes out safely in a preview deployment before rolling it out in production.</p><p>We've been working on adding more support for the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Streams_API">Streams API</a> to the Workers Runtime, and some of this functionality is gated behind the flags we added to the project earlier. <a href="https://developers.cloudflare.com/workers/platform/compatibility-dates/#change-history">These flags are currently scheduled to graduate</a> and become on-by-default on a future compatibility date, 2022-11-30.</p>
    <div>
      <h3>The <code>@cloudflare/next-on-pages</code> CLI</h3>
      <a href="#the-cloudflare-next-on-pages-cli">
        
      </a>
    </div>
    <p>Vercel introduced the <a href="https://vercel.com/blog/build-output-api">Build Output API</a> in July 2022 as a "zero configuration" directory structure which the Vercel platform inherently understands and can deploy. We've decided to hook into this same API as a way to build Next.js projects consistently that we can understand and deploy.</p><p>The <a href="https://github.com/cloudflare/next-on-pages">open-source</a> <code>[@cloudflare/next-on-pages](https://github.com/cloudflare/next-on-pages)</code> <a href="https://github.com/cloudflare/next-on-pages">CLI</a> runs <code>npx vercel build</code> behind the scenes, which produces a <code>.vercel/output</code> directory. This directory conforms to the <a href="https://vercel.com/docs/build-output-api/v3">Build Output API</a>, and of particular interest, contains a <code>config.json</code>, <code>static</code> folder and folder of <code>functions</code>. The <code>@cloudflare/next-on-pages</code> CLI then parses this <code>config.json</code> manifest, and combines all the <code>functions</code> into a single <a href="https://developers.cloudflare.com/pages/platform/functions/#advanced-mode">Pages Functions 'advanced mode' <code>_worker.js</code></a>.</p><p>At this point, the build is finished. Pages then automatically picks up this <code>_worker.js</code> and deploys it with Pages Functions atop the <code>static</code> directory.</p><p>Although currently just an implementation detail, we opted to use this Build Output API for a number of reasons. We’re also exploring other similar functionality natively on the Pages platform. We already have one "magical" directory, the <code>functions</code> directory which we use for the file-based routing of Pages Functions. It's possible that we offer other fixed directory structures which would reduce the need for configuration of any projects using frameworks which adopt the API. Let us know <a href="https://discord.com/channels/595317990191398933/910978223968518144">in Discord</a> if you have any thoughts or preferences on what you would like to see!</p><p>Additionally, if more full-stack frameworks do adopt Vercel's Build Output API, we may have automatic support for them running on Pages with this CLI. We've only been experimenting with Next.js here so far (and SvelteKit, Remix and Qwik all have their own way of building their projects on Pages at the moment), but it's possible that in the future we may converge on a standard approach which could be shared between frameworks and platforms. We're excited to see how this might transpire. Again, <a href="https://discord.com/channels/595317990191398933/910978223968518144">let us know</a> if you have thoughts!</p>
    <div>
      <h3>Experimental webpack minification</h3>
      <a href="#experimental-webpack-minification">
        
      </a>
    </div>
    <p>As part of the compilation from <code>.vercel/output/functions</code> to an <code>_worker.js</code>, the <code>@cloudflare/next-on-pages</code> CLI can perform an experimental minification to give you more space for your application to run on Workers. Right now, most accounts are <a href="https://developers.cloudflare.com/workers/platform/limits/#worker-size">limited to a maximum script size of 1MB</a> (although this can be raised in some circumstances—<a href="https://docs.google.com/forms/d/e/1FAIpQLSd_fwAVOboH9SlutMonzbhCxuuuOmiU1L_I5O2CFbXf_XXMRg/viewform">get in touch</a>!). You can ordinarily fit quite a lot of code in this, but one thing notable about Next.js' build process at the moment is that it creates webpack-compiled, fully-formed and fully-isolated functions scripts in each of the directories in <code>.vercel/output/functions</code>. This means that each function ends up looking something like this:</p>
            <pre><code>let _ENTRIES = {};
(() =&gt; {
  // webpackBootstrap
})();

(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([100], {

  123: (() =&gt; {
    // webpack chunk #123
  }),
  234: (() =&gt; {
    // webpack chunk #234
  }),
  345: (() =&gt; {
    // webpack chunk #345
  }),

  // …lots of webpack chunks…

}, () =&gt; {
  // webpackRuntimeModules
}]);

export default {
  async fetch(request, env, ctx) {
    return _ENTRIES['some_function'].default.call(request);
  }
}</code></pre>
            <p>The script contains everything that's needed to deploy this function, and most of the logic exists in these webpack chunks, but that means that each function has a lot of code shared with its siblings. Quickly, you'll reach the 1MB limit, if you naively deployed all these functions together.</p><p>Our <code>@cloudflare/next-on-pages --experimental-minify</code> CLI argument deals with this problem by analyzing webpack chunks which are re-used in multiple places in this <code>.vercel/output/functions</code> directory and extracts out that code to a common place. This allows our compiler (esbuild) to efficiently combine this code, without duplicating it in all of these places. This process is experimental for the time being, while we look to make this as efficient as possible, without introducing any bugs as a result. Please <a href="https://github.com/cloudflare/next-on-pages/issues/">file an issue on GitHub</a> if you notice any difference in behavior when using <code>--experimental-minify</code>.</p>
    <div>
      <h2>What's next?</h2>
      <a href="#whats-next">
        
      </a>
    </div>
    <p>Pages Functions has been in beta for almost a year, and we're very excited to say that general availability is just around the corner. We're polishing off the last of the remaining features which includes analytics, logging, and billing. In fact, for billing, we recently made <a href="https://developers.cloudflare.com/pages/platform/functions/billing/">the announcement of how you'll be able to use the Workers Paid plan to remove the request limits of the Pages Functions beta from November 15</a>.</p><p>Finally, we're also looking at how we can bring Wasm support to Pages Functions which will unlock ever more use-cases for your full-stack applications. Stay tuned for more information on how we'll be offering this soon.</p><p>Try creating a Next.js Edge Runtime application and deploying it to Cloudflare Pages with the example above or by following <a href="https://developers.cloudflare.com/pages/framework-guides/deploy-a-nextjs-site/">the guide in our documentation</a>. Let us know if you have any questions or face any issues in <a href="https://discord.com/channels/595317990191398933/910978223968518144">Discord</a> or on <a href="https://github.com/cloudflare/next-on-pages/issues/">GitHub</a>, and please report any quirks of the <code>--experimental-minify</code> argument. As always, we're excited to see what you build!</p> ]]></content:encoded>
            <category><![CDATA[Cloudflare Pages]]></category>
            <category><![CDATA[Full Stack]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Connectivity Cloud]]></category>
            <guid isPermaLink="false">6H5XhDzpuEfNdN2fJj9PO2</guid>
            <dc:creator>Greg Brimble</dc:creator>
        </item>
        <item>
            <title><![CDATA[Supporting Remix with full stack Cloudflare Pages]]></title>
            <link>https://blog.cloudflare.com/remix-on-cloudflare-pages/</link>
            <pubDate>Fri, 17 Dec 2021 20:40:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare Pages now natively supports full stack Remix applications ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4L8XNQXMAMjKwMWhI8FceZ/c893e90edadc4590e7229aebe4d5c447/remix-1.png" />
            
            </figure><p>We announced the <a href="/cloudflare-pages-goes-full-stack/">open beta of full stack Cloudflare Pages</a> in November and have since seen widespread uptake from developers looking to add dynamic functionality to their applications. Today, we're excited to announce Pages' support for Remix applications, powered by our full stack platform.</p>
    <div>
      <h3>The new kid on the block: Remix</h3>
      <a href="#the-new-kid-on-the-block-remix">
        
      </a>
    </div>
    <p><a href="https://remix.run/">Remix</a> is a new framework that is focused on fully utilizing the power of the web. Like Cloudflare Workers, it uses modern JavaScript APIs, and it places emphasis on web fundamentals such as meaningful HTTP status codes, caching and optimizing for both usability and performance. One of the biggest features of Remix is its transportability: Remix provides a platform-agnostic interface and adapters allowing it to be deployed to a growing number of providers. Cloudflare Workers was available at Remix's launch, but what makes Workers different in this case, is the native compatibility that Workers can offer.</p><blockquote><p><i>One of the main inspirations for Remix was the way Cloudflare Workers uses native web APIs for handling HTTP requests and responses. It's a brilliant decision because developers are able to reuse knowledge on the server that they gained building apps in the browser! Remix runs natively on Cloudflare Workers, and the results we've seen so far are fantastic. We are incredibly excited about the potential that Cloudflare Workers and Pages unlocks for building apps that run at the edge!</i>- <b>Michael Jackson</b>, CEO at <a href="https://remix.run/">Remix</a></p></blockquote><p>This native compatibility means that as you learn how to write applications in Remix, you're also learning how to write Cloudflare Workers (and vice versa). But it also means better performance! Rather than having a Node.js process running on a server — which could be far away from your users, could be overwhelmed in the case of high traffic, and has to map between Node.js' runtime and the modern Fetch API — you can deploy to Cloudflare's network and requests will be routed to any one of our 250+ locations. This means better performance for your users, with <a href="/250-cities-is-just-the-start/">95% of the entire Internet-connected world lying within 50ms of a Cloudflare presence, and 80% of the Internet-connected world within 20ms</a>.</p>
    <div>
      <h3>Integrating with Cloudflare</h3>
      <a href="#integrating-with-cloudflare">
        
      </a>
    </div>
    <p>More often than not, full stack applications need some place to store data. Cloudflare offers three all-encompassing options here:</p><ul><li><p>KV, our high performance and globally replicated key-value datastore.</p></li><li><p>Durable Objects, our strongly consistent coordination primitive which can be restricted to a given jurisdiction.</p></li><li><p><a href="https://www.cloudflare.com/developer-platform/products/r2/">R2</a> (coming soon!), our fast and reliable <a href="https://www.cloudflare.com/learning/cloud/what-is-object-storage/">object storage</a>.</p></li></ul><p>Remix already tightly integrates with <a href="https://remix.run/docs/en/v1/api/remix#createcloudflarekvsessionstorage-cloudflare-workers">KV for session storage</a>, and a Durable Objects integration is in progress. Additionally, Cloudflare's other features, such as <a href="https://developers.cloudflare.com/workers/runtime-apis/request#incomingrequestcfproperties">geolocating incoming requests</a>, <a href="https://developers.cloudflare.com/workers/runtime-apis/html-rewriter">HTMLRewriter</a> and our <a href="https://developers.cloudflare.com/workers/runtime-apis/cache">Cache API</a>, are all available from within your Remix application.</p>
    <div>
      <h3>Deploying to Cloudflare Pages</h3>
      <a href="#deploying-to-cloudflare-pages">
        
      </a>
    </div>
    <p>Cloudflare Pages was already capable of serving static assets from the Cloudflare edge, but now with November's release of serverless functions powered by Cloudflare Workers, it has evolved into an entire platform perfectly suited for <a href="https://www.cloudflare.com/developer-platform/solutions/hosting/">hosting full stack applications</a>.</p><p>To get started with Remix and Cloudflare Pages today, run the following in your terminal, and select "Cloudflare Pages" when asked "Where do you want to deploy?":</p>
            <pre><code>npx create-remix@latest</code></pre>
            <p>Then create a repository on <a href="https://developers.cloudflare.com/pages/platform/github-integration">GitHub</a> or <a href="/cloudflare-pages-partners-with-gitlab/">GitLab</a>, <code>git commit</code>, and <code>git push</code> the newly created folder. Finally, navigate to Cloudflare Pages, select your repository, and select "Remix" from the dropdown of framework presets. Your new application will be available on your <code>pages.dev</code> subdomain, or you can <a href="https://developers.cloudflare.com/pages/get-started#adding-a-custom-domain">connect it to any of your custom domains</a>.</p><p>Your folder will have a <code>functions/[[path]].ts</code> file. This is <a href="https://developers.cloudflare.com/pages/platform/functions">the functions integration</a> where we serve your Remix application on all paths of your website. <a href="https://remix.run/docs/en/v1/api/conventions#file-name-conventions">The <code>app</code> folder</a> is where the bulk of your Remix application's logic is. With Pages' support for <a href="https://developers.cloudflare.com/pages/platform/rollbacks">rollbacks</a> and <a href="https://developers.cloudflare.com/pages/platform/preview-deployments">preview deployments</a>, you can safely test any changes to your application, and, with <a href="/wrangler-v2-beta">the wrangler 2.0 beta</a>, testing locally is just a simple case of <code>npm run dev</code>.</p>
    <div>
      <h3>The future of frameworks on Cloudflare Pages</h3>
      <a href="#the-future-of-frameworks-on-cloudflare-pages">
        
      </a>
    </div>
    <p>Remix is the second framework to integrate natively with full stack Cloudflare Pages, following <a href="https://kit.svelte.dev/">SvelteKit</a>, which was available at launch. But this is just the beginning! We have a lot more in store for our integration with Remix and other frameworks. Stay tuned for improvements on  Pages’ build times and other areas of the developer experience, as well as new features to the platform.</p>
    <div>
      <h3>Join our community!</h3>
      <a href="#join-our-community">
        
      </a>
    </div>
    <p>If you are new to the Cloudflare Pages and Workers world, <a href="https://discord.com/invite/cloudflaredev">join our Discord server</a> and show us what you’re building. Whether it’s a new full stack application on Remix or even a simple static site, we’d love to hear from you.</p> ]]></content:encoded>
            <category><![CDATA[Cloudflare Pages]]></category>
            <category><![CDATA[Full Stack]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Serverless]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <guid isPermaLink="false">38eHIbplcXpnQ4Llvb0JEK</guid>
            <dc:creator>Greg Brimble</dc:creator>
        </item>
        <item>
            <title><![CDATA[Cloudflare Pages Goes Full Stack]]></title>
            <link>https://blog.cloudflare.com/cloudflare-pages-goes-full-stack/</link>
            <pubDate>Wed, 17 Nov 2021 13:59:32 GMT</pubDate>
            <description><![CDATA[ Cloudflare Pages with Functions is now in open beta! ]]></description>
            <content:encoded><![CDATA[ <p></p><p>When we announced Cloudflare Pages as <a href="/cloudflare-pages-ga/#:~:text=In%20December%2C%20we%20announced%20the,powerful%20tool%20in%20developers'%20hands.">generally available</a> in April, we promised you it was just the beginning. The journey of our platform started with support for static sites with small bits of dynamic functionality like setting <a href="/custom-headers-for-pages/">redirects and custom headers</a>. But we wanted to give even more power to you and your teams to begin building the unimaginable. We envisioned a future where your entire application — frontend, APIs, storage, data — could all be deployed with a single commit, easily testable in staging and requiring a single merge to deploy to production. So in the spirit of “Full Stack” Week, we’re bringing you the tools to do just that.</p><p>Welcome to the future, everyone. We’re thrilled to announce that Pages is now a Full Stack platform with help from <a href="https://workers.cloudflare.com/?&amp;_bt=521144407143&amp;_bk=&amp;_bm=b&amp;_bn=g&amp;_bg=123914288844&amp;_placement=&amp;_target=&amp;_loc=9067609&amp;_dv=c&amp;awsearchcpc=1&amp;gclid=Cj0KCQiAsqOMBhDFARIsAFBTN3eyQsvbPzy3y3BOeCnYZMDVjSd8QkaoPbOfFiFWxSK8zEm9lSCNAJsaAnfkEALw_wcB&amp;gclsrc=aw.ds">Cloudflare Workers</a>!</p>
    <div>
      <h2>But how?</h2>
      <a href="#but-how">
        
      </a>
    </div>
    <p>It works the exact same way Pages always has: write your code, <code>git push</code> to your git provider (<a href="/cloudflare-pages-partners-with-gitlab/">now supporting GitLab</a>!) and we’ll deploy your entire site for you. The only difference is, it won’t just be your frontend but your backend too using Cloudflare Workers to help deploy serverless functions.</p>
    <div>
      <h3>The integration you’ve been waiting for</h3>
      <a href="#the-integration-youve-been-waiting-for">
        
      </a>
    </div>
    <p>Cloudflare Workers provides a serverless execution environment that allows you to create entirely new applications or augment existing ones without configuring or maintaining infrastructure. Before today, it was <i>possible</i> to connect Workers to a Pages project—installing Wrangler and manually deploying a Worker by writing your app in both Pages and Workers. But we didn’t just want “possible”, we wanted something that came as second nature to you so you wouldn’t have to think twice about adding dynamic functionality to your site.</p>
    <div>
      <h2>How it works</h2>
      <a href="#how-it-works">
        
      </a>
    </div>
    <p>By using your repo’s filesystem convention and exporting one or more function handlers, Pages can leverage Workers to deploy serverless functions on your behalf. To begin, simply add a <code>./functions</code> directory in the root of your project, and inside a JavaScript or TypeScript file, export a function handler. For example, let’s say in your <code>./functions</code> directory, you have a file, <code>hello.js</code>, containing:</p>
            <pre><code>// GET requests to /filename would return "Hello, world!"
export const onRequestGet = () =&gt; {
  return new Response("Hello, world!")
}

// POST requests to /filename with a JSON-encoded body would return "Hello, &lt;name&gt;!"
export const onRequestPost = async ({ request }) =&gt; {
  const { name } = await request.json()
  return new Response(`Hello, ${name}!`)
}</code></pre>
            <p>If you perform a <code>git commit</code>, it will trigger a new Pages build to deploy your dynamic site! During the build pipeline, Pages traverses your directory, mapping the filenames to URLs relative to your repo structure.</p><p>Under the hood, Pages generates Workers which include all your routing and functionality from the source.  Functions supports deeply-nested routes, wildcard matching, middleware for things like authentication and error-handling, and more! To demonstrate all of its bells and whistles, we’ve created a blog post to walk through an <a href="/building-full-stack-with-pages">example full stack application</a>.</p>
    <div>
      <h2>Letting you do what you do best</h2>
      <a href="#letting-you-do-what-you-do-best">
        
      </a>
    </div>
    <p>As your site grows in complexity, with Pages’ new full stack functionality, your developer experience doesn’t have to. You can enjoy the workflow you know and love while unlocking even more depth to your site.</p>
    <div>
      <h3>Seamlessly build</h3>
      <a href="#seamlessly-build">
        
      </a>
    </div>
    <p>In the same way we’ve handled builds and deployments with your static sites — with a <code>git commit</code> and <code>git push</code> — we’ll deploy your functions for you automatically. As long as your directory follows the proper structure, Pages will identify and deploy your functions to our network with your site.</p>
    <div>
      <h3>Define your bindings</h3>
      <a href="#define-your-bindings">
        
      </a>
    </div>
    <p>While bringing your Workers to Pages, bindings are a big part of what makes your application a <b><i>full stack</i></b> application**.** We’re so excited to bring to Pages all the bindings you’ve previously used with regular Workers!</p><ul><li><p><b>KV namespace:</b> Our serverless and globally accessible key-value storage solution. Within Pages, you can integrate with any of the KV namespaces you set in your Workers dashboard for your Pages project.</p></li><li><p><b>Durable Object namespace:</b> Our strongly consistent coordination primitive that makes connecting WebSockets, handling state and building entire applications a breeze. As with KV, you can set your namespaces within the Workers dashboard and choose from that list within the Pages interface.</p></li><li><p><b>R2 (coming soon!):</b> Our <a href="https://www.cloudflare.com/developer-platform/solutions/s3-compatible-object-storage/">S3-compatible Object Storage solution</a> that’s slashing <a href="https://www.cloudflare.com/learning/cloud/what-are-data-egress-fees/">egress fees</a> to zero.</p></li><li><p><b>Environment Variable: </b> An injected value that can be accessed by your functions and is stored as plain-text. You can set your environment variables directly within the Pages interface for both your production and preview environments at build-time and run-time.</p></li><li><p><b>Secret (coming soon!): </b> An encrypted environment variable, which cannot be viewed by wrangler or any dashboard interfaces. Secrets are a great home for sensitive data including passwords and API tokens.</p></li></ul>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6AIqWYs5VMYZhxNRAGoLvY/3b3c1572fba8a42b73f4712091d1c7a7/image2-15.png" />
            
            </figure>
    <div>
      <h3>Preview deployments — now for your backend too</h3>
      <a href="#preview-deployments-now-for-your-backend-too">
        
      </a>
    </div>
    <p>With the deployment of your serverless functions, you can still enjoy the ease of collaboration and testing like you did previously. Before you deploy to production, you can easily deploy your project to a preview environment to stage your changes. Even with your functions, Pages lets you keep a version history of every commit with a unique URL for each, making it easy to gather feedback whether it’s from a fellow developer, PM, designer or marketer! You can also enjoy the same infinite staging privileges that you did for static sites, with a consistent URL for the latest changes.</p>
    <div>
      <h3>Develop and preview locally too</h3>
      <a href="#develop-and-preview-locally-too">
        
      </a>
    </div>
    <p>However, we realize that building and deploying with every small change just to stage your changes can be cumbersome at times if you’re iterating quickly. You can now develop full stack Pages applications with the latest release of our wrangler CLI. Backed by Miniflare, you can run your entire application locally with support for mocked secrets, environment variables, and KV (Durable Objects support coming soon!). Point wrangler at a directory of static assets, or seamlessly connect to your existing tools:</p>
            <pre><code># Install wrangler v2 beta
npm install wrangler@beta

# Serve a folder of static assets
npx wrangler pages dev ./dist

# Or automatically proxy your existing tools
npx wrangler pages dev -- npx react-scripts start</code></pre>
            <p>This is just the beginning of Pages' integrations with wrangler. Stay tuned as we continue to enhance your developer experience.</p>
    <div>
      <h2>What else can you do?</h2>
      <a href="#what-else-can-you-do">
        
      </a>
    </div>
    <p>Everything you can do with HTTP Workers today!</p><p>When deploying a Pages application with functions, Pages is compiling and deploying first class Workers on your behalf. This means there is zero functionality loss when deploying a Worker within your Pages application — instead, there are only new benefits to be gained!</p>
    <div>
      <h3>Integrate with SvelteKit — out of the box!</h3>
      <a href="#integrate-with-sveltekit-out-of-the-box">
        
      </a>
    </div>
    <p><a href="https://github.com/sveltejs/kit">SvelteKit</a> is a web framework for building Svelte applications. It’s built and maintained by the Svelte team, which makes it the Svelte user’s go-to solution for all their application needs. Out of the box, SvelteKit allows users to build projects with complex API backends.</p><p>As of today, SvelteKit projects can attach and configure the <a href="https://github.com/sveltejs/kit"><code>@sveltejs/adapter-cloudflare</code></a> package. After doing this, the project can be added to Pages and is ready for its first deployment! With Pages, your SvelteKit project(s) can deploy with API endpoints and full server-side rendering support. Better yet, the entire project — including the API endpoints — can enjoy the benefits of preview deployments, too! This, even on its own, is a huge victory for advanced projects that were previously on the Workers adapter. Check out this <a href="http://github.com/lukeed/pages-fullstack">example to see the SvelteKit adapter</a> for Pages in action!</p>
    <div>
      <h3>Use server-side rendering</h3>
      <a href="#use-server-side-rendering">
        
      </a>
    </div>
    <p>You are now able to intercept any request that comes into your Pages project. This means that you can define Workers logic that will receive incoming URLs and, instead of serving static HTML, your Worker can render fresh HTML responses with dynamic data.</p><p>For example, an application with a product page can define a single <code>product/[id].js</code> file that will receive the <code>id</code> parameter, retrieve the product information from a Workers KV binding, and then generate an HTML response for that page. Compared to a static-site generator approach, this is more succinct and easier to maintain over time since you do not need to build a static HTML page <i>per product</i> at build-time… which may potentially be tens or even hundreds of thousands of pages!</p>
    <div>
      <h2>Already have a Worker? We’ve got you!</h2>
      <a href="#already-have-a-worker-weve-got-you">
        
      </a>
    </div>
    <p>If you already have a single Worker and want to bring it right on over to Pages to reap the developer experience benefits of our platform, our announcement today also enables you to do precisely that. Your build can generate an ES module Worker called <code>_worker.js</code> in the output directory of your project, perform your git commands to deploy, and we’ll take care of the rest! This can be especially advantageous to you if you’re a framework author or have a more complex use case that doesn’t follow our provided file structure.</p>
    <div>
      <h2>Try it at no cost — for a limited time only</h2>
      <a href="#try-it-at-no-cost-for-a-limited-time-only">
        
      </a>
    </div>
    <p>We’re thrilled to be releasing our open beta today for everyone to try at no additional cost to your Cloudflare plan. While we will still have <a href="https://developers.cloudflare.com/pages/platform/functions#pricing-and-limits">limits</a> in place, we are using this open beta period to learn more about how you and your teams are deploying functions with your Pages projects. For the time being, we encourage you to lean into your creativity and build out that site you’ve been thinking about for a long time — without the worry of getting billed.</p><p>In just a few short months, when we announce General Availability, you can expect our billing to reflect that of the Workers Bundled plan — after all, these are just Workers under the hood!</p>
    <div>
      <h2>Coming up…</h2>
      <a href="#coming-up">
        
      </a>
    </div>
    <p>As we’re only announcing this release as an open beta, we have some really exciting things planned for the coming weeks and months. We want to improve on the quick and easy Pages developer experience that you're already familiar with by adding support for integrated logging and more analytics for your deployed functions.</p><p>Beyond that, we'll be expanding our first-class support for the next generation of frontend frameworks. As we've shown with SvelteKit, Pages' ability to seamlessly deploy both static and dynamic code together enables unbeatable end-user performance &amp; developer ease, and we're excited to unlock that for more people. Fans of similar frameworks &amp; technologies, such as NextJS, NuxtJS, React Server Components, Remix, Hydrogen, etc., stay tuned to this blog for more announcements. Or better yet, come <a href="https://www.cloudflare.com/careers/">join us</a> and help make it happen!</p><p>Additionally, as we’ve done with SvelteKit, we’re looking to include more first-class integration with existing frameworks, so Pages can become the primary home for your preferred frameworks of choice. Work is underway on making NextJS, NuxtJS, React Server Components, Shopify Hydrogen and more integrate seamlessly as you develop your full stack apps.</p><p>Finally, we’re working to speed up those build times, so you can focus on pushing changes and iterating quickly — without the wait!</p>
    <div>
      <h2>Getting started</h2>
      <a href="#getting-started">
        
      </a>
    </div>
    <p>To get started head over to our <a href="https://developers.cloudflare.com/pages/platform/functions">Pages docs</a> and check out our <a href="/building-full-stack-with-pages">demo blog</a> to learn more about how to deploy serverless functions to Pages using Cloudflare Workers.</p><p>Of course, what we love most is seeing what you build! Pop into <a href="https://discord.com/invite/cloudflaredev">our Discord</a> and show us how you’re using Pages to build your full stack apps.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5TghCmJGOGyp3tdbWO6xmV/9cb9456f183c182837b9b0fd19d6b692/image3-21.png" />
            
            </figure>
    <div>
      <h3>Watch on Cloudflare TV</h3>
      <a href="#watch-on-cloudflare-tv">
        
      </a>
    </div>
    <div></div><p></p> ]]></content:encoded>
            <category><![CDATA[Full Stack Week]]></category>
            <category><![CDATA[Cloudflare Pages]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Full Stack]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <guid isPermaLink="false">34bHu85gjHcwSanuNv6VQ8</guid>
            <dc:creator>Nevi Shah</dc:creator>
            <dc:creator>Glen Maddern</dc:creator>
            <dc:creator>Cina Saffary</dc:creator>
        </item>
        <item>
            <title><![CDATA[Building a full stack application with Cloudflare Pages]]></title>
            <link>https://blog.cloudflare.com/building-full-stack-with-pages/</link>
            <pubDate>Wed, 17 Nov 2021 13:58:53 GMT</pubDate>
            <description><![CDATA[ Full-stack support for Cloudflare Pages is now in open beta, and you can test it today with this example image-sharing project that integrates with KV, Durable Objects, Cloudflare Images and Cloudflare Access.  ]]></description>
            <content:encoded><![CDATA[ <p></p><p>We were so excited to <a href="/cloudflare-pages-goes-full-stack">announce support for full stack applications in Cloudflare Pages</a> that we knew we had to show it off in a big way. We've built a sample image-sharing platform to demonstrate how you can add serverless functions right from within Pages with help from Cloudflare Workers. With just one new file to your project, you can add dynamic rendering, interact with other APIs, and persist data with KV and Durable Objects. The possibilities for full-stack applications, in combination with Pages' quick development cycles and unlimited preview environments, gives you the power to create almost any application.</p><p>Today, we're walking through our example image-sharing platform. We want to be able to share pictures with friends while still also keeping some images private. We'll build a JSON API with Functions (storing data on KV and Durable Objects), integrate with Cloudflare Images and Cloudflare Access, and use React for our front end.</p><p>If you're wanting to dive right into the good stuff, <a href="https://images.pages.dev/">our demo instance is published here</a>, and <a href="https://github.com/cloudflare/images.pages.dev">the code is on GitHub</a>, but stick around for a more gentle approach.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6ONc6WtXvEqXxJXIVlwX4o/85109aa1b16e6a79fc0b1ed60eccf485/image2-17.png" />
            
            </figure>
    <div>
      <h2>Building serverless functions with Cloudflare Pages</h2>
      <a href="#building-serverless-functions-with-cloudflare-pages">
        
      </a>
    </div>
    
    <div>
      <h3>File-based routing</h3>
      <a href="#file-based-routing">
        
      </a>
    </div>
    <p>If you're not already familiar, Cloudflare Pages <a href="https://developers.cloudflare.com/pages/get-started">connects with your git provider</a> (GitHub and <a href="/cloudflare-pages-partners-with-gitlab">GitLab</a>), and automates the deployment of your static site to Cloudflare's network. Functions lets you enhance these apps by sprinkling in dynamic data. If you haven't already, <a href="https://dash.cloudflare.com/sign-up/pages">you can sign up here</a>.</p><p>In our project, let's create a new function:</p>
            <pre><code>// ./functions/time.js


export const onRequest = () =&gt; {
  return new Response(new Date().toISOString())
}</code></pre>
            <p><code>git commit</code>-ing and pushing this file should trigger a build and deployment of your first Pages function. Any requests for <code>/time</code> will be served by this function, and all other requests will fall-back to the static assets of your project. Placing Functions files in directories works as you'd expect: <code>./functions/api/time.js</code> would be available at <code>/api/time</code> and <code>./functions/some_directory/index.js</code> would be available at <code>/some_directory</code>.</p><p>We also support TypeScript (<code>./functions/time.ts</code> would work just the same), as well as parameterized files:</p><ul><li><p><code>./functions/todos/[id].js</code> with single square brackets will match all requests like <code>/todos/123</code>;</p></li><li><p>and <code>./functions/todos/[[path]].js</code> with double square brackets, will match requests for any number of path segments (e.g. <code>/todos/123/subtasks</code>).</p></li></ul><p>We declare a <code>PagesFunction</code> type in the <a href="https://github.com/cloudflare/workers-types">@cloudflare/workers-types</a> library which you can use to type-check your Functions.</p>
    <div>
      <h3>Dynamic data</h3>
      <a href="#dynamic-data">
        
      </a>
    </div>
    <p>So, returning to our image-sharing app, let's assume we already have some images uploaded, and we want to display them on the homepage. We'll need an endpoint which will return a list of these images, which the front-end can call:</p>
            <pre><code>// ./functions/api/images.ts

export const jsonResponse = (value: any, init: ResponseInit = {}) =&gt;
  new Response(JSON.stringify(value), {
    headers: { "Content-Type": "application/json", ...init.headers },
    ...init,
  });

const generatePreviewURL = ({
  previewURLBase,
  imagesKey,
  isPrivate,
}: {
  previewURLBase: string;
  imagesKey: string;
  isPrivate: boolean;
}) =&gt; {
  // If isPrivate, generates a signed URL for the 'preview' variant
  // Else, returns the 'blurred' variant URL which never requires signed URLs
  // https://developers.cloudflare.com/images/cloudflare-images/serve-images/serve-private-images-using-signed-url-tokens

  return "SIGNED_URL";
};

export const onRequestGet: PagesFunction&lt;{
  IMAGES: KVNamespace;
}&gt; = async ({ env }) =&gt; {
  const { imagesKey } = (await env.IMAGES.get("setup", "json")) as Setup;

  const kvImagesList = await env.IMAGES.list&lt;ImageMetadata&gt;({
    prefix: `image:uploaded:`,
  });

  const images = kvImagesList.keys
    .map((kvImage) =&gt; {
      try {
        const { id, previewURLBase, name, alt, uploaded, isPrivate } =
          kvImage.metadata as ImageMetadata;

        const previewURL = generatePreviewURL({
          previewURLBase,
          imagesKey,
          isPrivate,
        });

        return {
          id,
          previewURL,
          name,
          alt,
          uploaded,
          isPrivate,
        };
      } catch {
        return undefined;
      }
    })
    .filter((image) =&gt; image !== undefined);

  return jsonResponse({ images });
};</code></pre>
            <p>Eagle-eyed readers will notice we're exporting <code>onRequestGet</code> which lets us only respond to <code>GET</code> requests.</p><p>We're also using a KV namespace (accessed with <code>env.IMAGES</code>) to store information about images that have been uploaded. To create a binding in your Pages project, navigate to the "Settings" tab.</p><p>![](<a href="/content/images/2021/11/unnamed-15.png_REGULAR">http://staging.blog.mrk.cfdata.org/content/images/2021/11/unnamed-15.png_REGULAR</a> "Screenshot of the "Functions" page on the Pages project "Settings" tab in the Cloudflare dashboard")</p>
    <div>
      <h3>Interfacing with other APIs</h3>
      <a href="#interfacing-with-other-apis">
        
      </a>
    </div>
    <p>Cloudflare Images is an inexpensive, high-performance, and featureful service for <a href="https://www.cloudflare.com/developer-platform/solutions/hosting/">hosting</a> and transforming images. You can create multiple variants to render your images in different ways and control access with signed URLs. We'll add a function to interface with this service's API and upload incoming files to Cloudflare Images:</p>
            <pre><code>// ./functions/api/admin/upload.ts

export const onRequestPost: PagesFunction&lt;{
  IMAGES: KVNamespace;
}&gt; = async ({ request, env }) =&gt; {
  const { apiToken, accountId } = (await env.IMAGES.get(
    "setup",
    "json"
  )) as Setup;

  // Prepare the Cloudflare Images API request body
  const formData = await request.formData();
  formData.set("requireSignedURLs", "true");
  const alt = formData.get("alt") as string;
  formData.delete("alt");
  const isPrivate = formData.get("isPrivate") === "on";
  formData.delete("isPrivate");

  // Upload the image to Cloudflare Images
  const response = await fetch(
    `https://api.cloudflare.com/client/v4/accounts/${accountId}/images/v1`,
    {
      method: "POST",
      body: formData,
      headers: {
        Authorization: `Bearer ${apiToken}`,
      },
    }
  );

  // Store the image metadata in KV
  const {
    result: {
      id,
      filename: name,
      uploaded,
      variants: [url],
    },
  } = await response.json&lt;{
    result: {
      id: string;
      filename: string;
      uploaded: string;
      requireSignedURLs: boolean;
      variants: string[];
    };
  }&gt;();

  const metadata: ImageMetadata = {
    id,
    previewURLBase: url.split("/").slice(0, -1).join("/"),
    name,
    alt,
    uploaded,
    isPrivate,
  };

  await env.IMAGES.put(
    `image:uploaded:${uploaded}`,
    "Values stored in metadata.",
    { metadata }
  );
  await env.IMAGES.put(`image:${id}`, JSON.stringify(metadata));

  return jsonResponse(true);
};</code></pre>
            
    <div>
      <h3>Persisting data</h3>
      <a href="#persisting-data">
        
      </a>
    </div>
    <p>We're already using KV to store information that is read often but rarely written to. What about features that require a bit more synchronicity?</p><p>Let's add a download counter to each of our images. We can create a <code>highres</code> variant in Cloudflare Images, and increment the counter every time a user requests a link. This requires a bit more setup, but unlocking the power of Durable Objects in your projects is absolutely worth it.</p><p>We'll need to create and publish the Durable Object class capable of maintaining this download count:</p>
            <pre><code>// ./durable_objects/downloadCounter.js
ts#example---counter

export class DownloadCounter {
  constructor(state) {
    this.state = state;
    // `blockConcurrencyWhile()` ensures no requests are delivered until initialization completes.
    this.state.blockConcurrencyWhile(async () =&gt; {
      let stored = await this.state.storage.get("value");
      this.value = stored || 0;
    });
  }

  async fetch(request) {
    const url = new URL(request.url);
    let currentValue = this.value;

    if (url.pathname === "/increment") {
      currentValue = ++this.value;
      await this.state.storage.put("value", currentValue);
    }

    return jsonResponse(currentValue);
  }
}</code></pre>
            
    <div>
      <h3>Middleware</h3>
      <a href="#middleware">
        
      </a>
    </div>
    <p>If you need to execute some code (such as authentication or logging) before you run your function, Pages offers easy-to-use middleware which can be applied at any level in your file-based routing. By creating a <code>_middleware.ts</code> file in a directory, we know to first run this file, and then execute your function when <code>next()</code> is called.</p><p>In our application, we want to prevent unauthorized users from uploading images (<code>/api/admin/upload</code>) or deleting images (<code>/api/admin/delete</code>). Cloudflare Access lets us apply <a href="https://www.cloudflare.com/learning/access-management/role-based-access-control-rbac/">role-based access control</a> to all or part of our application, and you only need a single file to integrate it into our serverless functions. We create  <code>./functions/api/admin/_middleware.ts</code> which will apply to all incoming requests at <code>/api/admin/*</code>:</p>
            <pre><code>// ./functions/api/admin/_middleware.ts

const validateJWT = async (jwtAssertion: string | null, aud: string) =&gt; {
  // If the JWT is valid, return the JWT payload
  // Else, return false
  // https://developers.cloudflare.com/cloudflare-one/identity/users/validating-json

  return jwtPayload;
};

const cloudflareAccessMiddleware: PagesFunction&lt;{ IMAGES: KVNamespace }&gt; =
  async ({ request, env, next, data }) =&gt; {
    const { aud } = (await env.IMAGES.get("setup", "json")) as Setup;

    const jwtPayload = await validateJWT(
      request.headers.get("CF-Access-JWT-Assertion"),
      aud
    );

    if (jwtPayload === false)
      return new Response("Access denied.", { status: 403 });

    // We could also use the data object to pass information between middlewares
    data.user = jwtPayload.email;

    return await next();
  };

export const onRequest = [cloudflareAccessMiddleware];</code></pre>
            <p>Middleware is a powerful tool at your disposal allowing you to easily protect parts of your application with Cloudflare Access, or quickly integrate with <a href="https://www.cloudflare.com/learning/performance/what-is-observability/">observability</a> and error logging platforms such as Honeycomb and Sentry.</p>
    <div>
      <h2>Integrating as Jamstack</h2>
      <a href="#integrating-as-jamstack">
        
      </a>
    </div>
    <p>The "Jam" of "Jamstack" stands for JavaScript, API and Markup. Cloudflare Pages previously provided the 'J' and 'M', and with Workers in the middle, you can truly go full-stack Jamstack.</p><p>We've built the front end of this image sharing platform with <a href="https://create-react-app.dev/">Create React App</a> as an approachable example, but <a href="https://developers.cloudflare.com/pages/platform/build-configuration#framework-presets">Cloudflare Pages natively integrates with an ever-growing number of frameworks</a> (currently 23), and you can always <a href="https://developers.cloudflare.com/pages/platform/build-configuration#build-commands-and-directories">configure your own entirely custom build command</a>.</p><p>Your front end simply needs to make a call to the Functions we've already configured, and render out that data. We're using <a href="https://swr.vercel.app/">SWR</a> to simplify things, but you could do this with entirely vanilla JavaScript <code>fetch</code>-es, if that's your preference.</p>
            <pre><code>// ./src/components/ImageGrid.tsx

export const ImageGrid = () =&gt; {
  const { data, error } = useSWR&lt;{ images: Image[] }&gt;("/api/images");

  if (error || data === undefined) {
    return &lt;div&gt;An unexpected error has occurred when fetching the list of images. Please try again.&lt;/div&gt;;
  }


  return (
    &lt;div&gt;
      {data.images.map((image) =&gt; (
        &lt;ImageCard image={image} key={image.id} /&gt;
      ))}
    &lt;/div&gt;
  );

}</code></pre>
            
    <div>
      <h2>Local development</h2>
      <a href="#local-development">
        
      </a>
    </div>
    <p>No matter how fast it is, iterating on a project like this can be painful if you have to push up every change in order to test how it works. We've released a first-class integration with wrangler for local development of Pages projects, including full support for Functions, Workers, secrets, environment variables and KV. Durable Objects support is coming soon.</p><p>Install from npm:</p>
            <pre><code>npm install wrangler@beta</code></pre>
            <p>and either serve a folder of static assets, or proxy your existing tooling:</p>
            <pre><code># Serve a directory
npx wrangler pages dev ./public

# or integrate with your other tools
npx wrangler pages dev -- npx react-scripts start</code></pre>
            
    <div>
      <h2>Go forth, and build!</h2>
      <a href="#go-forth-and-build">
        
      </a>
    </div>
    <p>If you like puppies, <a href="https://images.pages.dev/">we've deployed our image-sharing application here</a>, and if you like code, <a href="https://github.com/cloudflare/images.pages.dev">that's over on GitHub</a>. Feel free to fork and deploy it yourself! There's a five-minute setup wizard, and you'll need Cloudflare Images, Access, Workers, and Durable Objects.</p><p>We are so excited about the future of the Pages platform, and we want to hear what you're building! Show off your full-stack applications in the <a href="https://discord.com/channels/595317990191398933/783765338692386886">#what-i-built channel</a>, or get assistance in the <a href="https://discord.com/channels/595317990191398933/789155108529111069">#pages-help channel</a> on <a href="https://discord.gg/cloudflaredev">our Discord server</a>.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3FMhGC7kxjUEspTnvUGjeQ/50a9a9bd201ed390f1f62c72bc9e2cb4/image1-37.png" />
            
            </figure>
    <div>
      <h3>Watch on Cloudflare TV</h3>
      <a href="#watch-on-cloudflare-tv">
        
      </a>
    </div>
    <div></div><p></p> ]]></content:encoded>
            <category><![CDATA[Full Stack Week]]></category>
            <category><![CDATA[Cloudflare Pages]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Full Stack]]></category>
            <category><![CDATA[Cloudflare Images]]></category>
            <category><![CDATA[Cloudflare Access]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <guid isPermaLink="false">48ToA8dVaTtXmVL58V9bJm</guid>
            <dc:creator>Greg Brimble</dc:creator>
            <dc:creator>Obinna Ekwuno</dc:creator>
        </item>
    </channel>
</rss>