The whole framework, one binary.
Soli is a programming language with a complete MVC framework built in —
models, validations, auth, background jobs, mailer, PDF, WebSockets, live views,
i18n, tests. Ruby's expressiveness, Rust's speed, and nothing to install but
soli itself.
Anatomy of a request
One route, one controller, one model, one view — and the dev bar times every hop. This is the entire stack. There is nothing else to wire up.
get("/posts", "posts#index")
class PostsController < Controller
def index
@posts = Post
.where("doc.status == @s", { "s": "published" })
.order("created_at", "desc")
.limit(10).all
end
end
class Post < Model
validates("title", { "presence": true, "min_length": 3 })
def author
User.find(this.author_id)
end
end
FOR doc IN posts FILTER doc.status == @s SORT doc.created_at DESC LIMIT 10 RETURN doc
<% for post in @posts %>
<article>
<h2><%= h(post["title"]) %></h2>
<p><%= post["excerpt"] %></p>
</article>
<% end %>
HTTP/1.1 200 OK
X-Soli-Route: posts#index
X-Soli-Render-Us: 240
240 µs of server time — the dev bar measures every request, every query, on every page you build.
Soli MVC
Batteries actually included
The parts every app needs live in the binary, not in a package registry. No Gemfile, no package.json, no supply chain — one real line of code each.
Authentication & policies
soli generate auth scaffolds login, sessions, and a Pundit-style policy layer.
authorize(post) # 403 unless PostPolicy allows it
Validations & callbacks
Declared on the model, enforced on every create and update.
validates("email", { "presence": true, "uniqueness": true })
Background jobs
SolidB-backed queue with scheduling, priorities, retries, and cron.
WelcomeEmailJob.perform_in("5 minutes", { "user_id": 42 })
Mailer
Rails-style mailers with templates, layouts, and attachments.
UserMailer.welcome(user).deliver_later
PDF generation
JSON templates to invoice-grade PDFs, returned straight from an action.
pdf_response(template, data, { "filename": "invoice.pdf" })
WebSockets
Channels, rooms, and broadcast — hashes serialize themselves.
ws_broadcast_room(room, { "user": name, "body": msg })
Live views
Server-rendered reactive components without writing JavaScript.
<button soli-click="increment">+</button>
i18n
Translations with interpolation and pluralization built in.
t("welcome.greeting", { "name": user["name"] })
From zero to CRUD in one command
Scaffolds generate the model, controller, views, tests, migration, and routes. The auth generator does the same for login, sessions, and policies.
$ soli generate scaffold blog_posts title:string content:text author:string published:boolean Success! Created scaffold for blog_posts # Generated files: app/models/blog_posts_model.sl app/controllers/blog_posts_controller.sl app/views/blog_posts/index.html.slv app/views/blog_posts/show.html.slv app/views/blog_posts/new.html.slv app/views/blog_posts/edit.html.slv app/views/blog_posts/_form.html.slv tests/models/blog_posts_test.sl tests/controllers/blog_posts_controller_test.sl db/migrations/*create_blog_posts_*.sl ✓ Routes added to config/routes.sl $ soli generate auth Success! Session authentication generated app/policies/application_policy.sl app/policies/user_policy.sl app/helpers/auth_helper.sl + User model, login/signup/logout controllers & views
Fast enough to be the whole stack
Measured by TechEmpower on 21× AWS c7i.2xlarge instances.
Powered by SoliDB
A distributed, ACID-compliant multi-model database built in Rust. Documents, graph, vector search, time series, full-text, and blobs — the ORM speaks to all of it.
class User < Model
validates("email", { "presence": true, "uniqueness": true })
before_save("normalize_email")
def normalize_email
this.email = this.email.trim().downcase() unless this.email.blank?
end
end
# Chainable query builder — compiles to a single AQL query
admins = User
.where("doc.role == @r", { "r": "admin" })
.order("created_at", "desc")
.limit(20).all
This counter is live, right now
A server-rendered reactive component over a WebSocket — no JavaScript written, a ~7 KB (gzipped) client served by the binary itself and loaded only on pages that use it. Type in the field: every keystroke round-trips the server and the patch lands without stealing your focus or caret.
Connecting...
<!-- That's the whole component. -->
<div class="counter">
<h2><%= count %></h2>
<button soli-click="decrement">-</button>
<button soli-click="increment">+</button>
</div>
In production
Built with Soli. Running for real.
Bonfire is a full project-management SaaS — real-time chat over WebSockets, file uploads with inline previews, browser push, iCal feeds, public share links, and an interface translated into nine languages — running on Soli and SolidB in production. Not a demo. Not a benchmark. A product with users.
-
✓
Migrate the importer - Copy review with Mara
- Ship it THU
Build something this afternoon
Join the developer* who is already shipping with Soli.
* It's just me. But I'm having a great time!