README.md

# Dialup (English)

WebSocket-first, file-based routing Elixir framework.

[日本語](./README.ja.md)

## Overview

Dialup is an Elixir framework for building WebSocket-first applications with a Next.js-like developer experience.

### Features

- **File-based routing** — file placement maps directly to URLs
- **WebSocket-first** — real-time communication built in
- **Server-side state** — no client-side state management needed
- **Simple architecture** — lighter than Phoenix/LiveView
- **Colocated CSS** — `.css` files next to `.ex` files, auto-scoped at compile time
- **Static file serving** — `priv/static/` served automatically
- **WebSocket origin verification** — cross-origin connection protection built in

## Quick Start

### 1. Install the generator

```bash
mix archive.install hex dialup_new
```

### 2. Create a new project

```bash
mix dialup.new my_app
cd my_app
mix deps.get
mix run --no-halt
```

Then visit http://localhost:4000

### Generated project structure

```
my_app/
├── mix.exs
├── lib/
│   ├── my_app.ex          # Application entry point
│   ├── root.html.heex     # HTML shell — customize <head>, hooks, analytics
│   └── app/
│       ├── layout.ex / layout.css   # Root layout
│       ├── page.ex   / page.css     # Home page at /
│       └── error.ex  / error.css    # Error page (404, 500)
└── priv/static/           # Static assets (images, fonts, favicon)
```

### Minimal app

```elixir
# lib/my_app.ex
defmodule MyApp do
  use Application
  use Dialup, app_dir: __DIR__ <> "/app"

  def start(_type, _args) do
    children = [
      {Dialup, app: __MODULE__, port: 4000}
    ]
    Supervisor.start_link(children, strategy: :one_for_one, name: __MODULE__.Supervisor)
  end
end
```

```elixir
# lib/app/page.ex
defmodule Dialup.App.Page do
  use Dialup.Page

  def mount(_params, assigns) do
    {:ok, assigns |> set_default(%{count: 0})}
  end

  def handle_event("increment", _value, assigns) do
    {:update, assigns |> overwrite(%{count: assigns.count + 1})}
  end

  def render(assigns) do
    ~H"""
    <h1>Hello Dialup</h1>
    <p>Count: {@count}</p>
    <button ws-event="increment">+</button>
    """
  end
end
```

## Documentation

Run `mix docs --open` to browse the full documentation locally.

Guide source files live in `guides/`:

- [Getting Started](./guides/getting-started.md) — installation and basic usage
- [Routing](./guides/routing.md) — routing in depth
- [State Management](./guides/state-management.md) — managing server-side state
- [Lifecycle](./guides/lifecycle.md) — page lifecycle hooks
- [Events](./guides/events.md) — handling events
- [Helpers](./guides/helpers.md) — helper functions
- [Deployment](./guides/deployment.md) — deploying to production
- [Fullstack Example](./guides/fullstack-example.md) — a practical app using Ecto and PubSub

## Architecture

```
Browser          Elixir Server
   |                    |
dialup.js ←──WS──→ UserSessionProcess (1 tab = 1 process)
   |                    |
idiomorph            render/1
                        |
                     assigns (state)
```

## License

MIT