Refrakt

A convention-first web framework for Gleam. Productive like Phoenix, explicit like Gleam, composable with Wisp and Lustre.


Light enters a prism, structure emerges. Refrakt takes the Gleam ecosystem — Wisp, Lustre, Mist — and gives you one obvious way to build serious web apps. No macros. No magic. Just conventions, generators, and plain Gleam code you own.

What It Does

# Create a new project
refrakt new my_app --db postgres

# Generate a full CRUD resource
cd my_app
refrakt gen resource posts title:string body:text published:bool

# Run it
gleam run
# → http://localhost:4000/posts

That one gen resource command creates a handler, views, form with validation, domain type, database repo, migration, test — and wires the routes into your router. Every generated file is plain Gleam you can read, modify, and own.

How It Works

Refrakt is two things:

A CLI (refrakt) that generates code. It reads your gleam.toml, produces .gleam and .sql files from templates, and patches your router. It does not run at runtime.

A library (refrakt) that provides small helpers: form validation, flash messages, migration runner, test utilities, dev error pages. Everything else lives in your project as generated code.

my_app/
  src/
    my_app.gleam                  ← entry point (Wisp + Mist)
    my_app/
      config.gleam                ← typed config, env-driven
      router.gleam                ← all routes, pattern matched

      web/                        ← HTTP/UI layer
        post_handler.gleam        ← index, show, new, create, edit, update, delete
        post_views.gleam          ← Lustre HTML functions
        forms/post_form.gleam     ← typed decoder + validation
        layouts/root_layout.gleam

      domain/                     ← business logic (zero framework imports)
        post.gleam                ← pub type Post { Post(...) }

      data/                       ← persistence
        post_repo.gleam           ← raw SQL, typed decoders
        migrations/
          001_create_posts.sql

Principles

Conventions over assembly — One default project layout. One routing shape. One way to structure handlers, views, forms, and repos. You spend time building features, not debating file organization.

Generated code is your code — There is no “framework code” vs “your code” distinction. Every file the CLI creates looks like something a skilled Gleam developer would write by hand. Modify anything.

No magic — Routing is pattern matching. Views are functions. Validation is functions. If you can read Gleam, you can read a Refrakt app without consulting docs.

Build on the ecosystem — Wisp handles HTTP. Lustre handles HTML. Mist runs the server. Pog or Sqlight talk to the database. Refrakt adds conventions and generators on top — it doesn’t reinvent the stack.

Commands

CommandDescription
refrakt new <name>Create a new project (--db postgres, --db sqlite)
refrakt gen page <name>Generate a page (handler + route)
refrakt gen resource <name> <fields...>Generate full CRUD (handler, views, form, domain, repo, migration)
refrakt gen authGenerate starter authentication
refrakt gen migration <name>Generate a SQL migration file
refrakt migrateRun pending migrations
refrakt devStart the dev server
refrakt routesPrint the route table

Generated Router

pub fn handle_request(req: Request, ctx: Context) -> Response {
  use req <- middleware(req)

  case wisp.path_segments(req), req.method {
    [], http.Get -> home_handler.index(req, ctx)

    ["posts"], http.Get -> post_handler.index(req, ctx)
    ["posts", "new"], http.Get -> post_handler.new(req, ctx)
    ["posts"], http.Post -> post_handler.create(req, ctx)
    ["posts", id], http.Get -> post_handler.show(req, ctx, id)
    ["posts", id, "edit"], http.Get -> post_handler.edit(req, ctx, id)
    ["posts", id], http.Put -> post_handler.update(req, ctx, id)
    ["posts", id], http.Delete -> post_handler.delete(req, ctx, id)

    _, _ -> error_handler.not_found(req)
  }
}

Plain Gleam pattern matching. A new developer reads this file and understands every route in 30 seconds.

Status

Phase 0 — designing the golden path. Not yet usable.

Coming:

Building from Source

# Requires Gleam 1.14+, Erlang/OTP 27+
gleam build
gleam test

License

MIT

Search Document