Files
felhom.eu/website/en/technology.html
T
admin 30b932bb10
gates / gates (push) Successful in 5m34s
website: publish the closed-test legal set (R-813 narrowed)
Two new Hungarian pages, live on push: /adatkezeles (privacy notice) and
/feltetelek (what the free closed test is, and is not). Operator rulings of
2026-10-09: no company exists yet, so the operator is named as a PRIVATE
PERSON with no postal address and no phone; publish before the lawyer has
seen it, because the site was collecting data with no notice at all; the full
ASZF, the impresszum and the review wait for the company (R-802, R-809).

- All 18 pages carry the operator, info@felhom.eu and both links in the
  footer. Counted, not assumed: 18 pages found = 18 with both links = 18
  structurally valid. English footers say the legal texts are Hungarian.
- The contact form stopped claiming something untrue. The old consent said
  "az adatokat harmadik felnek nem adjuk ki" while Resend, Cloudflare and
  Google carry the message. Both languages replaced; the link opens in a new
  tab so a filled form is not lost.
- site_gates.py NO_TWIN gains the two pages ON PURPOSE, with the reason in a
  comment: an unreviewed English legal text would be worse than an honest
  pointer from the English footer.
- documentation/legal/{adatkezelesi-tajekoztato,feltetelek}-1.0.md are the
  text of record, DERIVED from the published HTML so they cannot drift. The
  drafts are kept and marked superseded for the closed test.

FOUR LOAD-BEARING CLAIMS WERE MEASURED, not copied from a vendor or a README:

  cookies      zero, and no local storage - checked in the browser WITH A
               POSITIVE CONTROL (a probe cookie WAS visible to the same
               method) after the tracker fired; no Set-Cookie on any response
  beacon       the exact Umami payload: site id, screen, language, title,
               url, referrer - no visitor identifier
  Cloudflare   DNS only: the public A record 37.191.56.193 is not a
               Cloudflare address, so site traffic cannot be proxied
  fsn1         Falkenstein, Germany (Hetzner's own location list)

Also measured: felhom-ep0-copy-gc.timer is installed and RAN SUCCESSFULLY
(2026-10-09 08:00, exit 0), so "deleted within 30 days" is true today where
on 2026-10-08 it was written but not switched on.

Three retentions are stated as having NO deadline, deliberately and with the
operator's word: website statistics, web server logs and contact messages
have no automatic deletion, and the pages say so instead of promising a date
nothing enforces. Every other period is enforced by configuration and cited.

No placeholder survived onto either page (0 of "[[", control: the draft still
has 36). The impresszum and the full ASZF are NOT published.

R-813 -> NARROWED. R-915 unblocked: the operator enters the two URLs in the
Meta app's Basic settings; the Live switch stays a separate decision.
R-917 and R-920 -> DEFERRED on the operator's (c): park, publish as posts
once posting starts.
2026-10-09 12:11:37 +02:00

511 lines
30 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>Technology — Docker, the Dashboard and Proxmox for a home server | Felhom.eu</title>
<meta name="description" content="Industry-grade technology at home, in Hungary: Docker containers, a Dashboard in English or Hungarian, Proxmox virtualisation. HTTPS and an encrypted tunnel — with no open port.">
<meta name="keywords" content="Docker, dashboard, Proxmox, container, virtualisation, reverse proxy, HTTPS, encrypted tunnel, home server technology">
<meta name="robots" content="index, follow">
<link rel="canonical" href="https://felhom.eu/en/technology">
<link rel="alternate" hreflang="hu" href="https://felhom.eu/technologiak">
<link rel="alternate" hreflang="en" href="https://felhom.eu/en/technology">
<link rel="alternate" hreflang="x-default" href="https://felhom.eu/technologiak">
<meta property="og:type" content="article">
<meta property="og:url" content="https://felhom.eu/en/technology">
<meta property="og:title" content="Professional technology for a home server">
<meta property="og:description" content="Docker, a Dashboard in English or Hungarian, Proxmox — industry-grade tools at home.">
<meta property="og:image" content="https://felhom.eu/assets/og-image-en.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="Professional technology for a home server">
<meta name="twitter:description" content="Docker, a Dashboard in English or Hungarian, Proxmox — industry tools, at home.">
<meta name="twitter:image" content="https://felhom.eu/assets/og-image-en.png">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "The technology behind a Felhom home server",
"description": "Docker containers, a Dashboard in English or Hungarian and Proxmox virtualisation for a home server.",
"author": {"@type": "Organization", "name": "Felhom.eu"},
"publisher": {"@type": "Organization", "name": "Felhom.eu", "logo": {"@type": "ImageObject", "url": "https://felhom.eu/assets/logo.png"}},
"mainEntityOfPage": "https://felhom.eu/en/technology"
}
</script>
<!-- shared assets: bump ?v= together on any site.css/icons.svg change -->
<link rel="stylesheet" href="/assets/site.css?v=6">
<link rel="icon" type="image/png" href="/assets/logo_favicon_2.svg">
<script defer src="/assets/gallery.js?v=2"></script>
<script defer src="https://stats.felhom.eu/script.js" data-website-id="d419db57-5e1c-48df-bdb3-c29f25fb1661"></script>
</head>
<body class="page-technologiak">
<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">Apps</a></li>
<li><a href="/en/technology" class="active">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="/technologiak" lang="hu" hreflang="hu" class="lang-globe-item">Magyar</a></li><li><a href="/en/technology" 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>The <span>technology</span></h1>
<p>Modern, proven tools for running a home server. This is how we build the system.</p>
</div>
</section>
<!-- Table of Contents -->
<section class="content-section" style="padding-top: 0;">
<div class="container">
<div class="toc-nav">
<h3>Contents</h3>
<ul class="toc-links">
<li><a href="#containers">Why containers?</a></li>
<li><a href="#dashboard">The control layer (Dashboard)</a></li>
<li><a href="#proxmox">Virtualisation (Proxmox)</a></li>
<li><a href="#network">Network and security</a></li>
<li><a href="#storage">Storage</a></li>
<li><a href="#hardware">Hardware set-ups</a></li>
</ul>
</div>
</div>
</section>
<!-- Miért konténerek? -->
<section class="content-section alt-bg" id="containers">
<div class="container">
<div class="section-header">
<h2>Why <span>containers?</span></h2>
<p>The cornerstone of running a modern server</p>
</div>
<div class="info-card">
<h3><span class="icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-package"/></svg></span> What is a container?</h3>
<p>Imagine that every app runs in its own sealed "box". The box holds the app and everything it depends on – so it works the same way anywhere, on any server.</p>
<p>Containers (Docker) changed how servers are run: simpler installs, easier updates, and more reliable operation.</p>
<div class="highlight-box">
<p><strong>An analogy:</strong> as if every app lived in its own flat in a block of flats. It has its own front door and its own meters, and it does not bother the neighbours – but they still share one building.</p>
</div>
</div>
<div class="comparison-grid">
<div class="comparison-card">
<div class="card-icon"><svg class="ico-tile" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-monitor"/></svg></div>
<h3>Traditional install</h3>
<div class="subtitle">"Straight onto the system"</div>
<p>The apps are installed straight onto the operating system. They can clash with each other, and they are hard to remove.</p>
<ul class="feature-list cons">
<li>Dependencies can get tangled</li>
<li>Hard to reproduce on another server</li>
<li>Update = risk</li>
<li>Removing an app leaves "rubbish" behind</li>
</ul>
</div>
<div class="comparison-card recommended">
<div class="card-icon"><svg class="ico-tile" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-container"/></svg></div>
<h3>Container install</h3>
<div class="subtitle">Docker</div>
<p>Every app runs on its own. A clean, tidy system that is easy to manage.</p>
<ul class="feature-list">
<li>Fully isolated apps</li>
<li>One command = installed</li>
<li>Simple updates, and a simple way back</li>
<li>Reproducible anywhere</li>
</ul>
</div>
</div>
</div>
</section>
<!-- Single Node - vezérlőpult -->
<section class="content-section" id="dashboard">
<div class="container">
<div class="section-header">
<h2>The control layer: <span>the Dashboard</span></h2>
<p>The interface of every Felhom box, in English or Hungarian</p>
</div>
<div class="info-card">
<h3><span class="icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-target"/></svg></span> What does the Dashboard do?</h3>
<p>The Dashboard is on every Felhom box: it is the interface, in English or Hungarian, that runs your system on its Proxmox base. It was designed for home servers: you install apps in a few clicks and never touch a command line — Docker and Proxmox do the work in the background.</p>
<ul class="feature-list">
<li>A web interface in English or Hungarian – the household chooses, and no command-line knowledge is needed</li>
<li>App catalog – 56 apps to install in a few clicks</li>
<li>Resource view – memory and storage use as it happens</li>
<li>Automatic backups – databases and files, with their status watched</li>
<li>App updates – only versions we have tried, a fresh backup first, and if the new version does not start, the box goes back to the previous one by itself</li>
<li>System monitoring – health watched all the time, with alerts</li>
</ul>
<div class="dash-grid">
<figure class="dash-shot">
<a href="/assets/dashboard-apps-en.webp" data-gallery="dashboard"><img src="/assets/dashboard-apps-en.webp" alt="The Apps page: cards of installed and installable apps, with their status" width="1440" height="900" loading="lazy"></a>
<figcaption><strong>Apps</strong> — install in a few clicks, and see what runs and what is up to date.</figcaption>
</figure>
<figure class="dash-shot">
<a href="/assets/dashboard-backups-en.webp" data-gallery="dashboard"><img src="/assets/dashboard-backups-en.webp" alt="The backups page: each app's database backed up overnight, and checked" width="1440" height="900" loading="lazy"></a>
<figcaption><strong>Backups</strong> — every night each app's database is backed up and checked.</figcaption>
</figure>
</div>
<div class="highlight-box">
<p><strong>Good for:</strong> a home media server, a family cloud, personal projects, a small office.</p>
</div>
</div>
<div class="stack-diagram">
<h3>How a Felhom box is built</h3>
<div class="stack-layers">
<div class="stack-layer">
<div class="layer-label">Control + apps</div>
<div class="layer-content highlight">
<div class="layer-name">Dashboard + Apps</div>
<div class="layer-tech">An interface in English or Hungarian · Nextcloud, Jellyfin, Immich…</div>
</div>
</div>
<div class="stack-layer">
<div class="layer-label">Container engine</div>
<div class="layer-content">
<div class="layer-name">Docker</div>
<div class="layer-tech">The apps run in isolated containers</div>
</div>
</div>
<div class="stack-layer">
<div class="layer-label">System environment</div>
<div class="layer-content">
<div class="layer-name">Isolated system environment</div>
<div class="layer-tech">Your box — a cleanly separated system</div>
</div>
</div>
<div class="stack-layer">
<div class="layer-label">Base layer</div>
<div class="layer-content">
<div class="layer-name">Proxmox VE</div>
<div class="layer-tech">Virtualisation base · backing up the whole box, restoring</div>
</div>
</div>
<div class="stack-layer">
<div class="layer-label">Hardware</div>
<div class="layer-content">
<div class="layer-name">The server machine</div>
<div class="layer-tech">Mini PC, tower or server</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Proxmox -->
<section class="content-section alt-bg" id="proxmox">
<div class="container">
<div class="section-header">
<h2>The base layer: <span>Proxmox</span></h2>
<p>Every Felhom machine is built on this stable base</p>
</div>
<div class="info-card">
<h3><span class="icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-layers"/></svg></span> What is Proxmox?</h3>
<p>Proxmox VE is a free, professional virtualisation platform — the same kind of technology data centres and companies use. It is the base of every Felhom system: we build every machine on it, and the isolated system environment your apps run in sits on top of it.</p>
<div class="highlight-box">
<p><svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-layers"/></svg> <strong>The base, not an option:</strong> Proxmox is on every Felhom box. You do not need to know about it or deal with it — it works quietly in the background, and it is what makes your system safe and able to be backed up.</p>
</div>
</div>
<div class="info-card">
<h3><span class="icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-target"/></svg></span> What does the Proxmox base give you?</h3>
<ul class="feature-list">
<li><strong>A backup before each update</strong> – before an app is updated, a fresh backup is made, and if the new version does not start, the box puts the previous one back by itself</li>
<li><strong>The whole system is backed up</strong> – not only your data: the whole box goes into a backup too, and it can be restored from it</li>
<li><strong>Clean separation</strong> – the control layer and your apps run well apart, which makes the system more stable and safer</li>
<li><strong>A fast, repeatable install</strong> – setting up a new box is quick and predictable, the same way every time</li>
</ul>
<div class="highlight-box">
<p><strong>One base, one job:</strong> on a Felhom box, Proxmox runs a single isolated system environment — the one your apps work in.</p>
</div>
</div>
</div>
</section>
<!-- Hálózat -->
<section class="content-section alt-bg" id="network">
<div class="container">
<div class="section-header">
<h2>Network and <span>security</span></h2>
<p>How do you reach your server safely, from anywhere?</p>
</div>
<div class="info-card">
<h3><span class="icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-rotate-cw"/></svg></span> Reverse Proxy</h3>
<p>A reverse proxy is a "doorkeeper" that takes incoming requests and passes them to the right app. It also handles the HTTPS encryption.</p>
<div class="network-flow">
<div class="flow-node">
<div class="node-icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-globe"/></svg></div>
<div class="node-label">Internet</div>
</div>
<div class="flow-arrow">→</div>
<div class="flow-node">
<div class="node-icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-lock"/></svg></div>
<div class="node-label">Reverse Proxy</div>
<div class="node-tech">Traefik</div>
</div>
<div class="flow-arrow">→</div>
<div class="flow-node">
<div class="node-icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-package"/></svg></div>
<div class="node-label">App</div>
</div>
</div>
<ul class="feature-list">
<li><strong>Traefik</strong> – every app on its own subdomain, over HTTPS</li>
<li><strong>Encrypted tunnel</strong> – the box itself builds the connection outwards, so no port has to be opened at home</li>
</ul>
</div>
<div class="info-card">
<h3><span class="icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-shield"/></svg></span> Protection</h3>
<ul class="feature-list">
<li><strong>No open port</strong> – from outside, the box is reached only through the encrypted tunnel</li>
<li><strong>Own sign-in</strong> – every app has its own accounts, and the Dashboard has a password</li>
<li><strong>Family gate</strong> – some apps sit behind each family member's own sign-in, so a stranger never even reaches the app</li>
<li><strong>Security updates</strong> – the box's system gets them by itself</li>
</ul>
</div>
</div>
</section>
<!-- Tárolás -->
<section class="content-section" id="storage">
<div class="container">
<div class="section-header">
<h2>Storage and <span>data safety</span></h2>
<p>Where and how should you keep your data?</p>
</div>
<div class="comparison-grid">
<div class="comparison-card">
<div class="card-icon"><svg class="ico-tile" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-zap"/></svg></div>
<h3>SSD (NVMe/SATA)</h3>
<div class="subtitle">Fast storage</div>
<ul class="feature-list">
<li>Operating system</li>
<li>Databases</li>
<li>Apps</li>
</ul>
</div>
<div class="comparison-card">
<div class="card-icon"><svg class="ico-tile" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-database"/></svg></div>
<h3>HDD</h3>
<div class="subtitle">Large capacity</div>
<ul class="feature-list">
<li>Media library</li>
<li>Photo archive</li>
<li>Backups</li>
</ul>
</div>
</div>
<div class="info-card" style="margin-top: 32px;">
<h3><span class="icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-rotate-cw"/></svg></span> Backups on three levels – how we protect your data</h3>
<p>Every night a Felhom box makes a <strong>backup on the box</strong>, a <strong>second copy on a second drive</strong>, and an <strong>encrypted copy on remote storage</strong>. The levels protect together: the local one is fast, and the remote one survives even if the box itself is physically harmed.</p>
<div class="warning-box">
<p><svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-triangle-alert"/></svg> <strong>More disks are not a backup on their own!</strong> RAID-like set-ups protect against hardware failure, but not against an accidental delete or ransomware. That is why our backups always sit on a separate level, not in the disks.</p>
</div>
</div>
</div>
</section>
<!-- Hardver konfigurációk -->
<section class="content-section alt-bg" id="hardware">
<div class="container">
<div class="section-header">
<h2>Hardware <span>set-ups</span></h2>
<p>Which machine do you need? A few example set-ups</p>
</div>
<div class="hardware-grid">
<div class="hardware-card">
<div class="hardware-card-header">
<div class="hw-icon"><svg class="ico-tile" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-package"/></svg></div>
<h3>Mini PC + NAS</h3>
<div class="hw-subtitle">Starter / Home</div>
</div>
<div class="hardware-card-body">
<p>Compact, quiet and energy-saving.</p>
<ul class="spec-list">
<li><span class="spec-label">CPU</span><span class="spec-value">Intel N100</span></li>
<li><span class="spec-label">RAM</span><span class="spec-value">16-32 GB</span></li>
<li><span class="spec-label">SSD</span><span class="spec-value">256-512 GB</span></li>
<li><span class="spec-label">Power use</span><span class="spec-value">15-35W</span></li>
</ul>
<div class="price-range">
<div class="label">Estimated cost</div>
<div class="price">80.000 - 150.000 Ft</div>
</div>
</div>
</div>
<div class="hardware-card">
<div class="hardware-card-header">
<div class="hw-icon"><svg class="ico-tile" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-radio-tower"/></svg></div>
<h3>Tower server</h3>
<div class="hw-subtitle">Advanced / Family</div>
</div>
<div class="hardware-card-body">
<p>More power and more storage.</p>
<ul class="spec-list">
<li><span class="spec-label">CPU</span><span class="spec-value">Intel i5/i7</span></li>
<li><span class="spec-label">RAM</span><span class="spec-value">32-64 GB</span></li>
<li><span class="spec-label">Storage</span><span class="spec-value">4-8 TB</span></li>
<li><span class="spec-label">Power use</span><span class="spec-value">50-120W</span></li>
</ul>
<div class="price-range">
<div class="label">Estimated cost</div>
<div class="price">200.000 - 400.000 Ft</div>
</div>
</div>
</div>
<div class="hardware-card">
<div class="hardware-card-header">
<div class="hw-icon"><svg class="ico-tile" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-building-2"/></svg></div>
<h3>Rack server</h3>
<div class="hw-subtitle">Business / on request</div>
</div>
<div class="hardware-card-body">
<p>Industrial quality, high reliability.</p>
<ul class="spec-list">
<li><span class="spec-label">CPU</span><span class="spec-value">Xeon / EPYC</span></li>
<li><span class="spec-label">RAM</span><span class="spec-value">64-256 GB ECC</span></li>
<li><span class="spec-label">Storage</span><span class="spec-value">8-24 bay</span></li>
<li><span class="spec-label">Extra</span><span class="spec-value">IPMI, red. PSU</span></li>
</ul>
<div class="price-range">
<div class="label">Estimated cost (used)</div>
<div class="price">150.000 - 600.000 Ft</div>
</div>
</div>
</div>
</div>
<div class="info-card" style="margin-top: 48px;">
<h3><span class="icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-lightbulb"/></svg></span> Which one should you choose?</h3>
<div class="highlight-box">
<p><strong>Our advice:</strong> start small! A good mini PC is enough for most homes, and you can expand it later. A rack server is a business / on-request set-up — a home rarely needs one.</p>
</div>
</div>
</div>
</section>
<!-- CTA -->
<section class="cta-section">
<div class="container">
<h2>Not sure which <span>set-up is right for you?</span></h2>
<p>Let's talk through what you need, and we will help you find the right set-up.</p>
<a href="/en/contact" class="cta-button">Get in touch →</a>
<a href="/en/apps" class="cta-button-secondary">Browse the apps →</a>
</div>
</section>
</main>
<footer>
<div class="container">
<p>© 2026 felhom.eu — Your own cloud, your own rules. Felhom serves households in Hungary.</p>
<p class="footer-legal">Operated by Nagyfenyvesi Viktor · <a href="mailto:info@felhom.eu">info@felhom.eu</a> · <a href="/adatkezeles">Privacy notice (Hungarian)</a> · <a href="/feltetelek">Terms (Hungarian)</a></p>
</div>
</footer>
<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>