1. A new app
melee new, the nine files it writes, and the development server.
melee new notes
cd notes
created ./notes
The name has to be lowercase letters, digits and dashes, not starting with a dash, at most 40 characters —
the same rule the server applies, so a name that scaffolds is a name that deploys. melee new refuses a
directory that already exists and is not empty.
What it wrote
notes/
melee.toml which server, and what URL the app will answer at
spin.toml the compiler's manifest: this app depends on the melee library
app.rb your routes
views/layout.erb the page wrapper
views/index.erb the one page
public/app.css served straight from disk at /app.css
db/migrations/001_init.sql
.meleeignore paths melee push should not send
README.md
Nine files, and you will edit four of them. Two of the others are worth a look now.
melee.toml is the only configuration:
name = "notes"
server = "http://127.0.0.1:7070"
url = "http://notes.localhost:8080"
spin.toml tells the compiler that this app is a package which depends on the melee library. You will not
normally touch it:
[package]
name = "notes"
version = "0.1.0"
[dependencies]
melee = { path = "/path/to/melee/stdlib" }
And app.rb is a working two-route app:
# frozen_string_literal: true
title "New App"
get "/" do
render :index, greeting: greeting
end
post "/greeting" do
setting "greeting", params.fetch(:greeting)
redirect "/"
end
def greeting = setting("greeting") || "World"
Three things to notice, because they are true of every melee file:
# frozen_string_literal: trueat the top. String literals are frozen in this dialect. Build strings with+""and<<rather than mutating a literal.greetingis a plain top-level method and the route calls it with no receiver. That works because a request is handled by a process that handles nothing else, so there is no instance to hang it off and nothing to thread through.settingis a key/value store in the app’s database — handy for exactly this kind of “one value the app remembers”.
The scaffold also leaves a commented-out durable object at the bottom of app.rb. Delete it; step 5 writes a
real one.
Run it
melee dev
melee dev: prepared 2 templates, 1 migrations
melee dev: http://127.0.0.1:4567 (Ctrl-C to stop)
Open http://127.0.0.1:4567. Type a name into the box, submit, and the page greets you.
Every request prints a line:
GET / -> 200 (4.5 ms)
GET / -> 200 (0.2 ms)
GET /app.css -> 200 (public/)
GET /nope -> 404 (0.0 ms)
melee dev runs your app under ordinary CRuby, not the compiled binary. That is what makes the loop fast,
and it is also the one thing to keep in mind: CRuby will happily run Ruby that Spinel cannot compile. Step 6
runs the real compiler; until then, if something works here it might still not build.
There is no reload. Changing app.rb, a template or a migration means Ctrl-C and melee dev again. The
database lives at .melee/app.sqlite inside the app directory — delete it to start over — and environment
variables come from your shell.
Next
Routes and templates — turn the greeting into a notes board.