benevolent-games / turtle

slow and steady static site generator
MIT License
2 stars 0 forks source link

🐢 @benev/turtle

📦 turtle is an npm package: @benev/turtle
🪄 turtle is a one-line static-site-generator
📜️ turtle scripts standardize our ts app builds
⚙️ turtle patterns optimize our websites' prod/dev modes
🧐 turtle is typescript-first, but you can use plain javascript
❤️ turtle is free and open source



🪄 turtle static-site-generator


generate a website with turtle's cli

npx @benev/turtle --in="s:x" --out="x" --exclude="**/*.partial.html.js" --verbose="true"

image: turtle example output

note: turtle can accept multiple input directories.
that's because you'll likely keep your .css files alongside your typescript sources, whereas your .html.js javascript will be built into your typescript's output directory.


ask turtle for help

npx @benev/turtle --help

image: turtle help page


write your first webpage template

turtle will sniff out your .html.js files as inputs, then output matching .html files.

index.html.js

import {template, html} from "@benev/turtle"

export default template(async({path}) => html`
  <!doctype html>
  <html>
    <head>
      <title>@benev/turtle</title>
      <link
        rel="stylesheet"
        href="https://github.com/benevolent-games/turtle/blob/master/${path(import.meta.url).version.root('style.css')}"
        />
    </head>
    <body>
      <h1>@benev/turtle</h1>
    </body>
  </html>
`)


you can write template partials

notice the x parameter, which is the example "context" for this template. it doesn't need to be a number, it could be anything.

page.partial.ts

import {template, html} from "@benev/turtle"

export default template(async({path}, x: number) => html`
  <!doctype html>
  <html>
    <head>
      <meta charset="utf-8"/>
      <title>@benev/turtle - stamp test</title>
      <link
        rel="stylesheet"
        href="https://github.com/benevolent-games/turtle/blob/master/${path(import.meta.url).version.root('style.css')}"
        />
    </head>
    <body>
      <h1>@benev/turtle - stamp test</h1>
      <p>${x}</p>
    </body>
  </html>
`)


write your first turtle script

turtle also sniffs out .turtle.js scripts and executes them.

in these, you can do anything you want. your turtle script function is provided some handy stuff like the write_webpage function.

stamp.turtle.ts

import {turtle_script} from "@benev/turtle"

// import the partial from the previous example
import page from "./page.partial.js"

// we'll stamp out a webpage for each of these values
const values = [1, 2]

// your default export must be a turtle_script
export default turtle_script(async({write_webpage}) => {

  // loop over each value
  await Promise.all(values.map(async(x) => {

    // write a webpage
    await write_webpage({

      // provide the page template
      template: page,

      // provide the x value in the context
      context: x,

      // specify the destination relative
      // to this build script
      destination: `${x}.html`,
    })
  }))
})


you've gotta get into file path hash versioning!


use path in your templates

turtle gives you a path utility that allows you to link to file from different reference points. it can also do file path hash versioning for you.

to understand it, consider a hypothetical file structure like this:

s/ <-- (source directory)
  favicon.png
  cool/
    awesome.html.ts <-- (your turtle template)
    style.css

also, we'll assume you've set const {url} = import.meta

okay, this might make more sense when you consider file path versioning.

simply add .version to the above commands, and turtle will attach a hash query param suffix, which will magically fix all your browser caching problems:


remember, the templates are just async js functions


be sure to escape globs



📜️ turtle scripts

we use turtle scripts to standardize the whole build routine for our typescript apps across our many projects, to reduce repetitive boilerplate and centralize its maintenance.

with turtle installed, you can run these scripts with like npx turtle-standard at the command line, or in an npm package.json script, just turtle-standard will work as a one-line command.

primary scripts:

there are more scripts/ but i don't feel like documenting them all.



⚙️ turtle patterns

these are just functions for your turtle html templates that make life easier.