A simple, fun way to build websites.
A simple, fun way to build websites with Haskell.
The main points:
It's server side rendered and uses websockets to communicate HTML updates and to receive events.
State can be broken up into small components.
Attributes flow down to concrete HTML, events bubble up to handlers.
Handlers can send further events to a parent handler or themselves
It's inspired by Phoenix LiveView, React, Redux, and Redux-Sagas.
Purview
A simple, fun way to build websites with Haskell. It's inspired by Phoenix LiveView, React, and Redux + Sagas.
The main points:
- It's server side rendered and uses websockets to communicate HTML updates and to receive events.
- State can be broken up into small components.
- Attributes flow down to concrete HTML, events bubble up to state handlers.
- Handlers can send further events to a parent handler or themselves
It's still in early development so expect things to break or be missing!
What it looks like
module Main where
import Prelude hiding (div)
import Purview
import Purview.Server
data CountEvent = Increment | Decrement
deriving (Show, Eq)
view :: Int -> Purview CountEvent m
view count = div
[ h1 [ text (show count) ]
, div [ onClick Increment $ button [ text "increment" ]
, onClick Decrement $ button [ text "decrement" ]
]
]
-- passes state down to the child and maintains type safety of actions
countHandler :: (Int -> Purview CountEvent m) -> Purview () m
-- arguments are initial actions, initial state, and then the reducer
countHandler = handler' [] (0 :: Int) reducer
where
reducer Increment state = (state + 1, []) -- new events can be added in the []
reducer Decrement state = (state - 1, [])
-- url is passed in to the top level component by `serve`
component url = countHandler view
main = serve defaultConfiguration component
More detailed docs on the use and particulars of Purview are mainly on Hackage.
Overview of how it works
Using an imagined example of getting the time, here's how events flow when the user clicks "check time"
The event is sent from the browser in a form like
{ event: click, value: undefined, location: [0], childLocation: [0,0] }
The event is put onto the channel for the event loop to process
It goes down the tree to find the event in Haskell by childLocation
It takes that event and applies it to the handler found by location
The handler does its work in a green thread, creating a new event that looks like
{ event: stateChange, fn: state -> state, location: [0] }
The state change event is put onto the channel for the event loop to process
By going down the tree it applies the state change fn to the latest state in the tree, returning a new tree
Any HTML changes are sent to the browser, completing the loop
Contributing
Anything is welcome, including examples or patterns you found nice. There's still a lot to discover.
The roadmap is, loosely, determined by adding things required to build real websites. The first two site-based goals:
- The Purview website itself, which will have more in depth tutorials (so requiring at least navigation)
- A stripe-based checkout (requiring communication with javascript)
Installation
- Install stack
stack build
Running Tests
- The same as above with stack and build
stack test
.