polar
โ† Blog

Your lucky ticket

Dispatch 2 ยท October 6, 2026

Every expedition needs a ticket. On the Polar expedition, in the Icebreaker era, that ticket is Ticket: a Rails-shaped web framework written in Polar, for Polar projects. It is the pass for your own journey, and it is also the best test of the language we have: a real framework, written in the language it serves.

What you get

Controllers, views and components, resource routing, SQLite with migrations and typed queries, validations, forms, sessions, flash and CSRF protection, generators and a test runner. All of it is Polar.

$ ticket new blog
$ cd blog
$ ticket server        # http://127.0.0.1:3000

Routes

A routes zone turns a few lines into a router, a route table and path helpers:

routes
  root  -> PostsController.index

  resources posts       -> PostsController
    resources comments  -> CommentsController  only create destroy

The schema is migrations

You write the schema as migrations. Each table gets a record, an insert type and a typed constant for every column, and each migration's down is worked out for you:

migrations
  20261001_120000 create_table users
    name   String
    email  String  unique

  20261001_130000 create_table posts
    title      String
    published  Bool              default false
    author_id  Option<Id<User>>  references users

Queries are typed. A column from another table, or a value of the wrong type, is a compile error, not a runtime surprise:

let posts = Posts.filter(
  [Query.eq(Schema.post_published, true)],
  [Query.order_desc(Schema.post_id)],
)

Validations and effects

Validations read like Rails' validates, and they report every message at once:

validations
  title   presence  length 3..120
  status  inclusion "draft" "live"
  slug    presence  format "^[a-z0-9-]+$"  uniqueness

Because Polar tracks effects, a controller action says what it needs in its signature, such as Posts, Throws<DbFailure> or Clock. Tests bind those effects to something else, like an in-memory database, without mocking anything.

Generators

ticket g scaffold Post title:String body:String? writes the migration, a model with validations, a controller with the seven actions, views, a test and the route.

Still in the ice

Ticket is at version 0.1.0, like the rest of Icebreaker, and its APIs will change between milestones. It needs the polar toolchain and Node 22.5 or newer. Read the Ticket site for the docs, or the source on GitHub. If you haven't met the language yet, read why we are setting out. Grab your ticket, and we'll see you at the next camp.