Files
felhom.eu/website/en/apps.html
T

1459 lines
108 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Apps to install — 56 apps for a home server | Felhom.eu</title>
<meta name="description" content="Nextcloud, Immich, Jellyfin, Vaultwarden — 56 apps for your home server in Hungary, almost all of them open source. Alternatives to Google Drive, iCloud Photos and Spotify.">
<meta name="keywords" content="Nextcloud, Immich, Jellyfin, Plex, Sonarr, Radarr, Vaultwarden, open-source apps, self-hosted apps, home server apps, Google Photos alternative, Dropbox alternative">
<meta name="robots" content="index, follow">
<link rel="canonical" href="https://felhom.eu/en/apps">
<link rel="alternate" hreflang="hu" href="https://felhom.eu/alkalmazasok">
<link rel="alternate" hreflang="en" href="https://felhom.eu/en/apps">
<link rel="alternate" hreflang="x-default" href="https://felhom.eu/alkalmazasok">
<meta property="og:type" content="website">
<meta property="og:url" content="https://felhom.eu/en/apps">
<meta property="og:title" content="56 apps for a home server">
<meta property="og:description" content="Nextcloud, Immich, Jellyfin, Vaultwarden and many more. Files, photos, media, documents — all from your own server.">
<meta property="og:image" content="https://felhom.eu/assets/og-image.png">
<meta property="og:locale" content="en_GB">
<meta property="og:site_name" content="Felhom.eu">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="56 apps for a home server">
<meta name="twitter:description" content="Nextcloud, Immich, Jellyfin and many more — from your own server.">
<meta name="twitter:image" content="https://felhom.eu/assets/og-image.png">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "ItemList",
"name": "Felhom.eu — Apps to install",
"description": "Self-hosted apps for a home server, almost all of them open source",
"numberOfItems": 56,
"itemListElement": [
{"@type": "ListItem", "position": 1, "name": "Nextcloud", "description": "Files and office suite"},
{"@type": "ListItem", "position": 2, "name": "Immich", "description": "Photos and videos (a Google Photos alternative)"},
{"@type": "ListItem", "position": 3, "name": "Jellyfin", "description": "Media player and server"},
{"@type": "ListItem", "position": 4, "name": "Vaultwarden", "description": "Password manager (Bitwarden compatible)"},
{"@type": "ListItem", "position": 5, "name": "Paperless-ngx", "description": "Document management"}
]
}
</script>
<!-- shared assets: bump ?v= together on any site.css/icons.svg change -->
<link rel="stylesheet" href="/assets/site.css?v=3">
<link rel="icon" type="image/png" href="/assets/logo_favicon_2.svg">
<script defer src="https://stats.felhom.eu/script.js" data-website-id="d419db57-5e1c-48df-bdb3-c29f25fb1661"></script>
</head>
<body class="page-alkalmazasok">
<nav>
<div class="container">
<a href="/en/" class="logo">
<img src="/assets/logo.png" alt="Felhom.eu logo">
<span class="logo-text">felhom.eu</span>
</a>
<ul class="nav-links">
<li><a href="/en/#services">Services</a></li>
<li><a href="/en/apps" class="active">Apps</a></li>
<li><a href="/en/technology">Technology</a></li>
<li><a href="/en/backups">Backups</a></li>
<li><a href="/en/faq">FAQ</a></li>
<li><a href="/en/contact">Contact</a></li>
<li class="lang-globe-li"><details class="lang-globe"><summary class="lang-globe-btn" aria-label="Language" title="Language"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-globe"/></svg></summary><ul class="lang-globe-menu"><li><a href="/alkalmazasok" lang="hu" hreflang="hu" class="lang-globe-item">Magyar</a></li><li><a href="/en/apps" lang="en" hreflang="en" class="lang-globe-item current" aria-current="true">English</a></li></ul></details></li>
</ul>
<button class="hamburger" id="hamburger" aria-label="Open menu" aria-expanded="false">
<span class="hamburger-box">
<span class="hamburger-line"></span>
<span class="hamburger-line"></span>
<span class="hamburger-line"></span>
</span>
</button>
</div>
</nav>
<div class="mobile-overlay" id="mobileOverlay"></div>
<main>
<section class="page-header">
<div class="container">
<h1>Apps to <span>install</span></h1>
<p>Choose from 56 apps. Almost all of them are free, open-source software, and every one runs on your own server.</p>
<div class="disclaimer-banner">
<h3><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-info"/></svg> Good to know</h3>
<ul>
<li>Almost all of the apps are <strong>open source</strong> – anyone can check how they work. The exceptions are marked on the card: <em>Closed source</em> (Plex, Emby), <em>Restricted licence</em> (the source can be read, but the licence limits its use), <em>Felhom's own</em> (built by us)</li>
<li>Our service covers <strong>installing</strong> the apps, not developing or selling them</li>
<li>The original developers are responsible for how the apps work and for their updates</li>
<li>If an app is missing, we look at whether it can join the catalog – <a href="/en/contact">just ask!</a></li>
</ul>
</div>
</div>
</section>
<section class="apps-section">
<div class="container">
<!-- ==================== -->
<!-- 1. FILES & OFFICE -->
<!-- ==================== -->
<div class="category-section" id="files">
<div class="category-header">
<span class="category-icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-folder"/></svg></span>
<h2>Files & Office</h2>
<span class="app-count">6 apps + 1 built in</span>
</div>
<div class="app-grid">
<!-- Nextcloud -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/nextcloud-logo.svg" alt="Nextcloud" class="app-logo">
<div class="app-title-area"><h3>Nextcloud</h3><span class="app-tagline">Your own Google Drive</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A full cloud service on your own server. File sync, calendar, contacts, document editing and a great many add-ons.</p>
<div class="app-features"><span class="app-feature">File sync</span><span class="app-feature">Calendar</span><span class="app-feature">Documents</span><span class="app-feature">Mobile app</span></div>
<img src="/assets/nextcloud-screenshot-1.webp" alt="Nextcloud screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/nextcloud/server" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- FileBrowser -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/filebrowser-logo.svg" alt="FileBrowser" class="app-logo">
<div class="app-title-area"><h3>FileBrowser</h3><span class="app-tagline">Simple web file manager</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A light, fast web file manager, built into every Felhom box. Browse, upload and share your files from anywhere, in a modern interface.</p>
<div class="app-features"><span class="app-feature">Drag & drop</span><span class="app-feature">Sharing</span><span class="app-feature">Preview</span><span class="app-feature">Search</span></div>
<img src="/assets/filebrowser-screenshot-1.webp" alt="FileBrowser screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/filebrowser/filebrowser" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source · Built in</span>
</div>
</div>
<!-- Gokapi -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/gokapi-logo.png" alt="Gokapi" class="app-logo">
<div class="app-title-area"><h3>Gokapi</h3><span class="app-tagline">Temporary file sharing</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A lightweight file-sharing server with expiry dates and download limits. Good for sharing large files quickly and safely.</p>
<div class="app-features"><span class="app-feature">Expiry date</span><span class="app-feature">Download limit</span><span class="app-feature">Password protection</span></div>
<img src="/assets/gokapi-screenshot-1.webp" alt="Gokapi screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/Forceu/Gokapi" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Zipline -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/zipline-logo.png" alt="Zipline" class="app-logo">
<div class="app-title-area"><h3>Zipline</h3><span class="app-tagline">ShareX/Flameshot server</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A modern file and image sharing server with many features. Good for sharing screenshots, shortening links and keeping text snippets.</p>
<div class="app-features"><span class="app-feature">Screenshots</span><span class="app-feature">Link shortener</span><span class="app-feature">Gallery</span><span class="app-feature">API</span></div>
<img src="/assets/zipline-screenshot-1.webp" alt="Zipline screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/diced/zipline" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- OnlyOffice -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/onlyoffice-logo.svg" alt="OnlyOffice" class="app-logo">
<div class="app-title-area"><h3>OnlyOffice</h3><span class="app-tagline">An office suite in the browser</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A full office suite in your browser. Edit documents, spreadsheets and presentations, with very good Microsoft Office compatibility.</p>
<div class="app-features"><span class="app-feature">Documents</span><span class="app-feature">Spreadsheets</span><span class="app-feature">Presentations</span><span class="app-feature">Collaboration</span></div>
<img src="/assets/onlyoffice-screenshot-1.webp" alt="OnlyOffice screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/ONLYOFFICE/DocumentServer" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- BentoPDF -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/bentopdf-logo.svg" alt="BentoPDF" class="app-logo">
<div class="app-title-area"><h3>BentoPDF</h3><span class="app-tagline">PDF toolkit (privacy first)</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A privacy-first PDF toolkit with more than 70 tools. Merge, split, convert, compress, OCR, encrypt and sign, all in the browser, with nothing sent to a server.</p>
<div class="app-features"><span class="app-feature">70+ tools</span><span class="app-feature">Client-side</span><span class="app-feature">OCR</span><span class="app-feature">Convert</span></div>
<img src="/assets/bentopdf-screenshot-1.webp" alt="BentoPDF screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/alam00000/bentopdf" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Papra -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/papra-logo.svg" alt="Papra" class="app-logo">
<div class="app-title-area"><h3>Papra</h3><span class="app-tagline">A minimal document archive</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A clean, modern document archive. Automatic tags, e-mail import and OCR text recognition: a digital filing cabinet, simple and tidy.</p>
<div class="app-features"><span class="app-feature">Auto tags</span><span class="app-feature">E-mail import</span><span class="app-feature">OCR</span><span class="app-feature">Modern UI</span></div>
<img src="/assets/papra-screenshot-1.webp" alt="Papra screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/papra-hq/papra" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
</div>
</div>
<!-- ==================== -->
<!-- 2. MEDIA & ENTERTAINMENT -->
<!-- ==================== -->
<div class="category-section" id="media">
<div class="category-header">
<span class="category-icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-tv"/></svg></span>
<h2>Media & Entertainment</h2>
<span class="app-count">15 apps</span>
</div>
<div class="app-grid">
<!-- Immich -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/immich-logo.svg" alt="Immich" class="app-logo">
<div class="app-title-area"><h3>Immich</h3><span class="app-tagline">A Google Photos alternative</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A fast, modern photo and video backup. Automatic upload from your phone, face and object recognition, sharing and memories.</p>
<div class="app-features"><span class="app-feature">Auto backup</span><span class="app-feature">Face recognition</span><span class="app-feature">Map</span><span class="app-feature">Mobile app</span></div>
<img src="/assets/immich-screenshot-1.webp" alt="Immich screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/immich-app/immich" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Jellyfin -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/jellyfin-logo.svg" alt="Jellyfin" class="app-logo">
<div class="app-title-area"><h3>Jellyfin</h3><span class="app-tagline">Media server (Netflix)</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A free, open-source media server. Stream films, series and music from anywhere, to any device.</p>
<div class="app-features"><span class="app-feature">Streaming</span><span class="app-feature">Transcoding</span><span class="app-feature">Mobile app</span><span class="app-feature">TV app</span></div>
<img src="/assets/jellyfin-screenshot-1.webp" alt="Jellyfin screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/jellyfin/jellyfin" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Plex -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/plex-logo.svg" alt="Plex" class="app-logo">
<div class="app-title-area"><h3>Plex</h3><span class="app-tagline">Media server (premium)</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A popular media server with a polished interface. Films, series, music and photos in one place, with very good app support.</p>
<div class="app-features"><span class="app-feature">Streaming</span><span class="app-feature">Plex Pass</span><span class="app-feature">Intro skip</span><span class="app-feature">Watch Together</span></div>
<img src="/assets/plex-screenshot-1.webp" alt="Plex screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://www.plex.tv" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Website</a>
<span class="open-source-badge" style="color: var(--warn);"><img src="/assets/checkmark-yellow.svg" alt="">Closed source</span>
</div>
</div>
<!-- Emby -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/emby-logo.svg" alt="Emby" class="app-logo">
<div class="app-title-area"><h3>Emby</h3><span class="app-tagline">Media server</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A personal media server with live TV and DVR support. An organised library, remote access, and sync for offline playback.</p>
<div class="app-features"><span class="app-feature">Streaming</span><span class="app-feature">Live TV</span><span class="app-feature">DVR</span><span class="app-feature">Sync</span></div>
<img src="/assets/emby-screenshot-1.webp" alt="Emby screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://emby.media" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Website</a>
<span class="open-source-badge" style="color: var(--warn);"><img src="/assets/checkmark-yellow.svg" alt="">Closed source</span>
</div>
</div>
<!-- Navidrome -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/navidrome-logo.svg" alt="Navidrome" class="app-logo">
<div class="app-title-area"><h3>Navidrome</h3><span class="app-tagline">Music server (Spotify)</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A light, modern music server. Stream your own music collection from anywhere; Subsonic-compatible, with many mobile apps.</p>
<div class="app-features"><span class="app-feature">Streaming</span><span class="app-feature">Subsonic API</span><span class="app-feature">Mobile apps</span><span class="app-feature">Playlists</span></div>
<img src="/assets/navidrome-screenshot-1.webp" alt="Navidrome screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/navidrome/navidrome" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Audiobookshelf -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/audiobookshelf-logo.svg" alt="Audiobookshelf" class="app-logo">
<div class="app-title-area"><h3>Audiobookshelf</h3><span class="app-tagline">Audiobooks & podcasts</span></div>
</div>
<div class="app-card-body">
<p class="app-description">An audiobook and podcast server. Details fetched for you, carry on where you stopped, and its own mobile apps.</p>
<div class="app-features"><span class="app-feature">Audiobooks</span><span class="app-feature">Podcasts</span><span class="app-feature">Sync</span><span class="app-feature">Mobile app</span></div>
<img src="/assets/audiobookshelf-screenshot-1.webp" alt="Audiobookshelf screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/advplyr/audiobookshelf" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- MeTube -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/metube-logo.svg" alt="MeTube" class="app-logo">
<div class="app-title-area"><h3>MeTube</h3><span class="app-tagline">Download videos from a link</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Download a video or a playlist from its link, as video or audio only. The downloads go to your drive; you see them in the file browser and your media player. Only your family members reach it.</p>
<div class="app-features"><span class="app-feature">Video and audio</span><span class="app-feature">Playlists</span><span class="app-feature">To your drive</span><span class="app-feature">Family only</span></div>
<img src="/assets/metube-screenshot-1.webp" alt="MeTube screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/alexta69/metube" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Calibre-web -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/calibre-web-logo.svg" alt="Calibre-Web Automated" class="app-logo">
<div class="app-title-area"><h3>Calibre-Web Automated</h3><span class="app-tagline">E-book library</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A web interface for your Calibre library. Browse, read and download your e-books from anywhere, with Kindle support.</p>
<div class="app-features"><span class="app-feature">E-books</span><span class="app-feature">Send to Kindle</span><span class="app-feature">OPDS</span><span class="app-feature">Reader</span></div>
<img src="/assets/calibre-web-screenshot-1.webp" alt="Calibre-Web Automated screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/crocodilestick/Calibre-Web-Automated" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Komga -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/komga-logo.svg" alt="Komga" class="app-logo">
<div class="app-title-area"><h3>Komga</h3><span class="app-tagline">Comics & manga server</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Manage and read comics, manga and magazines. A modern web reader, OPDS support and popular mobile apps.</p>
<div class="app-features"><span class="app-feature">Web reader</span><span class="app-feature">OPDS</span><span class="app-feature">Metadata</span><span class="app-feature">Tachiyomi</span></div>
<img src="/assets/komga-screenshot-1.webp" alt="Komga screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/gotson/komga" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Grimmory -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/grimmory-logo.svg" alt="Grimmory" class="app-logo">
<div class="app-title-area"><h3>Grimmory</h3><span class="app-tagline">E-book library in the browser</span></div>
</div>
<div class="app-card-body">
<p class="app-description">E-books and comics in a tidy library, with covers and details. Read in the browser with your progress saved; Kobo and KOReader sync, and an OPDS catalog for reader apps. Only your family members reach it, each with their own sign-in.</p>
<div class="app-features"><span class="app-feature">Browser reader</span><span class="app-feature">Kobo sync</span><span class="app-feature">KOReader</span><span class="app-feature">OPDS</span></div>
<img src="/assets/grimmory-screenshot-1.webp" alt="Grimmory screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/grimmory-tools/grimmory" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Sonarr -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/sonarr-logo.svg" alt="Sonarr" class="app-logo">
<div class="app-title-area"><h3>Sonarr</h3><span class="app-tagline">Series manager</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Downloads and organises series for you. Follow your favourite series and new episodes are downloaded automatically.</p>
<div class="app-features"><span class="app-feature">Auto download</span><span class="app-feature">Calendar</span><span class="app-feature">Quality profiles</span><span class="app-feature">Integrations</span></div>
<img src="/assets/sonarr-screenshot-1.webp" alt="Sonarr screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/Sonarr/Sonarr" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Radarr -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/radarr-logo.png" alt="Radarr" class="app-logo">
<div class="app-title-area"><h3>Radarr</h3><span class="app-tagline">Film manager</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Downloads and organises films for you. Make a wish list and the films arrive in your library on their own.</p>
<div class="app-features"><span class="app-feature">Wish list</span><span class="app-feature">Auto download</span><span class="app-feature">Quality profiles</span><span class="app-feature">Integrations</span></div>
<img src="/assets/radarr-screenshot-1.webp" alt="Radarr screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/Radarr/Radarr" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Seerr -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/seerr-logo.png" alt="Seerr" class="app-logo">
<div class="app-title-area"><h3>Seerr</h3><span class="app-tagline">Media request manager</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Ask for films and series the easy way. Family and friends can request titles, and the system downloads them for you.</p>
<div class="app-features"><span class="app-feature">Requests</span><span class="app-feature">Users</span><span class="app-feature">Notifications</span><span class="app-feature">Integrations</span></div>
<img src="/assets/seerr-screenshot-1.webp" alt="Seerr screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/Fallenbagel/jellyseerr" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- RoMM -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/romm-logo.svg" alt="RoMM" class="app-logo">
<div class="app-title-area"><h3>RoMM</h3><span class="app-tagline">ROM collection manager</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A good-looking web interface for your retro game ROM collection. Details and cover art fetched for you, sorted by platform, and playable in the browser.</p>
<div class="app-features"><span class="app-feature">ROM library</span><span class="app-feature">Metadata</span><span class="app-feature">EmulatorJS</span><span class="app-feature">IGDB</span></div>
<img src="/assets/romm-screenshot-1.webp" alt="RoMM screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/rommapp/romm" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Crafty Controller -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/crafty-logo.png" alt="Crafty Controller" class="app-logo">
<div class="app-title-area"><h3>Crafty Controller</h3><span class="app-tagline">Minecraft server manager</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A modern web manager for Minecraft servers. Run several servers from one interface, with automatic backups, player statistics and full remote access.</p>
<div class="app-features"><span class="app-feature">Multi-server</span><span class="app-feature">Backups</span><span class="app-feature">Console</span><span class="app-feature">Statistics</span></div>
<img src="/assets/crafty-screenshot-1.webp" alt="Crafty Controller screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://gitlab.com/crafty-controller/crafty-4" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
</div>
</div>
<!-- ==================== -->
<!-- 3. HOME & LIFESTYLE -->
<!-- ==================== -->
<div class="category-section" id="home">
<div class="category-header">
<span class="category-icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-home"/></svg></span>
<h2>Home & Lifestyle</h2>
<span class="app-count">14 apps</span>
</div>
<div class="app-grid">
<!-- Home Assistant -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/homeassistant-logo.svg" alt="Home Assistant" class="app-logo">
<div class="app-title-area"><h3>Home Assistant</h3><span class="app-tagline">Smart home hub</span></div>
</div>
<div class="app-card-body">
<p class="app-description">The world's most popular open-source smart home platform. More than 3000 integrations, local control and automations, with no cloud and full privacy.</p>
<div class="app-features"><span class="app-feature">3000+ integrations</span><span class="app-feature">Automations</span><span class="app-feature">Local control</span><span class="app-feature">Mobile app</span></div>
<img src="/assets/homeassistant-screenshot-1.webp" alt="Home Assistant screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/home-assistant/core" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- n8n -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/n8n-logo.svg" alt="n8n" class="app-logo">
<div class="app-title-area"><h3>n8n</h3><span class="app-tagline">Workflow automation</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Visual workflow automation in the style of Zapier or Make. Connect any service and build automations without code, on your own server.</p>
<div class="app-features"><span class="app-feature">400+ integrations</span><span class="app-feature">Visual editor</span><span class="app-feature">AI features</span><span class="app-feature">Webhooks</span></div>
<img src="/assets/n8n-screenshot-1.webp" alt="n8n screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/n8n-io/n8n" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge" style="color: var(--warn);"><img src="/assets/checkmark-yellow.svg" alt="">Restricted licence</span>
</div>
</div>
<!-- Tandoor Recipes -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/tandoor-logo.png" alt="Tandoor Recipes" class="app-logo">
<div class="app-title-area"><h3>Tandoor Recipes</h3><span class="app-tagline">Recipe manager</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Keep your recipes, plan meals and make a shopping list. Import recipes from the web and share them with your family.</p>
<div class="app-features"><span class="app-feature">Recipe import</span><span class="app-feature">Meal planning</span><span class="app-feature">Shopping list</span><span class="app-feature">Sharing</span></div>
<img src="/assets/tandoor-screenshot-1.webp" alt="Tandoor Recipes screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/TandoorRecipes/recipes" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge" style="color: var(--warn);"><img src="/assets/checkmark-yellow.svg" alt="">Restricted licence</span>
</div>
</div>
<!-- Mealie -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/mealie-logo.svg" alt="Mealie" class="app-logo">
<div class="app-title-area"><h3>Mealie</h3><span class="app-tagline">Recipes and meal plans</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A recipe manager and meal planner for the household. Import a recipe from a web page, plan the week's meals and get a shopping list, and share recipes with the family; the interface speaks English and Hungarian among others.</p>
<div class="app-features"><span class="app-feature">Recipe import</span><span class="app-feature">Weekly menu</span><span class="app-feature">Shopping list</span><span class="app-feature">Multilingual</span></div>
<img src="/assets/mealie-screenshot-1.webp" alt="Mealie screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/mealie-recipes/mealie" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Recipe Importer -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/recipe-importer-logo.svg" alt="Recipe Importer" class="app-logo">
<div class="app-title-area"><h3>Recipe Importer</h3><span class="app-tagline">From Hungarian recipe sites</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Import recipes from six Hungarian sites (mindmegette.hu, streetkitchen.hu, nosalty.hu, sobors.hu, kiskegyed.hu, gastrohobbi.hu) into Mealie and Tandoor, one at a time or in bulk, and edit them before they are saved.</p>
<div class="app-features"><span class="app-feature">6 Hungarian sites</span><span class="app-feature">Bulk import</span><span class="app-feature">Mealie</span><span class="app-feature">Tandoor</span></div>
<img src="/assets/recipe-importer-screenshot-1.webp" alt="Recipe Importer screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<span class="open-source-badge" style="color: var(--warn);"><img src="/assets/checkmark-yellow.svg" alt="">Felhom's own</span>
</div>
</div>
<!-- Wishlist -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/wishlist-logo.svg" alt="Wishlist" class="app-logo">
<div class="app-title-area"><h3>Wishlist</h3><span class="app-tagline">Family wish list</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A wish list you can share, for Christmas, birthdays and other occasions. The family can reserve gifts, so nobody buys the same present twice.</p>
<div class="app-features"><span class="app-feature">Groups</span><span class="app-feature">Reservations</span><span class="app-feature">Link import</span><span class="app-feature">PWA</span></div>
<img src="/assets/wishlist-screenshot-1.webp" alt="Wishlist screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/cmintey/wishlist" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Homebox -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/homebox-logo.svg" alt="Homebox" class="app-logo">
<div class="app-title-area"><h3>Homebox</h3><span class="app-tagline">Home inventory</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Keep track of what you own: sorted by location, tag and category, with warranties and what you paid. Scan a barcode to add something quickly, and have the list ready for an insurance claim.</p>
<div class="app-features"><span class="app-feature">Inventory</span><span class="app-feature">Warranties</span><span class="app-feature">Barcode</span><span class="app-feature">Tags</span></div>
<img src="/assets/homebox-screenshot-1.webp" alt="Homebox screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/sysadminsmedia/homebox" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Gramps Web -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/grampsweb-logo.png" alt="Gramps Web" class="app-logo">
<div class="app-title-area"><h3>Gramps Web</h3><span class="app-tagline">Family tree builder</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A web platform for family trees and genealogy. Build your family tree, add photos and documents, and share it with your family safely.</p>
<div class="app-features"><span class="app-feature">Family tree</span><span class="app-feature">GEDCOM</span><span class="app-feature">Collaboration</span><span class="app-feature">Sync</span></div>
<img src="/assets/grampsweb-screenshot-1.webp" alt="Gramps Web screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/gramps-project/gramps-web" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- SparkyFitness -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/sparkyfitness-logo.png" alt="SparkyFitness" class="app-logo">
<div class="app-title-area"><h3>SparkyFitness</h3><span class="app-tagline">Food diary</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Log what you eat and how many calories it comes to, track your weight and measurements on a graph, and record workouts. Set nutrition targets (protein, carbohydrate, fat) and follow them.</p>
<div class="app-features"><span class="app-feature">Calorie counter</span><span class="app-feature">Weight</span><span class="app-feature">Workouts</span><span class="app-feature">Nutrition targets</span></div>
<img src="/assets/sparkyfitness-screenshot-1.webp" alt="SparkyFitness screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/CodeWithCJ/SparkyFitness" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge" style="color: var(--warn);"><img src="/assets/checkmark-yellow.svg" alt="">Restricted licence</span>
</div>
</div>
<!-- Actual Budget -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/actualbudget-logo.svg" alt="Actual Budget" class="app-logo">
<div class="app-title-area"><h3>Actual Budget</h3><span class="app-tagline">Budget planner</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Local-first personal finance. Plan a budget, track transactions and set money goals.</p>
<div class="app-features"><span class="app-feature">Budget</span><span class="app-feature">Sync</span><span class="app-feature">Bank import</span><span class="app-feature">Reports</span></div>
<img src="/assets/actualbudget-screenshot-1.webp" alt="Actual Budget screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/actualbudget/actual" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- AdventureLog -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/adventurelog-logo.png" alt="AdventureLog" class="app-logo">
<div class="app-title-area"><h3>AdventureLog</h3><span class="app-tagline">Travel log</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Record your trips and adventures. A map view, photos and statistics about the places you have been.</p>
<div class="app-features"><span class="app-feature">Map</span><span class="app-feature">Photos</span><span class="app-feature">Statistics</span><span class="app-feature">Sharing</span></div>
<img src="/assets/adventurelog-screenshot-1.webp" alt="AdventureLog screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/seanmorley15/AdventureLog" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Wanderer -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/wanderer-logo.svg" alt="Wanderer" class="app-logo">
<div class="app-title-area"><h3>Wanderer</h3><span class="app-tagline">Hike planner</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Plan hikes and routes and keep your GPX files. A map with contour lines, and route statistics.</p>
<div class="app-features"><span class="app-feature">GPX import</span><span class="app-feature">Maps</span><span class="app-feature">Elevation</span><span class="app-feature">Routes</span></div>
<img src="/assets/wanderer-screenshot-1.webp" alt="Wanderer screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/Flomp/wanderer" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Dawarich -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/dawarich-logo.svg" alt="Dawarich" class="app-logo">
<div class="app-title-area"><h3>Dawarich</h3><span class="app-tagline">Instead of Google Timeline</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Your own location history on a map: your phone sends where you have been to your own server. A map, statistics and trips; bring your old data from a Google Takeout, GPX or GeoJSON file.</p>
<div class="app-features"><span class="app-feature">Map</span><span class="app-feature">Statistics</span><span class="app-feature">Takeout import</span><span class="app-feature">Mobile app</span></div>
<img src="/assets/dawarich-screenshot-1.webp" alt="Dawarich screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/Freika/dawarich" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Cal.com -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/calcom-logo.svg" alt="Cal.com" class="app-logo">
<div class="app-title-area"><h3>Cal.com</h3><span class="app-tagline">Appointment booking</span></div>
</div>
<div class="app-card-body">
<p class="app-description">An open-source Calendly alternative. Easy appointment booking with clients, calendar integrations and automatic reminders.</p>
<div class="app-features"><span class="app-feature">Booking page</span><span class="app-feature">Calendar sync</span><span class="app-feature">Teams</span><span class="app-feature">Reminders</span></div>
<img src="/assets/calcom-screenshot-1.webp" alt="Cal.com screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/calcom/cal.com" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
</div>
</div>
<!-- ==================== -->
<!-- 4. PRODUCTIVITY & KNOWLEDGE -->
<!-- ==================== -->
<div class="category-section" id="productivity">
<div class="category-header">
<span class="category-icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-chart-column"/></svg></span>
<h2>Productivity & Knowledge</h2>
<span class="app-count">12 apps</span>
</div>
<div class="app-grid">
<!-- Vikunja -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/vikunja-logo.svg" alt="Vikunja" class="app-logo">
<div class="app-title-area"><h3>Vikunja</h3><span class="app-tagline">Task manager (Todoist)</span></div>
</div>
<div class="app-card-body">
<p class="app-description">An open-source Todoist alternative. Tasks, projects and deadlines, in Kanban, Gantt and list views. Reminders and team work.</p>
<div class="app-features"><span class="app-feature">Kanban</span><span class="app-feature">Gantt</span><span class="app-feature">Reminders</span><span class="app-feature">Teams</span></div>
<img src="/assets/vikunja-screenshot-1.webp" alt="Vikunja screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/go-vikunja/vikunja" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Radicale -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/radicale-logo.svg" alt="Radicale" class="app-logo">
<div class="app-title-area"><h3>Radicale</h3><span class="app-tagline">Calendar and contacts</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Your phone calendar and contacts on your own server, not with Google or Apple. A shared family calendar; on Android DAVx5, on iPhone and Mac the built-in calendar syncs with it.</p>
<div class="app-features"><span class="app-feature">CalDAV</span><span class="app-feature">CardDAV</span><span class="app-feature">Family calendar</span><span class="app-feature">Thunderbird</span></div>
<img src="/assets/radicale-screenshot-1.webp" alt="Radicale screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/Kozea/Radicale" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Kimai -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/kimai-logo.png" alt="Kimai" class="app-logo">
<div class="app-title-area"><h3>Kimai</h3><span class="app-tagline">Time tracking</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Professional time tracking for freelancers and teams. Projects, clients, reports and invoice export in one system.</p>
<div class="app-features"><span class="app-feature">Projects</span><span class="app-feature">Reports</span><span class="app-feature">Export</span><span class="app-feature">Invoicing</span></div>
<img src="/assets/kimai-screenshot-1.webp" alt="Kimai screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/kimai/kimai" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Rallly -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/rallly-logo.svg" alt="Rallly" class="app-logo">
<div class="app-title-area"><h3>Rallly</h3><span class="app-tagline">Meeting poll (Doodle)</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Find a time for a meeting or an event, the easy way. A Doodle alternative: people vote without an account, and time zones are handled.</p>
<div class="app-features"><span class="app-feature">Polls</span><span class="app-feature">No sign-up</span><span class="app-feature">Time zones</span><span class="app-feature">Notifications</span></div>
<img src="/assets/rallly-screenshot-1.webp" alt="Rallly screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/lukevella/rallly" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Claper -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/claper-logo.svg" alt="Claper" class="app-logo">
<div class="app-title-area"><h3>Claper</h3><span class="app-tagline">Interactive presentations</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Live polls, questions and word clouds for presentations. A Mentimeter and AhaSlides alternative that makes your talks interactive.</p>
<div class="app-features"><span class="app-feature">Live polls</span><span class="app-feature">Questions</span><span class="app-feature">Word cloud</span><span class="app-feature">Reactions</span></div>
<img src="/assets/claper-screenshot-1.webp" alt="Claper screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/ClaperCo/Claper" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Ghost -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/ghost-logo.svg" alt="Ghost" class="app-logo">
<div class="app-title-area"><h3>Ghost</h3><span class="app-tagline">Blog & newsletter platform</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A modern publishing platform for bloggers and creators. Good-looking themes, a built-in newsletter, and members and subscriptions.</p>
<div class="app-features"><span class="app-feature">Blog</span><span class="app-feature">Newsletter</span><span class="app-feature">Members</span><span class="app-feature">SEO</span></div>
<img src="/assets/ghost-screenshot-1.webp" alt="Ghost screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/TryGhost/Ghost" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Paperless-ngx -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/paperless-ngx-logo.svg" alt="Paperless-ngx" class="app-logo">
<div class="app-title-area"><h3>Paperless-ngx</h3><span class="app-tagline">A digital filing cabinet</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Scan your paper documents and stop worrying about them. OCR, automatic sorting and full-text search.</p>
<div class="app-features"><span class="app-feature">OCR</span><span class="app-feature">Auto sorting</span><span class="app-feature">Search</span><span class="app-feature">Tags</span></div>
<img src="/assets/paperless-ngx-screenshot-1.webp" alt="Paperless-ngx screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/paperless-ngx/paperless-ngx" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- BookStack -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/bookstack-logo.svg" alt="BookStack" class="app-logo">
<div class="app-title-area"><h3>BookStack</h3><span class="app-tagline">Book-style documentation</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A simple self-hosted wiki. Arrange what you know into books, chapters and pages that are easy to search.</p>
<div class="app-features"><span class="app-feature">WYSIWYG</span><span class="app-feature">Books</span><span class="app-feature">Search</span><span class="app-feature">Permissions</span></div>
<img src="/assets/bookstack-screenshot-1.webp" alt="BookStack screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/BookStackApp/BookStack" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Outline -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/outline-logo.svg" alt="Outline" class="app-logo">
<div class="app-title-area"><h3>Outline</h3><span class="app-tagline">Team knowledge base</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A good-looking wiki and knowledge base for teams. Markdown, real-time collaboration and structured documentation.</p>
<div class="app-features"><span class="app-feature">Markdown</span><span class="app-feature">Collaboration</span><span class="app-feature">Search</span><span class="app-feature">Integrations</span></div>
<img src="/assets/outline-screenshot-1.webp" alt="Outline screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/outline/outline" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge" style="color: var(--warn);"><img src="/assets/checkmark-yellow.svg" alt="">Restricted licence</span>
</div>
</div>
<!-- Docmost -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/docmost-logo.png" alt="Docmost" class="app-logo">
<div class="app-title-area"><h3>Docmost</h3><span class="app-tagline">A Notion-like wiki</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A modern wiki and documentation platform with a Notion-like block editor. Spaces and pages in a tree, several people editing at once, and search across all of it.</p>
<div class="app-features"><span class="app-feature">Block editor</span><span class="app-feature">Co-editing</span><span class="app-feature">Search</span><span class="app-feature">Tables</span></div>
<img src="/assets/docmost-screenshot-1.webp" alt="Docmost screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/docmost/docmost" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Karakeep -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/karakeep-logo.svg" alt="Karakeep" class="app-logo">
<div class="app-title-area"><h3>Karakeep</h3><span class="app-tagline">Your own searchable archive</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Bookmarks, articles, notes and images in one place. Karakeep downloads and keeps the content of the pages you save, even if a page disappears later. Full-text search, a browser extension and a phone app.</p>
<div class="app-features"><span class="app-feature">Page saving</span><span class="app-feature">Search</span><span class="app-feature">Browser extension</span><span class="app-feature">Mobile app</span></div>
<img src="/assets/karakeep-screenshot-1.webp" alt="Karakeep screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/karakeep-app/karakeep" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- PrivateBin -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/privatebin-logo.png" alt="PrivateBin" class="app-logo">
<div class="app-title-area"><h3>PrivateBin</h3><span class="app-tagline">Encrypted note sharing</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A minimal, encrypted pastebin. The server cannot see what you share, which makes it right for sending sensitive text safely.</p>
<div class="app-features"><span class="app-feature">E2E encryption</span><span class="app-feature">Expiry</span><span class="app-feature">Burn after reading</span><span class="app-feature">Password protection</span></div>
<img src="/assets/privatebin-screenshot-1.webp" alt="PrivateBin screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/PrivateBin/PrivateBin" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
</div>
</div>
<!-- ==================== -->
<!-- 5. SYSTEM & DEVELOPMENT -->
<!-- ==================== -->
<div class="category-section" id="system">
<div class="category-header">
<span class="category-icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-wrench"/></svg></span>
<h2>System & Development</h2>
<span class="app-count">9 apps</span>
</div>
<div class="app-grid">
<!-- Vaultwarden -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/vaultwarden-logo.svg" alt="Vaultwarden" class="app-logo">
<div class="app-title-area"><h3>Vaultwarden</h3><span class="app-tagline">Password manager (Bitwarden)</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A light Bitwarden server. Keep your passwords safe and in sync on every device.</p>
<div class="app-features"><span class="app-feature">E2E encryption</span><span class="app-feature">Mobile app</span><span class="app-feature">Browser extension</span><span class="app-feature">2FA</span></div>
<img src="/assets/vaultwarden-screenshot-1.webp" alt="Vaultwarden screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/dani-garcia/vaultwarden" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Homepage -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/homepage-logo.svg" alt="Homepage" class="app-logo">
<div class="app-title-area"><h3>Homepage</h3><span class="app-tagline">Personal start page</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A good-looking, feature-rich start page for your server. Service status, widgets and bookmarks in one place.</p>
<div class="app-features"><span class="app-feature">Widgets</span><span class="app-feature">Integrations</span><span class="app-feature">Themes</span><span class="app-feature">Status</span></div>
<img src="/assets/homepage-screenshot-1.webp" alt="Homepage screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/gethomepage/homepage" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Glance -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/glance-logo.svg" alt="Glance" class="app-logo">
<div class="app-title-area"><h3>Glance</h3><span class="app-tagline">Information dashboard</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A minimal, fast dashboard for all kinds of information. RSS, weather, bookmarks, Reddit, YouTube and more on one page.</p>
<div class="app-features"><span class="app-feature">RSS</span><span class="app-feature">Weather</span><span class="app-feature">YouTube</span><span class="app-feature">Fast</span></div>
<img src="/assets/glance-screenshot-1.webp" alt="Glance screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/glanceapp/glance" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Uptime Kuma -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/uptimekuma-logo.svg" alt="Uptime Kuma" class="app-logo">
<div class="app-title-area"><h3>Uptime Kuma</h3><span class="app-tagline">Service monitoring</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A neat service monitor. Watch your websites and APIs and get told when something stops working.</p>
<div class="app-features"><span class="app-feature">HTTP/TCP/DNS</span><span class="app-feature">Notifications</span><span class="app-feature">Status page</span><span class="app-feature">Charts</span></div>
<img src="/assets/uptimekuma-screenshot-1.webp" alt="Uptime Kuma screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/louislam/uptime-kuma" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Grafana -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/grafana-logo.svg" alt="Grafana" class="app-logo">
<div class="app-title-area"><h3>Grafana</h3><span class="app-tagline">Data visualisation</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A professional monitoring and visualisation platform. Good-looking dashboards, alerts and analysis, from any data source.</p>
<div class="app-features"><span class="app-feature">Dashboards</span><span class="app-feature">Alerts</span><span class="app-feature">Data sources</span><span class="app-feature">Queries</span></div>
<img src="/assets/grafana-screenshot-1.webp" alt="Grafana screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/grafana/grafana" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Termix -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/termix-logo.svg" alt="Termix" class="app-logo">
<div class="app-title-area"><h3>Termix</h3><span class="app-tagline">Server manager (SSH)</span></div>
</div>
<div class="app-card-body">
<p class="app-description">A web SSH terminal and server management platform. Connect to your servers from a browser anywhere, manage SSH tunnels and edit files remotely.</p>
<div class="app-features"><span class="app-feature">SSH terminal</span><span class="app-feature">Tunnels</span><span class="app-feature">File manager</span><span class="app-feature">2FA</span></div>
<img src="/assets/termix-screenshot-1.webp" alt="Termix screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/Termix-SSH/Termix" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Gitea -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/gitea-logo.svg" alt="Gitea" class="app-logo">
<div class="app-title-area"><h3>Gitea</h3><span class="app-tagline">Git server (GitHub)</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Light, fast Git hosting. Your own GitHub or GitLab, with issue tracking, CI/CD and a package registry.</p>
<div class="app-features"><span class="app-feature">Git hosting</span><span class="app-feature">Issues</span><span class="app-feature">CI/CD</span><span class="app-feature">Wiki</span></div>
<img src="/assets/gitea-screenshot-1.webp" alt="Gitea screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/go-gitea/gitea" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- Code-Server -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/code-server-logo.svg" alt="Code-Server" class="app-logo">
<div class="app-title-area"><h3>Code-Server</h3><span class="app-tagline">VS Code in the browser</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Visual Studio Code in the browser. Work from anywhere, on any device, with the same familiar interface.</p>
<div class="app-features"><span class="app-feature">VS Code</span><span class="app-feature">Extensions</span><span class="app-feature">Terminal</span><span class="app-feature">Git</span></div>
<img src="/assets/code-server-screenshot-1.webp" alt="Code-Server screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/coder/code-server" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
<!-- OpenGist -->
<div class="app-card">
<div class="app-card-header">
<img src="/assets/opengist-logo.png" alt="OpenGist" class="app-logo">
<div class="app-title-area"><h3>OpenGist</h3><span class="app-tagline">Code snippets (Gist)</span></div>
</div>
<div class="app-card-body">
<p class="app-description">Your own GitHub Gist server. Share code snippets with syntax highlighting and Git-based version history.</p>
<div class="app-features"><span class="app-feature">Snippets</span><span class="app-feature">Syntax</span><span class="app-feature">Git</span><span class="app-feature">Embed</span></div>
<img src="/assets/opengist-screenshot-1.webp" alt="OpenGist screenshot" class="app-screenshot">
</div>
<div class="app-card-footer">
<a href="https://github.com/thomiceli/opengist" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Stats Section -->
<section class="stats-section">
<div class="container">
<div class="stats-grid">
<div class="stat-item">
<h3>56</h3>
<p>Apps available</p>
</div>
<div class="stat-item">
<h3>5</h3>
<p>Categories</p>
</div>
<div class="stat-item">
<h3>49</h3>
<p>Open source</p>
</div>
<div class="stat-item">
<h3>0 Ft</h3>
<p>Licence cost</p>
</div>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="cta-section">
<div class="container">
<h2>Can't find what you are looking for?</h2>
<p>This is the whole catalog. If you need something specific, get in touch — we will look at whether the right app can join it.</p>
<a href="/en/contact" class="cta-button">Get in touch →</a>
</div>
</section>
</main>
<footer>
<div class="container">
<p>© 2026 felhom.eu — Your own cloud, your own rules. Felhom serves households in Hungary.</p>
</div>
</footer>
<!-- Lightbox HTML -->
<div class="lightbox-overlay" id="lightbox">
<button class="lightbox-close" aria-label="Close">&times;</button>
<div class="lightbox-content">
<button class="lightbox-nav lightbox-prev" aria-label="Previous">‹</button>
<img class="lightbox-image" id="lightbox-img" src="" alt="">
<button class="lightbox-nav lightbox-next" aria-label="Next">›</button>
</div>
<div class="lightbox-counter" id="lightbox-counter"></div>
<div class="lightbox-dots" id="lightbox-dots"></div>
</div>
<script>
/**
* Screenshot Gallery / Lightbox functionality
* - Click on app screenshot to open lightbox
* - Automatically detects multiple screenshots (app-screenshot-1.webp, app-screenshot-2.webp, etc.)
* - Navigate with arrows or keyboard
*/
(function() {
'use strict';
// Debug mode - set to true for console logging
const DEBUG = false;
function log(...args) {
if (DEBUG) console.log('[Gallery]', ...args);
}
// DOM elements
const lightbox = document.getElementById('lightbox');
const lightboxImg = document.getElementById('lightbox-img');
const lightboxCounter = document.getElementById('lightbox-counter');
const lightboxDots = document.getElementById('lightbox-dots');
const closeBtn = lightbox.querySelector('.lightbox-close');
const prevBtn = lightbox.querySelector('.lightbox-prev');
const nextBtn = lightbox.querySelector('.lightbox-next');
// State
const state = {
images: [],
currentIndex: 0,
appName: ''
};
/**
* Check if an image URL exists
* @param {string} url
* @returns {Promise<boolean>}
*/
async function imageExists(url) {
return new Promise((resolve) => {
const img = new Image();
img.onload = () => resolve(true);
img.onerror = () => resolve(false);
img.src = url;
});
}
/**
* Detect all available screenshots for an app
* @param {string} appName
* @returns {Promise<string[]>}
*/
async function detectScreenshots(appName) {
const screenshots = [];
const maxScreenshots = 10; // Maximum to check
for (let i = 1; i <= maxScreenshots; i++) {
const url = `/assets/${appName}-screenshot-${i}.webp`;
const exists = await imageExists(url);
if (exists) {
screenshots.push(url);
log(`Found: ${url}`);
} else {
// Stop checking after first missing number
break;
}
}
// Fallback: if no numbered screenshots found, use the clicked image
if (screenshots.length === 0) {
const fallbackUrl = `/assets/${appName}-screenshot-1.webp`;
screenshots.push(fallbackUrl);
}
return screenshots;
}
/**
* Extract app name from screenshot URL
* @param {string} src
* @returns {string} - The app name
*/
function extractAppName(src) {
// Match patterns: app-screenshot-1.webp or app-screenshot-1.webp
const match = src.match(/\/assets\/([a-z0-9-]+)-screenshot(?:-\d+)?\.webp/i);
return match ? match[1] : '';
}
/**
* Update the lightbox display
*/
function updateLightbox() {
if (state.images.length === 0) return;
const currentImg = state.images[state.currentIndex];
lightboxImg.src = currentImg;
lightboxImg.alt = `${state.appName} screenshot ${state.currentIndex + 1}`;
// Update counter
lightboxCounter.textContent = `${state.currentIndex + 1} / ${state.images.length}`;
// Update dots
const dots = lightboxDots.querySelectorAll('.lightbox-dot');
dots.forEach((dot, i) => {
dot.classList.toggle('active', i === state.currentIndex);
});
// Update nav buttons
prevBtn.disabled = state.currentIndex === 0;
nextBtn.disabled = state.currentIndex === state.images.length - 1;
// Hide nav and dots if only one image
const singleImage = state.images.length <= 1;
prevBtn.style.display = singleImage ? 'none' : 'flex';
nextBtn.style.display = singleImage ? 'none' : 'flex';
lightboxDots.style.display = singleImage ? 'none' : 'flex';
lightboxCounter.style.display = singleImage ? 'none' : 'block';
}
/**
* Create navigation dots
*/
function createDots() {
lightboxDots.innerHTML = '';
state.images.forEach((_, i) => {
const dot = document.createElement('button');
dot.className = 'lightbox-dot' + (i === state.currentIndex ? ' active' : '');
dot.setAttribute('aria-label', `Go to image ${i + 1}`);
dot.addEventListener('click', () => goToImage(i));
lightboxDots.appendChild(dot);
});
}
/**
* Go to specific image
* @param {number} index
*/
function goToImage(index) {
if (index >= 0 && index < state.images.length) {
state.currentIndex = index;
updateLightbox();
}
}
/**
* Open lightbox for an app
* @param {HTMLImageElement} thumbnailImg
*/
async function openLightbox(thumbnailImg) {
const appName = extractAppName(thumbnailImg.src);
if (!appName) {
log('Could not extract app name from:', thumbnailImg.src);
return;
}
log('Opening lightbox for:', appName);
// Show loading state
lightbox.classList.add('active');
document.body.style.overflow = 'hidden';
lightboxImg.src = thumbnailImg.src; // Show thumbnail immediately
lightboxImg.alt = thumbnailImg.alt;
lightboxCounter.textContent = 'Loading...';
lightboxDots.innerHTML = '';
// Detect available screenshots
state.appName = appName;
state.images = await detectScreenshots(appName);
state.currentIndex = 0;
log('Found screenshots:', state.images);
createDots();
updateLightbox();
}
/**
* Close the lightbox
*/
function closeLightbox() {
lightbox.classList.remove('active');
document.body.style.overflow = '';
state.images = [];
state.currentIndex = 0;
}
/**
* Navigate to previous image
*/
function prevImage() {
if (state.currentIndex > 0) {
state.currentIndex--;
updateLightbox();
}
}
/**
* Navigate to next image
*/
function nextImage() {
if (state.currentIndex < state.images.length - 1) {
state.currentIndex++;
updateLightbox();
}
}
// Event Listeners
// Click on screenshot thumbnails
document.addEventListener('click', (e) => {
const screenshot = e.target.closest('.app-screenshot');
if (screenshot) {
e.preventDefault();
openLightbox(screenshot);
}
});
// Close button
closeBtn.addEventListener('click', closeLightbox);
// Navigation buttons
prevBtn.addEventListener('click', prevImage);
nextBtn.addEventListener('click', nextImage);
// Click on overlay (outside image) to close
lightbox.addEventListener('click', (e) => {
if (e.target === lightbox) {
closeLightbox();
}
});
// Keyboard navigation
document.addEventListener('keydown', (e) => {
if (!lightbox.classList.contains('active')) return;
switch (e.key) {
case 'Escape':
closeLightbox();
break;
case 'ArrowLeft':
prevImage();
break;
case 'ArrowRight':
nextImage();
break;
}
});
// Touch/swipe support for mobile
let touchStartX = 0;
let touchEndX = 0;
lightbox.addEventListener('touchstart', (e) => {
touchStartX = e.changedTouches[0].screenX;
}, { passive: true });
lightbox.addEventListener('touchend', (e) => {
touchEndX = e.changedTouches[0].screenX;
const diff = touchStartX - touchEndX;
if (Math.abs(diff) > 50) { // Minimum swipe distance
if (diff > 0) {
nextImage(); // Swipe left = next
} else {
prevImage(); // Swipe right = prev
}
}
}, { passive: true });
log('Gallery initialized');
})();
</script>
<script>
(function() {
var hamburger = document.getElementById('hamburger');
var navLinks = document.querySelector('.nav-links');
var overlay = document.getElementById('mobileOverlay');
var body = document.body;
if (!hamburger || !navLinks || !overlay) {
console.warn('[mobile-menu] Missing elements:', {
hamburger: !!hamburger,
navLinks: !!navLinks,
overlay: !!overlay
});
return;
}
function openMenu() {
hamburger.classList.add('is-active');
navLinks.classList.add('is-open');
overlay.classList.add('is-visible');
body.classList.add('menu-open');
hamburger.setAttribute('aria-expanded', 'true');
hamburger.setAttribute('aria-label', 'Close menu');
}
function closeMenu() {
hamburger.classList.remove('is-active');
navLinks.classList.remove('is-open');
overlay.classList.remove('is-visible');
body.classList.remove('menu-open');
hamburger.setAttribute('aria-expanded', 'false');
hamburger.setAttribute('aria-label', 'Open menu');
}
hamburger.addEventListener('click', function() {
if (navLinks.classList.contains('is-open')) {
closeMenu();
} else {
openMenu();
}
});
overlay.addEventListener('click', closeMenu);
navLinks.querySelectorAll('a').forEach(function(link) {
link.addEventListener('click', closeMenu);
});
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && navLinks.classList.contains('is-open')) {
closeMenu();
}
});
window.addEventListener('resize', function() {
if (window.innerWidth > 900 && navLinks.classList.contains('is-open')) {
closeMenu();
}
});
})();
</script>
</body>
</html>