From 9452190d0c885e17c8a5dd1a9ff85794350391e9 Mon Sep 17 00:00:00 2001 From: myrmidex Date: Sun, 10 May 2026 16:54:34 +0200 Subject: [PATCH] Redesign: red-digital theme, custom layout, drop linkita, docker dev setup --- config.toml | 21 --- content/_index.md | 18 +-- content/announcements/_index.md | 7 - docker/dev/docker-compose.yml | 11 ++ shell.nix | 28 +++- static/style.css | 277 ++++++++++++++++++++++++++++++++ templates/index.html | 101 ++++++++++++ 7 files changed, 414 insertions(+), 49 deletions(-) delete mode 100644 content/announcements/_index.md create mode 100644 docker/dev/docker-compose.yml create mode 100644 static/style.css create mode 100644 templates/index.html diff --git a/config.toml b/config.toml index 038e394..4d819dd 100644 --- a/config.toml +++ b/config.toml @@ -1,24 +1,3 @@ -# The URL the site will be built for base_url = "https://lvl0.xyz" title = "lvl0" -theme = "linkita" - -# Whether to automatically compile all Sass files in the sass directory -compile_sass = true - -# Whether to build a search index to be used later on by a JavaScript library build_search_index = false - -[markdown] -# Whether to do syntax highlighting -# Theme can be customised by setting the `highlight_theme` variable to a theme supported by Zola -highlight_code = false - -[extra] -# Put all your custom variables here -show_title_as_logo = true - -# Header menu -menu = [ - { name = "Announcements", url = "/announcements/" } -] diff --git a/content/_index.md b/content/_index.md index 237c306..1ba7b23 100644 --- a/content/_index.md +++ b/content/_index.md @@ -1,20 +1,4 @@ +++ title = "lvl0" -template = "home.html" +template = "index.html" +++ - -**lvl0 is a starting point.** - -We build tiny, focused tools that support calm productivity, self-hosting, and long-term thinking. - -Our projects embrace minimalism and the pursuit of autonomy — in tech and life. - -## Current Projects - -**fedi-feed-router** — A lightweight, self-hostable tool for routing and filtering fediverse feeds. Tame the firehose. - -**buckets** — Bucket-based budgeting. Income flows in, fills up, trickles down. - -## On the Horizon - -**convox** — A federated application platform. Early design. diff --git a/content/announcements/_index.md b/content/announcements/_index.md deleted file mode 100644 index d637f70..0000000 --- a/content/announcements/_index.md +++ /dev/null @@ -1,7 +0,0 @@ -+++ -title = "Announcements" -template = "announcements.html" -sort_by = "date" -+++ - -Stay updated with the latest news and releases from lvl0. \ No newline at end of file diff --git a/docker/dev/docker-compose.yml b/docker/dev/docker-compose.yml new file mode 100644 index 0000000..9de1d45 --- /dev/null +++ b/docker/dev/docker-compose.yml @@ -0,0 +1,11 @@ +services: + zola: + image: ghcr.io/getzola/zola:v0.21.0 + container_name: lvl0-website-dev-zola + command: serve --interface 0.0.0.0 --port 1111 --base-url http://localhost --drafts + volumes: + - ../..:/site:Z + ports: + - "1111:1111" + - "1024:1024" + working_dir: /site diff --git a/shell.nix b/shell.nix index 04bf438..97124f3 100644 --- a/shell.nix +++ b/shell.nix @@ -1,17 +1,37 @@ { pkgs ? import {} }: +let + repoRoot = builtins.toString ./.; + composeFile = "${repoRoot}/docker/dev/docker-compose.yml"; +in + pkgs.mkShell { buildInputs = with pkgs; [ zola + docker-compose git ]; shellHook = '' + COMPOSE_FILE="${composeFile}" + # =================== # DEV COMMANDS # =================== dev-up() { - zola serve --interface 0.0.0.0 --port 1111 "$@" + echo "Starting lvl0-website dev server..." + docker compose -f $COMPOSE_FILE up -d "$@" + echo "" + echo "Site available at: http://localhost:1111" + } + + dev-down() { + echo "Stopping lvl0-website dev server..." + docker compose -f $COMPOSE_FILE down + } + + dev-logs() { + docker compose -f $COMPOSE_FILE logs -f zola "$@" } dev-build() { @@ -26,10 +46,10 @@ pkgs.mkShell { echo " lvl0-website Dev Environment " echo "=================================================" echo "" - echo " Zola: $(zola --version)" - echo "" echo "Commands:" - echo " dev-up Start zola serve (live reload)" + echo " dev-up Start zola dev server (background)" + echo " dev-down Stop dev server" + echo " dev-logs Tail zola output" echo " dev-build Build static site to /public" echo "" echo "Site: http://localhost:1111" diff --git a/static/style.css b/static/style.css new file mode 100644 index 0000000..b29b7fe --- /dev/null +++ b/static/style.css @@ -0,0 +1,277 @@ +@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@900&display=swap'); + +/* ============================================================ + Design tokens + ============================================================ */ +:root { + --background: oklch(0.1 0 0); + --foreground: oklch(0.62 0.18 30); + --muted: oklch(0.5 0.1 25); + --subtle: oklch(0.85 0.05 25); + --border: oklch(0.62 0.18 30 / 0.3); + --card: oklch(0.12 0 0); + --terminal-glow: 0 0 20px oklch(0.62 0.18 30 / 0.4); + --terminal-glow-hover: 0 0 25px oklch(0.62 0.18 30 / 0.6); + + --font-mono: 'Courier New', Courier, monospace; + --font-display: 'Orbitron', monospace; + + --container-width: 1100px; + --section-padding: 5rem 1.5rem; +} + +/* ============================================================ + Reset + ============================================================ */ +*, *::before, *::after { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +/* ============================================================ + Base + ============================================================ */ +html { font-size: 16px; scroll-behavior: smooth; } + +body { + background-color: var(--background); + color: var(--foreground); + font-family: var(--font-mono); + line-height: 1.7; + min-height: 100vh; +} + +a { + color: var(--foreground); + text-decoration: underline; + text-underline-offset: 3px; +} +a:hover { opacity: 0.75; } + +h1, h2, h3 { line-height: 1.2; font-weight: bold; } + +/* ============================================================ + Layout + ============================================================ */ +.container { + max-width: var(--container-width); + margin: 0 auto; + padding: 0 1.5rem; +} + +.section { padding: var(--section-padding); } +.section--alt { background-color: var(--card); } + +/* ============================================================ + Header + ============================================================ */ +.site-header { + position: sticky; + top: 0; + z-index: 100; + background-color: var(--background); + border-bottom: 1px solid var(--border); + padding: 1rem 0; +} + +.site-header .container { + display: flex; + align-items: center; + justify-content: space-between; +} + +.site-logo { + font-family: var(--font-display); + font-size: 1.5rem; + line-height: 1; + letter-spacing: 0.05em; + text-decoration: none; + text-shadow: + 0 0 8px oklch(0.62 0.18 30 / 0.8), + 0 0 20px oklch(0.62 0.18 30 / 0.4); +} + +.site-header nav { display: flex; gap: 2rem; } + +.site-header nav a { + text-decoration: none; + font-size: 0.875rem; + text-transform: uppercase; + letter-spacing: 0.1em; +} + +/* ============================================================ + Hero + ============================================================ */ +.hero { + padding-block: 8rem; + text-align: center; + border-bottom: 1px solid var(--border); +} + +.hero__inner { + display: flex; + flex-direction: column; + align-items: center; + gap: 1.5rem; +} + +.hero__logo { + font-family: var(--font-display); + font-size: clamp(5rem, 15vw, 10rem); + line-height: 1; + letter-spacing: 0.05em; + text-shadow: + 0 0 10px oklch(0.62 0.18 30 / 0.9), + 0 0 30px oklch(0.62 0.18 30 / 0.6), + 0 0 60px oklch(0.62 0.18 30 / 0.35), + 0 0 100px oklch(0.62 0.18 30 / 0.15); +} + +.hero__tagline { + font-family: var(--font-display); + font-size: 1.25rem; + letter-spacing: 0.1em; + color: var(--subtle); +} + +.hero__sub { + font-size: 1rem; + color: var(--muted); + max-width: 48ch; +} + +/* ============================================================ + Section title + ============================================================ */ +.section-title { + font-size: 0.875rem; + text-transform: uppercase; + letter-spacing: 0.15em; + color: var(--muted); + margin-bottom: 2.5rem; +} + +/* ============================================================ + Projects + ============================================================ */ +.projects { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: 1.5rem; +} + +.project-card { + border: 1px solid var(--border); + padding: 1.75rem; + display: flex; + flex-direction: column; + gap: 0.75rem; + transition: box-shadow 200ms ease, border-color 200ms ease; +} + +.project-card:hover { + box-shadow: var(--terminal-glow); + border-color: oklch(0.62 0.18 30 / 0.6); +} + +.project-card--wip { + opacity: 0.6; +} + +.project-card__header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; +} + +.project-card__name { + font-family: var(--font-display); + font-size: 1.1rem; + letter-spacing: 0.05em; +} + +.project-card__desc { + color: var(--muted); + font-size: 0.9rem; + flex: 1; +} + +.project-card__link { + font-size: 0.8125rem; + text-transform: uppercase; + letter-spacing: 0.1em; + text-decoration: none; + opacity: 0.7; + transition: opacity 150ms ease; +} + +.project-card__link:hover { opacity: 1; } + +/* ============================================================ + Badges + ============================================================ */ +.badge { + font-size: 0.6875rem; + font-family: var(--font-mono); + letter-spacing: 0.1em; + padding: 0.2em 0.6em; + border: 1px solid currentColor; + white-space: nowrap; +} + +.badge--live { + color: oklch(0.62 0.18 30); + border-color: oklch(0.62 0.18 30 / 0.5); +} + +.badge--wip { + color: var(--muted); + border-color: var(--muted); +} + +/* ============================================================ + About + ============================================================ */ +.about__body { + display: flex; + flex-direction: column; + gap: 1.25rem; + max-width: 64ch; + color: var(--muted); + font-size: 0.9375rem; +} + +.about__body a { color: var(--foreground); } + +/* ============================================================ + Footer + ============================================================ */ +.site-footer { + border-top: 1px solid var(--border); + padding: 2rem 0; + font-size: 0.875rem; +} + +.footer__inner { + display: flex; + justify-content: space-between; + align-items: center; +} + +/* ============================================================ + Utilities + ============================================================ */ +.muted { color: var(--muted); } +.subtle { color: var(--subtle); } + +/* ============================================================ + Responsive + ============================================================ */ +@media (max-width: 640px) { + .site-header nav { gap: 1.25rem; } + .hero { padding-block: 5rem; } + .footer__inner { flex-direction: column; gap: 0.5rem; text-align: center; } +} diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..7d3fb11 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,101 @@ + + + + + + lvl0 + + + + + + + + + + + +
+
+ +

Tools without ceilings.

+

Open source, self-hosted software. No accounts, no platforms, no gatekeepers — your server, your data, your rules.

+
+
+ + +
+
+

// projects

+
+ +
+
+ incr + LIVE +
+

Track what you accumulate. Quantity milestones, unit tracking, no financial noise.

+ incr.lvl0.xyz → +
+ +
+
+ buckets + LIVE +
+

Bucket-based budgeting. Income flows in, fills up, trickles down.

+ forge → +
+ +
+
+ fedi-feed-router + LIVE +
+

Route and filter fediverse feeds. Tame the firehose.

+ forge → +
+ +
+
+ convox + WIP +
+

A federated application platform. Early design.

+
+ +
+
+
+ + +
+
+

// about

+
+

lvl0 is an independent studio building small, self-hostable software. We believe your tools should be yours — to run, to inspect, to modify.

+

We favour focus over features, longevity over growth, and ownership over convenience. Every project starts at level zero and earns its complexity.

+

All code is open source and lives on our Forge.

+
+
+
+ + + + + +