summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-08-01 23:56:19 -0500
committerChristian Cleberg <[email protected]>2026-08-01 23:56:19 -0500
commitc03e38b07ce439f9e6f4d23cb470193393e840e2 (patch)
tree356657ff9396912e1c8bfb36f8c0d4afe283b152
parent65f7a9607a60adbcb33ce4227f96980345006d5e (diff)
downloadkrz.sh-c03e38b07ce439f9e6f4d23cb470193393e840e2.tar.gz
krz.sh-c03e38b07ce439f9e6f4d23cb470193393e840e2.tar.bz2
krz.sh-c03e38b07ce439f9e6f4d23cb470193393e840e2.zip
initial commit
-rw-r--r--.github/workflows/deploy.yml39
-rw-r--r--.gitignore1
-rw-r--r--README.md33
-rw-r--r--config.toml17
-rw-r--r--content/_index.md22
-rw-r--r--content/apps/_index.md10
-rw-r--r--content/apps/daybyday.md13
-rw-r--r--content/apps/domain-dig.md14
-rw-r--r--content/apps/hutch.md14
-rw-r--r--content/apps/solar.md13
-rw-r--r--content/services/_index.md42
-rw-r--r--sass/main.scss170
-rw-r--r--static/CNAME1
-rw-r--r--static/favicon.svg4
-rw-r--r--templates/base.html30
-rw-r--r--templates/index.html14
-rw-r--r--templates/page.html16
-rw-r--r--templates/section.html29
18 files changed, 482 insertions, 0 deletions
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
new file mode 100644
index 0000000..50b0584
--- /dev/null
+++ b/.github/workflows/deploy.yml
@@ -0,0 +1,39 @@
+name: Deploy to GitHub Pages
+
+on:
+ push:
+ branches: [main]
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: pages
+ cancel-in-progress: true
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Build with Zola
+ uses: shalzz/zola-deploy-action@master
+ env:
+ BUILD_ONLY: true
+ BUILD_DIR: .
+ - uses: actions/upload-pages-artifact@v3
+ with:
+ path: public
+
+ deploy:
+ needs: build
+ runs-on: ubuntu-latest
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ steps:
+ - id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c75eecc
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/public
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0e0b3e8
--- /dev/null
+++ b/README.md
@@ -0,0 +1,33 @@
+# krz.sh
+
+Source for [krz.sh](https://krz.sh) — the krazy warez website. Built with
+[Zola](https://www.getzola.org/).
+
+## Develop
+
+```sh
+zola serve
+```
+
+Then open http://127.0.0.1:1111.
+
+## Build
+
+```sh
+zola build
+```
+
+Output is written to `public/`.
+
+## Structure
+
+- `config.toml` — site configuration
+- `content/` — pages (home, `services/`, `apps/`, `about/`)
+- `templates/` — Tera templates
+- `sass/main.scss` — styles (compiled to `main.css`)
+- `static/` — assets, `favicon.svg`, and `CNAME`
+
+## Deploy
+
+Pushing to `main` builds and publishes to GitHub Pages via
+`.github/workflows/deploy.yml`. The custom domain is set in `static/CNAME`.
diff --git a/config.toml b/config.toml
new file mode 100644
index 0000000..950133c
--- /dev/null
+++ b/config.toml
@@ -0,0 +1,17 @@
+base_url = "https://krz.sh"
+title = "krazy warez"
+description = "Small, durable software focused on utility, privacy, and control."
+default_language = "en"
+
+compile_sass = true
+minify_html = true
+build_search_index = false
+generate_feeds = false
+
+[markdown]
+smart_punctuation = true
+
+[extra]
+github = "https://github.com/krazywarez"
+tagline = "Small, durable software focused on utility, privacy, and control."
diff --git a/content/_index.md b/content/_index.md
new file mode 100644
index 0000000..8320355
--- /dev/null
+++ b/content/_index.md
@@ -0,0 +1,22 @@
++++
+title = "krazy warez"
++++
+
+## about
+
+krazy warez builds native apps and self-hosted, privacy-respecting frontends. two people, a few servers, no investors. local-first data, few dependencies, no ads, no tracking.
+
+## principles
+
+- fixed scope. a tool that's done stays done.
+- local-first. your data stays on your device, not our servers.
+- fewer dependencies. less to break, less to trust.
+- maintenance over features. we'd rather fix than pad.
+
+## status
+
+active. slow. not recruiting.
+
+## greetz
+
+everyone still writing plain text on purpose.
diff --git a/content/apps/_index.md b/content/apps/_index.md
new file mode 100644
index 0000000..2855663
--- /dev/null
+++ b/content/apps/_index.md
@@ -0,0 +1,10 @@
++++
+title = "Apps"
+description = "Small, durable apps and privacy-focused frontends from krazy warez."
+sort_by = "weight"
+template = "section.html"
+page_template = "page.html"
++++
+
+Native apps and privacy-respecting frontends. Each one is small, focused, and
+built to last. Source is on [GitHub](https://github.com/krazywarez).
diff --git a/content/apps/daybyday.md b/content/apps/daybyday.md
new file mode 100644
index 0000000..8760620
--- /dev/null
+++ b/content/apps/daybyday.md
@@ -0,0 +1,13 @@
++++
+title = "Day by Day"
+description = "An educational iOS app that helps children learn the calendar."
+weight = 5
+
+[extra]
+link = "https://github.com/krazywarez/daybyday"
+link_label = "Source"
+appstore = "https://apps.apple.com/app/day-by-day/id000000000"
++++
+
+Day by Day is a gentle, ad-free iOS app that helps children learn days, weeks,
+months, and seasons. Designed for little hands, with no data collection.
diff --git a/content/apps/domain-dig.md b/content/apps/domain-dig.md
new file mode 100644
index 0000000..e83d3e2
--- /dev/null
+++ b/content/apps/domain-dig.md
@@ -0,0 +1,14 @@
++++
+title = "Domain Dig"
+description = "DNS and SSL analysis, in your pocket."
+weight = 2
+
+[extra]
+link = "https://github.com/krazywarez/domain-dig"
+link_label = "Source"
+appstore = "https://apps.apple.com/app/domain-dig/id000000000"
++++
+
+Domain Dig is an iOS app for inspecting DNS records and SSL certificates on the
+go. Look up A, AAAA, MX, TXT, and more, and check certificate chains — no
+account, no tracking.
diff --git a/content/apps/hutch.md b/content/apps/hutch.md
new file mode 100644
index 0000000..223842a
--- /dev/null
+++ b/content/apps/hutch.md
@@ -0,0 +1,14 @@
++++
+title = "Hutch"
+description = "A native iOS client for Sourcehut."
+weight = 1
+
+[extra]
+link = "https://github.com/krazywarez/hutch"
+link_label = "Source"
+appstore = "https://apps.apple.com/app/hutch/id000000000"
++++
+
+Hutch is a fast, focused iOS client for [Sourcehut](https://sr.ht) — browse
+repositories, read tickets, and follow activity without leaving your phone.
+Built to be minimal and offline-friendly.
diff --git a/content/apps/solar.md b/content/apps/solar.md
new file mode 100644
index 0000000..40e4d2a
--- /dev/null
+++ b/content/apps/solar.md
@@ -0,0 +1,13 @@
++++
+title = "Solar"
+description = "A native iOS client for Cloudflare."
+weight = 3
+
+[extra]
+link = "https://github.com/krazywarez/solar"
+link_label = "Source"
++++
+
+Solar is an iOS client for [Cloudflare](https://cloudflare.com) — manage DNS,
+review analytics, and tweak settings across your zones from a clean, native
+interface.
diff --git a/content/services/_index.md b/content/services/_index.md
new file mode 100644
index 0000000..8a02950
--- /dev/null
+++ b/content/services/_index.md
@@ -0,0 +1,42 @@
++++
+title = "Services"
+description = "Public self-hosted services from krazy warez."
+sort_by = "weight"
++++
+
+Public services hosted by krazy warez.
+
+These are maintained on a best-effort basis. Logging and retention are kept
+minimal where practical.
+
+## proxies / front-ends
+
+- [AnonymousOverflow](https://ao.krz.sh) — StackOverflow alternative front-end
+- [SkunkyArt](https://art.krz.sh) — DeviantArt alternative front-end
+- [BiblioReads](https://br.krz.sh) — Goodreads alternative front-end
+- [BreezeWiki](https://bw.krz.sh) — Fandom alternative front-end
+- [Gothub](https://gh.krz.sh) — alternative GitHub interface
+- [hn](https://hn.krz.sh) — Hacker News proxy
+- [LibremDB](https://ld.krz.sh) — IMDb alternative front-end
+- [Binternet](https://pin.krz.sh) — Pinterest alternative front-end
+- [Piped](https://pipedapi.krz.sh) — YouTube alternative front-end
+- [Small](https://small.krz.sh) — Medium alternative front-end
+
+## other services
+
+- [CyberChef](https://cc.krz.sh) — the Cyber Swiss Army Knife
+- [Hat.sh](https://hat.krz.sh) — simple, fast, secure client-side file encryption
+- [LibreTranslate](https://lt.krz.sh) — a translation engine
+- [Mazanoke](https://mz.krz.sh) — local image optimizer that runs in your browser
+- [Office](https://office.krz.sh) — the world's smallest office suite
+- [SearXNG](https://search.krz.sh) — a privacy-respecting open metasearch engine
+- [Send](https://send.krz.sh) — simple, private file sharing
+
+## services i built
+
+- [1kb](https://rogue.krz.sh/1kb/#g) — ultra-small roguelike game
+- [1mb](https://rogue.krz.sh/1mb/) — extension of 1kb, showing what's possible with 1mb
+- [FlashPaper](https://paste.krz.sh) — one-time encrypted password and secret sharing
+- [org-live](https://org.krz.sh) — a basic org-mode editor for the web
+- [projects](https://projects.krz.sh) — bare nginx directory listing of web-based projects
+- [Slash](https://slash.krz.sh) — bookmark and link sharing platform
diff --git a/sass/main.scss b/sass/main.scss
new file mode 100644
index 0000000..8c9d15b
--- /dev/null
+++ b/sass/main.scss
@@ -0,0 +1,170 @@
+// krazy warez — plain-text-on-purpose. ascii frames, uppercase labels,
+// mono, near-black/white, mostly monochrome with one link accent.
+
+@mixin dark {
+ --bg: #0a0a0b;
+ --surface: #101012;
+ --border: #2a2a2e;
+ --text: #f1f1ef;
+ --muted: #9b9b9e;
+ --dim: #6a6a6e;
+ --blue: #6f9dff;
+ --btn-bg: #f1f1ef;
+ --btn-fg: #0a0a0b;
+ --sel-bg: #6f9dff;
+ --sel-fg: #0a0a0b;
+}
+
+@mixin light {
+ --bg: #fbfbf9;
+ --surface: #ffffff;
+ --border: #d9d8d2;
+ --text: #17171a;
+ --muted: #5c5c5f;
+ --dim: #8a8a8d;
+ --blue: #2f6bd6;
+ --btn-bg: #17171a;
+ --btn-fg: #fbfbf9;
+ --sel-bg: #2f6bd6;
+ --sel-fg: #ffffff;
+}
+
+:root { @include dark; }
+@media (prefers-color-scheme: light) { :root { @include light; } }
+
+:root {
+ --mono: "SF Mono", "JetBrains Mono", "Fira Code", ui-monospace, Menlo, Consolas, monospace;
+ --max: 52rem;
+}
+
+* { box-sizing: border-box; }
+html { -webkit-text-size-adjust: 100%; }
+
+body {
+ margin: 0;
+ background: var(--bg);
+ color: var(--muted);
+ font-family: var(--mono);
+ font-size: 15.5px;
+ line-height: 1.7;
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+ -webkit-font-smoothing: antialiased;
+}
+
+a { color: var(--blue); text-decoration: none; }
+a:hover { text-decoration: underline; text-underline-offset: 3px; }
+
+::selection { background: var(--sel-bg); color: var(--sel-fg); }
+
+// ---- Header ----------------------------------------------------------------
+.site-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 1rem;
+ flex-wrap: wrap;
+ max-width: var(--max);
+ width: 100%;
+ margin: 0 auto;
+ padding: 1.5rem 1.25rem;
+ border-bottom: 1px solid var(--border);
+}
+.brand { color: var(--text); font-weight: 700; letter-spacing: -0.01em; }
+.brand:hover { text-decoration: none; }
+
+.site-nav { display: flex; align-items: center; gap: 0.7rem; font-size: 0.92rem; }
+.site-nav a { color: var(--muted); }
+.site-nav a:hover { color: var(--text); text-decoration: none; }
+.sep { color: var(--dim); }
+
+// ---- Main ------------------------------------------------------------------
+.site-main {
+ flex: 1;
+ max-width: var(--max);
+ width: 100%;
+ margin: 0 auto;
+ padding: 3rem 1.25rem 4rem;
+}
+
+// ---- Hero ------------------------------------------------------------------
+.tagline { color: var(--muted); font-size: 1rem; margin: 0 0 2rem; }
+
+.hero-actions { display: flex; gap: 0.75rem; flex-wrap: wrap; margin: 0 0 1rem; }
+.btn {
+ display: inline-block;
+ font-family: var(--mono);
+ font-size: 0.92rem;
+ padding: 0.6rem 1.1rem;
+ border: 1px solid var(--border);
+ color: var(--text);
+ background: transparent;
+}
+.btn:hover { text-decoration: none; border-color: var(--dim); }
+.btn-primary { background: var(--btn-bg); color: var(--btn-fg); border-color: var(--btn-bg); }
+.btn-primary:hover { opacity: 0.88; border-color: var(--btn-bg); }
+
+// ---- Prose -----------------------------------------------------------------
+.prose { max-width: 44rem; }
+.page-label {
+ color: var(--text);
+ font-size: 1rem;
+ font-weight: 700;
+ text-transform: uppercase;
+ letter-spacing: 0.2em;
+ margin: 0 0 1.75rem;
+}
+.prose h2 {
+ color: var(--dim);
+ font-size: 0.82rem;
+ font-weight: 700;
+ text-transform: uppercase;
+ letter-spacing: 0.18em;
+ margin: 2.5rem 0 0.85rem;
+}
+.prose p { margin: 0 0 1rem; }
+.prose a { color: var(--blue); }
+.prose strong { color: var(--text); font-weight: 700; }
+.prose ul { list-style: none; padding-left: 0; margin: 1rem 0; }
+.prose li { margin: 0.4rem 0; padding-left: 1.3rem; position: relative; }
+.prose li::before { content: "-"; position: absolute; left: 0; color: var(--dim); }
+.prose hr { border: 0; border-top: 1px solid var(--border); margin: 2rem 0; }
+.prose .lede { color: var(--muted); margin: -0.5rem 0 1.25rem; }
+
+.back { font-size: 0.9rem; margin: 0 0 1.5rem; }
+.back a { color: var(--muted); }
+
+// ---- Plain list (services / apps) ------------------------------------------
+.plainlist { list-style: none; padding: 0; margin: 1.5rem 0 0; }
+.plainlist li {
+ padding: 0.85rem 0;
+ border-bottom: 1px solid var(--border);
+ display: flex;
+ flex-direction: column;
+ gap: 0.4rem;
+}
+.plainlist li:last-child { border-bottom: 0; }
+.pl-main { color: var(--muted); }
+.pl-name { color: var(--text); font-weight: 700; }
+.pl-desc { color: var(--muted); }
+.pl-links { display: flex; gap: 1.1rem; font-size: 0.88rem; }
+.pl-link { color: var(--blue); }
+.pl-link-off { color: var(--dim); cursor: not-allowed; }
+
+@media (min-width: 40rem) {
+ .plainlist li { flex-direction: row; align-items: baseline; gap: 1rem; }
+ .pl-links { margin-left: auto; white-space: nowrap; }
+}
+
+// ---- Footer ----------------------------------------------------------------
+.site-footer {
+ max-width: var(--max);
+ width: 100%;
+ margin: 0 auto;
+ padding: 1.5rem 1.25rem 2.5rem;
+ border-top: 1px solid var(--border);
+}
+.foot-links { color: var(--dim); font-size: 0.85rem; margin: 0; }
+.foot-links a { color: var(--muted); }
+.foot-links a:hover { color: var(--text); }
diff --git a/static/CNAME b/static/CNAME
new file mode 100644
index 0000000..d562b09
--- /dev/null
+++ b/static/CNAME
@@ -0,0 +1 @@
+krz.sh
diff --git a/static/favicon.svg b/static/favicon.svg
new file mode 100644
index 0000000..d8eb75d
--- /dev/null
+++ b/static/favicon.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
+ <rect width="32" height="32" fill="#0a0a0b"/>
+ <text x="16" y="22" font-family="ui-monospace, monospace" font-size="16" font-weight="700" fill="#6f9dff" text-anchor="middle">▚</text>
+</svg>
diff --git a/templates/base.html b/templates/base.html
new file mode 100644
index 0000000..09c565d
--- /dev/null
+++ b/templates/base.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html lang="{{ lang | default(value="en") }}">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>{% block title %}{{ config.title }}{% endblock title %}</title>
+ <meta name="description" content="{% block description %}{{ config.description }}{% endblock description %}">
+ <meta name="color-scheme" content="dark light">
+ <link rel="stylesheet" href="{{ get_url(path="main.css", cachebust=true) | safe }}">
+ <link rel="icon" href="{{ get_url(path="favicon.svg") | safe }}">
+</head>
+<body>
+ <header class="site-header">
+ <a class="brand" href="{{ get_url(path="/") | safe }}">krazy warez</a>
+ <nav class="site-nav">
+ <a href="{{ get_url(path="/services/") | safe }}">services</a>
+ <span class="sep">·</span>
+ <a href="{{ get_url(path="/apps/") | safe }}">apps</a>
+ </nav>
+ </header>
+
+ <main class="site-main">
+ {% block content %}{% endblock content %}
+ </main>
+
+ <footer class="site-footer">
+ <p class="foot-links"><a href="mailto:{{ config.extra.email }}">{{ config.extra.email }}</a> · <a href="{{ config.extra.github }}">github</a> · &copy; {{ now() | date(format="%Y") }} · public domain</p>
+ </footer>
+</body>
+</html>
diff --git a/templates/index.html b/templates/index.html
new file mode 100644
index 0000000..a9dd0fc
--- /dev/null
+++ b/templates/index.html
@@ -0,0 +1,14 @@
+{% extends "base.html" %}
+
+{% block content %}
+<p class="tagline">small, durable software · privacy-first tools you control</p>
+
+<div class="hero-actions">
+ <a class="btn btn-primary" href="{{ get_url(path="/services/") | safe }}">view services &rarr;</a>
+ <a class="btn" href="{{ get_url(path="/apps/") | safe }}">browse apps</a>
+</div>
+
+<article class="prose">
+ {{ section.content | safe }}
+</article>
+{% endblock content %}
diff --git a/templates/page.html b/templates/page.html
new file mode 100644
index 0000000..32b1607
--- /dev/null
+++ b/templates/page.html
@@ -0,0 +1,16 @@
+{% extends "base.html" %}
+
+{% block title %}{{ page.title | lower }} &middot; {{ config.title }}{% endblock title %}
+{% block description %}{{ page.description | default(value=config.description) }}{% endblock description %}
+
+{% block content %}
+<p class="back"><a href="{{ section.permalink | default(value=get_url(path="/")) | safe }}">&larr; back</a></p>
+<article class="prose">
+ <h1 class="page-label">{{ page.title }}</h1>
+ {% if page.description %}<p class="lede">{{ page.description }}</p>{% endif %}
+ {{ page.content | safe }}
+ {% if page.extra.link %}
+ <p><a class="btn btn-primary" href="{{ page.extra.link }}">{{ page.extra.link_label | default(value="source") | lower }} &rarr;</a></p>
+ {% endif %}
+</article>
+{% endblock content %}
diff --git a/templates/section.html b/templates/section.html
new file mode 100644
index 0000000..c3a9489
--- /dev/null
+++ b/templates/section.html
@@ -0,0 +1,29 @@
+{% extends "base.html" %}
+
+{% block title %}{{ section.title | lower }} &middot; {{ config.title }}{% endblock title %}
+{% block description %}{{ section.description | default(value=config.description) }}{% endblock description %}
+
+{% block content %}
+<article class="prose">
+ <h1 class="page-label">{{ section.title }}</h1>
+ {{ section.content | safe }}
+</article>
+
+{% if section.pages %}
+<ul class="plainlist">
+ {% for page in section.pages %}
+ <li>
+ <span class="pl-main">
+ <span class="pl-name">{{ page.title }}</span>
+ {% if page.description %}<span class="pl-desc">— {{ page.description }}</span>{% endif %}
+ </span>
+ <span class="pl-links">
+ {% if page.extra.appstore %}<a class="pl-link" href="{{ page.extra.appstore }}">app store &rarr;</a>
+ {% else %}<span class="pl-link pl-link-off" aria-disabled="true">app store — soon</span>{% endif %}
+ {% if page.extra.link %}<a class="pl-link" href="{{ page.extra.link }}">{{ page.extra.link_label | default(value="source") | lower }} &rarr;</a>{% endif %}
+ </span>
+ </li>
+ {% endfor %}
+</ul>
+{% endif %}
+{% endblock content %}