#!/usr/bin/env nu # extract-template.nu — derive a website template from a living model project # (jpl-website) as a sanitized snapshot with safe defaults + COMPLETE markers. # # Reproducible seed for templates/website-htmx-ssr and templates/website-leptos. # Re-run to re-snapshot when the model evolves (snapshot model, not a live mirror). # # nu extract-template.nu --mode htmx-ssr --out ../templates/website-htmx-ssr # nu extract-template.nu --mode leptos --out ../templates/website-leptos # # Design: # - crate names stay neutral ("website-*"); the generator renames to the chosen # project later. Only the jpl-named pages_htmx crate is normalised to website-*. # - deploy identity (domain, registry, secrets base, author) is replaced with # safe defaults so NCL still parses and the site runs, each marked COMPLETE. # - jesusperez portfolio pages and real content are pruned to generic examples. # Binary / huge extensions to skip during sanitization (everything else is text). def binary-ext [] { [png jpg jpeg gif ico svg webp avif woff woff2 ttf otf eot wasm db "db-shm" "db-wal" pdf zip tgz gz xz lock map] } # Ordered, specific-before-generic substitutions applied to text files. def subs [] { [ # crate normalisation (the one jpl-named crate) ["jpl-pages-htmx" "website-pages-htmx"] ["jpl_pages_htmx" "website_pages_htmx"] ["jpl-website" "website"] ["jpl_website" "website"] # deploy identity → safe defaults (COMPLETE: set to your own) ["hello@jesusperez.pro" "hello@example.com"] ["dev@jesusperez.pro" "dev@example.com"] ["repo.jesusperez.pro/jesus" "repo.example.com/org"] ["daoreg.librecloud.online" "registry.example.com"] ["daoreg" "registry"] ["reg.librecloud.online" "registry.example.com"] ["librecloud.online" "example.com"] ["jesusperez.pro" "example.com"] ["reg-librecloud-pull" "registry-pull-secret"] ["librecloud-fip-wuji" "gateway-fip"] ["libre-wuji" "secrets-base"] ["librecloud" "example"] ["jesusperezlorenzo" "example-org"] ["@jesusperez_dev" "@example_dev"] ["JesusPerez" "ExampleOrg"] ["jesusperez" "example"] ] } def main [ --mode: string = "htmx-ssr" # htmx-ssr | leptos --src: string = "/Users/Akasha/Development/jpl-website" --out: string # target template dir (required) ] { if ($out | is-empty) { error make { msg: "--out is required" } } if ($mode not-in ["htmx-ssr" "leptos"]) { error make { msg: $"bad --mode ($mode)" } } let src = ($src | path expand) let out = ($out | path expand) if not ($src | path exists) { error make { msg: $"src not found: ($src)" } } print $"[extract] mode=($mode) src=($src) out=($out)" if ($out | path exists) { rm -rf $out } mkdir $out # --- 1. rsync the tree with explicit excludes ------------------------------- let common_excludes = [ ".git/" ".gitignore" "target/" "node_modules/" ".env" ".env.dev" ".k" "cache/" "dist/" "works-pv/" "lian-build-out/" ".DS_Store" ".ontoref/" ".ontoref-backup-pre-0023.tgz" ".coder/" ".config/" ".cargo/" ".claude/" ".rustelo.ontoref/" ".woodpecker/" "Cargo.lock" "pnpm-lock.yaml" "rel.sh" "RESUME.md" "test_img_gen.sh" "card.ncl" "rustelo-deps-overlay.toml" # jpl-only top-level cruft "data/" "rustelo/" "crates/site/" "templates/" ".woodpecker/" ".npmrc" "just/claude-admin.just" "just/claude-content.just" "just/claude-dev.just" # cluster/workspace-specific deploy bundles — a new site generates its own "provisioning/workspaces/" "provisioning/rustelo_website/" # real content — replaced by seed example post + pruned extras "site/content/blog/" "site/content/projects/" "site/content/recipes/" "site/content/activities/" "site/guide/" "site/info/" "site/reflection/" "site/public/kitdigital/" "site/public/r/" "site/public/content/" "site/public/docs/" # build artifacts in lian-build "lian-build/save/" "lian-build/all_Dockerfile" "lian-build/Dockerfile.server" "lian-build/build_directives_server.ncl" # jesusperez portfolio pages (htmx j2) "crates/pages_htmx/templates/pages/kogral.j2" "crates/pages_htmx/templates/pages/ontoref.j2" "crates/pages_htmx/templates/pages/provisioning.j2" "crates/pages_htmx/templates/pages/rustelo.j2" "crates/pages_htmx/templates/pages/secretumvault.j2" "crates/pages_htmx/templates/pages/stratumiops.j2" "crates/pages_htmx/templates/pages/syntaxis.j2" "crates/pages_htmx/templates/pages/typedialog.j2" "crates/pages_htmx/templates/pages/vapora.j2" # jpl logos (binary, name-bearing) "site/assets/logos/" "site/public/images/logos/" ] # NOTE: crates are NOT split by mode. jpl's server hard-depends on website-pages # and optionally website-client; mode is selected via cargo features + cfg, not # crate membership. Both templates carry the full workspace; only rendering.ncl # default_profile, the kept Dockerfile, and build features differ. (A pure-htmx # site can prune the leptos crates later only after making those deps optional.) let excludes = $common_excludes let exfile = (mktemp -t rsync-ex.XXXXXX) $excludes | str join "\n" | save -f $exfile (^rsync -a --exclude-from $exfile $"($src)/" $"($out)/") rm -f $exfile # --- 2. sanitize text files ------------------------------------------------- let bin = (binary-ext) let files = (glob ($out | path join "**" "*") --no-dir | where { |f| (($f | path parse | get extension) not-in $bin) and (not ($f | str contains "node_modules")) }) let table = (subs) mut done = 0 for f in $files { try { mut content = (open --raw $f | decode utf-8) for pair in $table { $content = ($content | str replace --all ($pair | get 0) ($pair | get 1)) } $content | save -f $f $done = $done + 1 } catch { # binary or non-utf8 file — leave untouched } } print $"[extract] sanitized ($done) / ($files | length) text files" # --- 3. mode-specific tweaks ------------------------------------------------ # rendering profile default let rendering = ($out | path join "site" "config" "rendering.ncl") if ($rendering | path exists) { let want = (if $mode == "htmx-ssr" { "htmx-ssr" } else { "leptos-hydration" }) open --raw $rendering | decode utf-8 | str replace --all --regex 'default_profile\s*=\s*"[^"]*"' $'default_profile = "($want)"' | save -f $rendering } # workspace members are left as-is (full workspace; see note above). # drop the non-active Dockerfile (rsync excludes are unreliable for single files here) let drop_dockerfile = (if $mode == "htmx-ssr" { "Dockerfile.leptos-hydration" } else { "Dockerfile.htmx-ssr" }) let df = ($out | path join "lian-build" $drop_dockerfile) if ($df | path exists) { rm -f $df } # --- 4. overlay seed (example content, setup doc) --------------------------- let seed = ($env.FILE_PWD | path join "seed" "common") if ($seed | path exists) { ^rsync -a $"($seed)/" $"($out)/" print $"[extract] seed overlaid from ($seed)" } print $"[extract] done: ($out)" }