The purpose of this guide is to show how to use the create-cloudflare
Command Line Interface (CLI) or C3
to create a new project directory, with Cloudflare dependencies but configured for SvelteKit and TailwindCSS. This guide replaces the previously posted: Cloudflare, Svelte and TailwindCSS Template and Starter Kit, which is now deprecated.
The only command required is:
# Create cloudflare project
bun create cloudflare@latest c3-svelte-template --framework=svelte
The guide is based on the official Cloudflare SvelteKit guide. The repository created using this guide is also available on GitHub as an alternative to running the command above:
Node Runtime Setup
It’s recommended to use the Node Version Manager tool to control and manage different versions of node.js
. Installation is relatively simple, using the supplied script.
The following commands list the available versions of node.js
and what is currently installed:
# List versions available for download
<snip>
-> v20.5.0
<snip>
v20.18.0 (LTS: Iron)
v20.18.1 (Latest LTS: Iron)
v21.0.0
v21.1.0
v22.10.0
<snip>
v22.11.0 (LTS: Jod)
v22.12.0 (Latest LTS: Jod)
v23.0.0
<snip>
# Installed versions
nvm ls
-> v20.5.0
system
default -> stable (-> v20.5.0)
iojs -> N/A (default)
unstable -> N/A (default)
node -> stable (-> v20.5.0) (default)
stable -> 20.5 (-> v20.5.0) (default)
lts/* -> lts/jod (-> N/A)
lts/argon -> v4.9.1 (-> N/A)
lts/boron -> v6.17.1 (-> N/A)
lts/carbon -> v8.17.0 (-> N/A)
lts/dubnium -> v10.24.1 (-> N/A)
lts/erbium -> v12.22.12 (-> N/A)
lts/fermium -> v14.21.3 (-> N/A)
lts/gallium -> v16.20.2 (-> N/A)
lts/hydrogen -> v18.20.5 (-> N/A)
lts/iron -> v20.18.1 (-> N/A)
lts/jod -> v22.12.0 (-> N/A)
We can ascertain the current system
version with the run command:
# Current system version
nvm run system --version
Running node system (npm v8.19.3)
v18.13.0
There are two different versions of node.js
installed the system
version and v20.5.0
, which is now out of date. We can install common versions using various aliases such as stable
or lts
.
# Install latest LTS
nvm install --lts
Installing latest LTS version.
Downloading and installing node v22.12.0...
Downloading https://nodejs.org/dist/v22.12.0/node-v22.12.0-linux-x64.tar.xz...
################################################################## 100.0%
Computing checksum with sha256sum
Checksums matched!
Now using node v22.12.0 (npm v10.9.0)
# Check versions installed
nvm ls
v20.5.0
-> v22.12.0
system
default -> stable (-> v22.12.0)
iojs -> N/A (default)
unstable -> N/A (default)
node -> stable (-> v22.12.0) (default)
stable -> 22.12 (-> v22.12.0) (default)
lts/* -> lts/jod (-> v22.12.0)
lts/argon -> v4.9.1 (-> N/A)
lts/boron -> v6.17.1 (-> N/A)
lts/carbon -> v8.17.0 (-> N/A)
lts/dubnium -> v10.24.1 (-> N/A)
lts/erbium -> v12.22.12 (-> N/A)
lts/fermium -> v14.21.3 (-> N/A)
lts/gallium -> v16.20.2 (-> N/A)
lts/hydrogen -> v18.20.5 (-> N/A)
lts/iron -> v20.18.1 (-> N/A)
lts/jod -> v22.12.0
In the example above, nvm
has automatically switched to the newly installed version. In most instances, typically switching to the Long Term Support (LTS) version is done with nvm use lts
. However, some systems can struggle to recognise nvm
on its first use hence switching to the system
version first resolves most of these issues:
# Switch to LTS (or stable)
nvm use system && nvm use stable
Now using system version of node: v18.13.0 (npm v8.19.3)
Now using node v22.12.0 (npm v10.9.0)
Cloudflare Setup
The following command launches the Cloudflare wizard but pre-populates the framework
as svelte
due to the -- framework=svelte
flag. The next set of questions are from the new Svelte CLI tool called sv
, which asks for the type of Svelte project (SvelteKit minimal
), typescript
support before selecting addons such as prettier
and tailwindcss
.
This is followed by configuration of the selected addons, in this instance tailwindcss
and its plugins of typography
and forms
. Finally, the selection of the package manager as (bun
).
cloudflate-create
# Launch wizard
bun create cloudflare@latest c3-svelte-template --framework=svelte
─────────────────────────────────────────────────────────────────────────
👋 Welcome to create-cloudflare v2.35.1!
🧡 Let's get started.
📊 Cloudflare collects telemetry about your usage of Create-Cloudflare.
Learn more at: https://github.com/cloudflare/workers-sdk/blob/main/packages/create-cloudflare/telemetry.md
─────────────────────────────────────────────────────────────────────────
╭ Create an application with Cloudflare Step 1 of 3
│
├ In which directory do you want to create your application?
│ dir ./c3-svelte-template
│
├ What would you like to start with?
│ category Framework Starter
│
├ Which development framework do you want to use?
│ framework SvelteKit
│
├ Continue with SvelteKit via `bunx [email protected] create c3-svelte-template`
│
┌ Welcome to the Svelte CLI! (v0.6.7)
│
◇ Which template would you like?
│ SvelteKit minimal
│
◇ Add type checking with Typescript?
│ Yes, using Typescript syntax
│
◆ Project created
│
◇ What would you like to add to your project? (use arrow keys / space
bar)
│ prettier, tailwindcss
│
◇ tailwindcss: Which plugins would you like to add?
│ typography, forms
│
◇ Which package manager do you want to install dependencies with?
│ bun
│
◆ Successfully setup add-ons
│
◆ Successfully installed dependencies
│
◇ Successfully formatted modified files
│
◇ Project next steps ─────────────────────────────────────────────────────╮
│
│
│ 1: cd c3-svelte-template
│
│ 2: git init && git add -A && git commit -m "Initial commit" (optional) │
│ 3: bun dev --open
│
│
│
│ To close the dev server, hit Ctrl-C
│
│
│
│ Stuck? Visit us at https://svelte.dev/chat
│
│
│
├──────────────────────────────────────────────────────────────────────────╯
│
└ You're all set!
├ Copying template files
│ files copied to project directory
│
╰ Application created
╭ Configuring your application for Cloudflare Step 2 of 3
│
├ Installing wrangler A command line tool for building Cloudflare Workers
│ installed via `bun install wrangler --save-dev`
│
├ Installing @cloudflare/workers-types
│ installed via bun
│
├ Adding latest types to `tsconfig.json`
│ added @cloudflare/workers-types/2023-07-01
│
├ Retrieving current workerd compatibility date
│ compatibility date 2024-12-18
│
├ Adding the Cloudflare Pages adapter
│ installed @sveltejs/adapter-cloudflare
│
├ Changing adapter in svelte.config.js
│
├ Updating global type definitions in app.d.ts
│
├ Adding Wrangler files to the .gitignore file
│ updated .gitignore file
│
├ Updating `package.json` scripts
│ updated `package.json`
│
├ Do you want to use git for version control?
│ yes git
│
├ Initializing git repo
│ initialized git
│
├ Committing new files
│ git commit
│
╰ Application configured
╭ Deploy with Cloudflare Step 3 of 3
│
├ Do you want to deploy your application?
│ no deploy via `bun run deploy`
│
╰ Done
────────────────────────────────────────────────────────────
🎉 SUCCESS Application created successfully!
💻 Continue Developing
Change directories: cd c3-svelte-template
Start dev server: bun run dev
Deploy: bun run deploy
📖 Explore Documentation
https://developers.cloudflare.com/pages
🐛 Report an Issue
https://github.com/cloudflare/workers-sdk/issues/new/choose
💬 Join our Community
https://discord.cloudflare.com
────────────────────────────────────────────────────────────
The tailend of the wizard asks whether we want to deploy
using wrangler
and I’ve selected no as we’ll illustrate that later.
Validation & Post-Install Config
The single command provided a working configuration for all three elements: the ability to deploy on Cloudflare, use the SvelteKit framework and utilise TailwindCSS.
Navigate to the newly created folder:
# Navigate to project folder
cd c3-svelte-template
The code below illustrates how the C3 tool has updated the svelte.config.js
file:
svelte.config.js
- 1
-
The default
adapter-auto
has been replaced withadapter-cloudflare
. - 2
-
vitePreprocess
has been added for TailwindCSS support.
tailwind.config.ts
import forms from '@tailwindcss/forms'; // <2>
import typography from '@tailwindcss/typography';
import type { Config } from 'tailwindcss';
export default {
: ['./src/**/*.{html,js,svelte,ts}'], // <1>
content
: {
theme: {}
extend,
}
: [typography, forms] // <3>
plugins; } satisfies Config
- Note the addition of
svelte
files. - TailwindCSS plugins have been imported.
- TailwindCSS plugins have been registered.
The Cascading Style Sheets (CSS) under the src
folder has also been updated:
src/app.css
@tailwind base;
@tailwind components;
@tailwind utilities;
This is directly imported into the default route at +layout.svelte
:
+layout.svelte
<script lang="ts">
import '../app.css';
let { children } = $props();
</script>
{@render children()}
Git Repository
The c3
utility creates a project folder, installs the selected packages, initiates a git
repository and makes the first commit
. To connect this to an external repository, follow the Cloudflare Github Rep Instructions.
Create the external repository; for GitHub (if logged in) use this shortcut URL: repo.new.
Once created navigate to the project folder (i.e. cd
into it) and enter the following commands:
# Add remote origin
git remote add origin [email protected]:miah0x41/c3-svelte-tailwind-v2.git
# Rename current branch to main
git branch -M main
# Track the main branch upstream
git branch --set-upstream-to=origin/main main
Branch 'main' set up to track remote branch 'main' from 'origin'.
# Set upstream branch
git push --set-upstream origin margin
Attempting to either pull
or push
will lead to an error. If the upstream (external) git
repository was empty then the commands should be sufficient. If however, if additional files were created such as LICENSE
or README.md
, then there is a mismatch between the local and remote git status.
To resolve, we need to pull
the external repo first and resolve any conflicts:
# Attempt merges (default)
git config pull.rebase false
# Attempt pull
git pull
fatal: refusing to merge unrelated histories
# Fix with correct flag to override histories
git pull origin main --allow-unrelated-histories
From github.com:miah0x41/c3-svelte-tailwind-v2
* branch main -> FETCH_HEAD
Merge made by the 'ort' strategy.
LICENSE | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 201 insertions(+)
create mode 100644 LICENSE
# Push changes to remote repo
git push
Enumerating objects: 32, done.
Counting objects: 100% (32/32), done.
Delta compression using up to 20 threads
Compressing objects: 100% (28/28), done.
Writing objects: 100% (31/31), 47.63 KiB | 1.91 MiB/s, done.
Total 31 (delta 3), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (3/3), done.
To github.com:miah0x41/c3-svelte-tailwind-v2.git
da5bf60..9f18021 main -> main
Deployment
To test the configuration, run the development server:
# Run dev server
bun run dev -- --open
$ vite dev --open
Forced re-optimization of dependencies
VITE v6.0.5 ready in 2632 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show help
To test the configuration, update the +page.svelte
with some TailwindCSS classes:
src/routes/+page.svelte
<div class="flex h-screen items-center justify-center bg-gray-100">
<div class="flex items-center rounded-lg bg-white p-4 shadow-lg">
<img src="logo_youtube.png" alt="Logo" class="mr-4 h-20" />
<span class="text-4xl font-semibold">Curious Data Explorer</span>
</div>
</div>
The output should reflect the TailwindCSS classes:
The project is now ready for deployment but first we need to check what the site looks and behaves like in the Cloudflare infrastructure using the preview
command:
bun-run-preview.sh
bun run preview
$ bun run build && wrangler pages dev
$ vite build
vite v6.0.5 building SSR bundle for production...
✓ 153 modules transformed.
vite v6.0.5 building for production...
✓ 131 modules transformed.
.svelte-kit/output/client/_app/version.json
0.03 kB │ gzip: 0.05 kB
.svelte-kit/output/client/.vite/manifest.json
3.08 kB │ gzip: 0.58 kB
.svelte-kit/output/client/_app/immutable/assets/0.VTS2zFfF.css
10.98 kB │ gzip: 2.79 kB
.svelte-kit/output/client/_app/immutable/chunks/legacy.CHFpNJ_D.js
0.04 kB │ gzip: 0.06 kB
.svelte-kit/output/client/_app/immutable/entry/start.D4CGAcgR.js
0.07 kB │ gzip: 0.08 kB
.svelte-kit/output/client/_app/immutable/chunks/index-client.DNI3gCIi.js
0.33 kB │ gzip: 0.26 kB
.svelte-kit/output/client/_app/immutable/nodes/0.vec3NjHj.js
0.38 kB │ gzip: 0.27 kB
.svelte-kit/output/client/_app/immutable/nodes/2.BCXTYHEi.js
0.44 kB │ gzip: 0.32 kB
.svelte-kit/output/client/_app/immutable/chunks/disclose-version.D48o4b0F.js 0.98 kB │ gzip: 0.56 kB
.svelte-kit/output/client/_app/immutable/nodes/1.Bg7X2pRM.js
1.26 kB │ gzip: 0.69 kB
.svelte-kit/output/client/_app/immutable/chunks/render.Bk9H9iQr.js
2.48 kB │ gzip: 1.37 kB
.svelte-kit/output/client/_app/immutable/entry/app.CJSKkdwc.js
9.61 kB │ gzip: 4.39 kB
.svelte-kit/output/client/_app/immutable/chunks/runtime.DVmAVPAN.js
12.44 kB │ gzip: 5.02 kB
.svelte-kit/output/client/_app/immutable/chunks/entry.CA7GdDSB.js
31.32 kB │ gzip: 12.24 kB
✓ built in 1.52s
.svelte-kit/output/server/.vite/manifest.json 1.77 kB
.svelte-kit/output/server/_app/immutable/assets/_layout.VTS2zFfF.css 10.98 kB
.svelte-kit/output/server/entries/pages/_layout.svelte.js 0.24 kB
.svelte-kit/output/server/internal.js 0.31 kB
.svelte-kit/output/server/entries/pages/_page.svelte.js 0.35 kB
.svelte-kit/output/server/chunks/equality.js 0.61 kB
.svelte-kit/output/server/chunks/index.js 2.29 kB
.svelte-kit/output/server/entries/fallbacks/error.svelte.js 3.08 kB
.svelte-kit/output/server/chunks/exports.js 7.53 kB
.svelte-kit/output/server/chunks/internal.js 42.11 kB
.svelte-kit/output/server/index.js 95.88 kB
✓ built in 9.71s
Run npm run preview to preview your production build locally.
> Using @sveltejs/adapter-cloudflare
✔ done
⛅️ wrangler 3.99.0
-------------------
✨ Compiled Worker successfully
✨ Parsed 2 valid header rules.
[wrangler:inf] Ready on http://localhost:8788
⎔ Starting local server...
[wrangler:inf] GET / 200 OK (95ms)
[wrangler:inf] GET /_app/immutable/assets/0.VTS2zFfF.css 200 OK (63ms)
[wrangler:inf] GET /_app/immutable/chunks/disclose-version.D48o4b0F.js 200 OK (29ms)
[wrangler:inf] GET /_app/immutable/entry/start.D4CGAcgR.js 200 OK (97ms)
[wrangler:inf] GET /_app/immutable/chunks/index-client.DNI3gCIi.js 200 OK (198ms)
[wrangler:inf] GET /_app/immutable/chunks/legacy.CHFpNJ_D.js 200 OK (98ms)
[wrangler:inf] GET /_app/immutable/entry/app.CJSKkdwc.js 200 OK (184ms)
[wrangler:inf] GET /_app/immutable/chunks/render.Bk9H9iQr.js 200 OK (180ms)
[wrangler:inf] GET /logo_youtube.png 200 OK (68ms)
[wrangler:inf] GET /_app/immutable/nodes/0.vec3NjHj.js 200 OK (23ms)
[wrangler:inf] GET /_app/immutable/chunks/runtime.DVmAVPAN.js 200 OK (136ms)
[wrangler:inf] GET /_app/immutable/chunks/entry.CA7GdDSB.js 200 OK (116ms)
[wrangler:inf] GET /_app/immutable/nodes/2.BCXTYHEi.js 200 OK (97ms)
[wrangler:inf] GET /favicon.png 200 OK (25ms)
[wrangler:inf] GET /_app/immutable/nodes/1.Bg7X2pRM.js 200 OK (17ms)
[wrangler:inf] GET /favicon.png 200 OK (19ms)
We can now deploy
to Cloudflare, however note the prompts at the bottom. The first is to get an authentication key for wrangler
via the browser.
bun-run-deploy-1.sh
# Attempt deployment
bun run deploy
$ bun run build && wrangler pages deploy
$ vite build
vite v6.0.5 building SSR bundle for production...
✓ 153 modules transformed.
vite v6.0.5 building for production...
✓ 131 modules transformed.
.svelte-kit/output/client/_app/version.json
0.03 kB │ gzip: 0.05 kB
.svelte-kit/output/client/.vite/manifest.json
3.08 kB │ gzip: 0.58 kB
.svelte-kit/output/client/_app/immutable/assets/0.VTS2zFfF.css
10.98 kB │ gzip: 2.79 kB
.svelte-kit/output/client/_app/immutable/chunks/legacy.CHFpNJ_D.js
0.04 kB │ gzip: 0.06 kB
.svelte-kit/output/client/_app/immutable/entry/start.BmoqV0fV.js
0.07 kB │ gzip: 0.08 kB
.svelte-kit/output/client/_app/immutable/chunks/index-client.DNI3gCIi.js
0.33 kB │ gzip: 0.26 kB
.svelte-kit/output/client/_app/immutable/nodes/0.vec3NjHj.js
0.38 kB │ gzip: 0.27 kB
.svelte-kit/output/client/_app/immutable/nodes/2.BCXTYHEi.js
0.44 kB │ gzip: 0.32 kB
.svelte-kit/output/client/_app/immutable/chunks/disclose-version.D48o4b0F.js 0.98 kB │ gzip: 0.56 kB
.svelte-kit/output/client/_app/immutable/nodes/1.CzBC74I5.js
1.26 kB │ gzip: 0.69 kB
.svelte-kit/output/client/_app/immutable/chunks/render.Bk9H9iQr.js
2.48 kB │ gzip: 1.37 kB
.svelte-kit/output/client/_app/immutable/entry/app.BR5rdV8r.js
9.61 kB │ gzip: 4.39 kB
.svelte-kit/output/client/_app/immutable/chunks/runtime.DVmAVPAN.js
12.44 kB │ gzip: 5.02 kB
.svelte-kit/output/client/_app/immutable/chunks/entry.BeExm4ad.js
31.32 kB │ gzip: 12.24 kB
✓ built in 858ms
.svelte-kit/output/server/.vite/manifest.json 1.77 kB
.svelte-kit/output/server/_app/immutable/assets/_layout.VTS2zFfF.css 10.98 kB
.svelte-kit/output/server/entries/pages/_layout.svelte.js 0.24 kB
.svelte-kit/output/server/internal.js 0.31 kB
.svelte-kit/output/server/entries/pages/_page.svelte.js 0.35 kB
.svelte-kit/output/server/chunks/equality.js 0.61 kB
.svelte-kit/output/server/chunks/index.js 2.29 kB
.svelte-kit/output/server/entries/fallbacks/error.svelte.js 3.08 kB
.svelte-kit/output/server/chunks/exports.js 7.53 kB
.svelte-kit/output/server/chunks/internal.js 42.11 kB
.svelte-kit/output/server/index.js 95.88 kB
✓ built in 7.94s
Run npm run preview to preview your production build locally.
> Using @sveltejs/adapter-cloudflare
✔ done
Attempting to login via OAuth...
Opening a link in your default browser: https://dash.cloudflare.com/oauth2/auth?response_type=code&client_id=54d11594-84e4-41aa-b438-e81b8fa78ee7&redirect_uri=http%3A%2F%2Flocalhost%3A8976%2Foauth%2Fcallback&scope=account%3Aread%20user%3Aread%20workers%3Awrite%20workers_kv%3Awrite%20workers_routes%3Awrite%20workers_scripts%3Awrite%20workers_tail%3Aread%20d1%3Awrite%20pages%3Awrite%20zone%3Aread%20ssl_certs%3Awrite%20ai%3Awrite%20queues%3Awrite%20pipelines%3Awrite%20offline_access&state=4oAPIYvDHoIOCH3ZFiIvMs1O_E2UVBYu&code_challenge=FzlKQQnIXMz7nEIVtWgAdWdxpyiQfRuife1ZPkT8Xg4&code_challenge_method=S256
Once logged in, the prompt for the authorisation of wrangler
is presented:
Post authorisation, you can close the browser window down:
The tool has recognised that no Cloudflare project exists and creates one and confirms the branch
prior to deployment.
bun-run-deploy-2.sh
Successfully logged in.
✔ The project you specified does not exist: "c3-svelte-template". Would you like to create it? › Create a new project
✔ Enter the production branch name: … main
✨ Successfully created the 'c3-svelte-template' project.
▲ [WARNING] Warning: Your working directory is a git repo and has uncommitted changes
To silence this warning, pass in --commit-dirty=true
✨ Success! Uploaded 19 files (2.80 sec)
✨ Uploading _headers
✨ Compiled Worker successfully
✨ Uploading Worker bundle
✨ Uploading _routes.json
🌎 Deploying...
✨ Deployment complete! Take a peek over at https://2e6b0ffb.c3-svelte-template.pages.dev
Whilst the wrangler
tool does a significant amount of compilation, the source is based on the committed changes, so any not committed is excluded. So if the URL provided is blank or it appears unusual, check of any uncommitted changes.
That concludes this guide, which configures a Cloudflare project with SvelteKit and TailwindCSS using a single command.
Attribution
Images based on:
Citation
@online{2024,
author = {, miah0x41},
title = {Cloudflare, {Svelte} and {TailwindCSS} 2024 and {Beyond}},
date = {2024-12-24},
url = {https://blog.curiodata.pro/posts/10-svelte-cloudflare-update/},
langid = {en}
}