Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/eldr-io/hastl

Production ready, modern web-application starter template using haskell and htmx
https://github.com/eldr-io/hastl

alpinejs haskell htmx lucid servant tailwindcss template web

Last synced: 24 days ago
JSON representation

Production ready, modern web-application starter template using haskell and htmx

Awesome Lists containing this project

README

        





Production ready, modern web-application starter template

hastl is a modern Haskell web application using (H)tmx, (A)lpine.js, (S)ervant, (T)ailwind-css and (L)ucid. It is based on the awesome servant-persistent example and is licensed under MIT and is entirely free and open source.

#### Built with

[![Haskell][Haskell]][Haskell-url]
[![Htmx][Htmx]][Htmx-url]
[![Alpine][Alpine]][Alpine-url]
[![Servant][Servant]][Servant-url]
[![Tailwind][Tailwind]][Tailwind-url]
[![Lucid][Lucid]][Lucid-url]

hastl is primarily tested with PostgreSQL but it uses the popular persistent haskell library as an ORM and therefore can be used with most popular databases.

### Features

Type-safe APIs - hastl uses Servant to define APIs that make up the application, providing type safety and consistency across the application, with the haskell type-checker keeping you honest as you develop


Modern frontend with htmx - the use of htmx in hastl allows you to build modern user interfaces with the simplicity and power of hypertext, with haskell and lucid2 doing the heavy lifting


Live reloading with GHCID - since we're writing almost all of our code in the backend, hastl uses GHCID to instantly reload your project as you make changes


Integration testing with TestContainers - hastl uses testcontainers to spin up a database on the fly to run integration tests and give you confidence in your business logic

### Get Started

Start by creating a new repo from the hastl template by clicking "Use this template" in the top right corner.

#### Setting up dependencies

Hastl requires the tailwindcss standalone CLI executable locally in the root folder as described here. In addition, it expects a local postgreSQL database to be running on port 5432, alternatively use the provided compose.yaml file to run either Podman or Docker to spin it up.

The project includes a Makefile to provide you with convenient targets for running the server in development mode as well as running the tailwindcss CLI in watch mode to generate stylesheets on the fly.

Navigate into your cloned repo and run:

```
make run
```
This will build and run hastl and you should be able to navigate to `localhost:8081` in your browser and see the hastl demo application:

![Screenshot from 2024-06-08 15-41-54](https://github.com/eldr-io/hastl/assets/83576392/19af0d8e-33b8-411e-a19e-e2e4f8c3420f)

To run the development live reloading mode, make sure that ghcid is installed and then use the watch target:

```
make watch
```

#### Running unit tests

The unit tests of the project can be found in the `test` directory and can assert things like HTML generation from database types.

You can run all the unit tests with:

```
make test
```

#### Running integration tests

Hastl ships with built-in integration tests that use testcontainers to start a local postgreSQL database inside a container (using docker or podman) on-the-fly, as well as running the project web-server, allowing the tests to exercise the actual HTTP endpoints to assert correctness.

The integration tests manage the containers, starting them and tearing them down as the tests complete.

You can run all the integration tests with:
```
make test-integration
```

#### Changing the routes and templates

Hastl allows you to combine strongly-typed Servant APIs to make up your application. To add a new route and endpoint, you can create a new file similar to `lib/Api/Guest.hs` e.g. if you wanted to create a Todo-list API you could create `lib/Api/Todo.hs`. Additionally, you can create a new directory within `lib/Api/Templates` to store your Lucid-powered Haskell template files. Within the template files, you have access to the full power of HTMX and Alpine through helper functions.

If you wish to use persistent models in your application, you can define your models in `lib/Models.hs` and persistent will automatically create the Haskell types, as well as handling the database migrations for DEVELOPMENT setups (note: is it recommended to use a more robust migration mechanism for production).

#### Documentation Recipes

- [Using UUIDs instead of Integer IDs as Primary Keys in database](https://github.com/eldr-io/hastl/blob/main/docs/recipes/using-uuids-for-db-ids.md)

[Haskell]: https://img.shields.io/badge/haskell-5D4F85?style=for-the-badge&logo=haskell&logoColor=white
[Haskell-url]: https://haskell.org
[Htmx]: https://img.shields.io/badge/htmxjs-3366CC?style=for-the-badge&logo=htmx&logoColor=white
[Htmx-url]: https://htmx.org
[Alpine]: https://img.shields.io/badge/alpinejs-8BC0D0?style=for-the-badge&logo=alpine.js&logoColor=white
[Alpine-url]: https://alpinejs.dev
[Servant]: https://img.shields.io/badge/Servant-5D4F85?style=for-the-badge&logo=haskell&logoColor=white"
[Servant-url]: https://www.servant.dev
[Tailwind]: https://img.shields.io/badge/Tailwind-06B6D4?style=for-the-badge&logo=tailwindcss&logoColor=white
[Tailwind-url]: https://tailwindcss.com
[Lucid]: https://img.shields.io/badge/Lucid-5D4F85?style=for-the-badge&logo=haskell&logoColor=white
[Lucid-url]: https://hackage.haskell.org/package/lucid2