npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

astro-cloudflare-pages-static

v1.0.1

Published

Astro integration for client-side dynamic routes with Cloudflare Pages

Readme

astro-cloudflare-pages-static

An Astro integration for client-side dynamic routes with Cloudflare Pages.

Without this integration, Astro dynamic routes are only supported two scenarios:

  1. Itemizing every path using getStaticPaths()
  2. Using server-side rendering without itemizing every path

This integration offers a third option: Using static rendering without itemizing every path. This enables lightweight routing similar to SvelteKit's adapter-static, serving the same HTML shell for dynamic paths and handling content client-side.

By making use of Cloudflare Pages Functions exclusively for lightweight routing, cost, execution time and complexity remains minimal. Compared to full SSR, this approach is significantly cheaper (invoking functions only for routing) and faster (sub-1ms latency for hot starts), making it ideal for SaaS dashboards and other dynamic routes that can tolerate loading progressively.

All pages in your Astro project remain rendered statically, while benefiting from some server-side rendering features (such as dynamic path pre-rendering).

Features

  • 🚀 Automatic Route Detection - Uses standard Astro [param] syntax
  • 📦 Zero Config - Works out of the box
  • 🪄 Auto-Injection - Automatically handles getStaticPaths for you
  • 🎨 Real Astro Pages - Your dynamic routes are actual .astro files with full styling and pre-rendering
  • 🔧 Client-Side First - Serves pre-rendered HTML shell, you handle data fetching in the browser
  • 🌐 Dev Mode Support - No Wrangler needed during development
  • Lightweight - Generates minimal Cloudflare Worker code (typically <1ms execution time)

Installation

npm install astro-cloudflare-pages-static

Usage

1. Add to Astro Config

// astro.config.mjs
import { defineConfig } from 'astro';
import cloudflare from "@astrojs/cloudflare";
import cloudflarePagesStatic from 'astro-cloudflare-pages-static';

export default defineConfig({
  output: 'static',
  adapter: cloudflare(), // optional
  integrations: [
    cloudflarePagesStatic()
  ]
});

2. Create Dynamic Routes

Just like using Astro with server-side rendering, creating routes is as simple as naming a file or folder [slug].astro or [...slug].astro.

You can access route parameters using Astro.params:

<!-- src/pages/user/[id].astro -->
---
import Layout from '../../layouts/Layout.astro';
const { id } = Astro.params;
---

<Layout title={`User ${id}`}>
  <div id="app">
    <p>Loading user {id}...</p>
  </div>
  
  <script define:vars={{ id }}>
    // Fetch your data client-side
    async function loadUser() {
      const response = await fetch(`/api/users/${id}`);
      const user = await response.json();
      
      // Render your content
      document.getElementById('app').innerHTML = `
        <h1>${user.name}</h1>
        <p>User ID: ${id}</p>
      `;
    }
    
    loadUser();
  </script>
</Layout>

3. Build and Deploy

npm run build
# Deploy dist/ to Cloudflare Pages

Cloudflare Adapter Compatibility

This integration is designed for static output with client-side routing. When used with @astrojs/cloudflare adapter output: 'static' configuration must be used.

If you are using server-side rendering (output: 'server') this integration is redundant, dynamic pages already work for you.

Security Considerations

This integration works cheaply by using simple regex string replacement. While cost effective, only light content sanitation is done (escaping basic HTML tokens). Use caution when working with parameter values as they are user generated content, do not use them for innerHTML without sanitizing first.

API

Options

interface DynamicRoutesOptions {
  // Additional paths to exclude from routing
  excludePaths?: string[];
}

Examples

You can find a complete working example in the examples/ directory.

cd examples
npm install
npm run dev

Advanced Features

Worker Chaining

If you have an existing _worker.js in your project, this integration will automatically chain it in the dist directory. This allows you to combine multiple Cloudflare Workers.

This behavior is experimental, if you have issues open an issue containing a minimal reproduction.

Excluding Paths

Additional paths to avoid running Cloudflare Pages Functions:

cloudflarePagesStatic({
  excludePaths: ['/api/*', '/admin/*']
})

Limitations

This integration relies on string replacement of an "encoded" static parameter stub at the edge. If you modify the parameter string in your pre-rendered component logic, the parameter will not be correctly replaced until client-side hydration completes.

To avoid this, delay manipulation of the parameter value until client-side render. Or better yet, use CSS to visually manipulate the parameter value while maintaining the full source.