Pages Plugins
Cloudflare maintains a number of official Pages Plugins for you to use in your Pages projects:
- Cloudflare Access
- Google Chat
- GraphQL
- hCaptcha
- Honeycomb
- Sentry
- Static Forms
- Stytch
- Turnstile
- Community Plugins
- vercel/og
A Pages Plugin is a Pages Functions distributable which includes built-in routing and functionality. Developers can include a Plugin as a part of their Pages project wherever they chose, and can pass it some configuration options. The full power of Functions is available to Plugins, including middleware, parameterized routes, and static assets.
For example, a Pages Plugin could:
- Intercept HTML pages and inject in a third-party script.
- Proxy a third-party service's API.
- Validate authorization headers.
- Provide a full admin web app experience.
- Store data in KV or Durable Objects.
- Server-side render (SSR) webpages with data from a CMS.
- Report errors and track performance.
A Pages Plugin is essentially a library that developers can use to augment their existing Pages project with a deep integration to Functions.
Developers can enhance their projects by mounting a Pages Plugin at a route of their application. Plugins will provide instructions of where they should typically be mounted (for example, an admin interface might be mounted at functions/admin/[[path]].ts
, and an error logger might be mounted at functions/_middleware.ts
). Additionally, each Plugin may take some configuration (for example, with an API token).
In this example, you will build a Pages Plugin and then include it in a project.
The first Plugin should:
- intercept HTML forms.
- store the form submission in KV.
- respond to submissions with a developer's custom response.
Create a package.json
with the following:
In our example, dist/index.js
will be the entrypoint to your Plugin. This is a generated file built by Wrangler with the npm run build
command. Add the dist/
directory to your .gitignore
.
Next, create a functions
directory and start coding your Plugin. The functions
folder will be mounted at some route by the developer, so consider how you want to structure your files. Generally:
- if you want your Plugin to run on a single route of the developer's choice (for example,
/foo
), create afunctions/index.ts
file. - if you want your Plugin to be mounted and serve all requests beyond a certain path (for example,
/admin/login
and/admin/dashboard
), create afunctions/[[path]].ts
file. - if you want your Plugin to intercept requests but fallback on either other Functions or the project's static assets, create a
functions/_middleware.ts
file.
You are free to use as many different files as you need. The structure of a Plugin is exactly the same as Functions in a Pages project today, except that the handlers receive a new property of their parameter object, pluginArgs
. This property is the initialization parameter that a developer passes when mounting a Plugin. You can use this to receive API tokens, KV/Durable Object namespaces, or anything else that your Plugin needs to work.
Returning to your static form example, if you want to intercept requests and override the behavior of an HTML form, you need to create a functions/_middleware.ts
. Developers could then mount your Plugin on a single route, or on their entire project.
To create a good developer experience, you should consider adding TypeScript typings to your Plugin. This allows developers to use their IDE features for autocompletion, and also ensure that they include all the parameters you are expecting.
In the index.d.ts
, export a function which takes your pluginArgs
and returns a PagesFunction
. For your static form example, you take two properties, kv
, a KV namespace, and respondWith
, a function which takes an object with a formData
property (FormData
) and returns a Promise
of a Response
:
We are still working on creating a great testing experience for Pages Plugins authors. Please be patient with us until all those pieces come together. In the meantime, you can create an example project and include your Plugin manually for testing.
You can distribute your Plugin however you choose. Popular options include publishing on npm ↗, showcasing it in the #what-i-built or #pages-discussions channels in our Developer Discord ↗, and open-sourcing on GitHub ↗.
Make sure you are including the generated dist/
directory, your typings index.d.ts
, as well as a README.md
with instructions on how developers can use your Plugin.
If you want to include a Pages Plugin in your application, you need to first install that Plugin to your project.
If you are not yet using npm
in your project, run npm init
to create a package.json
file. The Plugin's README.md
will typically include an installation command (for example, npm install --save @cloudflare/static-form-interceptor
).
The README.md
of the Plugin will likely include instructions for how to mount the Plugin in your application. You will need to:
- Create a
functions
directory, if you do not already have one. - Decide where you want this Plugin to run and create a corresponding file in the
functions
directory. - Import the Plugin and export an
onRequest
method in this file, initializing the Plugin with any arguments it requires.
In the static form example, the Plugin you have created already was created as a middleware. This means it can run on either a single route, or across your entire project. If you had a single contact form on your website at /contact
, you could create a functions/contact.ts
file to intercept just that route. You could also create a functions/_middleware.ts
file to intercept all other routes and any other future forms you might create. As the developer, you can choose where this Plugin can run.
A Plugin's default export is a function which takes the same context parameter that a normal Pages Functions handler is given.
You can use wrangler pages dev
to test a Pages project, including any Plugins you have installed. Remember to include any KV bindings and environment variables that the Plugin is expecting.
With your Plugin mounted on the /contact
route, a corresponding HTML file might look like this:
Your plugin should pick up the data-static-form-name="contact"
attribute, set the method="POST"
, inject in an <input type="hidden" name="static-form-name" value="contact" />
element, and capture POST
submissions.
Make sure the new Plugin has been added to your package.json
and that everything works locally as you would expect. You can then git commit
and git push
to trigger a Cloudflare Pages deployment.
If you experience any problems with any one Plugin, file an issue on that Plugin's bug tracker.
If you experience any problems with Plugins in general, we would appreciate your feedback in the #pages-discussions channel in Discord ↗! We are excited to see what you build with Plugins and welcome any feedback about the authoring or developer experience. Let us know in the Discord channel if there is anything you need to make Plugins even more powerful.
Finally, as with Pages Functions generally, it is possible to chain together Plugins in order to combine together different features. Middleware defined higher up in the filesystem will run before other handlers, and individual files can chain together Functions in an array like so: