A static site generator is a tool that generates a full static
HTML website based on raw data and a set of templates.
Essentially, a static site generator automates the task of
coding individual HTML pages and gets those pages ready to
serve to users ahead of time. Because these HTML pages are
pre-built, they can load very quickly in browsers. You can use
Ink, TypeScript and the native Node.js HTTP server to
generate HTML documents in order to be served statically.
First, create a project with the following structure and files.
src/index.ts
src/page.ink
package.json
src
index.ts
page.ink
package.json
import http from 'http';
import ink, { cache } from '@stackpress/ink/compiler';
//where your pages are:
const pages = path.join(__dirname, 'pages');
//where your build files are:
const build = path.join(__dirname, '../build');
//create ink compiler
const compiler = ink({
cwd: __dirname
}).use(cache({
buildPath: path.join(build, 'build')
}));
//create http server
const server = http.createServer(async (req, res) => {
//for build asset:
if (req.url?.startsWith('/build/')) {
//get filename ie. abc123.js
const filename = req.url.substring(7);
//get asset
const { type, content } = await compiler.asset(filename);
//send response
res.writeHead(200, { 'Content-Type': type });
return res.end(content);
}
// from /foo/bar.html to foo/bar.html
const route = request.url?.substring(1) || 'index.html';
const { fs } = compiler;
const file = path.join(build, route);
//for document pages:
if (file.endsWith('.html')) {
const route = file.substring(0, file.length - 5);
const template = path.join(pages, route + '.ink');
if (fs.existsSync(template)) {
//send response
return res.type('text/html').render(route, props);
}
}
//for static files:
if (fs.existsSync(file)) {
res.writeHead(200);
fs.createReadStream(file).pipe(res);
return;
}
//anything else?
res.statusCode = 404;
res.end('Not Found');
});
//listen on port 3000
server.listen(3000);
<style>
.title { text-align: center; }
</style>
<script>
import { env, props } from '@stackpress/ink';
const { BUILD_ID, APP_DATA } = env();
const { title } = props();
</script>
<html>
<head>
<title>{title}</title>
<link rel="stylesheet" type="text/css" href={`/build/${BUILD_ID}.css`} />
<script data-app={APP_DATA} src={`/build/${BUILD_ID}.js`}></script>
</head>
<body>
<h1 class="title">{title}</h1>
</body>
</html>
{
"name": "my-project",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "ts-node ./src/index.ts"
},
"dependencies": {
"@stackpress/ink": "0.3.24"
},
"devDependencies": {
"@stackpress/ink-dev": "0.3.24",
"@types/node": "22.1.0",
"ts-node": "10.9.2",
"typescript": "5.5.4"
}
}
To test the script and see the results, run the following
command in terminal.
npm run dev
Load
http://localhost:3000/
in your browser. After loading you should see files that were
generated in a new build folder found in your project root.