Your first web app

Sky's sweet spot is full-stack web apps. You write one program with Std.App; the server holds the state, renders the view, and streams minimal patches to the browser. No separate front-end language, no API to hand-roll, no client state to sync. Std.App is the single front door — a build-time --target (default web) picks the backend, and the web target is Sky.Live, a server-driven UI in the Elm architecture.

The Elm architecture

A Std.App web app is four things:

The runtime loops: render the view, a user event produces a Msg, update returns a new Model, the view is re-rendered, and only the difference is sent to the browser.

A complete counter

Here's the whole app — save it as src/Main.sky in a project and sky run it:

module Main exposing (main)

import Sky.Core.Prelude exposing (..)
import Sky.Core.String as String
import Sky.Core.Error exposing (Error)
import Sky.Core.Task exposing (Task)
import Std.App as App
import Std.Ui as Ui exposing (Element)
import Std.Ui.Font as Font
import Std.Cmd as Cmd
import Std.Sub as Sub


type alias Model =
    { count : Int }


type Msg
    = Increment
    | Decrement


init : () -> ( Model, Cmd Msg )
init _ =
    ( { count = 0 }, Cmd.none )


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Increment ->
            ( { model | count = model.count + 1 }, Cmd.none )

        Decrement ->
            ( { model | count = model.count - 1 }, Cmd.none )


subscriptions : Model -> Sub Msg
subscriptions _ =
    Sub.none


view : Model -> Element Msg
view model =
    Ui.row [ Ui.spacing 16, Ui.padding 24 ]
        [ Ui.button [] { onPress = Just Decrement, label = Ui.text "−" }
        , Ui.el [ Font.size 24, Font.bold ] (Ui.text (String.fromInt model.count))
        , Ui.button [] { onPress = Just Increment, label = Ui.text "+" }
        ]


appDef =
    App.app
        { init = init, update = update, view = view, subscriptions = subscriptions }
        |> App.withNotFound ()


main : Task Error ()
main =
    App.run appDef

sky run (with no --target) defaults to web. Open http://localhost:8000 and the buttons work — clicks go to the server, update runs, and the changed number is patched into the page.

What to notice

More depth — sessions, the request object, connection handling, and the other --target backends — is in the Sky.Live guide and the Std.App overview.

Next → UI with Std.Ui