Chord is a Lua-based full-stack platform. Write a few lines of code, push with one command, and end up with a full app on a subdomain. Auth, DB, AI, email and templates included!
☝️🤓 This site and the dashboard are both Chord apps.
$ curl -sSL chord.run/install | sh
Works on macOS and Linux!
Run chord login after install to pair the CLI with your account.
If you just prefer to host it yourself, take a look at the repo.
Three files, ~20 lines. The whole app:
## entities/post.lua entity("Post", { title = text, body = text, })
## routes/posts.lua route("GET", "/posts", function(req) respond(200, Post.all()) end) route("POST", "/posts", function(req) Post.create(req.body) respond(201) end, { auth = true })
## frontend/index.html <ul> <% for _, p in ipairs(Post.all()) do %> <li><%= p.title %></li> <% end %> </ul>
$ chord dev # run it locally $ chord deploy # ship to chord.run → live at https://my-app.chord.run
local post = Post.create({ title = "Hello", body = "World", })
entity("User") is defined.local user, err = Auth.login(email, password)
local answer = Ai.complete("Summarize: " .. text)
.htmlua files: <%= %>, auto-escape, partials via render(...). Pairs cleanly with htmx if you don't use a JS framework.<%# frontend/post.htmlua %> <article> <h1><%= post.title %></h1> <%- render("partials/byline", { user = post.author }) %> </article>
Mail.send_template("welcome.htmlua", { to = user.email, ctx = { name = user.display_name }, })
<%# emails/welcome.htmlua %> <% mail.subject = "Welcome, " .. ctx.name .. "!" %> <% mail.from = "noreply@chord.run" %> <p>Hi <%= ctx.name %>,</p> <p>Thanks for signing up.</p>
Hx.trigger("post-created", { id = p.id }) Hx.push_url("/posts/" .. p.id)
Kv.set("user:" .. user.id .. ":theme", "dark")
local res = Http.get("https://api.example.com/posts")
local key = Env.get("STRIPE_KEY")
Pick your approach: server-render with the built-in template engine, or ship a JS framework (React, Vue, Svelte) as a SPA. Both first-class.
For server-rendered pages, use .htmlua: ERB-style HTML
with <%= %>, auto-escape, partials. Each template
doubles as a fragment via render(name, ctx), which pairs
cleanly with htmx.
Anything else (.html, .css, .js,
bundled output from Vite or similar) is served raw. For an SPA with a
client-side router, flip a flag and unknown paths fall through to
index.html:
# chord.toml [frontend] spa = true
When you use templates, anything you interpolate with
<%= %> is escaped before it reaches the page. The
engine looks at where the interpolation lands and uses the right
escape function for that context: if the position is inherently
unsafe, the template fails to compile and the server won't start.
The runtime is AGPL v3. Clone the repo, run
cargo build --release, and drop the binary on your VPS with
Caddy or nginx in front: your code
doesn't know whether it's on chord.run or your own server.
The multi-tenant platform that runs chord.run (router, dashboard, billing) is closed source. That's where we make money. But your Lua sits on the open side, so when our prices or our policies stop working for you, you take it and walk.
Pricing details available soon. We're still setting up the infrastructure and finalizing the launch plan.
Reference and quickstart will land here as we publish the OSS runtime and finish setting up the infrastructure.