Skip to content

wscherphof/fastify-htmxample

Repository files navigation

fastify-htmxample

This repo aims to provide an example of a complete setup for an HTMX app.

HTMX provides extensions for HTML, so that HTML content is really capable of fullfilling the Hypermedia As The Engine Of Application State paradigm that the web was designed for.

HTMX also features Hyperscript to create additional client-side interactions. In this repo, it's used in ./views/secret.pug and in ./views/app.pug.

We use Fastify as the Node backend (Fastify is "the new Express"), and Vite as the "bundler" for the frontend.

Run

  1. Install Node
  2. Clone this repo
  3. Open a terminal and cd into the clone's root
  4. npm install to install all dependencies and build the Vite project
  5. npm run dev to start the Fastify server.

Browse to http://localhost:3000 and see that it worked.

Vite dev server

If you're going to make changes to the JavaScript project in the vite derictory, you can avoid having to rebuild it every time, by starting the Vite development server:

  1. Open another terminal (keep Fastify running on port 3000 in the existing terminal)
  2. cd to the vite folder
  3. npm run dev to start the Vite server on port 3001

Change the browser URL to http://localhost:3001. Now the browser will "hot reload" everything you change within the vite directory. Note that the Fastify server also restarts on every change of a file in the repo.

Demo

To demonstrate the setup, the app implements (not more than) a Register and Login sequence. Anyone can sign up by submitting their email address, which is stored in a database. Subsequently, an email is sent to that address, with a link to the password form. On submit, the token that was in the emailed link is verified, and the user record in the database is updated with a hash of the password. With the response, an encrypted cookie is set, which will authenticate the user on subsequent requests.

There's a live version running as an Azure App Service at https://fastify-htmxample.azurewebsites.net/. (It's hosted for free; it might take a minute to spin up for you)

Configure

To complete the intended functionality of the demo, you'd need the connection details of an email box. Open app.js and modify the configuration of the fastify-mailer plugin. You can enter a password in the code, or use an enivironment variable. For the environment variable, stop the Fastify server (Ctrl-C), then enter e.g. export GMAIL_PASSWORD=xxxxxx before you npm run dev again.

Now, when you click the Register or New Password buttons in your browser, and submit an email addres, you should recieve an email with a link (containing an encrypted token) to the form where you can create your password to sign in.

Note that if you connect to a Gmail account, you probably need to set it to allow access from "less secure apps".

URLs

You'll notice that the URL in de browser changes on each action (e.g. /users/session), even when the HTML document isn't actually replaced, but only updated with partial HTML content, that is requested through Ajax.

Still, shoud you hit the browser's refresh button (or copy the URL and paste it in a new window), the complete HTML document is fetched, with the content matching the URL.

JavaScript

Should you navigate the site from a non-JavaScript environment, it would largely still work. Any machine that speaks HTTP can use it. In this sense, the site effectively behaves as a data API to the application's resources, using HTML as the data format. It's a self-describing format: it lists the data you've requested, along with links to any related resources, including all the parameters you can send on to those links, and a user interface to provision them. This is what's cool about hypermedia and REST.

Tools

Apart from HTMX, Hyperscript, Fastify and Vite, the main packages that make this setup work, are:

  1. fastify-htmx, a Fastify plugin that arranges for:

    1. Serving the Vite build.
    2. Accepting Ajax requests (with cookies) from the Vite dev server.
    3. Serving the full document instead of the partial content when needed.
    4. HTMX utility functions as Fastify decorators.
  2. dev-htmx, the frontend complement of fastify-htmx, to:

    1. Enable HTMX and Hyperscript.
    2. Direct Ajax requests to the backend server while the page is served by the frontend dev server.
    3. Fetch the inital app content from the backend, and insert it in the "empty" index.html from the frontend dev server.

    Note that while we use Vite as the bundler in this repo, the dev-htmx package is not bound to it; you could replace Vite with any alternative that knows how to import things.

Template engine

We use point-of-view to load the pug engine to dynamically render parametrised HTML. But again: you're free to make different choices.

From pug, we use fastify-mdc-pug to render Material Design Components. It's also imported client-side, to instantiate the JavaScript objects needed.

The .pug files are in the views directory. You'll notice the use of pug's inheritance mechanism for rendering either the partial content, requested by HTMX, or the full HTML, including the surrounding app content.

New project

To create a new project like this repo, take the following steps:

  1. Install fastify-cli: npm install fastify-cli --global
  2. fastify generate <yourapp>
  3. cd <yourapp>
  4. npm install
  5. npm install fastify-htmx
  6. Edit app.js to register the plugin: fastify.register(require('fastify-htmx'))
  7. Optionally npm install fastify-mdc-pug and fastify.register(require('fastify-mdc-pug/plugin'))
  8. npm init vite@latest vite - choose vanilla or vanilla-ts (for TypeScript)
  9. cd vite
  10. npm install
  11. npm install dev-htmx
  12. Edit main.js:
    1. Delete the lines setting document.querySelector('#app').innerHTML
    2. Add the following:
      1. import devHtmx from 'dev-htmx'
      2. Optionally import 'fastify-mdc-pug'
      3. devHtmx.init()
  13. npm run build
  14. cd ..
  15. npm run dev to start Fastify on port 3000
  16. Browse to http://localhost:3000
  17. Optionally, in another terminal, in the vite directory: npm run dev to start the Vite server on port 3001, and change the browser's address to http://localhost:3001

To Do

  1. Add tests and remove --no-check-coverage from package.json.
  2. Have the GUI handle HTTP error codes 4xx/5xx.
  3. Please file a GitHub issue should you have comments, find bugs, or request new features.

Credits

Kudos to the fine people on HTMX's Discord.

Getting Started with Fastify-CLI Fastify-CLI

This project was bootstrapped with Fastify-CLI.

Available Scripts

In the project directory, you can run:

npm run dev

To start the app in dev mode.
Open http://localhost:3000 to view it in the browser.

npm start

For production mode

npm run test

Run the test cases.

Learn More

To learn Fastify, check out the Fastify documentation.

About

Spin up HTMX apps integrating a JavaScript bundler and a Node.js backend.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published