AdGuard
- networking -DNS based Ad Blocking
-diff --git a/.gitignore b/.gitignore index 7913f08..676baa7 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,10 @@ npm-debug.log* # Release build output (scripts/release/make_release.sh). /dist/ +# Eleventy site build output + generator-produced data (scripts/gen-data.mjs). +# site/ is the legacy website location (active site now lives in +# containers/weblibreportal); these are build artifacts, not source. +site/dist/ +site/src/_data/apps.json +site/src/_data/categories.json + diff --git a/site/dist/assets/apps/adguard.svg b/site/dist/assets/apps/adguard.svg deleted file mode 100644 index f6118fc..0000000 --- a/site/dist/assets/apps/adguard.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/authelia.svg b/site/dist/assets/apps/authelia.svg deleted file mode 100644 index 9880b3b..0000000 --- a/site/dist/assets/apps/authelia.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/bookstack.svg b/site/dist/assets/apps/bookstack.svg deleted file mode 100644 index a6ad581..0000000 --- a/site/dist/assets/apps/bookstack.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/crowdsec.svg b/site/dist/assets/apps/crowdsec.svg deleted file mode 100644 index fd4ffac..0000000 --- a/site/dist/assets/apps/crowdsec.svg +++ /dev/null @@ -1,32 +0,0 @@ - diff --git a/site/dist/assets/apps/dashy.svg b/site/dist/assets/apps/dashy.svg deleted file mode 100644 index ce68744..0000000 --- a/site/dist/assets/apps/dashy.svg +++ /dev/null @@ -1,161 +0,0 @@ - - diff --git a/site/dist/assets/apps/default.svg b/site/dist/assets/apps/default.svg deleted file mode 100644 index 343d2de..0000000 --- a/site/dist/assets/apps/default.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/focalboard.svg b/site/dist/assets/apps/focalboard.svg deleted file mode 100644 index b78e7e3..0000000 --- a/site/dist/assets/apps/focalboard.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/gitea.svg b/site/dist/assets/apps/gitea.svg deleted file mode 100644 index 11c6df8..0000000 --- a/site/dist/assets/apps/gitea.svg +++ /dev/null @@ -1,4 +0,0 @@ - diff --git a/site/dist/assets/apps/gluetun.svg b/site/dist/assets/apps/gluetun.svg deleted file mode 100644 index a39521c..0000000 --- a/site/dist/assets/apps/gluetun.svg +++ /dev/null @@ -1,13 +0,0 @@ - diff --git a/site/dist/assets/apps/grafana.svg b/site/dist/assets/apps/grafana.svg deleted file mode 100644 index 54be1e2..0000000 --- a/site/dist/assets/apps/grafana.svg +++ /dev/null @@ -1,70 +0,0 @@ - - - diff --git a/site/dist/assets/apps/headscale.svg b/site/dist/assets/apps/headscale.svg deleted file mode 100644 index 06f406a..0000000 --- a/site/dist/assets/apps/headscale.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/invidious.svg b/site/dist/assets/apps/invidious.svg deleted file mode 100644 index 80e78a4..0000000 --- a/site/dist/assets/apps/invidious.svg +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/site/dist/assets/apps/ipinfo.svg b/site/dist/assets/apps/ipinfo.svg deleted file mode 100644 index 656169c..0000000 --- a/site/dist/assets/apps/ipinfo.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/jellyfin.svg b/site/dist/assets/apps/jellyfin.svg deleted file mode 100644 index 0e56a50..0000000 --- a/site/dist/assets/apps/jellyfin.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/jitsimeet.svg b/site/dist/assets/apps/jitsimeet.svg deleted file mode 100644 index 5a3526a..0000000 --- a/site/dist/assets/apps/jitsimeet.svg +++ /dev/null @@ -1,650 +0,0 @@ - - - - diff --git a/site/dist/assets/apps/libreportal.svg b/site/dist/assets/apps/libreportal.svg deleted file mode 100644 index a476796..0000000 --- a/site/dist/assets/apps/libreportal.svg +++ /dev/null @@ -1,605 +0,0 @@ - \ No newline at end of file diff --git a/site/dist/assets/apps/linkding.svg b/site/dist/assets/apps/linkding.svg deleted file mode 100644 index 089630d..0000000 --- a/site/dist/assets/apps/linkding.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/mastodon.svg b/site/dist/assets/apps/mastodon.svg deleted file mode 100644 index dd5075e..0000000 --- a/site/dist/assets/apps/mastodon.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/nextcloud.svg b/site/dist/assets/apps/nextcloud.svg deleted file mode 100644 index 336aff5..0000000 --- a/site/dist/assets/apps/nextcloud.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/site/dist/assets/apps/ollama.svg b/site/dist/assets/apps/ollama.svg deleted file mode 100644 index 6bba73a..0000000 --- a/site/dist/assets/apps/ollama.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/onlyoffice.svg b/site/dist/assets/apps/onlyoffice.svg deleted file mode 100644 index 364522c..0000000 --- a/site/dist/assets/apps/onlyoffice.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/owncloud.svg b/site/dist/assets/apps/owncloud.svg deleted file mode 100644 index cf650c7..0000000 --- a/site/dist/assets/apps/owncloud.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/pihole.svg b/site/dist/assets/apps/pihole.svg deleted file mode 100644 index 5bda461..0000000 --- a/site/dist/assets/apps/pihole.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/portainer.svg b/site/dist/assets/apps/portainer.svg deleted file mode 100644 index 45cf83a..0000000 --- a/site/dist/assets/apps/portainer.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/prometheus.svg b/site/dist/assets/apps/prometheus.svg deleted file mode 100644 index 309d704..0000000 --- a/site/dist/assets/apps/prometheus.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/searxng.svg b/site/dist/assets/apps/searxng.svg deleted file mode 100644 index 2ddf53b..0000000 --- a/site/dist/assets/apps/searxng.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/speedtest.svg b/site/dist/assets/apps/speedtest.svg deleted file mode 100644 index 2fd0d2b..0000000 --- a/site/dist/assets/apps/speedtest.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/traefik.svg b/site/dist/assets/apps/traefik.svg deleted file mode 100644 index a86b9b7..0000000 --- a/site/dist/assets/apps/traefik.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/trilium.svg b/site/dist/assets/apps/trilium.svg deleted file mode 100644 index 2ecb6e4..0000000 --- a/site/dist/assets/apps/trilium.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/unbound.svg b/site/dist/assets/apps/unbound.svg deleted file mode 100644 index cfc5d8d..0000000 --- a/site/dist/assets/apps/unbound.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/vaultwarden.svg b/site/dist/assets/apps/vaultwarden.svg deleted file mode 100644 index 41ca105..0000000 --- a/site/dist/assets/apps/vaultwarden.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/apps/wireguard.svg b/site/dist/assets/apps/wireguard.svg deleted file mode 100644 index b778001..0000000 --- a/site/dist/assets/apps/wireguard.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/site/dist/assets/favicon.ico b/site/dist/assets/favicon.ico deleted file mode 100644 index 622f2d3..0000000 Binary files a/site/dist/assets/favicon.ico and /dev/null differ diff --git a/site/dist/assets/libreportal.svg b/site/dist/assets/libreportal.svg deleted file mode 100644 index a476796..0000000 --- a/site/dist/assets/libreportal.svg +++ /dev/null @@ -1,605 +0,0 @@ - \ No newline at end of file diff --git a/site/dist/assets/main.js b/site/dist/assets/main.js deleted file mode 100644 index d9dda04..0000000 --- a/site/dist/assets/main.js +++ /dev/null @@ -1,66 +0,0 @@ -// LibrePortal site — interactions (mobile drawer, copy, scrollspy, reveal, app filter) -(() => { - // mobile drawer (same behaviour as the dashboard) - const menuToggle = document.getElementById('mobile-menu-toggle'); - const drawer = document.getElementById('mobile-drawer'); - if (menuToggle && drawer) { - menuToggle.addEventListener('click', () => { - const open = drawer.classList.toggle('mobile-open'); - document.body.style.overflow = open ? 'hidden' : ''; - }); - drawer.querySelectorAll('a').forEach((a) => - a.addEventListener('click', () => { drawer.classList.remove('mobile-open'); document.body.style.overflow = ''; })); - } - - // copy the install command - const cmdEl = document.querySelector('[data-install-cmd]'); - const CMD = cmdEl ? cmdEl.getAttribute('data-install-cmd') : ''; - document.querySelectorAll('.copy').forEach((btn) => { - btn.addEventListener('click', async () => { - try { await navigator.clipboard.writeText(CMD); } - catch { const t = document.createElement('textarea'); t.value = CMD; document.body.appendChild(t); t.select(); document.execCommand('copy'); t.remove(); } - btn.classList.add('done'); - const span = btn.querySelector('span'); const prev = span.textContent; span.textContent = 'Copied ✓'; - setTimeout(() => { btn.classList.remove('done'); span.textContent = prev; }, 1700); - }); - }); - - // scrollspy → light up the active topbar pill - const spies = [...document.querySelectorAll('.nav-item[data-spy]')]; - if (spies.length) { - const spyIO = new IntersectionObserver((entries) => { - entries.forEach((e) => { - if (e.isIntersecting) spies.forEach((s) => s.classList.toggle('nav-active', s.dataset.spy === e.target.id)); - }); - }, { rootMargin: '-45% 0px -50% 0px', threshold: 0 }); - spies.map((s) => document.getElementById(s.dataset.spy)).filter(Boolean).forEach((s) => spyIO.observe(s)); - } - - // reveal on scroll - const io = new IntersectionObserver((entries) => { - entries.forEach((e) => { if (e.isIntersecting) { e.target.classList.add('in'); io.unobserve(e.target); } }); - }, { threshold: 0.16, rootMargin: '0px 0px -8% 0px' }); - document.querySelectorAll('.reveal, .stagger').forEach((el) => io.observe(el)); - - // app category filter - const filters = document.querySelector('.app-filters'); - if (filters) { - const cards = [...document.querySelectorAll('.app-card')]; - const countEl = document.querySelector('.app-count'); - const update = (cat) => { - let shown = 0; - cards.forEach((c) => { - const match = cat === 'all' || (c.dataset.cats || '').split(' ').includes(cat); - c.classList.toggle('hidden', !match); - if (match) shown++; - }); - if (countEl) countEl.textContent = `${shown} app${shown === 1 ? '' : 's'}`; - }; - filters.addEventListener('click', (e) => { - const chip = e.target.closest('.chip'); - if (!chip) return; - filters.querySelectorAll('.chip').forEach((c) => c.classList.toggle('active', c === chip)); - update(chip.dataset.cat); - }); - } -})(); diff --git a/site/dist/assets/style.css b/site/dist/assets/style.css deleted file mode 100644 index c187888..0000000 --- a/site/dist/assets/style.css +++ /dev/null @@ -1,276 +0,0 @@ -/* ============ NEBULA THEME (lifted from the dashboard) ============ */ -:root{ - --gradient-from:#1a1442; /* indigo */ - --gradient-mid:#1b2a5e; /* violet-blue */ - --gradient-to:#0f3b6e; /* ocean */ - --surface-solid:#0f1729; - - --accent:#00d4ff; - --accent-hover:#0099cc; - --accent-rgb:0,212,255; - --accent-soft:rgba(0,212,255,.15); - - --text-primary:#ffffff; - --text-secondary:rgba(255,255,255,.82); - --text-muted:rgba(255,255,255,.65); - --text-faint:rgba(255,255,255,.45); - --text-on-accent:#0a1426; - --text-rgb:255,255,255; - - --border:rgba(255,255,255,.16); - --border-strong:rgba(255,255,255,.26); - --border-subtle:rgba(255,255,255,.08); - - --card-bg:linear-gradient(155deg, rgba(255,255,255,.09) 0%, rgba(0,212,255,.05) 100%); - --card-border:rgba(255,255,255,.16); - --card-shadow:0 4px 18px rgba(0,0,0,.30), inset 0 1px 0 rgba(255,255,255,.06); - --card-shadow-hover:0 10px 32px rgba(0,212,255,.18), 0 4px 18px rgba(0,0,0,.40), inset 0 1px 0 rgba(255,255,255,.10); - - --topbar-bg:rgba(15,25,50,.40); - --console-bg:rgba(0,0,0,.40); - --surface-bg-solid:#0f1729; - - --font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; - --font-mono:"SF Mono", "Monaco", "Menlo", "Ubuntu Mono", "Courier New", monospace; - - --maxw:1180px; - --ease:cubic-bezier(.22,.61,.36,1); -} - -*{box-sizing:border-box;margin:0;padding:0} -html{scroll-behavior:smooth} -body{font-family:var(--font-sans);background:var(--surface-solid);color:var(--text-primary); - line-height:1.6;overflow-x:hidden;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility} - -/* ============ AURORA BACKDROP (from aurora-background.css) ============ */ -.cosmos{position:fixed;inset:0;z-index:-2;pointer-events:none;overflow:hidden; - background: - radial-gradient(ellipse at 20% 22%, var(--gradient-mid) 0%, transparent 55%), - radial-gradient(ellipse at 82% 74%, var(--gradient-to) 0%, transparent 55%), - linear-gradient(135deg, var(--gradient-from) 0%, var(--gradient-from) 40%, var(--gradient-mid) 100%);} -.cosmos::before{content:'';position:absolute;inset:-25%; - background:conic-gradient(from 0deg at 50% 50%, - rgba(var(--accent-rgb),0) 0deg, rgba(var(--accent-rgb),.18) 60deg, - rgba(var(--accent-rgb),.22) 130deg, rgba(var(--accent-rgb),.20) 200deg, - rgba(var(--accent-rgb),.18) 280deg, rgba(var(--accent-rgb),0) 360deg); - filter:blur(70px);animation:auroraSpin 38s linear infinite;} -.cosmos::after{content:'';position:absolute;inset:-10%; - background: - radial-gradient(circle at 18% 22%, rgba(var(--accent-rgb),.38) 0%, transparent 35%), - radial-gradient(circle at 78% 18%, rgba(var(--accent-rgb),.32) 0%, transparent 32%), - radial-gradient(circle at 30% 80%, rgba(var(--accent-rgb),.30) 0%, transparent 38%), - radial-gradient(circle at 84% 82%, rgba(var(--accent-rgb),.34) 0%, transparent 36%), - radial-gradient(circle at 50% 50%, rgba(var(--accent-rgb),.14) 0%, transparent 50%); - filter:blur(50px);animation:auroraDrift 22s ease-in-out infinite alternate;} -.stars{position:fixed;inset:0;z-index:-1;pointer-events:none} -.stars::before,.stars::after{content:'';position:absolute;inset:0;background-repeat:repeat} -.stars::before{background-image: - radial-gradient(1.5px 1.5px at 12px 18px, rgba(var(--text-rgb),.9), transparent 60%), - radial-gradient(1px 1px at 47px 92px, rgba(var(--accent-rgb),.85), transparent 60%), - radial-gradient(1.2px 1.2px at 110px 40px, rgba(var(--text-rgb),.75), transparent 60%), - radial-gradient(1px 1px at 165px 130px, rgba(var(--accent-rgb),.7), transparent 60%); - background-size:200px 200px;animation:auroraTwinkleA 4.5s ease-in-out infinite;} -.stars::after{background-image: - radial-gradient(1px 1px at 30px 60px, rgba(var(--accent-rgb),.8), transparent 60%), - radial-gradient(1.4px 1.4px at 88px 22px, rgba(var(--text-rgb),.7), transparent 60%), - radial-gradient(1px 1px at 140px 100px, rgba(var(--accent-rgb),.85), transparent 60%), - radial-gradient(1.2px 1.2px at 195px 70px, rgba(var(--text-rgb),.6), transparent 60%); - background-size:240px 240px;background-position:80px 50px;animation:auroraTwinkleB 6.5s ease-in-out infinite;} -@keyframes auroraSpin{to{transform:rotate(360deg)}} -@keyframes auroraDrift{0%{transform:translate(0,0) scale(1);opacity:.85}50%{transform:translate(-3%,4%) scale(1.08);opacity:1}100%{transform:translate(2%,-3%) scale(.95);opacity:.9}} -@keyframes auroraTwinkleA{0%,100%{opacity:.55}50%{opacity:1}} -@keyframes auroraTwinkleB{0%,100%{opacity:1}50%{opacity:.45}} - -/* ============ shared ============ */ -.grad{background:linear-gradient(100deg,#7ae9ff,#00d4ff 55%,#0aa6d6); - -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent} -.wrap{max-width:var(--maxw);margin:0 auto;padding:0 clamp(18px,5vw,48px)} -section{position:relative;z-index:1} -.eyebrow{font-family:var(--font-mono);font-size:.74rem;letter-spacing:.22em;text-transform:uppercase;color:var(--accent);margin-bottom:16px;display:block} -h2{font-size:clamp(2rem,4.6vw,3.2rem);line-height:1.08;letter-spacing:-.02em;font-weight:800} -.lead{color:var(--text-secondary);font-size:1.08rem;max-width:54ch;margin-top:18px;font-weight:400} -.pad{padding:clamp(80px,12vh,140px) 0} -.glass{background:var(--card-bg);border:1px solid var(--card-border);box-shadow:var(--card-shadow); - backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)} - -/* ============ TOPBAR — grafted from the dashboard (topbar.css) ============ */ -.topbar{display:flex;justify-content:space-between;align-items:center;padding:0 24px;height:60px; - position:fixed;top:0;left:0;right:0;z-index:1000;background:var(--topbar-bg); - border-bottom:1px solid var(--border);backdrop-filter:blur(12px) saturate(140%);-webkit-backdrop-filter:blur(12px) saturate(140%)} -.mobile-menu-toggle{display:none;background:none;border:none;color:var(--text-primary);cursor:pointer;padding:6px;margin-right:4px} -.topbar-left{display:flex;align-items:center;flex:0 0 auto} -.libreportal-logo{display:flex;align-items:center;gap:10px;text-decoration:none;color:var(--text-primary);font-weight:700;font-size:1.05rem} -.libreportal-logo img{width:32px;height:32px} -.libreportal-logo b{color:var(--accent);font-weight:700} -.mobile-drawer{display:flex;align-items:center;flex:1;justify-content:space-between;gap:12px;min-width:0;margin-left:24px} -.topbar-nav{display:flex;gap:8px;align-items:center} -.topbar-nav .nav-item{background:rgba(var(--text-rgb),.10);border:1px solid rgba(var(--text-rgb),.20);border-radius:8px; - padding:10px 16px;font-size:14px;font-weight:500;color:var(--text-muted);text-decoration:none;display:flex;align-items:center;gap:8px; - transition:all .2s ease;cursor:pointer;min-height:42px;white-space:nowrap} -.topbar-nav .nav-item:hover{background:rgba(var(--text-rgb),.20);transform:translateY(-1px);color:var(--text-primary)} -.topbar-nav .nav-item.nav-active{background:var(--accent);color:var(--text-primary);border-color:var(--accent)} -.topbar-nav .nav-item.nav-active:hover{background:var(--accent-hover);border-color:var(--accent-hover)} -.topbar-nav .nav-item svg{width:16px;height:16px} -.topbar-controls{display:flex;align-items:center;gap:12px} -.tb-ghost{display:inline-flex;align-items:center;gap:6px;padding:8px 14px;border:1px solid var(--border);border-radius:8px; - background:rgba(var(--text-rgb),.05);color:var(--text-secondary);text-decoration:none;font-size:.85rem;font-weight:600;transition:all .2s} -.tb-ghost:hover{background:rgba(var(--text-rgb),.12);color:var(--text-primary)} -.tb-cta{display:inline-flex;align-items:center;gap:6px;padding:8px 18px;border-radius:8px;background:var(--accent); - color:var(--text-on-accent);text-decoration:none;font-size:.85rem;font-weight:700;transition:all .2s} -.tb-cta:hover{background:#22dbff;transform:translateY(-1px);box-shadow:0 8px 22px -8px rgba(var(--accent-rgb),.6)} -@media(max-width:768px){ - .topbar{padding:0 12px;gap:8px;justify-content:flex-start} - .mobile-menu-toggle{display:flex;align-items:center} - .mobile-drawer{position:fixed;top:60px;left:0;width:100vw;height:calc(100vh - 60px);flex-direction:column;align-items:stretch; - justify-content:flex-start;gap:0;padding:16px;margin-left:0;background:var(--surface-bg-solid);border-right:1px solid var(--border); - box-shadow:6px 0 24px rgba(0,0,0,.35);overflow-y:auto;transform:translateX(-100%);transition:transform .3s ease;z-index:101} - .mobile-drawer.mobile-open{transform:translateX(0)} - .mobile-drawer .topbar-nav{flex-direction:column;align-items:stretch;gap:6px;width:100%} - .mobile-drawer .topbar-nav .nav-item{width:100%;justify-content:flex-start} - .mobile-drawer .topbar-controls{flex-direction:column;align-items:stretch;gap:8px;width:100%;margin-top:auto;padding-top:16px; - border-top:1px solid rgba(var(--text-rgb),.12)} - .mobile-drawer .topbar-controls a{width:100%;justify-content:center} -} - -/* ============ hero ============ */ -header.hero{min-height:100vh;display:flex;flex-direction:column;justify-content:center;align-items:center; - text-align:center;padding:140px clamp(18px,5vw,48px) 90px;position:relative} -.badge{display:inline-flex;align-items:center;gap:8px;font-family:var(--font-mono);font-size:.72rem; - letter-spacing:.14em;text-transform:uppercase;color:var(--accent);padding:7px 15px;border-radius:999px; - border:1px solid rgba(var(--accent-rgb),.35);background:var(--accent-soft);margin-bottom:30px} -.badge .dot{width:6px;height:6px;border-radius:50%;background:var(--accent);box-shadow:0 0 10px var(--accent);animation:pulse 2.4s ease-in-out infinite} -@keyframes pulse{0%,100%{opacity:.4}50%{opacity:1}} -.hero-logo{width:64px;height:64px;margin-bottom:22px;filter:drop-shadow(0 6px 24px rgba(var(--accent-rgb),.45))} -h1{font-size:clamp(2.6rem,7vw,5.2rem);line-height:1.03;letter-spacing:-.03em;font-weight:800;max-width:15ch} -.sub{margin:26px auto 0;max-width:50ch;font-size:clamp(1.02rem,2vw,1.2rem);color:var(--text-secondary);font-weight:400} - -/* install portal */ -.portal{margin:46px auto 0;width:min(660px,100%);position:relative} -.portal::before{content:"";position:absolute;inset:-26px;border-radius:28px;z-index:-1; - background:radial-gradient(60% 80% at 50% 50%, rgba(var(--accent-rgb),.5), transparent 70%);filter:blur(22px);animation:breathe 6s ease-in-out infinite} -@keyframes breathe{0%,100%{opacity:.45;transform:scale(.98)}50%{opacity:.8;transform:scale(1.03)}} -.term{border:1px solid var(--card-border);border-radius:16px;overflow:hidden; - background:linear-gradient(155deg, rgba(255,255,255,.10) 0%, rgba(0,212,255,.06) 100%); - backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);box-shadow:var(--card-shadow-hover)} -.term-bar{display:flex;align-items:center;gap:7px;padding:12px 16px;border-bottom:1px solid var(--border-subtle);background:var(--console-bg)} -.term-bar i{width:11px;height:11px;border-radius:50%;display:block} -.term-bar i:nth-child(1){background:#ff6b5e}.term-bar i:nth-child(2){background:#ffc107}.term-bar i:nth-child(3){background:var(--accent)} -.term-bar em{margin-left:auto;font-family:var(--font-mono);font-size:.72rem;color:var(--text-faint);font-style:normal} -.term-body{display:flex;align-items:center;gap:14px;padding:22px 20px} -.term-body code{font-family:var(--font-mono);font-size:clamp(.82rem,2.3vw,1.02rem);color:var(--text-primary); - white-space:nowrap;overflow-x:auto;flex:1;text-align:left;scrollbar-width:none} -.term-body code::-webkit-scrollbar{display:none} -.term-body code .p{color:var(--accent)} -.term-body code .u{color:#e6f3ff} -.copy{flex:0 0 auto;display:inline-flex;align-items:center;gap:7px;font-family:var(--font-sans);font-weight:700; - font-size:.84rem;color:var(--text-on-accent);background:var(--accent);border:none;border-radius:9px;padding:9px 15px;cursor:pointer; - transition:transform .15s,background .25s,box-shadow .25s} -.copy:hover{transform:translateY(-1px);background:#22dbff;box-shadow:0 8px 22px -8px rgba(var(--accent-rgb),.7)} -.copy.done{background:#28a745;color:#fff} -.portal-foot{display:flex;align-items:center;justify-content:center;gap:16px;margin-top:16px;flex-wrap:wrap;font-size:.86rem;color:var(--text-faint)} -.portal-foot a{color:var(--text-secondary);text-decoration:none;border-bottom:1px dashed rgba(255,255,255,.3);transition:color .2s,border-color .2s} -.portal-foot a:hover{color:var(--accent);border-color:var(--accent)} -.hint{font-family:var(--font-mono);font-size:.78rem} -.scroll-cue{position:absolute;bottom:28px;left:50%;transform:translateX(-50%);color:var(--text-faint); - font-family:var(--font-mono);font-size:.66rem;letter-spacing:.2em;text-transform:uppercase; - display:flex;flex-direction:column;align-items:center;gap:8px;animation:bob 2.6s ease-in-out infinite} -.scroll-cue::after{content:"";width:1px;height:34px;background:linear-gradient(var(--text-faint),transparent)} -@keyframes bob{0%,100%{transform:translateX(-50%) translateY(0)}50%{transform:translateX(-50%) translateY(8px)}} - -/* ============ features ============ */ -.feat-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;margin-top:54px} -.card{border-radius:16px;padding:28px 26px;position:relative;overflow:hidden;transition:transform .4s var(--ease),border-color .4s,box-shadow .4s} -.card:hover{transform:translateY(-6px);border-color:rgba(var(--accent-rgb),.45);box-shadow:var(--card-shadow-hover)} -.card .ico{width:44px;height:44px;border-radius:12px;display:grid;place-items:center;margin-bottom:18px; - background:var(--accent-soft);border:1px solid rgba(var(--accent-rgb),.30)} -.card .ico svg{width:22px;height:22px;stroke:var(--accent);fill:none;stroke-width:1.6} -.card h3{font-size:1.24rem;margin-bottom:8px;font-weight:700;letter-spacing:-.01em} -.card p{color:var(--text-secondary);font-size:.96rem} - -/* ============ apps (data-driven) ============ */ -.apps-section{text-align:center} -.app-filters{display:flex;flex-wrap:wrap;justify-content:center;gap:10px;margin-top:40px} -.chip{font-family:var(--font-mono);font-size:.76rem;letter-spacing:.04em;padding:8px 15px;border-radius:999px; - border:1px solid var(--border);background:rgba(255,255,255,.05);color:var(--text-secondary);cursor:pointer;transition:all .2s} -.chip:hover{color:var(--text-primary);border-color:rgba(var(--accent-rgb),.45)} -.chip.active{background:var(--accent);color:var(--text-on-accent);border-color:var(--accent);font-weight:600} -.chip .n{opacity:.55;margin-left:6px} -.app-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(248px,1fr));gap:16px;margin-top:34px;text-align:left} -.app-card{border-radius:14px;padding:20px;display:flex;flex-direction:column;gap:11px;transition:transform .3s var(--ease),border-color .3s,box-shadow .3s} -.app-card.hidden{display:none} -.app-card:hover{transform:translateY(-4px);border-color:rgba(var(--accent-rgb),.4);box-shadow:var(--card-shadow-hover)} -.app-card-head{display:flex;align-items:center;gap:12px} -.app-ico{width:42px;height:42px;border-radius:10px;background:rgba(255,255,255,.06);padding:6px;object-fit:contain;border:1px solid var(--border-subtle);flex:0 0 auto} -.app-card h3{font-size:1.06rem;font-weight:700;line-height:1.2} -.app-cat{font-family:var(--font-mono);font-size:.64rem;letter-spacing:.1em;text-transform:uppercase;color:var(--accent)} -.app-card p{font-size:.9rem;color:var(--text-secondary);margin:0} -.app-count{margin-top:26px;color:var(--text-faint);font-size:.85rem;font-family:var(--font-mono)} - -/* ============ connect / courier ============ */ -.connect{display:grid;grid-template-columns:1.05fr .95fr;gap:60px;align-items:center} -.pill{display:inline-flex;align-items:center;gap:8px;font-family:var(--font-mono);font-size:.72rem; - letter-spacing:.1em;text-transform:uppercase;color:var(--text-secondary);padding:7px 14px;border-radius:999px; - border:1px solid var(--border);background:rgba(255,255,255,.04);margin-top:24px} -.connect ul{list-style:none;margin-top:26px;display:flex;flex-direction:column;gap:15px} -.connect li{display:flex;gap:13px;color:var(--text-secondary);font-size:1rem} -.connect li svg{flex:0 0 auto;width:21px;height:21px;stroke:var(--accent);fill:none;stroke-width:1.6;margin-top:3px} -.connect li b{color:var(--text-primary);font-weight:700} -.vault{position:relative;aspect-ratio:1;display:grid;place-items:center} -.vault svg{width:min(360px,82%);height:auto;overflow:visible} -.orbit{transform-origin:center;animation:spin 26s linear infinite} -@keyframes spin{to{transform:rotate(360deg)}} - -/* ============ promise ============ */ -.promise{text-align:center} -.pledges{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-top:52px} -.pledge{border-radius:14px;padding:28px 18px} -.pledge .big{font-size:2.4rem;font-weight:800;margin-bottom:8px;line-height:1} -.pledge p{font-size:.92rem;color:var(--text-secondary)} -.promise .link{display:inline-block;margin-top:40px;color:var(--accent);text-decoration:none;font-weight:700; - border-bottom:1px solid rgba(var(--accent-rgb),.45);padding-bottom:2px;transition:color .2s,border-color .2s} -.promise .link:hover{color:#fff;border-color:#fff} - -/* ============ final ============ */ -.final{text-align:center;padding:clamp(90px,14vh,160px) 0} -.final h2{max-width:18ch;margin-inline:auto} -.final .portal{margin-top:42px} - -/* ============ footer ============ */ -footer{border-top:1px solid var(--border-subtle);padding:54px 0 70px;margin-top:40px;background:rgba(10,16,32,.55);backdrop-filter:blur(8px)} -.foot-grid{display:flex;justify-content:space-between;gap:40px;flex-wrap:wrap;align-items:flex-start} -.foot-grid .libreportal-logo{margin-bottom:14px} -.foot-col h4{font-size:.74rem;letter-spacing:.16em;text-transform:uppercase;color:var(--text-faint);margin-bottom:14px;font-family:var(--font-mono)} -.foot-col a{display:block;color:var(--text-secondary);text-decoration:none;font-size:.95rem;margin-bottom:9px;transition:color .2s} -.foot-col a:hover{color:var(--accent)} -.colophon{margin-top:46px;padding-top:26px;border-top:1px solid var(--border-subtle); - display:flex;justify-content:space-between;gap:18px;flex-wrap:wrap;color:var(--text-faint);font-size:.86rem} -.colophon a{color:var(--text-secondary);text-decoration:none} -.colophon a:hover{color:var(--accent)} - -/* ============ reveal ============ */ -.reveal{opacity:0;transform:translateY(28px);transition:opacity .9s var(--ease),transform .9s var(--ease)} -.reveal.in{opacity:1;transform:none} -.stagger>*{opacity:0;transform:translateY(20px);transition:opacity .7s var(--ease),transform .7s var(--ease)} -.stagger.in>*{opacity:1;transform:none} -.stagger.in>*:nth-child(2){transition-delay:.07s}.stagger.in>*:nth-child(3){transition-delay:.14s} -.stagger.in>*:nth-child(4){transition-delay:.21s}.stagger.in>*:nth-child(5){transition-delay:.28s}.stagger.in>*:nth-child(6){transition-delay:.35s} -.h-anim{opacity:0;transform:translateY(24px);animation:rise .95s var(--ease) forwards} -.d1{animation-delay:.05s}.d2{animation-delay:.16s}.d3{animation-delay:.28s}.d4{animation-delay:.4s}.d5{animation-delay:.52s} -@keyframes rise{to{opacity:1;transform:none}} - -/* ============ responsive ============ */ -@media(max-width:860px){ - .feat-grid{grid-template-columns:1fr 1fr} - .connect{grid-template-columns:1fr;gap:36px} - .vault{order:-1;max-width:320px;margin-inline:auto} - .pledges{grid-template-columns:1fr 1fr} -} -@media(max-width:540px){ - .feat-grid{grid-template-columns:1fr} - .term-body{flex-direction:column;align-items:stretch} - .copy{justify-content:center} -} -@media(prefers-reduced-motion:reduce){ - *{animation:none!important;transition:none!important} - .reveal,.stagger>*,.h-anim{opacity:1;transform:none} -} diff --git a/site/dist/index.html b/site/dist/index.html deleted file mode 100644 index ff5a8cf..0000000 --- a/site/dist/index.html +++ /dev/null @@ -1,586 +0,0 @@ - - -
- - -Self-host the apps you actually rely on — on your own server. - One command brings up a whole platform, and your data never leaves your orbit.
- -bash <(curl -fsSL https://get.libreportal.org) init
-
- No yak-shaving. LibrePortal wires up the boring, fiddly infrastructure so you can run the good stuff.
- -Nextcloud, Vaultwarden, Jellyfin, Gitea and dozens more — picked from a menu, deployed clean.
-A reverse proxy with automatic Let's Encrypt certificates. HTTPS everywhere, configured for you.
-Containers run without root and with sane security defaults — CrowdSec on guard out of the box.
-Install, configure, back up and monitor everything from a clean web UI. No SSH archaeology.
-Send any app's traffic through gluetun. Keep the things that should be private, private.
-Nothing phones home. No accounts required to self-host. The software is yours, entirely.
-Pulled straight from the repo — 31 apps you can light up from the dashboard, and switch off just as easily.
- -DNS based Ad Blocking
-Authentication & SSO
-Wiki/Knowledge Base
-Intrusion Prevention
-Dashboard Tool
-Project Management
-Git Repository Management
-VPN Container Router
-Metrics Visualizer
-WireGuard VPN Controller
-YouTube Frontend
-IP Information
-Media Server
-Video Conferencing
-WebUI Dashboard
-Bookmark Manager
-Social Network
-Household Money Management
-Self-hosted Cloud Storage
-Local AI Model Hosting
-Collaborative Office Suite
-Cloud Storage
-DNS-based Ad Blocking
-Monitoring and Alerting
-Search Engine
-Network Performance Monitoring
-Reverse Proxy
-Notes & Knowledge Management
-DNS Resolver
-Password Manager
-VPN Server
-31 apps
-Reaching your server from your phone and keeping off-site backups are the fiddly bits. - Connect handles them — but works like a courier carrying a sealed box.
-In plain language, so you can hold us to it.
-Every feature, free to self-host. Forever. No crippled edition.
Trackers. No telemetry, no phoning home, no accounts to run it.
Feature paywalls. You never pay to unlock — only for convenience.
What's open stays open. No rug-pulls, ever. AGPLv3.
bash <(curl -fsSL https://get.libreportal.org) init
-
-