spaceship_fusion
A build tool for Gleam projects that generates platform-specific shims, compiles class files, and bundles with esbuild.
Features
- Scan
.gleamclass files with annotations - Generate platform-specific runtime shims (Node, Cloudflare, Bun, Deno)
- Bundle with esbuild with source map support
- Configurable entry point function
- Static asset handling (copy to dist, embed for Cloudflare)
- Generate
wrangler.tomlfor Cloudflare Workers - Initialize projects with
fusion init
Installation
gleam add spaceship_fusion
CLI Commands
fusion init
Initialize a new project for fusion.
# Basic (Node runtime)
gleam run -m fusion -- init
# Cloudflare
gleam run -m fusion -- init --cloudflare
# Cloudflare with specific wrangler version
gleam run -m fusion -- init --cloudflare --wrangler=2
What it does:
- Edits
gleam.tomlwith[fusion]section - For
--cloudflare: generateswrangler.tomlwith D1 binding
Flags:
| Flag | Description | Default |
|---|---|---|
--cloudflare | Target Cloudflare Workers | false |
--wrangler=<ver> | Wrangler version (cloudflare only) | "latest" |
fusion build
Build the project.
gleam run -m fusion -- build
What it does:
- Scans
src/classes/for class.gleamfiles - Runs
gleam build --target javascript - Generates class adapter files in
build/fusion/classes/ - Generates platform-specific
shim.js - Processes static assets:
- Copies
directorytobuild/dist/(non-Cloudflare) - Embeds
includesas base64 inassets.mjs(Cloudflare)
- Copies
- Bundles with esbuild to
build/dist/index.js
fusion scan
Scan class files and display metadata.
gleam run -m fusion -- scan
fusion dev
Start development mode with file watching.
gleam run -m fusion -- dev
What it does:
- Runs full build
- Starts appropriate server based on runtime:
node→ runsnode build/fusion/shim.jscloudflare→ runsnpx wrangler dev
fusion class create <name>
Create a new class file.
gleam run -m fusion -- class create "greeter"
What it does:
- Creates
src/classes/if it doesn’t exist - Creates
src/classes/<name>.gleamwith template
fusion class list
List all class files.
gleam run -m fusion -- class list
Output:
Found 1 class(es)
Greeter (classes/greeter)
.greet(message: String)
Configuration
Add a [fusion] section to your gleam.toml:
[fusion]
runtime = "cloudflare" # or "node", "bun", "deno"
entry_point = "main" # function to call as entry point
port = 3000
minify = true
source_map = true
[fusion.assets]
directory = "public" # Public assets to serve
includes = ["priv/secret.cert"] # Files to embed in bundle
Entry Point
The entry point function is called by the generated shim. The function signature depends on the runtime:
Web server (all runtimes):
pub fn main(req: Request(BitArray)) -> Response(BitArray) {
// handle HTTP request
}
Cloudflare Workers (with env/ctx):
pub fn main(req: Request(BitArray), env: Dynamic, ctx: Dynamic) -> Response(BitArray) {
// access env vars and context
}
Class Files
Place .gleam files in src/classes/ with annotations:
/// @extends Service
/// @name MyService
/// @export
pub fn handle_message(msg: String) -> String {
// ...
}
Assets
Configure static assets in gleam.toml:
[fusion.assets]
# Public directory - served as static files
directory = "public"
# Private files - embedded in bundle for Cloudflare
includes = ["priv/cert.pem", "priv/config.json"]
Build behavior:
| Runtime | directory | includes |
|---|---|---|
| Node/Bun/Deno | Copied to dist/ | Copied to dist/ |
| Cloudflare | Copied for [site] | Embedded as base64 in assets.mjs |
Reading assets in code:
import fusion/asset
// Read asset as bytes
let assert Ok(cert) = asset.read("priv/cert.pem")
// Read asset as string
let assert Ok(config) = asset.read_string("priv/config.json")
On Cloudflare, embedded assets are loaded from the bundle. On other runtimes, assets are read from the filesystem.
Build Output
build/
fusion/
classes/ # Generated class adapters
shim.js # Platform-specific entry point
assets.mjs # Embedded assets (Cloudflare only)
dist/
index.js # esbuild output
index.js.map # Source map
public/ # Copied public assets
priv/ # Copied private assets (non-Cloudflare)
Runtime Shims
| Runtime | Entry Point Signature | Notes |
|---|---|---|
cloudflare | main(req, env, ctx) | Generates wrangler.toml |
node | main(req) | HTTP server with static files |
bun | main(req) | Bun.serve wrapper |
deno | main(req) | Deno.serve wrapper |
Examples
Basic Web Server (Node)
# gleam.toml
[fusion]
runtime = "node"
entry_point = "main"
port = 3000
// src/app.gleam
import gleam/http/request.{type Request}
import gleam/http/response
pub fn main(req: Request(BitArray)) -> response.Response(BitArray) {
response.new(200)
|> response.set_body(<<"Hello from Fusion!":utf8>>)
}
Cloudflare Worker with Assets
# gleam.toml
[fusion]
runtime = "cloudflare"
entry_point = "main"
[fusion.assets]
directory = "public"
includes = ["priv/api-key.txt"]
// src/app.gleam
import fusion/asset
pub fn main(req, env, ctx) {
// Read embedded asset
let assert Ok(api_key) = asset.read_string("priv/api-key.txt")
response.new(200)
|> response.set_body(<<"Hello!":utf8>>)
}
Development
gleam build # Build the project
gleam test # Run the tests
gleam format # Format the code
License
Apache-2.0