phosphor

Phosphor

For the Rails developer who misses the terminal

A Crystal terminal UI framework that maps Rails conventions onto the Elm Architecture (MVU). If you've written a Rails app, you can read this framework's code on day one.


Why Crystal?

Crystal reads almost exactly like Ruby but compiles to native binaries — no JIT, no GC pauses at the wrong moment, no runtime to ship. A Rails developer can read Crystal code on day one. The differences that matter for a TUI framework are type safety (no NoMethodError at runtime) and fibers (lightweight green threads, like Go's goroutines, built in).

# This is valid Crystal. It looks like Ruby.
class TodoItem
  getter text : String
  getter done : Bool

  def initialize(@text, @done = false)
  end

  def render
    done ? "[✓] #{text}" : "[ ] #{text}"
  end
end

The core mental model: Rails MVC → MVU

Rails developers think in Model–View–Controller. This framework maps most naturally to Model–View–Update — Elm's architecture, the same pattern Bubbletea uses — but with Rails naming conventions so nothing feels alien.

Rails concept TUI equivalent What it does
ActiveRecord model AppState struct Holds all app data — immutable snapshot
Controller action handle(event) method Returns a new AppState, never mutates
Shared concern / base model MockWidget Reusable, stateful UI primitive — lives in a shard
View component / ERB partial Widget App-specific wrapper: translates events → Msg
ActionView layout View Owns mounted widgets, focus stack, event routing
before_action Middleware chain Intercepts events before your handler
ApplicationController Screen base class Shared behaviour across all screens
config/routes.rb Router Maps key bindings to handler methods
rails server App.run Starts the explicit, readable event loop

For the full architectural rationale, see DESIGN.md.


Project structure

Familiar to any Rails developer:

my_tui_app/
├── src/
│   ├── app.cr                      # Entry point — like config/application.rb
│   ├── state/
│   │   └── app_state.cr            # Like your AR models, but an immutable struct
│   ├── screens/
│   │   ├── dashboard_screen.cr     # Like a controller — owns a View
│   │   └── detail_screen.cr
│   ├── widgets/
│   │   ├── mock/
│   │   │   ├── list_mock.cr        # Reusable primitive — could be its own shard
│   │   │   ├── input_mock.cr
│   │   │   └── spinner_mock.cr
│   │   ├── todo_list_widget.cr     # App-specific wrapper around ListMock
│   │   ├── search_input_widget.cr
│   │   └── status_bar_widget.cr
│   ├── ports/
│   │   ├── stdin_port.cr           # Continuous event source — keyboard
│   │   └── live_feed_port.cr       # Continuous event source — e.g. live data feed
│   ├── handlers/
│   │   └── key_handler.cr          # Like controller actions
│   └── router.cr                   # Like config/routes.rb
├── spec/
└── shard.yml                       # Like Gemfile

The key addition is widgets/mock/ — a home for reusable primitives that could be extracted into their own published shard, like a gem for UI components. The ports/ directory holds anything that emits events continuously, as opposed to one-shot async work.


What you get for free vs. Rails

Rails gives you This framework gives you
Database persistence In-memory state (you bring your own DB layer)
HTTP request/response cycle Terminal event/render cycle
Asset pipeline Shard ecosystem (termbox-cr, etc.)
ActionCable Port — continuous async event streams
ActiveJob / Sidekiq Cmd — one-shot async work in fibers
Devise / Pundit Not applicable — it's a local TUI
Puma thread pool Crystal's fiber scheduler
ViewComponent gem MockWidget shard (extractable)
rails generate scaffolding Could be added — conventions are all here

Platform support

phosphor supports Unix-like systems only: macOS, Linux, BSD, and WSL2 on Windows.

Native Windows console support is not on the roadmap. Windows users should run phosphor through WSL2, where it works the same as on any other Linux. See TASKS.md's Explicitly out of scope section for the full rationale.


Documentation

License

TBD

Repository

phosphor

Owner
Statistic
  • 0
  • 0
  • 0
  • 0
  • 1
  • about 3 hours ago
  • May 26, 2026
License

MIT License

Links
Synced at

Sun, 28 Jun 2026 16:36:14 GMT

Languages