Skip to content

Instantly share code, notes, and snippets.

@arisetyo
Last active January 26, 2025 16:30
Show Gist options
  • Save arisetyo/c06b876a6b575385bf887b1b1cf10724 to your computer and use it in GitHub Desktop.
Save arisetyo/c06b876a6b575385bf887b1b1cf10724 to your computer and use it in GitHub Desktop.
Fastify + EJS + htmx + Alpine
<head>
<title><%= title %></title>
<script src="https://unpkg.com/[email protected]"></script>
<script src="https://unpkg.com/alpinejs" defer></script>
<link rel="stylesheet" href="/styles.css">
</head>
<!-- index.ejs --->
<!DOCTYPE html>
<html>
<%- include('HEAD', { title: 'Fastify x EJS X htmx x Alpine' }) %>
<body>
<p>Hello, <%=USER_NAME%>! (name is from EJS)</p>
<h1>Fastify x EJS x htmx x Alpine</h1>
<div
x-data="{
clickCount: 0,
}"
>
<p>
Click the button to get data from server and increment the counter on the client
</p>
<button
hx-get="/clicked"
hx-target="#result"
@click="clickCount += 1"
>
CLICK ME
</button>
<div class="container">
<div class="content">
<p>This is from server, using htmx</p>
<div id="result" class="result"></div>
</div>
<div class="content">
<p>This is on the client, using Alpine</p>
<div class="result">
<span x-text="clickCount"></span>
</div>
</div>
</div>
</div>
<%- include('footer') %>
</body>
</html>
// The Fastify entry point
const fastify = require('fastify')();
const ejs = require("ejs");
const path = require('path');
const fastifyView = require("@fastify/view")
const fastifyStatic = require("@fastify/static");
const SERVICE_PORT_NUMBER = 3320;
const VIEWS_DIR = "views";
const USER_NAME = "AMP";
// Serve static files from the 'public' directory
fastify.register(fastifyStatic, {
root: path.join(__dirname, 'public')
});
fastify.register(fastifyView, {
engine: { ejs }
});
// Define routes - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Define the root route
fastify.get('/', async (_, reply) => {
return reply.view(`${VIEWS_DIR}/index.ejs`, { USER_NAME });
});
// Define the clicked route
// This route will return a random content inside a HTML template (using EJS) and is handled by htmx on the client side
fastify.get('/clicked', async (_, reply) => {
const time = new Date().toLocaleTimeString();
// Define the HTML templates
const resultHTML = async TEXT => await ejs.renderFile(`${VIEWS_DIR}/result.ejs`, { TEXT });
// Create several HTML template content
const contentHTML = await Promise.all([
resultHTML(`Hello, it is ${time}.`),
resultHTML(`It is ${time} ain't it?`),
resultHTML(`Hey! It's ${time}...!`),
]);
// Select a random HTML template
const selectedHTML = contentHTML[Math.floor(Math.random() * contentHTML.length)];
reply.type('text/html').send(selectedHTML);
});
// Start the server = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
const start = async () => {
try {
await fastify.listen({ port: SERVICE_PORT_NUMBER });
console.log(`Server listening on port ${SERVICE_PORT_NUMBER}`);
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
// Start the server
start();
<em>
<strong><%=TEXT%></strong>
</em>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment