site generator 3
Find a file
clover caruso 28ec939607
feat(lib/log): emit Message objects instead of text
the logging interface now returns a Message object instead of working
purely on ASCII text. messages contain the timestamp, ansi text, level,
scope, stack, and any extra metadata[^1].

this change considers four consumers:

- generally customizing the format of the terminal log
- in browsers, the module must call the correct 'console' API
- communicating rich log data across progress.ts' IPC 
- exporting logs to external tools for display/search/filtering

in addition, `scope.tee` is introduced, which allows duplicating log
output to another source, such as a file or to an external service.

[^1]: custom metadata cannot be set with this change
2025-10-27 01:42:01 -07:00
framework feat(lib/log): emit Message objects instead of text 2025-10-27 01:42:01 -07:00
lib feat(lib/log): emit Message objects instead of text 2025-10-27 01:42:01 -07:00
src chore: rename blog post 2025-10-27 01:42:00 -07:00
.dockerignore setup source of truth server 2025-10-14 02:40:46 -07:00
.gitignore feat(site): public code for blog september 2025 2025-10-14 02:40:48 -07:00
deno.jsonc add content type library 2025-10-14 02:40:44 -07:00
flake.lock feat(file-viewer): rework scan3, add mpeg-dash encoding 2025-10-14 02:40:47 -07:00
flake.nix feat(file-viewer): rework scan3, add mpeg-dash encoding 2025-10-14 02:40:47 -07:00
package-lock.json chore: update hono 2025-10-27 01:42:00 -07:00
package.json chore: update hono 2025-10-27 01:42:00 -07:00
readme.md chore(lib): promote progress as a top level module lib/progress 2025-10-18 10:45:04 -07:00
repl.js feat(file-viewer): finish scan3, cache layer, and other 2025-10-14 02:40:47 -07:00
run.js feat(lib/log): emit Message objects instead of text 2025-10-27 01:42:01 -07:00
suspense.test.tsx move more things into lib 2025-10-14 02:40:48 -07:00
suspense.ts move more things into lib 2025-10-14 02:40:48 -07:00
tsconfig.json move more things into lib 2025-10-14 02:40:48 -07:00

clover sitegen framework and typescript library

this repository contains clover's "sitegen" framework, which is a set of tools that assist building websites. additionally, this is the home of her typescript library lib, containing many high quality standalone sub-projects. all these tools power https://paperclover.net.

  • HTML ("Server Side Rendering") engine written from scratch. (~500 lines)
    • A more practical JSX runtime (class instead of className, built-in clsx, html() helper over dangerouslySetInnerHTML prop, etc).
    • Integration with Marko for concisely written components.
    • TODO: MDX-like compiler for content-heavy pages like blogs.
    • Different languages can be used at the same time. Supports async function components, <Suspense />, and custom extensions.
  • Incremental static site generator and build system.
    • Build both development and production sites on startup start. Incremental generator rebuilds changed pages; Build system state survives coding sessions.
    • Multiple backend support.
    • (TODO) Tests, Lints, and Type-checking is run alongside, and only re-runs checks when the files change. For example, changing a component re-tests only pages that use that component and re-lints only the changed file.
    • Static asset serving with automatic ETag and build-time compression.
    • Dynamic pages. Static pages can be regenerated (and cached) at runtime.
    • Font subsetting to reduce page bandwidth.
  • General purpose typescript libraries. (See ./lib)
  • Built on the stable and battle-tested Node.js runtime.

none of these tools are complex or revolutionary. rather, this project is the sum of many years of experience on managing content heavy websites, and an example on how other over-complicate other frameworks.

Included is src, which contains paperclover.net's source code. Highlights:

Development

minimum system requirements:

  • a cpu with at least 1 core.
  • random access memory.
  • windows 7 or later, macos, or other operating system.

required software:

  • node.js v24
  • python v3

my development machine, for example, is Dell Inspiron 7348 with Core i7

npm install

# build site using 'run.js' to enable runtime plugins
node run generate
# the built site runs in regular node.js
node --enable-source-maps .clover/o/backend

# watch-rebuild mode
node run watch

for unix systems, the provided flake.nix can be used with nix develop to open a shell with all needed system dependencies.

Deployment

there are two primary server components to be deployed: the web server and the sourth of truth server. The latter is a singleton that runs on Clover's NAS, which holds the full contents of the file storage. The web server pulls data from the source of truth and renders web pages, and can be duplicated to multiple cloud hosts without issue.

Deployment of the source of truth can be done with Docker Compose:

services:
  backend:
    container_name: backend
    build:
      # this uses loopback to hit the self-hosted git server,
      # docker will cache the image to not re-fetch on reboot.
      context: http://127.0.0.1:3000/clo/sitegen.git
      dockerfile: src/source-of-truth.dockerfile
    environment:
      # configuration
      - PORT=43200
      - CLOVER_DB=/data
      - CLOVER_FILE_RAW=/published
      - CLOVER_FILE_DERIVED=/data/derived
      - CLOVER_SOT_KEY=... # guards private/unreleased content
    ports:
      - '43200:43200'
    restart: unless-stopped
    volumes:
      - /mnt/storage1/clover/Documents/Config/paperclover:/data
      - /mnt/storage1/clover/Published:/published

Due to caching, images may need to be purged via docker image rm {image} -f when an update is desired. Some docker GUIs support force pulls, some are buggy.

The web server performs rendering. A Dockerfile for it is present in src/web.dockerfile but it is currently unused. Deployments are done by building the project locally, and then using rsync to copy files.

node run generate
rsync .clover/o "$REMOTE_USER:~/paperclover" --exclude=.clover --exclude=.env \
  --delete-after --progress --human-readable
ssh "$REMOTE_USER" /bin/bash << EOF
    set -e
    cd ~/paperclover
    npm ci
    pm2 restart site
    echo "-> https://paperclover.net"
EOF

Contributions

No contributions to src accepted, only framework.