/halogen-template

Template project for getting started with Halogen

Primary LanguageJavaScriptApache License 2.0Apache-2.0

authors title date layout categories description
Mediocre Hacker
Halogen Template
2024-12-09
tutorial
template
Template project for getting started with Halogen

Preliminaries

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

Introduction

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