Your lucky ticket
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.