authors | title | date | layout | categories | description | |
---|---|---|---|---|---|---|
Mediocre Hacker |
Halogen Template |
2024-12-09 |
tutorial |
|
Template project for getting started with Halogen |
Firstly, create a a flake in the current directory.
nix flake init
Add all needable dependencies to the flake.nix file.
{
description = "Halogen Template";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
purescript-overlay.url = "github:thomashoneyman/purescript-overlay";
};
outputs = { self, nixpkgs, purescript-overlay }:
let
name = "halogen-template";
system = "x86_64-linux";
overlays = [ purescript-overlay.overlays.default ];
pkgs = import nixpkgs { inherit system overlays; };
in {
devShells.${system}.default = pkgs.mkShell {
name = name;
buildInputs = [
pkgs.esbuild
pkgs.just
pkgs.nodejs_20
pkgs.nixpkgs-fmt
pkgs.purs
pkgs.purs-tidy
pkgs.purs-backend-es
pkgs.purescript-language-server
pkgs.spago-unstable
pkgs.watchexec
];
};
};
}
Start a shell with the build environment of the default package of the flake in the current directory:
nix develop
Create an app with npm using the following command.
npm init --yes
This is a template for starting a fresh project with the Halogen library for writing declarative, type-safe user interfaces.
Create index.html.
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" type="text/css" href="static/index.css" />
<title>Halogen Template</title>
</head>
<body>
<script src="static/index.js"></script>
</body>
</html>
Create style.css and a normalize using Open Props.
@import "https://unpkg.com/open-props";
@import "https://unpkg.com/open-props/normalize.min.css";
@import "https://unpkg.com/open-props/buttons.min.css";
Create index.js with a console messsage.
import { main } from "../output/Main";
import "./style.css";
new EventSource("/esbuild").addEventListener("change", () => location.reload());
console.log("Hello World!");
main();
Configure esbuild with a build script to configure our builds.
import * as esbuild from "esbuild";
let ctx;
try {
ctx = await esbuild.context({
entryPoints: ["src/index.js"],
bundle: true,
minify: false,
sourcemap: true,
outdir: "public/static",
plugins: [],
});
await ctx.watch();
console.log("Watching files ... ");
let { host, port } = await ctx.serve({
servedir: "public",
});
console.log(`Hot Refresh at http://${host}:${port}`);
} catch (error) {
console.error("An error occured", error);
process.exit(1);
}
Initialize a new PureScript project with Spago.
nix flake init
Adding PureScript files to the .gitignore file.
# Dependencies
.psci_modules
.spago
output/
output-es/
# Generated files
.psci
output
module Main where
import Prelude
import Effect (Effect)
import Halogen as H
import Halogen.Aff as HA
import Halogen.HTML as HH
import Halogen.HTML.Events as HE
import Halogen.VDom.Driver (runUI)
main :: Effect Unit
main = HA.runHalogenAff do
body <- HA.awaitBody
runUI component unit body
data Action = Increment | Decrement
component =
H.mkComponent
{ initialState
, render
, eval: H.mkEval $ H.defaultEval { handleAction = handleAction }
}
where
initialState _ = 0
render state =
HH.div_
[ HH.button [ HE.onClick \_ -> Decrement ] [ HH.text "-" ]
, HH.div_ [ HH.text $ show state ]
, HH.button [ HE.onClick \_ -> Increment ] [ HH.text "+" ]
]
handleAction = case _ of
Increment -> H.modify_ \state -> state + 1
Decrement -> H.modify_ \state -> state - 1
import Prelude
import Effect (Effect)
import Effect.Class.Console (log)
main :: Effect Unit
main = do
log "🍕"
log "Halogen Template !!!"
Install Halogen with Spago:
spago install halogen