Week 22 of 2025
Development log of Esc Collective website
27 items
- Import templates and assets from pages
- Write READMEs for this repo and pages (output)
- Implement a debug view for Tera context
- Get title and description from config
- Write a note about missing public/ and git errors
- Move the intro text to the index section
- Move the home page template logic to index.html
- Members' cards are now backed by markdown files
- Add miniserve to the development environment
- Write a smart (?) publish script
- Improve the publish
- Move people pages to a new People section
- Copy services description from Joachim to home page
- Let a developer publish from unclean source repo
- Fix publish script failing when public/ is removed
- Fix publish script wrongly detecting remote tracking
- Implement a dry-run mode for publish.nu
- Handle /@branch-preview/ prefix in links
- Separate services to own section, with emojis 😎
- Fix publish script to handle comma in a commit message
- Increase vertical space above the footer
- Move the tera context element to the top
- Remove obsolete --prompt-font-size variable
- Create an extremely simple main nav element
- Make bullets in main nav look like LEDs
- Make the people accent yellow
- Add more space between nav bullets and labels
Import templates and assets from pages
On by
The template needs to be separated into content and structure. For now it's together. But it produces the same output as had-crafted HTML, so it's a start.
index f03ce8a..e60811d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,10 @@
=.devenv
=.direnv
+
+
+## Codeber Pages
+
+# A bare repository for Codeberg Pages
+/pages.git
+# Content generated with Zola, to be pushed to Codeberg Pages
+/publicnew file mode 100644
index 0000000..fddb23d
--- /dev/null
+++ b/static/.domains
@@ -0,0 +1 @@
+escco.eunew file mode 100644
index 0000000..d00fcd0
Binary files /dev/null and b/static/apple-touch-icon.png differnew file mode 100644
index 0000000..a15e21f
--- /dev/null
+++ b/static/esc-logo.svg
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ width="160"
+ height="160"
+ viewBox="0 0 160 160"
+ version="1.1"
+ id="svg8"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <defs
+ id="defs2" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1">
+ <g
+ id="g169">
+ <rect
+ style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:none;stroke-width:0.816497;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;paint-order:markers stroke fill;stop-color:#000000;stop-opacity:1"
+ id="rect167"
+ width="160"
+ height="160"
+ x="0"
+ y="0"
+ ry="30"
+ rx="30" />
+ <ellipse
+ style="font-variation-settings:'wght' 800;fill:none;fill-opacity:1;stroke:#729fcf;stroke-width:18.5072;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;paint-order:markers stroke fill"
+ id="path1"
+ cy="80"
+ cx="80"
+ rx="50"
+ ry="30" />
+ <g
+ id="g146"
+ style="fill:#ffcd00;fill-opacity:1" />
+ <path
+ id="rect14"
+ style="fill:#ffc400;stroke-width:20;paint-order:markers stroke fill"
+ d="M 67.5,10 130,0 92.5,150 30,160 Z" />
+ <path
+ style="font-variation-settings:'wght' 800;fill:none;fill-opacity:1;stroke:#729fcf;stroke-width:18.4994;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;paint-order:markers stroke fill"
+ id="ellipse14"
+ d="m 126.98463,69.739397 a 50,30 0 0 1 -17.1267,34.324303 50,30 0 0 1 -59.71586,0 50,30 0 0 1 -17.126701,-34.324304" />
+ <rect
+ style="font-variation-settings:normal;vector-effect:none;fill:none;fill-opacity:1;stroke:none;stroke-width:0.816497;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;paint-order:markers stroke fill;stop-color:#000000"
+ id="rect167-5"
+ width="160"
+ height="160"
+ x="340"
+ y="1.4210855e-14"
+ ry="30"
+ rx="30" />
+ </g>
+ </g>
+</svg>new file mode 100644
index 0000000..4acfbee
Binary files /dev/null and b/static/favicon-96x96.png differnew file mode 100644
index 0000000..609cf59
Binary files /dev/null and b/static/favicon.ico differnew file mode 100644
index 0000000..07d03f0
--- /dev/null
+++ b/static/favicon.svg
@@ -0,0 +1,37 @@
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev/svgjs" width="160" height="160"><svg width="160" height="160" viewBox="0 0 160 160" version="1.1" id="SvgjsSvg1210" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <defs id="SvgjsDefs1209"></defs>
+ <metadata id="SvgjsMetadata1208">
+ <rdf:rdf>
+ <cc:work rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"></dc:type>
+ </cc:work>
+ </rdf:rdf>
+ </metadata>
+ <g id="SvgjsG1207">
+ <g id="SvgjsG1206">
+ <rect style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:none;stroke-width:0.816497;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;paint-order:markers stroke fill;stop-color:#000000;stop-opacity:1" id="SvgjsRect1205" width="160" height="160" x="0" y="0" ry="30" rx="30"></rect>
+ <ellipse style="font-variation-settings:'wght' 800;fill:none;fill-opacity:1;stroke:#729fcf;stroke-width:18.5072;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;paint-order:markers stroke fill" id="SvgjsEllipse1204" cy="80" cx="80" rx="50" ry="30"></ellipse>
+ <g id="SvgjsG1203" transform="translate(-324.625)">
+ <path id="SvgjsPath1202" style="font-variation-settings:'wght' 800;vector-effect:none;fill:#ffc400;fill-opacity:1;stroke-width:0.09795;paint-order:markers stroke fill;stop-color:#000000" d="m 230,80 h -10 l -13.875,74 h 10 z"></path>
+ <path id="SvgjsPath1201" style="font-variation-settings:'wght' 800;vector-effect:none;fill:#ffcd00;fill-opacity:1;stroke-width:0.09795;paint-order:markers stroke fill;stop-color:#000000" d="m 240,80 h -12 l -14.38616,76.7262 h 12 z"></path>
+ <path id="SvgjsPath1200" style="font-variation-settings:'wght' 800;vector-effect:none;fill:#ffc400;fill-opacity:1;stroke-width:0.09795;paint-order:markers stroke fill;stop-color:#000000" d="m 270,80 h -10 l -13.875,74 h 10 z"></path>
+ <path id="SvgjsPath1199" style="font-variation-settings:'wght' 800;vector-effect:none;fill:#ffcd00;fill-opacity:1;stroke-width:0.09795;paint-order:markers stroke fill;stop-color:#000000" d="m 262,80 h -12 l -14.25,76 h 12 z"></path>
+ <path id="SvgjsPath1198" style="font-variation-settings:'wght' 800;vector-effect:none;fill:#ffd733;fill-opacity:1;stroke-width:0.09795;paint-order:markers stroke fill;stop-color:#000000" d="m 252,80 h -14 l -15,80 h 14 z"></path>
+ </g>
+ <g id="SvgjsG1197" transform="translate(-324.625)">
+ <path id="SvgjsPath1196" style="font-variation-settings:'wght' 800;vector-effect:none;fill:#ffc400;fill-opacity:1;stroke-width:0.09795;paint-order:markers stroke fill;stop-color:#000000" d="M 233.125,10 220,80 h 10 l 13.125,-70 z"></path>
+ <path id="SvgjsPath1195" style="font-variation-settings:'wght' 800;vector-effect:none;fill:#ffcd00;fill-opacity:1;stroke-width:0.09795;paint-order:markers stroke fill;stop-color:#000000" d="M 242.26725,3.9079967 228,80 h 12 L 254.26725,3.9079967 Z"></path>
+ <path id="SvgjsPath1194" style="font-variation-settings:'wght' 800;vector-effect:none;fill:#ffc400;fill-opacity:1;stroke-width:0.09795;paint-order:markers stroke fill;stop-color:#000000" d="M 273.125,10 260,80 h 10 l 13.125,-70 z"></path>
+ <path id="SvgjsPath1193" style="font-variation-settings:'wght' 800;vector-effect:none;fill:#ffcd00;fill-opacity:1;stroke-width:0.09795;paint-order:markers stroke fill;stop-color:#000000" d="M 264.26725,3.9079967 250,80 h 12 L 276.26725,3.9079967 Z"></path>
+ <path id="SvgjsPath1192" style="font-variation-settings:'wght' 800;vector-effect:none;fill:#ffd733;fill-opacity:1;stroke-width:0.09795;paint-order:markers stroke fill;stop-color:#000000" d="m 253,0 -15,80 h 14 L 267,0 Z"></path>
+ </g>
+ <g id="SvgjsG1191" style="fill:#ffcd00;fill-opacity:1"></g>
+ <path id="SvgjsPath1190" style="fill:#ffc400;stroke-width:20;paint-order:markers stroke fill" d="M 67.5,10 130,0 92.5,150 30,160 Z"></path>
+ <path style="font-variation-settings:'wght' 800;fill:none;fill-opacity:1;stroke:#729fcf;stroke-width:18.4994;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;paint-order:markers stroke fill" id="SvgjsPath1189" d="m 126.98463,69.739397 a 50,30 0 0 1 -17.1267,34.324303 50,30 0 0 1 -59.71586,0 50,30 0 0 1 -17.126701,-34.324304"></path>
+ <rect style="font-variation-settings:normal;vector-effect:none;fill:none;fill-opacity:1;stroke:none;stroke-width:0.816497;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;paint-order:markers stroke fill;stop-color:#000000" id="SvgjsRect1188" width="160" height="160" x="340" y="1.4210855e-14" ry="30" rx="30"></rect>
+ </g>
+ </g>
+</svg><style>@media (prefers-color-scheme: light) { :root { filter: none; } }
+@media (prefers-color-scheme: dark) { :root { filter: none; } }
+</style></svg>
\ No newline at end of filenew file mode 100644
index 0000000..d430d9c
--- /dev/null
+++ b/static/site.webmanifest
@@ -0,0 +1,21 @@
+{
+ "name": "ESC Collective",
+ "short_name": "ESC Co",
+ "icons": [
+ {
+ "src": "/web-app-manifest-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "maskable"
+ },
+ {
+ "src": "/web-app-manifest-512x512.png",
+ "sizes": "512x512",
+ "type": "image/png",
+ "purpose": "maskable"
+ }
+ ],
+ "theme_color": "#dbdbdb",
+ "background_color": "#dbdbdb",
+ "display": "standalone"
+}new file mode 100644
index 0000000..2946743
Binary files /dev/null and b/static/social-media-banner.png differnew file mode 100644
index 0000000..b79fc9f
Binary files /dev/null and b/static/web-app-manifest-192x192.png differnew file mode 100644
index 0000000..ae37e05
Binary files /dev/null and b/static/web-app-manifest-512x512.png differnew file mode 100644
index 0000000..a08738f
--- /dev/null
+++ b/templates/base.html
@@ -0,0 +1,374 @@
+<!doctype html>
+<html class="no-js" lang="en">
+ <head>
+ <meta charset="utf-8" />
+ <meta http-equiv="x-ua-compatible" content="ie=edge" />
+ <title>ESC</title>
+ <meta name="description" content="" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+
+ <link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" />
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
+ <link rel="shortcut icon" href="/favicon.ico" />
+ <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
+ <meta name="apple-mobile-web-app-title" content="ESC Co." />
+ <link rel="manifest" href="/site.webmanifest" />
+
+ <meta property="og:title" content="ESC Collective">
+ <meta property="og:type" content="website" />
+ <meta property="og:image" content="https://escco.eu/social-media-banner.png">
+ <meta property="og:url" content="https://escco.eu/">
+ <meta name="twitter:card" content="summary_large_image">
+ <meta property="og:description" content="An international network of IT professionals and entrepreneurs dedicated to promote and support free software and use of services respecting human rights, dignity and privacy.">
+ <meta property="og:site_name" content="ESC Collective">
+ <meta name="twitter:image:alt" content="The ESC Collective logo">
+
+ <style type="text/css">
+ :root {
+ --typing-duration: 6s;
+ --prompts-count: 19;
+ --max-prompt-length: 63;
+ --prompt-height: 1.5em;
+ --prompt-font-size: 2rem;
+ --container-width: 960px;
+ --dark-color: hsl(0, 0%, 10%);
+ --light-color: hsl(0, 0%, 90%);
+ --full-bleed-margin: max(
+ 0px,
+ calc(0.5 * (100vw - var(--container-width)))
+ );
+ }
+
+ body {
+ font-family: sans-serif;
+ padding: 0;
+ margin: auto;
+ background: hsl(0, 0%, 86%);
+ max-width: 960px;
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ }
+
+ body > header {
+ font-size: var(--prompt-font-size);
+ align-items: center;
+ display: flex;
+ gap: 1ch;
+ color: var(--dark-color);
+ padding: 3rem 1rem;
+ overflow: hidden;
+ }
+
+ body > main {
+ flex-grow: 1;
+ padding: 0 1rem;
+ }
+
+ body > footer {
+ display: flex;
+ background: var(--dark-color);
+ align-items: center;
+ color: var(--light-color);
+ }
+
+ hgroup h1 {
+ margin: 0;
+ font-weight: 400;
+ }
+
+ hgroup p {
+ margin: 0;
+ font-size: 0.8rem;
+ font-weight: bold;
+ }
+
+ .title {
+ font-family: sans-serif;
+ white-space: nowrap;
+ }
+
+ .title h1 {
+ font-size: 3rem;
+ }
+
+ .icon {
+ height: 1.6em;
+ margin: 0 1ch;
+ }
+
+ #logo {
+ height: 3em;
+ }
+
+ p {
+ hyphens: auto;
+ line-height: 1.6em;
+ }
+
+ .lead {
+ font-size: 150%;
+ }
+
+ .card-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
+ grid-auto-rows: 1fr;
+ gap: 2em 2em;
+ margin: 4rem 0;
+
+
+ &> article {
+ background-color: white;
+ border-radius: 8px;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+ padding: 1em;
+ display: flex;
+ flex-direction: column;
+
+ h2 {
+ font-size: 1em;
+ font-weight: bold;
+ }
+
+ p {
+ margin-top: 1em;
+ font-size: 1rem;
+ flex-grow: 1;
+ text-align: start;
+ text-align: justify;
+ hyphens: auto;
+ }
+ }
+ }
+
+
+ /* UTILITY CLASSES */
+
+ .full-bleed-background {
+ margin: 0 calc(-1 * var(--full-bleed-margin));
+ padding: 3rem calc(1rem + var(--full-bleed-margin));
+ }
+
+ /* PROMPT ANIMATION */
+
+ .prompt {
+ font-family: monospace;
+ font-weight: 700;
+ white-space: nowrap;
+ overflow: hidden;
+ padding: 0;
+ margin: 0;
+ height: var(--prompt-height);
+ /* background: blue; */
+ line-height: var(--prompt-height);
+ }
+
+ .prompt > li {
+ height: var(--prompt-height);
+ animation: calc(var(--typing-duration) * var(--prompts-count)) infinite
+ switch-prompt;
+ animation-timing-function: steps(var(--prompts-count), end);
+ }
+
+ .prompt > li .input {
+ max-width: 0ch;
+ animation: var(--typing-duration) infinite typing;
+ animation-timing-function: steps(var(--max-prompt-length), end);
+ overflow: hidden;
+ display: inline-block;
+ /* background: pink; */
+ }
+
+ .prompt > li:after {
+ content: "█";
+ display: inline;
+ vertical-align: top;
+ animation: 1s infinite blinking;
+ /* color: green; */
+ }
+
+ @keyframes typing {
+ 0% {
+ max-width: 0ch;
+ }
+
+ 60%,
+ 70% {
+ max-width: 63ch;
+ }
+
+ 90%,
+ 100% {
+ max-width: 0ch;
+ }
+ }
+
+ @keyframes switch-prompt {
+ from {
+ transform: translateY(0);
+ }
+
+ to {
+ transform: translateY(
+ calc(-1 * var(--prompts-count) * var(--prompt-height))
+ );
+ }
+ }
+
+ @keyframes blinking {
+ 0%,
+ 20% {
+ opacity: 0;
+ }
+
+ 40%,
+ 60% {
+ opacity: 100%;
+ }
+
+ 80%,
+ 100% {
+ opacity: 0;
+ }
+ }
+
+ @media (max-width: 36rem) {
+ #logo {
+ height: 2em;
+ }
+
+ .title > h1 {
+ font-size: 2rem;
+ }
+
+ .title > p {
+ font-size: 0.6rem;
+ }
+ }
+ </style>
+ </head>
+
+ <body>
+ <!--[if lt IE 8]>
+ <p class="browserupgrade">
+ You are using an <strong>outdated</strong> browser. Please
+ <a href="http://browsehappy.com/">upgrade your browser</a> to improve
+ your experience.
+ </p>
+ <![endif]-->
+
+ <header>
+ <img
+ id="logo"
+ src="esc-logo.svg"
+ alt="The ESC logo with a sky-blue ring and a bright yellow ray passing through it."
+ />
+
+ <hgroup class="title">
+ <h1>esc collective</h1>
+ <p>supporting european digital independence</p>
+ </hgroup>
+ </header>
+ <main>
+ <p class="lead">
+ We are an international network of IT professionals and entrepreneurs
+ dedicated to promote and support free software and use of services
+ respecting human rights, dignity and privacy.
+ </p>
+
+ <section class="card-grid">
+ <article>
+ <h2>Tad Lazurski</h2>
+ <p>
+ AKA Tad Lispy. I'm a software developer, entrepreneur, and an
+ educator based in the Netherlands, founder and facilitator of EscCo.
+ My delight is finding simple, creative and practical solutions to
+ real business problems. Find out more at <a href="https://tad-lispy.com/">tad-lispy.com</a>.
+ </p>
+ </article>
+
+ <article>
+ <h2>Richard Cronan</h2>
+ <p>
+ I’m an experienced consultant and team leader with a background in
+ digital strategy and analytics who translates between technical and
+ non-technical teams to drive successful, people-centred digital
+ solutions. I believe we can do business ethically.
+ </p>
+ </article>
+
+ <article>
+ <h2>Vítor Andrade</h2>
+ <p>
+ I am a devops / SRE / infrastructure engineer happy to help with
+ anything that runs on a Linux system - from a bash script to a
+ multi-continental distributed system. I love solving problems and
+ working with great people. Fun is an essential ingredient.
+ </p>
+ </article>
+
+ <article>
+ <h2>Tibor Eszes</h2>
+ <p>
+ I have a deep experience in cloud, data and systems engineering,
+ software architecture, AI, backend programming (Go and Python),
+ Kubernetes and embedded systems. I'm also interested in electrical
+ and mechanical engineering, genetics and genomics.
+ </p>
+ </article>
+
+ <article>
+ <h2>João Campos</h2>
+ <p>
+ I'm a researcher and a software engineer from Portugal, with a
+ passion for building efficient and scalable systems, specialized in
+ designing reliable infrastructure for distributed systems.
+ </p>
+ </article>
+
+ <article>
+ <h2>Joachim Nuyttens</h2>
+ <p>
+ I'm the COO of
+ <a href="https://trevalco.com/" target="_blank">Trevalco</a>,
+ an SME providing services to the life sciences industry. As a
+ technology, open-source and Linux enthusiast I advise ESC on the
+ development of services of value to small and medium sized companies
+ in EU.
+ </p>
+ </article>
+
+ </section>
+ </main>
+
+ <footer class="full-bleed-background">
+ <img src="favicon.svg" alt="ESC Icon" class="icon" />
+
+ <ul class="prompt">
+ <!-- Remember to adjust the --prompts-count variable -->
+ <li><span class="input">Enterprise Systems Collective</span></li>
+ <li><span class="input">European Systems Collective</span></li>
+ <li><span class="input">Enabling Successful Cooperation</span></li>
+ <li><span class="input">Ethical and Sustainable Computing</span></li>
+ <li><span class="input">European Sovereign Computing</span></li>
+ <li>
+ <span class="input">Empresa de Sistemas para Computadoras</span>
+ </li>
+ <li><span class="input">Extremely Sassy and Classy</span></li>
+ <li><span class="input">Electronic Sustainability Collective</span></li>
+ <li><span class="input">Etiam Secundum Comodum</span></li>
+ <li><span class="input">ESC Sounds Cool</span></li>
+ <li><span class="input">Europe Stands with Canada</span></li>
+ <li><span class="input">Egalitarian Software Community</span></li>
+ <li><span class="input">Einstein Collective</span></li>
+ <li><span class="input">Escape the Scary Clown</span></li>
+ <li><span class="input">European Syndicate for Computing</span></li>
+ <li><span class="input">Égalité, Sécurité, Calcule</span></li>
+ <li><span class="input">European Solutions for Computers</span></li>
+ <li><span class="input">Energetic, Silly Coders</span></li>
+ <li><span class="input">Exuberantis Serendipitatis Conatus</span></li>
+ </ul>
+ </footer>
+ </body>
+</html>new file mode 100644
index 0000000..94d9808
--- /dev/null
+++ b/templates/index.html
@@ -0,0 +1 @@
+{% extends "base.html" %}Write READMEs for this repo and pages (output)
On by
new file mode 100644
index 0000000..b24e8b0
--- /dev/null
+++ b/README.md
@@ -0,0 +1,44 @@
+This repository contains sources to build escco.eu website: content, templates, assets. Use Zola to generate a website from it and push it to
+
+
+# Development
+
+Start by cloning this repository. Then from within clone the pages using the following command:
+
+``` shell
+git --work-tree public clone ssh://git@codeberg.org/escco/pages.git pages.git
+```
+
+This should create two sub-directories:
+
+ - `public` containing the website (index.html and such)
+ - `pages.git` containing git history and configuration
+
+
+> Why? Because Zola will wipe out everything in public/, including .git/ if it were there. So we need to keep git directory outside of public.
+
+This is the directory structure you should have now:
+
+``` shellsession
+escco.eu/
+ ./config.toml
+ ./content <-- markdown files
+ ./flake.lock
+ ./flake.nix
+ ./pages.git <-- git history of public
+ ./public <-- generated web content to be published
+ ./README.md
+ ./sass <-- stylesheets
+ ./static
+ ./templates <-- reusable html templates
+```
+
+`
+
+Use `zola serve` command to preview the website on your local machine.
+
+Use `zola build` to write production ready files to `public/`.
+
+Change directory to `pages.git/`, commit and push to publish the website.
+
+Inside `pages.git` you can use branches and other features of Git. Just remember that `pages.git/` and `public/` are a separate repository from this one. If it feels too complicated, talk to Tad - he will explain or try find a way to make it simpler.new file mode 100644
index 0000000..53b6373
--- /dev/null
+++ b/static/README.md
@@ -0,0 +1 @@
+This repository contains website assets for escco.eu. We now use Zola to generate it from sources in a separate repository at <https://codeberg.org/escco/escco.eu>. If you modify them by hand, your changes will get overwritten. Instead work in the sources repository.Implement a debug view for Tera context
On by
Only visible in development (i.e. with zola serve), at the very bottom
of the page (below the footer). It shows all the variables that can be
used in a template.
index a08738f..0d3a8a7 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -370,5 +370,14 @@
= <li><span class="input">Exuberantis Serendipitatis Conatus</span></li>
= </ul>
= </footer>
+
+ {% if config.mode == "serve" %}
+ <details style="overflow: scroll">
+ <summary>Rendering context</summary>
+ <pre>
+{{ __tera_context | escape | safe }}
+ </pre>
+ </details>
+ {% endif %}
= </body>
=</html>Get title and description from config
On by
Small steps to separate templates from content.
index 1e07357..badacc2 100644
--- a/config.toml
+++ b/config.toml
@@ -1,6 +1,12 @@
=# The URL the site will be built for
=base_url = "https://escco.eu/"
=
+# The base title - will be concatenated with page titles
+title = "Esc Co."
+
+# Fallback description if no page-specific is provided
+description = "Esc Collective is an international network of IT professionals and entrepreneurs dedicated to promote and support free software and use of services respecting human rights, dignity and privacy."
+
=# Whether to automatically compile all Sass files in the sass directory
=compile_sass = true
=index d430d9c..0a98b5e 100644
--- a/static/site.webmanifest
+++ b/static/site.webmanifest
@@ -1,6 +1,6 @@
={
- "name": "ESC Collective",
- "short_name": "ESC Co",
+ "name": "Esc Collective",
+ "short_name": "Esc Co.",
= "icons": [
= {
= "src": "/web-app-manifest-192x192.png",index 0d3a8a7..4eb0cfc 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -1,26 +1,51 @@
+{#
+ Templates can set their custom title and description, otherwise here is the
+ fallback logic.
+#}
+
+{%- if not title -%}
+ {%- if section and section.title -%}
+ {%- set title = section.title ~ " - " ~ config.title -%}
+ {%- elif page and page.title -%}
+ {%- set title = page.title ~ " - " ~ config.title -%}
+ {%- else -%}
+ {%- set title = config.title -%}
+ {%- endif -%}
+{%- endif -%}
+
+{%- if not description -%}
+ {%- if section and section.description -%}
+ {%- set description = section.description -%}
+ {%- elif page and page.description -%}
+ {%- set description = page.description -%}
+ {%- else -%}
+ {%- set description = config.description -%}
+ {%- endif -%}
+{%- endif -%}
+
=<!doctype html>
=<html class="no-js" lang="en">
= <head>
= <meta charset="utf-8" />
= <meta http-equiv="x-ua-compatible" content="ie=edge" />
- <title>ESC</title>
- <meta name="description" content="" />
+ <title>{{ title }}</title>
+ <meta name="description" content="{{ description }}" />
= <meta name="viewport" content="width=device-width, initial-scale=1" />
=
= <link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" />
= <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
= <link rel="shortcut icon" href="/favicon.ico" />
= <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
- <meta name="apple-mobile-web-app-title" content="ESC Co." />
+ <meta name="apple-mobile-web-app-title" content="{{ config.title }}" />
= <link rel="manifest" href="/site.webmanifest" />
=
- <meta property="og:title" content="ESC Collective">
+ <meta property="og:title" content="{{ title }}">
= <meta property="og:type" content="website" />
= <meta property="og:image" content="https://escco.eu/social-media-banner.png">
= <meta property="og:url" content="https://escco.eu/">
= <meta name="twitter:card" content="summary_large_image">
- <meta property="og:description" content="An international network of IT professionals and entrepreneurs dedicated to promote and support free software and use of services respecting human rights, dignity and privacy.">
- <meta property="og:site_name" content="ESC Collective">
+ <meta property="og:description" content="{{ description }}">
+ <meta property="og:site_name" content="{{ config.title }}">
= <meta name="twitter:image:alt" content="The ESC Collective logo">
=
= <style type="text/css">
@@ -282,9 +307,10 @@
= <h2>Tad Lazurski</h2>
= <p>
= AKA Tad Lispy. I'm a software developer, entrepreneur, and an
- educator based in the Netherlands, founder and facilitator of EscCo.
- My delight is finding simple, creative and practical solutions to
- real business problems. Find out more at <a href="https://tad-lispy.com/">tad-lispy.com</a>.
+ educator based in the Netherlands, founder and facilitator of Esc
+ Co. My delight is finding simple, creative and practical solutions
+ to real business problems. Find out more at
+ <a href="https://tad-lispy.com/">tad-lispy.com</a>.
= </p>
= </article>
=Write a note about missing public/ and git errors
On by
index b24e8b0..25a36fd 100644
--- a/README.md
+++ b/README.md
@@ -42,3 +42,12 @@ Use `zola build` to write production ready files to `public/`.
=Change directory to `pages.git/`, commit and push to publish the website.
=
=Inside `pages.git` you can use branches and other features of Git. Just remember that `pages.git/` and `public/` are a separate repository from this one. If it feels too complicated, talk to Tad - he will explain or try find a way to make it simpler.
+
+> NOTE: The `zola serve` command, when stopped, will remove `public/`. If you are getting weird errors from git, like
+>
+> ``` shellsession
+> $ git status
+> fatal: this operation must be run in a work tree
+> ```
+>
+> inside pages repository, check if it exists. If not, just run `zola build` again to re-create it.Move the intro text to the index section
On by
new file mode 100644
index 0000000..69b1963
--- /dev/null
+++ b/content/_index.md
@@ -0,0 +1,4 @@
+---
+---
+
+We are an international network of IT professionals and entrepreneurs dedicated to promote and support free software and use of services respecting human rights, dignity and privacy.index 4eb0cfc..5c4834b 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -131,7 +131,7 @@
= line-height: 1.6em;
= }
=
- .lead {
+ main > p:first-child {
= font-size: 150%;
= }
=
@@ -296,11 +296,8 @@
= </hgroup>
= </header>
= <main>
- <p class="lead">
- We are an international network of IT professionals and entrepreneurs
- dedicated to promote and support free software and use of services
- respecting human rights, dignity and privacy.
- </p>
+
+ {{ section.content | safe }}
=
= <section class="card-grid">
= <article>Move the home page template logic to index.html
On by
Previously it was in the base template, which is used for every page and section.
index 5c4834b..8888a53 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -296,73 +296,10 @@
= </hgroup>
= </header>
= <main>
-
- {{ section.content | safe }}
-
- <section class="card-grid">
- <article>
- <h2>Tad Lazurski</h2>
- <p>
- AKA Tad Lispy. I'm a software developer, entrepreneur, and an
- educator based in the Netherlands, founder and facilitator of Esc
- Co. My delight is finding simple, creative and practical solutions
- to real business problems. Find out more at
- <a href="https://tad-lispy.com/">tad-lispy.com</a>.
- </p>
- </article>
-
- <article>
- <h2>Richard Cronan</h2>
- <p>
- I’m an experienced consultant and team leader with a background in
- digital strategy and analytics who translates between technical and
- non-technical teams to drive successful, people-centred digital
- solutions. I believe we can do business ethically.
- </p>
- </article>
-
- <article>
- <h2>Vítor Andrade</h2>
- <p>
- I am a devops / SRE / infrastructure engineer happy to help with
- anything that runs on a Linux system - from a bash script to a
- multi-continental distributed system. I love solving problems and
- working with great people. Fun is an essential ingredient.
- </p>
- </article>
-
- <article>
- <h2>Tibor Eszes</h2>
- <p>
- I have a deep experience in cloud, data and systems engineering,
- software architecture, AI, backend programming (Go and Python),
- Kubernetes and embedded systems. I'm also interested in electrical
- and mechanical engineering, genetics and genomics.
- </p>
- </article>
-
- <article>
- <h2>João Campos</h2>
- <p>
- I'm a researcher and a software engineer from Portugal, with a
- passion for building efficient and scalable systems, specialized in
- designing reliable infrastructure for distributed systems.
- </p>
- </article>
-
- <article>
- <h2>Joachim Nuyttens</h2>
- <p>
- I'm the COO of
- <a href="https://trevalco.com/" target="_blank">Trevalco</a>,
- an SME providing services to the life sciences industry. As a
- technology, open-source and Linux enthusiast I advise ESC on the
- development of services of value to small and medium sized companies
- in EU.
- </p>
- </article>
-
- </section>
+ {% filter indent(prefix=" ") -%}
+ {%- block main_content -%}
+ {%- endblock main_content -%}
+ {%- endfilter %}
= </main>
=
= <footer class="full-bleed-background">index 94d9808..0d97221 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -1 +1,70 @@
={% extends "base.html" %}
+
+{%- block main_content -%}
+{{- section.content | safe -}}
+
+<section class="card-grid">
+ <article>
+ <h2>Tad Lazurski</h2>
+ <p>
+ AKA Tad Lispy. I'm a software developer, entrepreneur, and an
+ educator based in the Netherlands, founder and facilitator of Esc
+ Co. My delight is finding simple, creative and practical solutions
+ to real business problems. Find out more at
+ <a href="https://tad-lispy.com/">tad-lispy.com</a>.
+ </p>
+ </article>
+
+ <article>
+ <h2>Richard Cronan</h2>
+ <p>
+ I’m an experienced consultant and team leader with a background in
+ digital strategy and analytics who translates between technical and
+ non-technical teams to drive successful, people-centred digital
+ solutions. I believe we can do business ethically.
+ </p>
+ </article>
+
+ <article>
+ <h2>Vítor Andrade</h2>
+ <p>
+ I am a devops / SRE / infrastructure engineer happy to help with
+ anything that runs on a Linux system - from a bash script to a
+ multi-continental distributed system. I love solving problems and
+ working with great people. Fun is an essential ingredient.
+ </p>
+ </article>
+
+ <article>
+ <h2>Tibor Eszes</h2>
+ <p>
+ I have a deep experience in cloud, data and systems engineering,
+ software architecture, AI, backend programming (Go and Python),
+ Kubernetes and embedded systems. I'm also interested in electrical
+ and mechanical engineering, genetics and genomics.
+ </p>
+ </article>
+
+ <article>
+ <h2>João Campos</h2>
+ <p>
+ I'm a researcher and a software engineer from Portugal, with a
+ passion for building efficient and scalable systems, specialized in
+ designing reliable infrastructure for distributed systems.
+ </p>
+ </article>
+
+ <article>
+ <h2>Joachim Nuyttens</h2>
+ <p>
+ I'm the COO of
+ <a href="https://trevalco.com/" target="_blank">Trevalco</a>,
+ an SME providing services to the life sciences industry. As a
+ technology, open-source and Linux enthusiast I advise ESC on the
+ development of services of value to small and medium sized companies
+ in EU.
+ </p>
+ </article>
+
+</section>
+{%- endblock main_content -%}Members' cards are now backed by markdown files
On by
Technically they are pages (in Zola nomenclature). To maintain stable order (i.e. so it doesn't change on each rebuild) the cards are sorted by date attribute, which is roughly the date and time a given member joined the collective.
index 69b1963..acdeccb 100644
--- a/content/_index.md
+++ b/content/_index.md
@@ -2,3 +2,4 @@
=---
=
=We are an international network of IT professionals and entrepreneurs dedicated to promote and support free software and use of services respecting human rights, dignity and privacy.
+new file mode 100644
index 0000000..1b16067
--- /dev/null
+++ b/content/joachim-nuyttens.md
@@ -0,0 +1,7 @@
+---
+title: Joachim Nuyttens
+date: 2025-05-09T22:10:00
+---
+
+
+I'm the COO of [Trevalco](https://trevalco.com/), an SME providing services to the life sciences industry. As a technology, open-source and Linux enthusiast I advise ESC on the development of services of value to small and medium sized companies in EU.new file mode 100644
index 0000000..82b25f3
--- /dev/null
+++ "b/content/jo\303\243o-campos.md"
@@ -0,0 +1,6 @@
+---
+title: João Campos
+date: 2025-04-21T18:55:00
+---
+
+I'm a researcher and a software engineer from Portugal, with a passion for building efficient and scalable systems, specialized in designing reliable infrastructure for distributed systems.new file mode 100644
index 0000000..603ec84
--- /dev/null
+++ b/content/richard-cronan.md
@@ -0,0 +1,6 @@
+---
+title: Richard Cronan
+date: 2025-05-09T13:58:00
+---
+
+I’m an experienced consultant and team leader with a background in digital strategy and analytics who translates between technical and non-technical teams to drive successful, people-centred digital solutions. I believe we can do business ethically.new file mode 100644
index 0000000..47cba24
--- /dev/null
+++ b/content/tad-lazurski.md
@@ -0,0 +1,6 @@
+---
+title: Tad Lazurski
+date: 2025-04-21T12:20:00
+---
+
+AKA Tad Lispy. I'm a software developer, entrepreneur, and an educator based in the Netherlands, founder and facilitator of Esc Co. My delight is finding simple, creative and practical solutions to real business problems. Find out more at [tad-lispy.com](https://tad-lispy.com/).new file mode 100644
index 0000000..def1585
--- /dev/null
+++ b/content/tibor-eszes.md
@@ -0,0 +1,6 @@
+---
+title: Tibor Eszes
+date: 2025-05-09T14:00:00
+---
+
+I have a deep experience in cloud, data and systems engineering, software architecture, AI, backend programming (Go and Python), Kubernetes and embedded systems. I'm also interested in electrical and mechanical engineering, genetics and genomics.new file mode 100644
index 0000000..d1302ac
--- /dev/null
+++ "b/content/v\303\255tor-andrade.md"
@@ -0,0 +1,6 @@
+---
+title: Vítor Andrade
+date: 2025-05-09T13:59:00
+---
+
+I am a devops / SRE / infrastructure engineer happy to help with anything that runs on a Linux system - from a bash script to a multi-continental distributed system. I love solving problems and working with great people. Fun is an essential ingredient.index 0d97221..4645233 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -4,67 +4,15 @@
={{- section.content | safe -}}
=
=<section class="card-grid">
- <article>
- <h2>Tad Lazurski</h2>
- <p>
- AKA Tad Lispy. I'm a software developer, entrepreneur, and an
- educator based in the Netherlands, founder and facilitator of Esc
- Co. My delight is finding simple, creative and practical solutions
- to real business problems. Find out more at
- <a href="https://tad-lispy.com/">tad-lispy.com</a>.
- </p>
- </article>
-
- <article>
- <h2>Richard Cronan</h2>
- <p>
- I’m an experienced consultant and team leader with a background in
- digital strategy and analytics who translates between technical and
- non-technical teams to drive successful, people-centred digital
- solutions. I believe we can do business ethically.
- </p>
- </article>
-
- <article>
- <h2>Vítor Andrade</h2>
- <p>
- I am a devops / SRE / infrastructure engineer happy to help with
- anything that runs on a Linux system - from a bash script to a
- multi-continental distributed system. I love solving problems and
- working with great people. Fun is an essential ingredient.
- </p>
- </article>
+ {# Each page in this category represents a person.
=
+ It's a bit clunky. We will improve it later.
+ #}
+ {%- for page in section.pages | sort(attribute="date") -%}
= <article>
- <h2>Tibor Eszes</h2>
- <p>
- I have a deep experience in cloud, data and systems engineering,
- software architecture, AI, backend programming (Go and Python),
- Kubernetes and embedded systems. I'm also interested in electrical
- and mechanical engineering, genetics and genomics.
- </p>
+ <h2>{{ page.title }}</h2>
+ {{ page.content | safe }}
= </article>
-
- <article>
- <h2>João Campos</h2>
- <p>
- I'm a researcher and a software engineer from Portugal, with a
- passion for building efficient and scalable systems, specialized in
- designing reliable infrastructure for distributed systems.
- </p>
- </article>
-
- <article>
- <h2>Joachim Nuyttens</h2>
- <p>
- I'm the COO of
- <a href="https://trevalco.com/" target="_blank">Trevalco</a>,
- an SME providing services to the life sciences industry. As a
- technology, open-source and Linux enthusiast I advise ESC on the
- development of services of value to small and medium sized companies
- in EU.
- </p>
- </article>
-
+ {%- endfor -%}
=</section>
={%- endblock main_content -%}Add miniserve to the development environment
On by
To preview the website generated for production, before publishing it.
index 5cab3c9..ff26771 100644
--- a/flake.nix
+++ b/flake.nix
@@ -32,7 +32,10 @@
= modules = [
= {
= # https://devenv.sh/reference/options/
- packages = [ pkgs.zola ];
+ packages = [
+ pkgs.zola
+ pkgs.miniserve
+ ];
= }
= ];
= };Write a smart (?) publish script
On by
There's a lot of moving parts in publishing to Codeberg Pages. Some concerns:
- Publish to the same branch as source.
- Make sure the generated files are fresh.
- Only publish when changes to source are committed.
- Make sure there the histories did not diverge.
The publish.nu script (implemented in Nushell) tries to ensure all of the above.
new file mode 100755
index 0000000..61bc9e8
--- /dev/null
+++ b/publish.nu
@@ -0,0 +1,97 @@
+use std/dirs
+
+def main [] {
+ # Get the current source branch
+ # Switch pages to the same branch. Create it if needed.
+ # Find the time of last commit to pages.
+ # Make a list of commits in source since then.
+ # Format it as markdown list (only titles and hashes)
+ # Prepare a commit, showing a diff for users review
+ # Push to publish
+
+ if (not (git is-clean)) {
+ print "The source repository is not clean. First commit, then publish."
+ git status
+ exit 2
+ }
+
+ let source_branch = (git symbolic-ref --short HEAD)
+ print $"Source branch is ($source_branch)"
+
+ dirs add pages.git
+
+ print "Cleaning pages worktree..."
+ git restore .
+ git clean -fd
+
+ if (git has branch $source_branch) {
+ print "The branch exists in pages repository. Switching."
+ git switch --quiet $source_branch
+
+ if (git is-tracking) {
+ print "The branch was already deployed. Pulling."
+ git pull --quiet
+ }
+ } else {
+ print "The branch does not exist in pages repository."
+ loop {
+ match (input --numchar 1 $"Create and deploy a new branch '($source_branch)'? [y|n]: ") {
+ "y" => break,
+ "n" => { exit 1 },
+ _ => continue,
+ }
+ }
+ git switch main
+ git switch --quiet --create $source_branch
+ }
+
+ let last_commit_time = git show --no-patch --format=%cI
+ print $"Pages last published on ($last_commit_time)"
+
+ let commit_template = mktemp --tmpdir
+ let now = date now | date to-timezone utc | format date "%A, %F %T (utc)"
+
+ echo $"Update ($now)"
+ | save --append $commit_template
+ echo "\n\n"
+ | save --append $commit_template
+ echo $"Changes since ($last_commit_time | date to-timezone utc | format date '%A, %F %T (utc)')\n\n"
+ | save --append $commit_template
+ dirs prev
+
+ git log --pretty=reference --since=$last_commit_time
+ | save --append $commit_template
+
+ zola build
+
+ dirs next
+ git add .
+ git commit --verbose --file $commit_template --edit
+ git push --set-upstream origin $source_branch
+}
+
+# List all branches that can be switched to
+def "git list branches" [] {
+ git branch --list --all --format='%(refname:lstrip=-1)'
+ | lines
+ | filter { |line| $line != "HEAD" }
+ | uniq
+}
+
+def "git has branch" [name: string] {
+ $name in (git list branches)
+}
+
+
+def "git is-tracking" [] {
+ try {
+ git rev-parse --abbrev-ref --symbolic-full-name @{u} err> /dev/null
+ true
+ } catch {
+ false
+ }
+}
+
+def "git is-clean" [] {
+ git status --porcelain | is-empty
+}Improve the publish
On by
Fix the changelog containing too many items (a bug).
Add two chances to abort: before committing and before pushing.
Print a nice table with a summary.
Modularize the logic into many neat functions. Leverage that a function will not pollute environment, including $PWD. So now each function changes directory to where it needs to be.
index 61bc9e8..2d0e5be 100755
--- a/publish.nu
+++ b/publish.nu
@@ -1,97 +1,155 @@
-use std/dirs
-
-def main [] {
- # Get the current source branch
- # Switch pages to the same branch. Create it if needed.
- # Find the time of last commit to pages.
- # Make a list of commits in source since then.
- # Format it as markdown list (only titles and hashes)
- # Prepare a commit, showing a diff for users review
- # Push to publish
-
- if (not (git is-clean)) {
- print "The source repository is not clean. First commit, then publish."
- git status
- exit 2
+# Build and publish the website
+def main [
+ --source: path = "." # path to the source repository
+ --pages: path = "./pages.git" # path to the Codeberg Pages repository
+] {
+ # A record of information about source and pages repositories gathered as we go.
+ mut spec = {
+ source_path: ($source | path expand)
+ pages_path: ($pages | path expand)
= }
=
- let source_branch = (git symbolic-ref --short HEAD)
- print $"Source branch is ($source_branch)"
+ if (not (git is-clean $spec.source_path)) {
+ error make --unspanned {
+ msg: $"The source repository is not clean.",
+ help: $"First commit, then publish. Here are the changes:\n\n (git status --porcelain)"
+ }
+ }
+
+ $spec.branch = git current-branch $spec.source_path
=
- dirs add pages.git
+ git clean-repo $spec.pages_path
+ git switch-or-create $spec.pages_path $spec.branch
=
- print "Cleaning pages worktree..."
+ $spec.last_deployment_time = git last_commit_time $spec.pages_path
+
+ $spec.changelog = git changelog $spec.source_path $spec.last_deployment_time
+
+ let now = date now | date to-timezone utc | format date "%A, %F %T (utc)"
+
+ # TODO: Find a way to work with indentation.
+ # See https://github.com/nushell/nushell/issues/11477
+ let commit_template = $"
+Deployment ($now)
+
+Changes since ($spec.last_deployment_time | date to-timezone utc | format date '%A, %F %T (utc)'):
+
+($spec.changelog | format changelog)
+ "
+
+ zola build
+
+ print "About to commit and publish. Here is the summary: "
+ $spec | table --expand | print
+ input --numchar 1 "Press any key to continue, or ctrl-c to abort."
+
+ $commit_template | git publish $spec.pages_path $spec.branch
+}
+
+# Takes commit message as input
+def "git publish" [repo: path, branch: string]: string -> nothing {
+ cd $repo
+ let commit_template_file = mktemp --tmpdir
+ $in | save --append $commit_template_file
+ git add .
+ # TODO: Provide a mechanism to abort (use --template ?)
+ git commit --verbose --file $commit_template_file --edit
+
+ input --numchar 1 "Commit ready. Press any key to publish, or ctrl-c to abort."
+ git push --set-upstream origin $branch
+}
+
+def "git is-clean" [repo: path]: nothing -> bool {
+ cd $repo
+ git status --porcelain | is-empty
+}
+
+def "git current-branch" [repo: path]: nothing -> string {
+ cd $repo
+ git symbolic-ref --short HEAD
+}
+
+def "git clean-repo" [repo: path] {
+ cd $repo
+ print $"Cleaning ($repo) worktree..."
= git restore .
= git clean -fd
+}
=
- if (git has branch $source_branch) {
- print "The branch exists in pages repository. Switching."
- git switch --quiet $source_branch
+def "git switch-or-create" [repo: path, branch: string] {
+ cd $repo
+ if (git has branch $repo $branch) {
+ print $"The branch ($branch) already exists in ($repo). Switching..."
+ git switch --quiet $branch
=
= if (git is-tracking) {
- print "The branch was already deployed. Pulling."
+ print $"The branch ($branch) was already deployed. Pulling..."
= git pull --quiet
= }
= } else {
- print "The branch does not exist in pages repository."
+ print $"The branch ($branch) does not yet exist in ($repo)."
= loop {
- match (input --numchar 1 $"Create and deploy a new branch '($source_branch)'? [y|n]: ") {
+ match (input --numchar 1 $"Create a new branch '($branch)'? [y|n]: ") {
= "y" => break,
= "n" => { exit 1 },
= _ => continue,
= }
= }
- git switch main
- git switch --quiet --create $source_branch
+ git switch --quiet main
+ git switch --quiet --create $branch
= }
=
- let last_commit_time = git show --no-patch --format=%cI
- print $"Pages last published on ($last_commit_time)"
-
- let commit_template = mktemp --tmpdir
- let now = date now | date to-timezone utc | format date "%A, %F %T (utc)"
-
- echo $"Update ($now)"
- | save --append $commit_template
- echo "\n\n"
- | save --append $commit_template
- echo $"Changes since ($last_commit_time | date to-timezone utc | format date '%A, %F %T (utc)')\n\n"
- | save --append $commit_template
- dirs prev
-
- git log --pretty=reference --since=$last_commit_time
- | save --append $commit_template
-
- zola build
+}
=
- dirs next
- git add .
- git commit --verbose --file $commit_template --edit
- git push --set-upstream origin $source_branch
+def "git last_commit_time" [repo: path]: nothing -> datetime {
+ cd $repo
+ git show --no-patch --format=%cI | into datetime
=}
=
=# List all branches that can be switched to
-def "git list branches" [] {
+def "git list branches" [repo: path] {
+ cd $repo
= git branch --list --all --format='%(refname:lstrip=-1)'
= | lines
= | filter { |line| $line != "HEAD" }
= | uniq
=}
=
-def "git has branch" [name: string] {
- $name in (git list branches)
+def "git has branch" [repo: path, branch: string] {
+ cd $repo
+ $branch in (git list branches $repo)
=}
=
-
+# Check if the current branch is tracking a remote.
=def "git is-tracking" [] {
= try {
- git rev-parse --abbrev-ref --symbolic-full-name @{u} err> /dev/null
+ git rev-parse --abbrev-ref --symbolic-full-name @{u} err>| ignore
= true
= } catch {
= false
= }
=}
=
-def "git is-clean" [] {
- git status --porcelain | is-empty
+
+
+def "git changelog" [repo: path, since: datetime]: nothing -> table {
+ cd $repo
+ git log --pretty=reference --date=iso-strict
+ | parse "{hash} ({title}, {date})"
+ | update date { |row| $row.date | into datetime }
+ | where date > $since
+}
+
+def "format changelog" []: table -> string {
+ $in
+ | group-by { |row| $row.date | format date "%A, %F" }
+ | transpose date commits
+ | each { |day| $"($day.date):\n\n($day.commits | format changelog day)\n\n" }
+ | str join "\n\n"
+}
+
+def "format changelog day" []: table -> string {
+ $in
+ | format pattern " * {hash} {title}"
+ | str join "\n"
=}Move people pages to a new People section
On by
The home page now focuses on our services and commitments.
index acdeccb..b8c0bff 100644
--- a/content/_index.md
+++ b/content/_index.md
@@ -3,3 +3,8 @@
=
=We are an international network of IT professionals and entrepreneurs dedicated to promote and support free software and use of services respecting human rights, dignity and privacy.
=
+At the heart of our services lies a commitment to Free and Open Source Software (FOSS) and EU cloud solutions, ensuring privacy and adherence to open standards.
+
+Based entirely in Europe, [our team](@/people/_index.md) is on-shore, allowing us to provide localized, high-quality services. We offer assistance in multiple languages, including English, Dutch, French, Polish, Galician, Spanish, Portuguese, German, and Hungarian.
+
+Our primary focus is on helping European Small and Medium-sized Enterprises (SMEs), Non-Governmental Organizations (NGOs), local governments, and educational institutions with implementing free, open-source and European software solutions.new file mode 100644
index 0000000..00b8130
--- /dev/null
+++ b/content/people/_index.md
@@ -0,0 +1,7 @@
+---
+title: People
+template: people.html
+---
+
+We are an international network of IT professionals and entrepreneurs dedicated to promote and support free software and use of services respecting human rights, dignity and privacy.
+similarity index 100%
rename from content/joachim-nuyttens.md
rename to content/people/joachim-nuyttens.mdsimilarity index 100%
rename from "content/jo\303\243o-campos.md"
rename to "content/people/jo\303\243o-campos.md"similarity index 100%
rename from content/richard-cronan.md
rename to content/people/richard-cronan.mdsimilarity index 100%
rename from content/tad-lazurski.md
rename to content/people/tad-lazurski.mdsimilarity index 100%
rename from content/tibor-eszes.md
rename to content/people/tibor-eszes.mdsimilarity index 100%
rename from "content/v\303\255tor-andrade.md"
rename to "content/people/v\303\255tor-andrade.md"index 8888a53..12a7973 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -77,12 +77,17 @@
=
= body > header {
= font-size: var(--prompt-font-size);
- align-items: center;
- display: flex;
- gap: 1ch;
= color: var(--dark-color);
= padding: 3rem 1rem;
= overflow: hidden;
+
+ &> a {
+ align-items: center;
+ display: flex;
+ gap: 1ch;
+ text-decoration: none;
+ color: inherit;
+ }
= }
=
= body > main {
@@ -124,6 +129,7 @@
=
= #logo {
= height: 3em;
+ width: 3em;
= }
=
= p {
@@ -284,17 +290,20 @@
= <![endif]-->
=
= <header>
- <img
- id="logo"
- src="esc-logo.svg"
- alt="The ESC logo with a sky-blue ring and a bright yellow ray passing through it."
- />
-
- <hgroup class="title">
- <h1>esc collective</h1>
- <p>supporting european digital independence</p>
- </hgroup>
+ <a href="{{ get_url(path='@/_index.md') }}">
+ <img
+ id="logo"
+ src="{{ get_url(path='/esc-logo.svg') }}"
+ alt="The ESC logo with a sky-blue ring and a bright yellow ray passing through it."
+ />
+
+ <hgroup class="title">
+ <h1>esc collective</h1>
+ <p>supporting european digital independence</p>
+ </hgroup>
+ </a>
= </header>
+
= <main>
= {% filter indent(prefix=" ") -%}
= {%- block main_content -%}
@@ -303,7 +312,12 @@
= </main>
=
= <footer class="full-bleed-background">
- <img src="favicon.svg" alt="ESC Icon" class="icon" />
+ <img
+ src="{{ get_url(path='/favicon.svg') }}"
+ alt="ESC Icon"
+ class="icon"
+ />
+
=
= <ul class="prompt">
= <!-- Remember to adjust the --prompts-count variable -->index 4645233..4a9795b 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -2,17 +2,4 @@
=
={%- block main_content -%}
={{- section.content | safe -}}
-
-<section class="card-grid">
- {# Each page in this category represents a person.
-
- It's a bit clunky. We will improve it later.
- #}
- {%- for page in section.pages | sort(attribute="date") -%}
- <article>
- <h2>{{ page.title }}</h2>
- {{ page.content | safe }}
- </article>
- {%- endfor -%}
-</section>
={%- endblock main_content -%}new file mode 100644
index 0000000..223d7ed
--- /dev/null
+++ b/templates/page.html
@@ -0,0 +1,5 @@
+{% extends "base.html" %}
+
+{%- block main_content -%}
+{{- page.content | safe -}}
+{%- endblock main_content -%}new file mode 100644
index 0000000..4645233
--- /dev/null
+++ b/templates/people.html
@@ -0,0 +1,18 @@
+{% extends "base.html" %}
+
+{%- block main_content -%}
+{{- section.content | safe -}}
+
+<section class="card-grid">
+ {# Each page in this category represents a person.
+
+ It's a bit clunky. We will improve it later.
+ #}
+ {%- for page in section.pages | sort(attribute="date") -%}
+ <article>
+ <h2>{{ page.title }}</h2>
+ {{ page.content | safe }}
+ </article>
+ {%- endfor -%}
+</section>
+{%- endblock main_content -%}Copy services description from Joachim to home page
On by
Joachim wrote a draft of our services' description here:
https://club.tad-lispy.com/t/esc-services-definition-website/189/3?u=tad-lispy
I besically copied it verbatim. As he said himself, we need to work on this content more, but IMO it's a great start.
For now everything is on the home page, which now looks like a wall of text. We will need to separate some of it to sub-pages. Maybe also create some taxonomies for languages and skills, so people can be found this way.
index b8c0bff..435d9d3 100644
--- a/content/_index.md
+++ b/content/_index.md
@@ -7,4 +7,63 @@ At the heart of our services lies a commitment to Free and Open Source Software
=
=Based entirely in Europe, [our team](@/people/_index.md) is on-shore, allowing us to provide localized, high-quality services. We offer assistance in multiple languages, including English, Dutch, French, Polish, Galician, Spanish, Portuguese, German, and Hungarian.
=
+
+# Our Services
+
=Our primary focus is on helping European Small and Medium-sized Enterprises (SMEs), Non-Governmental Organizations (NGOs), local governments, and educational institutions with implementing free, open-source and European software solutions.
+
+
+## Cloud assistance
+
+Your organisation probably depends on multiple cloud services. Setting up, managing and migrating cloud services can be complicated. Or maybe your company is or wants to self-host some applications? Our team is happy to assist you on projects or provide operational support for your cloud and self-hosted services.
+
+Our technical capabilities include:
+
+ * Cloud infrastructure: Kubernetes, Docker, OpenShift, and pretty much any Cloud provider
+ * Infrastructure automation: Terraform, Ansible, GitOps with ArgoCD, GitHub Actions, Jenkins
+ * Service architecture: service mesh, service discovery, containerization, server-less
+ * System reliability: monitoring (Prometheus, Grafana, Nagios), observability, high availability
+ * Linux, Unix wizardry
+ * Scripting
+
+Reach out to us for any project or operational support in
+
+ * Setting up cloud or self-hosted services, applications
+ * Migrating your cloud or self-hosted services
+ * Administering your cloud or self-hosted services
+ * Trusted Admin Failover as a Service (TAFaaS), if you would like to have a backup plan when your trusted admin is absent unexpectedly
+
+
+## Software Development
+
+Need any customization or extension of FOSS functionalities? Need hard coding skills to set up a (web)application? Want to automate some tasks? Our team has a broad technical skillset, including (but not limited to):
+
+ * HTML, CSS, JavaScript
+ * Python
+ * Rust
+ * Elm
+ * Haskell
+ * Groovy
+ * SQL
+ * Bash
+ * Go
+
+
+## Consulting
+
+We can assist with small and big projects, provide momentary advice or define long term strategies for your organisation. Some examples:
+
+ * Project management
+ * Define migration strategies from concept to technical detail, for example moving to a new collaborative software platform (email, calendar, file sharing, etc.)
+ * Define technical solutions to meet your data security and data privacy requirements
+
+
+## Training and coaching
+
+We can provide training and coaching on different topics. The following list is not exhaustive, don't hesitate to reach out for other needs in the FOSS domain:
+
+ * Web Development
+ * Agile development, Test driven development, Pair prohramming
+ * Relational Databases (RDBMS)
+ * Version management using Git
+ * Operating Systems (Linux, Nix / NixOS)Let a developer publish from unclean source repo
On by
It's helpful when developing or debugging the publish.nu script.
index 2d0e5be..039730a 100755
--- a/publish.nu
+++ b/publish.nu
@@ -2,6 +2,7 @@
=def main [
= --source: path = "." # path to the source repository
= --pages: path = "./pages.git" # path to the Codeberg Pages repository
+ --allow-unclean # do not stutter on unclean repo. Useful when hacking on this script.
=] {
= # A record of information about source and pages repositories gathered as we go.
= mut spec = {
@@ -9,7 +10,7 @@ def main [
= pages_path: ($pages | path expand)
= }
=
- if (not (git is-clean $spec.source_path)) {
+ if (not ((git is-clean $spec.source_path) or $allow_unclean)) {
= error make --unspanned {
= msg: $"The source repository is not clean.",
= help: $"First commit, then publish. Here are the changes:\n\n (git status --porcelain)"Fix publish script failing when public/ is removed
On by
After running zola serve the public directory is removed. This is to
prevent stale files from lingering there. From git perspective, it leads
to non-existing worktree. The solution is to just re-create this
directory.
index 039730a..1fcf2c2 100755
--- a/publish.nu
+++ b/publish.nu
@@ -19,6 +19,9 @@ def main [
=
= $spec.branch = git current-branch $spec.source_path
=
+ # Make sure the worktree exists. Zola has a strange habit of deleting public/
+ git ensure worktree $spec.pages_path
+
= git clean-repo $spec.pages_path
= git switch-or-create $spec.pages_path $spec.branch
=
@@ -70,6 +73,12 @@ def "git current-branch" [repo: path]: nothing -> string {
= git symbolic-ref --short HEAD
=}
=
+def "git ensure worktree" [repo: path] {
+ cd $repo
+ let worktree_path = git config --get core.worktree
+ mkdir $worktree_path
+}
+
=def "git clean-repo" [repo: path] {
= cd $repo
= print $"Cleaning ($repo) worktree..."Fix publish script wrongly detecting remote tracking
On by
The idiomatic Nushell way to suppress error message is to pipe to
ignore command. But it has a side effect of supressing the error
itself. So in a try - catch block, it swallows the error I want to
detect.
For now I opted to classic Unix way of redirecting to /dev/null. It will probably make the script not compatible with Windows. Oh noes!
index 1fcf2c2..ce53715 100755
--- a/publish.nu
+++ b/publish.nu
@@ -133,7 +133,7 @@ def "git has branch" [repo: path, branch: string] {
=# Check if the current branch is tracking a remote.
=def "git is-tracking" [] {
= try {
- git rev-parse --abbrev-ref --symbolic-full-name @{u} err>| ignore
+ git rev-parse --abbrev-ref --symbolic-full-name @{u} err> /dev/null
= true
= } catch {
= falseImplement a dry-run mode for publish.nu
On by
It will show the commit message and diff, but won't actually commit.
index ce53715..e661123 100755
--- a/publish.nu
+++ b/publish.nu
@@ -3,6 +3,7 @@ def main [
= --source: path = "." # path to the source repository
= --pages: path = "./pages.git" # path to the Codeberg Pages repository
= --allow-unclean # do not stutter on unclean repo. Useful when hacking on this script.
+ --dry-run # do everything else, but don't commit or push
=] {
= # A record of information about source and pages repositories gathered as we go.
= mut spec = {
@@ -47,7 +48,17 @@ Changes since ($spec.last_deployment_time | date to-timezone utc | format date '
= $spec | table --expand | print
= input --numchar 1 "Press any key to continue, or ctrl-c to abort."
=
- $commit_template | git publish $spec.pages_path $spec.branch
+ if ($dry_run) {
+ print "---"
+ print $commit_template
+ print "---"
+ print "☝ this would be the commit message. You would have a chance to edit it."
+ input --numchar 1 "I will show you a diff now. Press any key when ready."
+ cd $spec.pages_path
+ git diff
+ } else {
+ $commit_template | git publish $spec.pages_path $spec.branch
+ }
=}
=
=# Takes commit message as inputHandle /@branch-preview/ prefix in links
On by
The build script will pass the prefix as base_url to zola. All linked assets and hyperlinks should now use this prefix.
index e661123..cc7ecf9 100755
--- a/publish.nu
+++ b/publish.nu
@@ -42,7 +42,11 @@ Changes since ($spec.last_deployment_time | date to-timezone utc | format date '
=($spec.changelog | format changelog)
= "
=
- zola build
+ let base_url = match $spec.branch {
+ "main" => "/",
+ _ => $"/@($spec.branch)/"
+ }
+ zola build --base-url $base_url
=
= print "About to commit and publish. Here is the summary: "
= $spec | table --expand | printindex 12a7973..fa7c605 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -32,12 +32,12 @@
= <meta name="description" content="{{ description }}" />
= <meta name="viewport" content="width=device-width, initial-scale=1" />
=
- <link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" />
- <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
- <link rel="shortcut icon" href="/favicon.ico" />
- <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
+ <link rel="icon" type="image/png" href="{{ get_url(path='/favicon-96x96.png') }}" sizes="96x96" />
+ <link rel="icon" type="image/svg+xml" href="{{ get_url(path='/favicon.svg') }}" />
+ <link rel="shortcut icon" href="{{ get_url(path='/favicon.ico') }}" />
+ <link rel="apple-touch-icon" sizes="180x180" href="{{ get_url(path='/apple-touch-icon.png') }}" />
= <meta name="apple-mobile-web-app-title" content="{{ config.title }}" />
- <link rel="manifest" href="/site.webmanifest" />
+ <link rel="manifest" href="{{ get_url(path='/site.webmanifest') }}" />
=
= <meta property="og:title" content="{{ title }}">
= <meta property="og:type" content="website" />Separate services to own section, with emojis 😎
On by
index 435d9d3..a834d7f 100644
--- a/content/_index.md
+++ b/content/_index.md
@@ -10,60 +10,14 @@ Based entirely in Europe, [our team](@/people/_index.md) is on-shore, allowing u
=
=# Our Services
=
-Our primary focus is on helping European Small and Medium-sized Enterprises (SMEs), Non-Governmental Organizations (NGOs), local governments, and educational institutions with implementing free, open-source and European software solutions.
+Our primary focus is on helping European Small and Medium-sized Enterprises (SMEs), Non-Governmental Organizations (NGOs), local governments, and educational institutions with implementing free, open-source and European software solutions. We provide
=
+🌤️ Cloud assistance
=
-## Cloud assistance
+💻 Software Development
=
-Your organisation probably depends on multiple cloud services. Setting up, managing and migrating cloud services can be complicated. Or maybe your company is or wants to self-host some applications? Our team is happy to assist you on projects or provide operational support for your cloud and self-hosted services.
+💬 Consulting
=
-Our technical capabilities include:
+📖 Training and coaching
=
- * Cloud infrastructure: Kubernetes, Docker, OpenShift, and pretty much any Cloud provider
- * Infrastructure automation: Terraform, Ansible, GitOps with ArgoCD, GitHub Actions, Jenkins
- * Service architecture: service mesh, service discovery, containerization, server-less
- * System reliability: monitoring (Prometheus, Grafana, Nagios), observability, high availability
- * Linux, Unix wizardry
- * Scripting
-
-Reach out to us for any project or operational support in
-
- * Setting up cloud or self-hosted services, applications
- * Migrating your cloud or self-hosted services
- * Administering your cloud or self-hosted services
- * Trusted Admin Failover as a Service (TAFaaS), if you would like to have a backup plan when your trusted admin is absent unexpectedly
-
-
-## Software Development
-
-Need any customization or extension of FOSS functionalities? Need hard coding skills to set up a (web)application? Want to automate some tasks? Our team has a broad technical skillset, including (but not limited to):
-
- * HTML, CSS, JavaScript
- * Python
- * Rust
- * Elm
- * Haskell
- * Groovy
- * SQL
- * Bash
- * Go
-
-
-## Consulting
-
-We can assist with small and big projects, provide momentary advice or define long term strategies for your organisation. Some examples:
-
- * Project management
- * Define migration strategies from concept to technical detail, for example moving to a new collaborative software platform (email, calendar, file sharing, etc.)
- * Define technical solutions to meet your data security and data privacy requirements
-
-
-## Training and coaching
-
-We can provide training and coaching on different topics. The following list is not exhaustive, don't hesitate to reach out for other needs in the FOSS domain:
-
- * Web Development
- * Agile development, Test driven development, Pair prohramming
- * Relational Databases (RDBMS)
- * Version management using Git
- * Operating Systems (Linux, Nix / NixOS)
+[Read more about our services](@/services/_index.md)new file mode 100644
index 0000000..190f667
--- /dev/null
+++ b/content/services/_index.md
@@ -0,0 +1,63 @@
+---
+title: Services
+---
+
+# Our Services
+
+Our primary focus is on helping European Small and Medium-sized Enterprises (SMEs), Non-Governmental Organizations (NGOs), local governments, and educational institutions with implementing free, open-source and European software solutions.
+
+
+## 🌤 ️Cloud assistance
+
+Your organisation probably depends on multiple cloud services. Setting up, managing and migrating cloud services can be complicated. Or maybe your company is or wants to self-host some applications? Our team is happy to assist you on projects or provide operational support for your cloud and self-hosted services.
+
+Our technical capabilities include:
+
+ * Cloud infrastructure: Kubernetes, Docker, OpenShift, and pretty much any Cloud provider
+ * Infrastructure automation: Terraform, Ansible, GitOps with ArgoCD, GitHub Actions, Jenkins
+ * Service architecture: service mesh, service discovery, containerization, server-less
+ * System reliability: monitoring (Prometheus, Grafana, Nagios), observability, high availability
+ * Linux, Unix wizardry
+ * Scripting
+
+Reach out to us for any project or operational support in
+
+ * Setting up cloud or self-hosted services, applications
+ * Migrating your cloud or self-hosted services
+ * Administering your cloud or self-hosted services
+ * Trusted Admin Failover as a Service (TAFaaS), if you would like to have a backup plan when your trusted admin is absent unexpectedly
+
+
+## 💻 Software Development
+
+Need any customization or extension of FOSS functionalities? Need hard coding skills to set up a (web)application? Want to automate some tasks? Our team has a broad technical skillset, including (but not limited to):
+
+ * HTML, CSS, JavaScript
+ * Python
+ * Rust
+ * Elm
+ * Haskell
+ * Groovy
+ * SQL
+ * Bash
+ * Go
+
+
+## 💬 Consulting
+
+We can assist with small and big projects, provide momentary advice or define long term strategies for your organisation. Some examples:
+
+ * Project management
+ * Define migration strategies from concept to technical detail, for example moving to a new collaborative software platform (email, calendar, file sharing, etc.)
+ * Define technical solutions to meet your data security and data privacy requirements
+
+
+## 📖 Training and coaching
+
+We can provide training and coaching on different topics. The following list is not exhaustive, don't hesitate to reach out for other needs in the FOSS domain:
+
+ * Web Development
+ * Agile development, Test driven development, Pair prohramming
+ * Relational Databases (RDBMS)
+ * Version management using Git
+ * Operating Systems (Linux, Nix / NixOS)new file mode 100644
index 0000000..61d3aed
--- /dev/null
+++ b/templates/section.html
@@ -0,0 +1,7 @@
+{# A generic section template #}
+
+{% extends "base.html" %}
+
+{%- block main_content -%}
+{{- section.content | safe -}}
+{%- endblock main_content -%}Fix publish script to handle comma in a commit message
On by
index cc7ecf9..a2da6c8 100755
--- a/publish.nu
+++ b/publish.nu
@@ -159,8 +159,8 @@ def "git is-tracking" [] {
=
=def "git changelog" [repo: path, since: datetime]: nothing -> table {
= cd $repo
- git log --pretty=reference --date=iso-strict
- | parse "{hash} ({title}, {date})"
+ git log --pretty="format:%h\t%s\t%cd" --date=iso-strict
+ | parse "{hash}\t{title}\t{date}"
= | update date { |row| $row.date | into datetime }
= | where date > $since
=}Increase vertical space above the footer
On by
It was unpleasantly narrow.
index fa7c605..3e9f69c 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -96,6 +96,7 @@
= }
=
= body > footer {
+ margin-top: 3rem;
= display: flex;
= background: var(--dark-color);
= align-items: center;
@@ -129,7 +130,6 @@
=
= #logo {
= height: 3em;
- width: 3em;
= }
=
= p {
@@ -177,7 +177,9 @@
= /* UTILITY CLASSES */
=
= .full-bleed-background {
- margin: 0 calc(-1 * var(--full-bleed-margin));
+ --negative-margin: calc(-1 * var(--full-bleed-margin));
+ margin-left: var(--negative-margin);
+ margin-right: var(--negative-margin);
= padding: 3rem calc(1rem + var(--full-bleed-margin));
= }
=Move the tera context element to the top
On by
Below the footer it was creating an uncanny bright stripe.
index 3e9f69c..2115811 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -291,6 +291,13 @@
= </p>
= <![endif]-->
=
+ {%- if config.mode == "serve" %}
+ <details style="overflow: scroll">
+ <summary>Rendering context</summary>
+ <pre>{{ __tera_context | escape | safe }}</pre>
+ </details>
+ {% endif -%}
+
= <header>
= <a href="{{ get_url(path='@/_index.md') }}">
= <img
@@ -347,13 +354,5 @@
= </ul>
= </footer>
=
- {% if config.mode == "serve" %}
- <details style="overflow: scroll">
- <summary>Rendering context</summary>
- <pre>
-{{ __tera_context | escape | safe }}
- </pre>
- </details>
- {% endif %}
= </body>
=</html>Remove obsolete --prompt-font-size variable
On by
It was used in a very confusing way to set the height of main logo. Must have been a relic of some early experiments with the funny prompt.
Now the logo is simply sized in rem units. Visually there should be no change.
index 2115811..27db92b 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -54,7 +54,6 @@
= --prompts-count: 19;
= --max-prompt-length: 63;
= --prompt-height: 1.5em;
- --prompt-font-size: 2rem;
= --container-width: 960px;
= --dark-color: hsl(0, 0%, 10%);
= --light-color: hsl(0, 0%, 90%);
@@ -76,7 +75,6 @@
= }
=
= body > header {
- font-size: var(--prompt-font-size);
= color: var(--dark-color);
= padding: 3rem 1rem;
= overflow: hidden;
@@ -129,7 +127,7 @@
= }
=
= #logo {
- height: 3em;
+ height: 6rem;
= }
=
= p {
@@ -268,7 +266,7 @@
=
= @media (max-width: 36rem) {
= #logo {
- height: 2em;
+ height: 4rem;
= }
=
= .title > h1 {Create an extremely simple main nav element
On by
index 27db92b..5d017ce 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -101,6 +101,13 @@
= color: var(--light-color);
= }
=
+ nav > ul {
+ display: flex;
+ justify-content: end;
+ flex-wrap: wrap;
+ gap: 2rem;
+ }
+
= hgroup h1 {
= margin: 0;
= font-weight: 400;
@@ -297,6 +304,13 @@
= {% endif -%}
=
= <header>
+ <nav>
+ <ul>
+ <li><a href="{{get_url(path='@/_index.md')}}">Home</a></li>
+ <li><a href="{{get_url(path='@/people/_index.md')}}">People</a></li>
+ <li><a href="{{get_url(path='@/services/_index.md')}}">Services</a></li>
+ </ul>
+ </nav>
= <a href="{{ get_url(path='@/_index.md') }}">
= <img
= id="logo"Make bullets in main nav look like LEDs
On by
To add a bit of playfulness. Also make the labels stronger.
Under the hood, navigation element is now controlled by site configuration (extra section in config.toml file).
index badacc2..1de2490 100644
--- a/config.toml
+++ b/config.toml
@@ -20,3 +20,15 @@ highlight_code = true
=
=[extra]
=# Put all your custom variables here
+[[extra.navigation]]
+label = "Home"
+class = "green-accent"
+path = "_index.md"
+[[extra.navigation]]
+label = "People"
+class = "red-accent"
+path = "people/_index.md"
+[[extra.navigation]]
+label = "Services"
+class = "blue-accent"
+path = "services/_index.md"index 5d017ce..15e8068 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -55,14 +55,22 @@
= --max-prompt-length: 63;
= --prompt-height: 1.5em;
= --container-width: 960px;
- --dark-color: hsl(0, 0%, 10%);
- --light-color: hsl(0, 0%, 90%);
= --full-bleed-margin: max(
= 0px,
= calc(0.5 * (100vw - var(--container-width)))
= );
+
+
+ /* Colors */
+ --dark-color: hsl(0, 0%, 10%);
+ --light-color: hsl(0, 0%, 90%);
+
+ --red: oklch(36% 80% 29deg);
+ --green: oklch(from var(--red) L C 142deg);
+ --blue: oklch(from var(--red) L C 264deg);
= }
=
+
= body {
= font-family: sans-serif;
= padding: 0;
@@ -101,11 +109,52 @@
= color: var(--light-color);
= }
=
+
+ /* playful colors */
+ .red-accent {
+ --accent-color: var(--red)
+ }
+ .green-accent {
+ --accent-color: var(--green)
+ }
+ .blue-accent {
+ --accent-color: var(--blue)
+ }
+
= nav > ul {
= display: flex;
= justify-content: end;
= flex-wrap: wrap;
= gap: 2rem;
+ list-style: none;
+
+ li {
+ --inactive-color: oklch(from var(--accent-color) L 30% H);
+ --active-color: oklch(from var(--accent-color) 63% C H);
+
+ &::before {
+ content: "•";
+
+ color: var(--inactive-color);
+ transition: color 1s, text-shadow 1s;
+ }
+
+ &.active::before {
+ color: var(--active-color);
+ text-shadow: 0 0 4px var(--active-color), 0 0 4px var(--active-color);
+ }
+
+ &:hover::before {
+ color: var(--active-color);
+ text-shadow: 0 0 4px var(--active-color), 0 0 4px var(--active-color);
+ }
+
+ a {
+ font-weight: bold;
+ color: var(--dark-color);
+ }
+ }
+
= }
=
= hgroup h1 {
@@ -303,12 +352,28 @@
= </details>
= {% endif -%}
=
+
= <header>
= <nav>
= <ul>
- <li><a href="{{get_url(path='@/_index.md')}}">Home</a></li>
- <li><a href="{{get_url(path='@/people/_index.md')}}">People</a></li>
- <li><a href="{{get_url(path='@/services/_index.md')}}">Services</a></li>
+ {# Code below assumes that every item points to a section.
+
+ If that's no longer the case, the code needs to get smarter.
+ Probably something to do with pattern matching on item.path.
+
+ 1. If it ends with _index.md it's a section,
+ 2. else if it it ends with .md it's a page,
+ 3. else if it starts with / it's a local asset (an image, pdf, etc.),
+ 4. else it's an external URL.
+ #}
+ {%- for item in config.extra.navigation %}
+ {%- set item_section = get_section(path=item.path) -%}
+ {%- set is_active = item_section.path == current_path %}
+ <li class="{{ item.class }} {% if is_active %}active{% endif %}">
+ <a href="{{ item_section.path }}">{{ item.label }}</a>
+ </li>
+ {% endfor -%}
+
= </ul>
= </nav>
= <a href="{{ get_url(path='@/_index.md') }}">Make the people accent yellow
On by
Red might look like something is wrong.
I used a yellow color from our logo. Other accents are based on this color too, just with heu rotated in OKLCH space.
index 1de2490..fe8fec3 100644
--- a/config.toml
+++ b/config.toml
@@ -26,7 +26,7 @@ class = "green-accent"
=path = "_index.md"
=[[extra.navigation]]
=label = "People"
-class = "red-accent"
+class = "yellow-accent"
=path = "people/_index.md"
=[[extra.navigation]]
=label = "Services"index 15e8068..1901c72 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -65,9 +65,10 @@
= --dark-color: hsl(0, 0%, 10%);
= --light-color: hsl(0, 0%, 90%);
=
- --red: oklch(36% 80% 29deg);
- --green: oklch(from var(--red) L C 142deg);
- --blue: oklch(from var(--red) L C 264deg);
+ --yellow: oklch(0.8498 0.173865 86.5517); /* same as our logo */
+ --red: oklch(from var(--yellow) L C 29deg);
+ --green: oklch(from var(--yellow) L C 142deg);
+ --blue: oklch(from var(--yellow) L C 264deg);
= }
=
=
@@ -111,6 +112,9 @@
=
=
= /* playful colors */
+ .yellow-accent {
+ --accent-color: var(--yellow)
+ }
= .red-accent {
= --accent-color: var(--red)
= }
@@ -129,8 +133,8 @@
= list-style: none;
=
= li {
- --inactive-color: oklch(from var(--accent-color) L 30% H);
- --active-color: oklch(from var(--accent-color) 63% C H);
+ --inactive-color: oklch(from var(--accent-color) 60% C H);
+ --active-color: oklch(from var(--accent-color) 83% C H);
=
= &::before {
= content: "•";Add more space between nav bullets and labels
On by
They were too close and it looked off.
index 1901c72..6987649 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -140,6 +140,7 @@
= content: "•";
=
= color: var(--inactive-color);
+ margin-right: 0.5ch;
= transition: color 1s, text-shadow 1s;
= }
=