[TOC]
TODO: for now this is a guide for just Cloudflare to internally contribute templates.
People like yourself being willing to share code with others that use our platform is what makes a free serverless platform like Cloudflare Workers possible. So, thank you!
Following these guidelines helps to keep our templates consistent and deliver the best developer experience for those using them. Cloudflare developer experience team maintains the template gallery. (..add more..?)
There are several ways to contribute to the Cloudflare Workers platform. The template gallery is focussed on streamlining the contribution of templates. When a template makes it through the process it will be made public in our template gallery. Since several developers - even beginners - will be using these templates, we must be scrupulous in the approval process. If you’re looking for a more relaxed way of sharing code, no worries! For other ways to contribute your Worker scripts see our community.
To start making a template, first one must decide what to build. When deciding a template to build, we highly encourage Cloudflare internally to use this list.
The goal of any template is to be reusable amongst several projects, developers and entities; therefore, any template must be able to be used in a generic form. That does not mean that one can't use things like hardcoded constants, it just means those constants must be obvious and the logic must be generic.
Examples of good templates that we need help building. (TODO: remove this link for external and replace with a different list?):
- How to send a redirect
Custom solutions that would could not clearly be reused make bad templates.
Examples of bad templates:
- Building out a full blown OAuth authentication server
Your template should have a programmatically name (I will refer to as name
) and human readable description:
Examples:
- Generic template for cloud storage with an arbitrary cloud provider -
cloud_storage
- Authentication with pre-shared header key -
auth_key_header
You'll want to make sure your name does not conflict with existing snippet names.
#Snippets versus Boilerplates
Template is an umbral term for both snippets and boilerplate. Our gallery uses both. Before building a template distinguish it as a template or a boilerplate. We define them as:
boilerplate: a reusable project likely containing more than one file that can serve as a skeleton code for those beginning a project
Boilerplates will be displayed in the template gallery as wrangler generate
commands
Examples (will add links):
- Rust Wasm
- Image Compression
- Create React App
- GraphQL
snippet: copy-pastable code for either those beginning a project or adding into a project. Meant to not depend on multiple files.
Snippets will be displayed by default in the template gallery as the code collapsed.
Examples (will add links):
- Modify header
- Bulk redirects
both(rare): a simple project that consists of a single file that one would use as a boilerplate for building out a project but could also easily copy-paste (e.g. hello-world). In this case, you can build out either or both.
If you are just designing a snippet, you can skip the setup and move to writing template.
First clone the template creator and follow the instructions in the README to get your project started.
Never commit your worker/
, wrangler.toml
, or any file in the .gitignore
.
For Javascript snippets and boilerplates, please make sure your code is ran through prettier with the following config:
{
"singleQuote": true,
"semi": false,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 80
}
For boilerplates this will be done automatically, but for snippets you can do this using the template creator or following a tutorial on using prettier.
All JavaScript must adhere to JavaScript Standard Style.
-
Always deconstruct when possible
const { url } = request
overconst url = request.url
-
Prefer the object spread operator (
{...anotherObj}
) toObject.assign()
-
Inline
export
s with expressions whenever possible// Use this: export default class ClassName { } // Instead of: class ClassName { } export default ClassName
-
Place requires in the following order:
- Built in Node Modules (such as
path
) - Local Modules (using relative paths)
- Built in Node Modules (such as
-
Use arrow functions
=>
over anonymous function expressions -
Place class properties in the following order:
- Class methods and properties (methods starting with
static
) - Instance methods and properties
- Class methods and properties (methods starting with
- Comment all functions using JSDoc style (e.g.
/***/
) and if not in Typescript include the param types
A boilerplate will always be a project of multiple files that can run with the wrangler generate
You must test using wrangler to generate a new project against your repo.
wrangler generate myTempName ./
cd myTempName
wrangler preview
You do not need to strictly follow the snippet format for boilerplates, but it is recommended.
Test your snippet code with the playground and live on a domain. All snippet code must work unminified in the playground and be tested live.
The format of a snippet should be in the order:
- Hardcoded constants, the developer will likely change
- Helper functions
handleRequest
addEventListener('fetch', event => {
For example:
/**
* Here are what developers are expected to fill in
* Replace url with the host you wish to send requests to
* @param {string} url
*/
const url = 'https://example.com'
/**
* Here is what my helper does
* @param {string} path
*/
function helper(path) {
return url + '/' + path
}
/**
* Return a simple Hello World response
* @param {Request} request
*/
async function handleRequest(request) {
helper(request.url.path)
return new Response('Hello worker!', { status: 200 })
}
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
For snippets, the meat of the logic should be in a function called handleRequest
, which should always exist in either forms:
function handleRequest(request: Request): Promise<Response>
function handleRequest(request: Request): Response
The event listener should almost always be exactly:
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
This process is for internal only and will improve
- Host a public repo, and then test your project by running
wrangler generate https://github.com/<your-repo>
. - Have Victoria (@victoriabernard92 on Github) review your code via a PR into your own repo.
- Submit a PR to add the template to the template gallery after having it approved. Make sure to follow the same format as other boilerplates in the gallery and include all the same fields (e.g. wrangler genereate, demo.. )
- Include victoria (@victoriabernard92 on Github) to a PR review to your own repo, or share a gist (e.g. some gist)
- Add the code to the template gallery following the format of another snippet like ___ (WIP).