ESC
Type to search...
S
Soli Docs

Introduction

Welcome to Soli, a dynamically-typed, high-performance web framework and programming language written in Rust. Soli combines the expressiveness of Ruby with a batteries-included MVC stack — 170,000+ requests/second and sub-millisecond response times, powered by a bytecode VM.

What you'll learn

This guide tours Soli's full feature surface — language, web framework, database, realtime, and tooling — then gets you from zero to a running app in three commands.

What is Soli?

Soli is two things in one: a dynamically-typed language with optional type annotations, and a batteries-included MVC web framework built on top of it. No compile step gates execution — but soli check will static type-check the parts you've annotated.

170,000+

requests/second, single server

Sub-millisecond

typical response times

3 commands

from install to running app

Feature Tour

A map of what Soli ships with. Each group links to the full deep-dive.

Language

Dynamic + optional types

Write fast, annotate where it pays off — runtime checks, IDE support, docs.

Classes & interfaces

Familiar OOP with inheritance — class Foo < Bar.

Pattern matching

match with guards and destructuring.

Enums

First-class enumerated types.

Closures & pipelines

fn(x) {}, |x| {}, and the |> pipeline operator.

Error handling

try/catch/finally plus postfix rescue.

Modern conveniences

String interpolation, ??, &., spread/rest, named params.

Metaprogramming

define_method, method_missing, and more.

Web Framework

Convention over configuration

Autoloaded controllers, models, services, policies, jobs, mailers.

Declarative routing

resources(), nesting, namespaces, named route helpers.

ERB-style views

.html.slv templates with layouts and partials.

Middleware pipeline

Request/response interceptors for auth, CORS, logging.

Data & Persistence

SoliDB

Built-in document database, queried with AQL.

Active-Record-style Model API

find, where, order, create, update.

Relationships

belongs_to, has_many, has-and-belongs-to-many.

Validations, migrations & more

Callbacks, state machines, query scopes.

Realtime

WebSockets

First-class bidirectional connections.

Live View

Server-rendered reactive components — no client JS needed.

Streaming / SSE

Push updates to the browser as they happen.

Batteries Included

Auth & security

JWT auth, policy-based authorization, CSRF, XSS sanitization, Argon2, secure cookies.

Sessions

Four pluggable backends: in-memory, disk, SoliDB, or SoliKV.

Jobs & cron

perform_later, perform_in, perform_at, scheduled jobs.

Mailer

HTML/text emails, attachments, SMTP delivery.

Document generation

PDF rendering, including Factur-X/EN16931 e-invoicing.

i18n

Multi-locale support out of the box.

Developer Tools

Hot reload

Edit and refresh — no restart needed.

Beautiful dev error pages

Variable inspection right in the browser.

Scaffold generator

soli generate scaffold builds a full resource in seconds.

Built-in package manager

soli add / install / publish against a registry, via soli.toml.

Lint, format, type-check

soli lint, soli fmt, soli check.

LSP + editor integration

Language server and VS Code extension.

BDD testing framework

describe/test, HTTP integration tests, coverage reporting.

The MVC Pattern

Soli follows the Model-View-Controller (MVC) architectural pattern, separating your app into three layers:

M

Model

Manages data, business logic, and database interactions. Located in app/models/.

V

View

Handles the presentation layer and HTML templates. Located in app/views/.

C

Controller

Coordinates between Models and Views to handle requests. Located in app/controllers/.

Quick Start

# Install the Soli CLI
curl -sSL https://raw.githubusercontent.com/solisoft/soli_lang/main/install.sh | sh

# Scaffold a new app
soli new my_app
cd my_app

# Start the dev server (auto-compiles Tailwind CSS, hot reload enabled)
soli serve . --dev

That's it

Your app is live at http://localhost:5011. No npm install required to get started — --dev mode compiles your Tailwind CSS for you.

Project Structure

my_app/
├── app/
│   ├── controllers/      # Request handlers
│   │   └── home_controller.sl
│   ├── jobs/              # Background jobs
│   ├── middleware/        # Request interceptors
│   ├── views/             # HTML templates
│   │   ├── layouts/       # Shared layouts
│   │   │   └── application.html.slv
│   │   └── home/
│   │       └── index.html.slv
│   └── assets/
│       └── css/           # Tailwind source
├── config/
│   ├── routes.sl        # Route definitions
│   ├── application.sl   # App configuration
│   └── locales/          # i18n translation files
├── public/
│   └── css/               # Compiled CSS output
└── package.json           # Tailwind toolchain (only needed if customizing)

Quick Example

Here's how the pieces fit together in a simple Soli application:

1 Define a Route

get("/", "home#index")
get("/users/:id", "users#show")

2 Create a Controller

class HomeController < Controller
  def index
    message = "Welcome to Soli!"

    render("home/index", {
      "title": "Home",
      "message": message
    })
  end
end

3 Build a View

<h1><%= message %></h1>
<p>Start building something amazing.</p>

The Package Manager

Soli ships with a built-in package manager — no separate tool needed:

soli init                       # create soli.toml in the current directory
soli add utils --path ../shared/utils
soli add soli-math --version 1.0.0
soli install                    # install everything from soli.toml
soli publish                    # publish your package to a registry

The manifest can also pin a minimum interpreter version with soli_version = "1.16.0" in [package]; soli serve/test/run then refuse to start on an older soli.

See Modules & Packages for the full soli.toml reference.

Design Philosophy

Soli favors convention over configuration. By following standard naming patterns, you write less glue code and focus on building features.

Next Steps