]> git.zndr.dk Git - zndr-11ty.git/commitdiff
Initial Eleventy (11ty) static site with service cards
authorJannik ZANDER <jzander@grundfos.com>
Sun, 7 Sep 2025 05:24:01 +0000 (07:24 +0200)
committerJannik ZANDER <jzander@grundfos.com>
Sun, 7 Sep 2025 05:24:01 +0000 (07:24 +0200)
.eleventy.js [new file with mode: 0644]
.gitignore [new file with mode: 0644]
package.json [new file with mode: 0644]
site/_data/services.json [new file with mode: 0644]
site/_includes/layouts/base.njk [new file with mode: 0644]
site/about.md [new file with mode: 0644]
site/assets/styles.css [new file with mode: 0644]
site/index.njk [new file with mode: 0644]
site/public/favicon.svg [new file with mode: 0644]

diff --git a/.eleventy.js b/.eleventy.js
new file mode 100644 (file)
index 0000000..63174fa
--- /dev/null
@@ -0,0 +1,16 @@
+module.exports = function(eleventyConfig) {
+  // Passthrough static files
+  eleventyConfig.addPassthroughCopy({ "site/public": "/" }); // favicon.svg → /favicon.svg
+  eleventyConfig.addPassthroughCopy({ "site/assets": "assets" });
+
+  return {
+    dir: {
+      input: "site",
+      includes: "_includes",
+      data: "_data",
+      output: "dist"
+    },
+    htmlTemplateEngine: "njk",
+    markdownTemplateEngine: "njk"
+  }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..cfd2e1c
--- /dev/null
@@ -0,0 +1,4 @@
+node_modules/
+dist/
+.cache/
+.DS_Store
diff --git a/package.json b/package.json
new file mode 100644 (file)
index 0000000..6608ce4
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "name": "zndr-11ty",
+  "private": true,
+  "scripts": {
+    "dev": "eleventy --serve --input=site --output=dist",
+    "build": "eleventy --input=site --output=dist"
+  },
+  "devDependencies": {
+    "@11ty/eleventy": "^2.0.0"
+  }
+}
diff --git a/site/_data/services.json b/site/_data/services.json
new file mode 100644 (file)
index 0000000..c926529
--- /dev/null
@@ -0,0 +1,50 @@
+[
+  {
+    "name": "Nextcloud",
+    "href": "https://nextcloud.zndr.dk",
+    "desc": "Files, calendars, contacts.",
+    "tag": "LAN/SSL"
+  },
+  {
+    "name": "Webmail",
+    "href": "https://mail.zndr.dk",
+    "desc": "Postfix \u00b7 Dovecot \u00b7 Roundcube.",
+    "tag": "IMAP/SMTP"
+  },
+  {
+    "name": "Pi-hole",
+    "href": "https://dns.zndr.dk/admin/",
+    "desc": "DNS-level ad/tracker blocking.",
+    "tag": "LAN-only"
+  },
+  {
+    "name": "Home Assistant",
+    "href": "https://ha.zndr.dk",
+    "desc": "Automation & dashboards.",
+    "tag": "Home"
+  },
+  {
+    "name": "Gitolite",
+    "href": "https://git.zndr.dk",
+    "desc": "Private repositories.",
+    "tag": "Git"
+  },
+  {
+    "name": "Status",
+    "href": "https://status.zndr.dk",
+    "desc": "Uptime & incidents.",
+    "tag": "Public"
+  },
+  {
+    "name": "Notes / Blog",
+    "href": "https://zndr.dk/blog/",
+    "desc": "Occasional write-ups.",
+    "tag": "Notes"
+  },
+  {
+    "name": "Contact",
+    "href": "mailto:post@zndr.dk",
+    "desc": "post@zndr.dk",
+    "tag": "Contact"
+  }
+]
diff --git a/site/_includes/layouts/base.njk b/site/_includes/layouts/base.njk
new file mode 100644 (file)
index 0000000..fbf4efa
--- /dev/null
@@ -0,0 +1,48 @@
+<!doctype html>
+<html lang="en">
+<head>
+  <meta charset="utf-8" />
+  <meta name="viewport" content="width=device-width, initial-scale=1" />
+  <title>{{ title or 'zndr.dk' }}</title>
+  <meta name="description" content="Minimal start page with quick links to my self‑hosted services." />
+  <meta name="color-scheme" content="light dark" />
+  <meta name="theme-color" content="#111111" />
+  <link rel="icon" href="/favicon.svg">
+  <link rel="stylesheet" href="/assets/styles.css">
+</head>
+<body>
+  <div class="container">
+    <header>
+      <a class="brand" href="/" aria-label="Home">
+        <span class="logo" aria-hidden="true">
+          <svg viewBox="0 0 24 24"><path d="M4 18h16L12 3 4 18zm2.5 3h11a1.5 1.5 0 0 0 0-3h-11a1.5 1.5 0 0 0 0 3z"/></svg>
+        </span>
+        <div>
+          <div class="title">zndr.dk</div>
+          <div class="subtitle">Self‑hosted services • Denmark</div>
+        </div>
+      </a>
+    </header>
+
+    {% block content %}{% endblock %}
+
+    <footer>
+      <div>© {{ now | date("yyyy") }} Jannik • Copenhagen</div>
+      <div class="foot-links">
+        <a href="/pgp.txt">PGP</a>
+        <a href="/keys.txt">SSH Keys</a>
+        <a href="/about.html">About</a>
+      </div>
+    </footer>
+  </div>
+
+  <script>
+    // Slash to focus any #filter found on page
+    window.addEventListener('keydown', (e) => {
+      const f = document.getElementById('filter');
+      if (!f) return;
+      if (e.key === '/' && document.activeElement !== f) { e.preventDefault(); f.focus(); }
+    });
+  </script>
+</body>
+</html>
diff --git a/site/about.md b/site/about.md
new file mode 100644 (file)
index 0000000..c1fd9ad
--- /dev/null
@@ -0,0 +1,8 @@
+---
+layout: layouts/base.njk
+title: About — zndr.dk
+---
+
+# About
+
+Tiny landing page for links to self‑hosted services. Reach me at [post@zndr.dk](mailto:post@zndr.dk).
diff --git a/site/assets/styles.css b/site/assets/styles.css
new file mode 100644 (file)
index 0000000..58d8df8
--- /dev/null
@@ -0,0 +1,22 @@
+:root { --bg: #f6f7fb; --card: #ffffff; --fg: #0f172a; --muted: #475569; --ring: #94a3b8; --accent: #2563eb; }
+@media (prefers-color-scheme: dark) { :root { --bg: #0b0f1a; --card: #0f172a; --fg: #e5e7eb; --muted: #94a3b8; --ring: #334155; } }
+*{box-sizing:border-box} html,body{height:100%}
+body{margin:0;font:16px/1.5 system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,Helvetica,Arial,"Apple Color Emoji","Segoe UI Emoji";color:var(--fg);background:radial-gradient(1200px 800px at 80% -10%, rgba(34,197,94,.08), transparent 50%),radial-gradient(800px 600px at -10% 10%, rgba(37,99,235,.08), transparent 50%),var(--bg)}
+.container{max-width:1100px;margin:0 auto;padding:32px 20px 48px}
+header{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:28px}
+.brand{display:flex;align-items:center;gap:12px;text-decoration:none;color:inherit}
+.logo{width:36px;height:36px;border-radius:10px;background:#111;display:grid;place-items:center;box-shadow:0 8px 24px rgba(0,0,0,.25)}
+.logo svg{width:22px;height:22px;fill:#fff}
+.title{font-weight:700;letter-spacing:.2px}
+.subtitle{color:var(--muted);font-size:.95rem}
+.search{width:100%;margin:18px 0 24px}
+.search input{width:100%;padding:12px 14px;border-radius:12px;border:1px solid var(--ring);background:var(--card);color:var(--fg)}
+.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:14px}
+.card{position:relative;border-radius:14px;background:linear-gradient(180deg,rgba(255,255,255,.65),rgba(255,255,255,.35));background-color:var(--card);border:1px solid var(--ring);padding:16px 14px 14px;text-decoration:none;color:inherit;transition:transform .12s ease,box-shadow .12s ease,border-color .12s ease;box-shadow:0 6px 22px rgba(2,6,23,.18)}
+.card:hover{transform:translateY(-2px);border-color:var(--accent);box-shadow:0 10px 28px rgba(37,99,235,.22)}
+.card h3{margin:0 0 6px;font-size:1rem}
+.card p{margin:0;color:var(--muted);font-size:.92rem}
+.chip{position:absolute;top:10px;right:10px;font-size:.75rem;border:1px solid var(--ring);padding:.1rem .5rem;border-radius:999px;color:var(--muted)}
+footer{margin-top:36px;display:flex;gap:12px;flex-wrap:wrap;align-items:center;justify-content:space-between;color:var(--muted);font-size:.9rem}
+.foot-links{display:flex;gap:12px;flex-wrap:wrap}
+.foot-links a{color:inherit;text-decoration:none;border-bottom:1px dashed var(--ring)}
diff --git a/site/index.njk b/site/index.njk
new file mode 100644 (file)
index 0000000..38be010
--- /dev/null
@@ -0,0 +1,30 @@
+---
+layout: layouts/base.njk
+title: zndr.dk — links
+---
+
+<div class="search" role="search">
+  <input id="filter" placeholder="Filter services… (press / to focus)" autocomplete="off" aria-label="Filter services" />
+</div>
+
+<main class="grid" id="grid" aria-live="polite">
+  {% for s in services %}
+    <a class="card" href="{{ s.href }}" rel="noopener">
+      {% if s.tag %}<span class="chip">{{ s.tag }}</span>{% endif %}
+      <h3>{{ s.name }}</h3>
+      <p>{{ s.desc }}</p>
+    </a>
+  {% endfor %}
+</main>
+
+<script>
+  (function(){
+    const f = document.getElementById('filter');
+    const cards = Array.from(document.querySelectorAll('.card'));
+    function apply(){
+      const q = f.value.toLowerCase().trim();
+      cards.forEach(c => { c.style.display = c.innerText.toLowerCase().includes(q) ? '' : 'none'; });
+    }
+    f.addEventListener('input', apply);
+  })();
+</script>
diff --git a/site/public/favicon.svg b/site/public/favicon.svg
new file mode 100644 (file)
index 0000000..c64a480
--- /dev/null
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect width="100" height="100" rx="20" fill="#000"/><path d="M22 70 L50 20 L78 70 Z" fill="#fff"/></svg>