website: the dashboard shown — 4 real screenshots per language on the home page, 2 on the technology page (controller 0.303.0, demo-hp household guest, privacy-scanned); site gate 19 (pictures in the page's language) + decoy; R-906, R-907 (dashboard defects seen); 129 -> 131
gates / gates (push) Successful in 4m12s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb
@@ -41,6 +41,13 @@ to the visible answers, and nothing after `</html>`.
|
||||
the nav listing every language in its own name, the current one marked. **A new language = one entry in
|
||||
`LANGS` in `scripts/site_gates.py` (and the globe's list) + its twin pages** — nothing else in the switch changes.
|
||||
|
||||
## The dashboard pictures
|
||||
|
||||
`website/assets/dashboard-<page>-hu.webp` / `-en.webp` show **controller 0.303.0** (taken 2026-10-08 on demo-hp's
|
||||
household guest; method and privacy scan: `documentation/audits/website-dashboard-2026-10-08/`). **A controller
|
||||
release that visibly changes a pictured page (Launcher, Apps, an app's page, Backup → Apps) should refresh them.**
|
||||
Every caption is a claim (`captions-claims.md` there). Gate 19 keeps each page on its own language's pictures.
|
||||
|
||||
## The encoding fences
|
||||
|
||||
- **All `website/` HTML is UTF-8 *with BOM*. Preserve it.** An editor that strips the BOM is a
|
||||
|
||||
@@ -1,36 +1,75 @@
|
||||
# REPORT — dashboard screenshots for the website (2026-10-08): STOPPED at the baseline
|
||||
# REPORT — the dashboard on the website (2026-10-08)
|
||||
|
||||
> `REPORT-website-dashboard.md`, not `REPORT.md`: another session works in this repo today.
|
||||
> `REPORT-website-dashboard.md`, not `REPORT.md`: another session works in this repo today. This file replaces this
|
||||
> morning's „stopped at the baseline" version of it (commit 4b5f74e4); the operator then approved moving 9202 to the
|
||||
> fleet's controller and said the physical demo boxes are test boxes too.
|
||||
|
||||
| Part | What | State |
|
||||
|---|---|---|
|
||||
| Baseline | a scratch guest that runs the fleet's controller | **Not met — stopped here, as the brief says** |
|
||||
| A | the scene + screenshots | not started |
|
||||
| B | the pages + the hu/en picture gate | not started |
|
||||
| C | rules, CHANGELOG, STATUS | not started (nothing changed on the site) |
|
||||
| Baseline | a box on the fleet's controller (0.303.0) | 9202 moved 0.301.0 → 0.303.0 (operator's word); pictures finally from demo-hp's household guest 9201 (see below) |
|
||||
| A | scene + screenshots, hu and en, privacy check | **Done** — 8 pictures published, 6 taken and kept off the site |
|
||||
| B | home-page section, technology page, captions as claims, gate 19 + decoy | **Done** |
|
||||
| C | rules, CHANGELOG, STATUS, rows | **Done** — two rows for dashboard defects (R-906, R-907) |
|
||||
|
||||
## What was measured (read only)
|
||||
**Register:** before **129**, after **131**, opened **2** (R-906, R-907), closed **0**.
|
||||
|
||||
- **Fleet controller: 0.303.0** — `STATUS.md` header („demo-hp, demo-felhom and Tester 1 run … controller 0.303.0"),
|
||||
newest entry in `felhom-controller/CHANGELOG.md`: `## v0.303.0` (2026-10-07).
|
||||
- **Scratch guest 9202 runs 0.301.0** — `pct exec 9202 -- cat /etc/felhom-controller-image` →
|
||||
`gitea.dooplex.hu/admin/felhom-controller:0.301.0`; `docker ps` shows `felhom-controller … 0.301.0 Up 55 minutes`.
|
||||
- **No other scratch guest exists** — `pct list` on the demo-hp host: 9201 (demo-hp, the demo household — no contact),
|
||||
9202 (scratch), 9401 (`upgrade-harness`, the catalog bench, stopped; it runs no controller). demo-felhom and the
|
||||
Testers are fenced.
|
||||
- **The site has no dashboard picture today** — `website/assets/` holds no `dashboard*` file.
|
||||
- 9202's controller restarted 55 minutes before this check, and it carries paperless-ngx: **another session may be
|
||||
using 9202 today** (session 1 reported „R-762 closed (9202 proven)" in d9147b02).
|
||||
## Why the pictures come from 9201, not 9202
|
||||
|
||||
Nothing was installed, changed or removed on 9202. The only host command was `pct exec 9202 -- …` (read) and `pct list`.
|
||||
On 9202 (now 0.303.0) four family apps were installed and a real backup ran, but **every page carried „+ 5 további
|
||||
figyelmeztetés"**: nine `disk-not-separate` warnings (9202's „second drive" is a folder on the host disk, plus earlier
|
||||
sessions' leftover folders) and the hub-off warning — true for a scratch guest, not a household's normal state. Faking it
|
||||
away was not an option. demo-hp's household guest 9201 runs 0.303.0 with **no alerts** (`/api/debug/dump` →
|
||||
`alerts: []`) and last night's app backups OK, so the pictures were taken there, read only. The one change: the
|
||||
household language switched to English for the English pictures and back to Hungarian right after (both 302; read back
|
||||
`lang="hu"`, first sidebar item „Indítópult").
|
||||
|
||||
## Pictures (`website/assets/`, 1440 × 900 WebP)
|
||||
|
||||
| Picture | hu bytes | en bytes | On |
|
||||
|---|---|---|---|
|
||||
| `dashboard-start` (Launcher) | 34,024 | 31,948 | home |
|
||||
| `dashboard-apps` (Apps) | 59,018 | 54,156 | home, technology |
|
||||
| `dashboard-app` (Paperless-ngx's page) | 83,124 | 78,992 | home |
|
||||
| `dashboard-backups` (Backup → Apps) | 52,638 | 45,292 | home, technology |
|
||||
|
||||
Kept off the site: the backups overview (a true amber „whole-box backup on the system disk" notice on demo-hp), the System
|
||||
page (operator details), the phone view (the launcher's share button runs off the edge at 390 px — R-907).
|
||||
|
||||
## Privacy check, per picture (`documentation/audits/website-dashboard-2026-10-08/privacy-scan.txt`)
|
||||
|
||||
Searched in each page's text (body, title/alt/placeholder/input values): e-mail addresses, IPv4 addresses, long hex
|
||||
(tokens/keys), the host's serial, password/recovery words, any domain other than the test domain. **All 8: 0 e-mails,
|
||||
0 IPs, 0 serials, no domain but `enkisfelhom.hu` (demo-hp's demo test domain) and `felhom.eu`.** One long hex per page =
|
||||
the hidden CSRF field, not visible in the picture. Password-word hits on the app pages are help text, not a password.
|
||||
**Positive control:** an app name known to be on the page (`Paperless-ngx` / `BookStack`) — found 8 of 8.
|
||||
|
||||
## Captions = claims (`captions-claims.md`)
|
||||
|
||||
Launcher → map E Indítópult (IMPLEMENTED); Apps → map B deploy + version (PROVEN-LIVE); an app's page → map B app
|
||||
lifecycle (PROVEN-LIVE) + catalog copy + file access (IMPLEMENTED); Backup → Apps → map C nightly DB dumps (PROVEN-LIVE).
|
||||
|
||||
## Clean-up
|
||||
|
||||
9202: Vaultwarden, Jellyfin, Nextcloud, Immich removed through the product (data and backups too); Paperless-ngx
|
||||
(running) and PrivateBin (stopped) were there before and are as found; screenshot folder removed, session files
|
||||
shredded; 9202 stays on 0.303.0. 9201: language back to Hungarian. demo-hp host: only `pct exec`/`pct list`. Hub:
|
||||
nothing. demo-felhom: one read-only `pct list` + `docker ps` (only one app there, so not used).
|
||||
|
||||
## Gate 19 decoy (`decoy.txt`)
|
||||
|
||||
Mutation: `website/en/index.html` `dashboard-start-en.webp` → `dashboard-start-hu.webp`.
|
||||
Failure line: `FAIL: en/index.html: a hu dashboard picture (/assets/dashboard-start-hu.webp) on a en page — use the page's own language`.
|
||||
Also in `scripts/test_gate_decoys.py` as `site/dashboard-picture-wrong-language` (with `must=` on that line).
|
||||
|
||||
## Rows filed (dashboard defects seen in the pictures; controller not changed)
|
||||
|
||||
- **R-906** (P4): a page can show „+5 more warnings" with none above it — the overflow is counted before the page filter.
|
||||
- **R-907** (P4): on a phone the Launcher's share button runs off the right edge.
|
||||
|
||||
## Files and pushes
|
||||
|
||||
Named in the chat after the push (commit hash and CI by commit).
|
||||
|
||||
## Decision for you
|
||||
|
||||
**May I move scratch guest 9202 to controller 0.303.0 — the fleet's version, not past it — and then take the
|
||||
screenshots?** (On 9202 the image is set by hand in `/etc/felhom-controller-image` + a restart of its bootstrap
|
||||
service; `operations/nodes.md` — allowed only there.)
|
||||
- **Pick: yes**, at a time when the other session is not using 9202. Cost: about two minutes of 9202 restart. The
|
||||
pictures then show what households really run.
|
||||
- Or: take the pictures on 0.301.0 now. Cost: the pictures show a dashboard two releases old (0.302.0 changed the
|
||||
format list and 22 messages).
|
||||
- **If you do nothing:** no pictures; the site stays as it is.
|
||||
None. Look at the home page once (`felhom.eu/#vezerlopult`, `felhom.eu/en/#dashboard`).
|
||||
|
||||
@@ -58,6 +58,7 @@ Full designs: `documentation/audits/day-2026-10-08/`.
|
||||
in the menu goes to the same page in the other language.
|
||||
- **A missing-page (404) page exists now.**
|
||||
- **The language link is now a globe icon**, like the dashboard's: a click shows „Magyar" and „English".
|
||||
- **The website now shows the dashboard**: four real pictures on the home page (and two on the technology page), Hungarian on Hungarian pages, English on English ones. Two small dashboard defects were filed.
|
||||
- **The contact form's lost program code was searched for everywhere I can reach: not found.** The running program is now saved in git, so it cannot be lost. A plan for a replacement is written. One question for you: is the February folder on your Windows computer?
|
||||
|
||||
**Needs you:** two choices in `REPORT-website-refresh.md`. If nothing: SparkyFitness stays listed; the contact
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
# Dashboard pictures for the website — evidence (2026-10-08)
|
||||
|
||||
## The scene, and why it moved
|
||||
|
||||
1. **9202 updated to the fleet's controller** (operator's word, 2026-10-08): `/etc/felhom-controller-image`
|
||||
`…:0.301.0` → `…:0.303.0` (old line kept as `/etc/felhom-controller-image.bak-0.301.0` in the guest), bootstrap
|
||||
restarted; `felhom-controller … 0.303.0 Up 13 seconds (healthy)`.
|
||||
2. **On 9202:** Vaultwarden, Jellyfin, Nextcloud and Immich installed through the product (Immich's first pull was
|
||||
refused by ghcr.io „toomanyrequests"; the second try deployed). One whole-box backup press and one Tier-2 run:
|
||||
`db_dump success, count 3`; „Tier 2 run complete: 6 app(s)".
|
||||
3. **The 9202 pictures were not used.** Every page carried a banner „+ 5 további figyelmeztetés" — nine
|
||||
`disk-not-separate` warnings (9202's „second drive" is a folder on the host's NVMe, plus earlier sessions' leftover
|
||||
app folders) and the hub-off warning. True for a scratch guest, not a household's normal state. The banner itself
|
||||
showed none of the five warnings it counted on those pages: **R-906**.
|
||||
4. **Pictures taken on demo-hp's household guest 9201** (operator: the physical boxes are test boxes too): controller
|
||||
0.303.0, 10 standing apps, hub connected, **no alerts** (`/api/debug/dump` → `alerts: []`), last night's app backup
|
||||
`success` at 04:16. Read only; the household language was switched to English for the English pictures and back to
|
||||
Hungarian right after (both POSTs 302; read back `lang="hu"`). Headless Chrome ran on 9202, reaching 9201's traefik
|
||||
at `192.168.0.155`; nothing ran on 9201.
|
||||
|
||||
## The pictures (`website/assets/`, 1440 × 900, WebP q82)
|
||||
|
||||
| File | Bytes |
|
||||
|---|---|
|
||||
| dashboard-start-hu.webp / -en | 34,024 / 31,948 |
|
||||
| dashboard-apps-hu.webp / -en | 59,018 / 54,156 |
|
||||
| dashboard-app-hu.webp / -en (Paperless-ngx) | 83,124 / 78,992 |
|
||||
| dashboard-backups-hu.webp / -en (Backup → Apps) | 52,638 / 45,292 |
|
||||
|
||||
Taken but not published: the backups overview, the System page, the phone view (`captions-claims.md` says why).
|
||||
The full-size PNGs stay out of the repository.
|
||||
|
||||
## Privacy
|
||||
|
||||
`privacy-scan.txt` — every published picture's page text: 0 e-mails, 0 IPv4 addresses, 0 serials, no domain except the
|
||||
test domain `enkisfelhom.hu` and `felhom.eu`; the one long hex value is the hidden CSRF field (not visible). Positive
|
||||
control: an app name known to be on each page, found 8 of 8. By eye: the pictures show the test domain, app names and
|
||||
backup sizes/times; no person's name (the household is „Demo HP", shown only on the unpublished System page).
|
||||
|
||||
## Clean-up (three layers)
|
||||
|
||||
- **9202:** Vaultwarden, Jellyfin, Nextcloud, Immich removed through the product (stop + remove with drive data and
|
||||
backups; volumes gone, stack folders back to their template files). Paperless-ngx (running) and PrivateBin
|
||||
(stopped) — there before this task — left as found; the whole-box backup restarted Paperless and it came back healthy.
|
||||
`/root/dash` removed; the session cookie file shredded on both sides. The `userdata/{immich,jellyfin,nextcloud}`
|
||||
folders on the scratch drive hold earlier sessions' content (`kept/`, `backups/`) and were left. **9202 stays on
|
||||
0.303.0** (operator-approved).
|
||||
- **9201:** nothing changed except the language round trip (ends Hungarian, as found).
|
||||
- **demo-hp host:** only `pct exec 9202/9201 -- …` and `pct list`. **Hub:** nothing touched.
|
||||
|
||||
## Decoy
|
||||
|
||||
`decoy.txt` — gate 19, mutation and failure line.
|
||||
@@ -0,0 +1,23 @@
|
||||
# Dashboard pictures — every caption is a claim (2026-10-08)
|
||||
|
||||
Pictures: demo-hp's household guest 9201, controller **0.303.0** (the fleet's version), read only — the only change
|
||||
was the household language switched to English for the English pictures and straight back to Hungarian (both
|
||||
switches answered 302; the launcher read back `lang="hu"`, first sidebar item „Indítópult"). Taken from scratch guest
|
||||
9202 with headless Chrome through 9201's traefik (`192.168.0.155`, host `felhom.enkisfelhom.hu`), 1440 × 900.
|
||||
|
||||
| Picture | Caption (hu / en) | Capability-map row | Status |
|
||||
|---|---|---|---|
|
||||
| `dashboard-start-*` | „Indítópult — minden alkalmazásod egy kattintásra." / „Launcher — every app you have, one click away." | E „Indítópult (app launcher) — one-tap grid of the household's openable apps" | IMPLEMENTED |
|
||||
| `dashboard-apps-*` | „Alkalmazások — telepítés pár kattintással, és látod, mi fut és mi naprakész." / „Apps — install in a few clicks, and see what runs and what is up to date." | B „Deploy an app from the catalog" (PROVEN-LIVE); B „What VERSION a box is running, and whether it is behind the catalog" (PROVEN-LIVE) | PROVEN-LIVE |
|
||||
| `dashboard-app-*` | „Egy alkalmazás oldala — mire jó, hova tedd a fájlokat, és hogyan kezdj hozzá." / „An app's page — what it is for, where your files go, and how to start." | B „App lifecycle: start/stop/restart/update/logs/remove/redeploy" (PROVEN-LIVE); the page's copy is the catalog's (`10-localisation.md` §7, slice 5); the drop-zone link is map E „File access via browser" (IMPLEMENTED, R-75) | PROVEN-LIVE / IMPLEMENTED |
|
||||
| `dashboard-backups-*` | „Mentések — minden éjjel minden alkalmazás adatbázisa mentésre kerül, és ellenőrizzük." / „Backups — every night each app's database is backed up and checked." | C „Nightly DB dumps (postgres/mariadb autodiscovery), atomic writes" (PROVEN-LIVE); the picture shows the night's run at 04:16 with a table count per database | PROVEN-LIVE |
|
||||
|
||||
Not published (taken, kept off the site): the backups **overview** (on demo-hp it truthfully shows an amber „the whole-box
|
||||
backup is on the system disk" notice — not a household's normal state), the **System** page (operator details: the
|
||||
template source and the monitoring address), and the **phone** view (the launcher's share button runs off the right edge
|
||||
at 390 px — R-907).
|
||||
|
||||
Privacy: `privacy-scan.txt` (per picture: e-mail, IPv4, long hex, the host's serial, password/recovery words, any domain
|
||||
other than the test domain `enkisfelhom.hu`; positive control an app name known to be on the page — found on all 8).
|
||||
The only long hex value is the page's hidden CSRF field, which is not visible in the picture. The two password-word hits
|
||||
are help text („a jelszó a Beállítások oldalon", „password manager"), not a password.
|
||||
@@ -0,0 +1,3 @@
|
||||
mutation: website/en/index.html src="/assets/dashboard-start-en.webp" -> dashboard-start-hu.webp
|
||||
FAIL: en/index.html: a hu dashboard picture (/assets/dashboard-start-hu.webp) on a en page — use the page's own language
|
||||
SITE GATES FAILED: 1 problem(s)
|
||||
@@ -0,0 +1,59 @@
|
||||
Privacy scan of the page text behind each published picture (body text + title/alt/placeholder/input values).
|
||||
Allowed by design: the test domain enkisfelhom.hu (demo-hp's demo customer) and felhom.eu.
|
||||
|
||||
== dashboard-start-hu (positive control 'Paperless-ngx': FOUND)
|
||||
e-mail: 0 []
|
||||
IPv4: 0 []
|
||||
long hex (token/key): 1 ['hidden CSRF field value, not visible on the page']
|
||||
serial 8CN944035T: 0 []
|
||||
recovery/password words: 0 []
|
||||
domain other than the test domain: 1 ['Felhom.eu']
|
||||
== dashboard-start-en (positive control 'Paperless-ngx': FOUND)
|
||||
e-mail: 0 []
|
||||
IPv4: 0 []
|
||||
long hex (token/key): 1 ['hidden CSRF field value, not visible on the page']
|
||||
serial 8CN944035T: 0 []
|
||||
recovery/password words: 0 []
|
||||
domain other than the test domain: 1 ['Felhom.eu']
|
||||
== dashboard-apps-hu (positive control 'BookStack': FOUND)
|
||||
e-mail: 0 []
|
||||
IPv4: 0 []
|
||||
long hex (token/key): 1 ['hidden CSRF field value, not visible on the page']
|
||||
serial 8CN944035T: 0 []
|
||||
recovery/password words: 0 []
|
||||
domain other than the test domain: 2 ['Cal.com', 'Felhom.eu']
|
||||
== dashboard-apps-en (positive control 'BookStack': FOUND)
|
||||
e-mail: 0 []
|
||||
IPv4: 0 []
|
||||
long hex (token/key): 1 ['hidden CSRF field value, not visible on the page']
|
||||
serial 8CN944035T: 0 []
|
||||
recovery/password words: 1 ['password']
|
||||
domain other than the test domain: 2 ['Cal.com', 'Felhom.eu']
|
||||
== dashboard-app-hu (positive control 'Paperless-ngx': FOUND)
|
||||
e-mail: 0 []
|
||||
IPv4: 0 []
|
||||
long hex (token/key): 1 ['hidden CSRF field value, not visible on the page']
|
||||
serial 8CN944035T: 0 []
|
||||
recovery/password words: 1 ['jelszó']
|
||||
domain other than the test domain: 1 ['Felhom.eu']
|
||||
== dashboard-app-en (positive control 'Paperless-ngx': FOUND)
|
||||
e-mail: 0 []
|
||||
IPv4: 0 []
|
||||
long hex (token/key): 1 ['hidden CSRF field value, not visible on the page']
|
||||
serial 8CN944035T: 0 []
|
||||
recovery/password words: 1 ['password']
|
||||
domain other than the test domain: 1 ['Felhom.eu']
|
||||
== dashboard-bapps-hu (positive control 'paperless-ngx': FOUND)
|
||||
e-mail: 0 []
|
||||
IPv4: 0 []
|
||||
long hex (token/key): 1 ['hidden CSRF field value, not visible on the page']
|
||||
serial 8CN944035T: 0 []
|
||||
recovery/password words: 0 []
|
||||
domain other than the test domain: 1 ['Felhom.eu']
|
||||
== dashboard-bapps-en (positive control 'paperless-ngx': FOUND)
|
||||
e-mail: 0 []
|
||||
IPv4: 0 []
|
||||
long hex (token/key): 1 ['hidden CSRF field value, not visible on the page']
|
||||
serial 8CN944035T: 0 []
|
||||
recovery/password words: 0 []
|
||||
domain other than the test domain: 1 ['Felhom.eu']
|
||||
@@ -0,0 +1,8 @@
|
||||
import sys, os, json
|
||||
sys.path.insert(0, '/mnt/5_hdd/felhom.eu/git/felhom.eu/documentation/audits/website-refresh-2026-10-08/shots/tools'); import sw; b = sw.b
|
||||
b.login()
|
||||
for app, sub in [("immich", "photos")]:
|
||||
ok = b.deploy(app, sub, {"HDD_PATH": "/mnt/felhom-drives/scratch_hdd"})
|
||||
print(app, "deploy", ok, flush=True)
|
||||
if ok:
|
||||
print(app, "answers", b.wait_app(sub), flush=True)
|
||||
@@ -0,0 +1,16 @@
|
||||
import sys, os, re
|
||||
sys.path.insert(0, '/mnt/5_hdd/felhom.eu/git/app-catalog-felhom.eu/scripts'); import box_walk as b
|
||||
lang = sys.argv[1]
|
||||
b.login()
|
||||
sess = open(f"{b.SC}/sess{os.getpid()}.txt").read().strip()
|
||||
r = b.sh(["curl", "-sk", "-H", b.HOSTHDR, "-H", f"Cookie: {sess}", f"{b.BASE}/launcher"])
|
||||
tok = re.search(r'name="_csrf" value="([^"]+)"', r.stdout).group(1)
|
||||
r = b.sh(["curl", "-sk", "-o", "/dev/null", "-w", "%{http_code}", "-H", b.HOSTHDR, "-H", f"Cookie: {sess}",
|
||||
"-H", f"Origin: https://felhom.{b.DOMAIN}", "-H", f"Referer: https://felhom.{b.DOMAIN}/launcher",
|
||||
"--data-urlencode", f"_csrf={tok}", "--data-urlencode", f"lang={lang}", "--data-urlencode", "back=/launcher",
|
||||
f"{b.BASE}/settings/language"])
|
||||
print("POST /settings/language", lang, "->", r.stdout)
|
||||
r = b.sh(["curl", "-sk", "-H", b.HOSTHDR, "-H", f"Cookie: {sess}", f"{b.BASE}/launcher"])
|
||||
print("launcher <html lang>:", re.search(r'<html lang="([^"]+)"', r.stdout).group(1) if re.search(r'<html lang="([^"]+)"', r.stdout) else "?",
|
||||
"| sidebar first item:", re.search(r'#i-rocket"/></svg>([^<]+)<', r.stdout).group(1) if re.search(r'#i-rocket"/></svg>([^<]+)<', r.stdout) else "?")
|
||||
fd = os.open(f"{b.SC}/session.txt", os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600); os.write(fd, sess.encode()); os.close(fd)
|
||||
@@ -0,0 +1,78 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Dashboard pictures on the website (2026-10-08): a home-page section after „Mit tud a doboz ma?" and two pictures in
|
||||
the technology page's dashboard card, each page in its own language. Reads the CURRENT pages; every insert asserts
|
||||
its anchor once."""
|
||||
import io, os, re, sys
|
||||
W = "/mnt/5_hdd/felhom.eu/git/felhom.eu/website"
|
||||
|
||||
|
||||
def rd(p): return io.open(os.path.join(W, p), encoding="utf-8-sig").read()
|
||||
|
||||
|
||||
def wr(p, s):
|
||||
with io.open(os.path.join(W, p), "w", encoding="utf-8-sig", newline="\n") as f: f.write(s)
|
||||
|
||||
|
||||
def sub1(s, old, new):
|
||||
assert s.count(old) == 1, (old[:80], s.count(old)); return s.replace(old, new)
|
||||
|
||||
|
||||
SHOTS = { # page: (hu alt, hu caption, en alt, en caption)
|
||||
"start": ("A vezérlőpult Indítópultja: az otthon telepített alkalmazások csempéi",
|
||||
"<strong>Indítópult</strong> — minden alkalmazásod egy kattintásra.",
|
||||
"The Dashboard's Launcher: tiles of the apps installed at home",
|
||||
"<strong>Launcher</strong> — every app you have, one click away."),
|
||||
"apps": ("Az Alkalmazások oldal: telepített és telepíthető alkalmazások kártyái, állapottal",
|
||||
"<strong>Alkalmazások</strong> — telepítés pár kattintással, és látod, mi fut és mi naprakész.",
|
||||
"The Apps page: cards of installed and installable apps, with their status",
|
||||
"<strong>Apps</strong> — install in a few clicks, and see what runs and what is up to date."),
|
||||
"app": ("Egy alkalmazás saját oldala: mire jó, képek, és az első lépések",
|
||||
"<strong>Egy alkalmazás oldala</strong> — mire jó, hova tedd a fájlokat, és hogyan kezdj hozzá.",
|
||||
"An app's own page: what it is for, pictures, and the first steps",
|
||||
"<strong>An app's page</strong> — what it is for, where your files go, and how to start."),
|
||||
"backups": ("A mentések oldala: minden alkalmazás adatbázisának éjszakai mentése, ellenőrizve",
|
||||
"<strong>Mentések</strong> — minden éjjel minden alkalmazás adatbázisa mentésre kerül, és ellenőrizzük.",
|
||||
"The backups page: each app's database backed up overnight, and checked",
|
||||
"<strong>Backups</strong> — every night each app's database is backed up and checked."),
|
||||
}
|
||||
|
||||
|
||||
def fig(page, lang):
|
||||
hu_alt, hu_cap, en_alt, en_cap = SHOTS[page]
|
||||
alt, cap = (hu_alt, hu_cap) if lang == "hu" else (en_alt, en_cap)
|
||||
src = "/assets/dashboard-%s-%s.webp" % (page, lang)
|
||||
return (' <figure class="dash-shot">\n'
|
||||
' <a href="%s"><img src="%s" alt="%s" width="1440" height="900" loading="lazy"></a>\n'
|
||||
' <figcaption>%s</figcaption>\n'
|
||||
' </figure>') % (src, src, alt, cap)
|
||||
|
||||
|
||||
def home_section(lang):
|
||||
if lang == "hu":
|
||||
sid, h2, sub = "vezerlopult", "Így néz ki <span>a vezérlőpult</span>", "Valódi képek egy Felhom dobozról — kattints rájuk a teljes mérethez"
|
||||
else:
|
||||
sid, h2, sub = "dashboard", "What the <span>Dashboard looks like</span>", "Real pictures from a Felhom box — click one for the full size"
|
||||
figs = "\n".join(fig(p, lang) for p in ("start", "apps", "app", "backups"))
|
||||
return (' <section class="content-section" id="%s">\n <div class="container">\n'
|
||||
' <div class="section-header">\n <h2>%s</h2>\n <p>%s</p>\n </div>\n'
|
||||
' <div class="dash-grid">\n%s\n </div>\n </div>\n </section>\n\n') % (sid, h2, sub, figs)
|
||||
|
||||
|
||||
ANCHOR_HOME = ' <section class="content-section alt-bg">\n'
|
||||
for p, lang in (("index.html", "hu"), ("en/index.html", "en")):
|
||||
s = rd(p)
|
||||
i = s.index('id="mit-tud"' if lang == "hu" else 'id="what-it-does"')
|
||||
j = s.index(ANCHOR_HOME, i)
|
||||
s = s[:j] + home_section(lang) + s[j:]
|
||||
wr(p, s)
|
||||
print(p, "section added")
|
||||
|
||||
TECH_ANCHOR = {"hu": ' <div class="highlight-box">\n <p><strong>Tökéletes:</strong>',
|
||||
"en": ' <div class="highlight-box">\n <p><strong>Good for:</strong>'}
|
||||
for p, lang in (("technologiak.html", "hu"), ("en/technology.html", "en")):
|
||||
s = rd(p)
|
||||
block = (' <div class="dash-grid">\n%s\n </div>\n\n'
|
||||
% "\n".join(" " + l for f in (fig("apps", lang), fig("backups", lang)) for l in f.split("\n")))
|
||||
s = sub1(s, TECH_ANCHOR[lang], block + TECH_ANCHOR[lang])
|
||||
wr(p, s)
|
||||
print(p, "pictures added")
|
||||
@@ -0,0 +1,44 @@
|
||||
// Dashboard screenshots for felhom.eu (2026-10-08): demo-hp's household guest 9201 (read only; run from 9202), controller 0.303.0, through traefik with the
|
||||
// real host name, headless Chrome. The session cookie comes from a 0600 file (never printed); each page's visible text
|
||||
// is saved beside its picture for the privacy scan.
|
||||
const puppeteer = require('puppeteer');
|
||||
const fs = require('fs');
|
||||
const sleep = ms => new Promise(r => setTimeout(r, ms));
|
||||
const HOST = 'felhom.enkisfelhom.hu', BASE = 'https://' + HOST;
|
||||
const sess = fs.readFileSync('/out/session.txt', 'utf8').trim(); // felhom_session=…
|
||||
const APP = process.env.APP || 'immich';
|
||||
const PAGES = (process.env.PAGES ? process.env.PAGES.split(',').map(x => x.split('=')) : [['start', '/launcher'], ['apps', '/stacks'], ['app', '/apps/' + APP], ['backups', '/backups'], ['system', '/settings']]);
|
||||
async function setLang(p, lang) {
|
||||
await p.goto(BASE + '/launcher', {waitUntil: 'networkidle2'});
|
||||
const btn = await p.$(`button.lang-globe-item[value="${lang}"]`);
|
||||
if (!btn) throw new Error('no globe item ' + lang);
|
||||
await p.evaluate(b => b.closest('form').submit(), btn);
|
||||
await p.waitForNavigation({waitUntil: 'networkidle2'}).catch(() => {});
|
||||
const got = await p.$eval('html', e => e.lang);
|
||||
console.log('language now', got);
|
||||
}
|
||||
async function shot(p, name) {
|
||||
await sleep(1500);
|
||||
await p.screenshot({path: `/out/${name}.png`});
|
||||
const t = await p.evaluate(() => document.body.innerText + '\n' + Array.from(document.querySelectorAll('[title],[alt],[placeholder],input[value]')).map(e => [e.title, e.alt, e.placeholder, e.value].join(' ')).join('\n'));
|
||||
fs.writeFileSync(`/out/${name}.txt`, t);
|
||||
console.log('shot', name);
|
||||
}
|
||||
(async () => {
|
||||
const b = await puppeteer.launch({args: ['--no-sandbox', '--ignore-certificate-errors', `--host-resolver-rules=MAP * ${process.env.TRAEFIK}`]});
|
||||
const p = await b.newPage();
|
||||
const [k, v] = sess.split('=');
|
||||
await p.setCookie({name: k, value: v, domain: HOST, path: '/', secure: true, httpOnly: true});
|
||||
for (const lang of (process.env.LANGS || 'hu,en').split(',')) {
|
||||
await p.setViewport({width: 1440, height: 900, deviceScaleFactor: 1});
|
||||
for (const [name, path] of PAGES) {
|
||||
await p.goto(BASE + path, {waitUntil: 'networkidle2'});
|
||||
await shot(p, `${name}-${lang}`);
|
||||
}
|
||||
if (process.env.NOPHONE) continue;
|
||||
await p.setViewport({width: 390, height: 844, deviceScaleFactor: 2, isMobile: true, hasTouch: true});
|
||||
await p.goto(BASE + '/launcher', {waitUntil: 'networkidle2'});
|
||||
await shot(p, `phone-${lang}`);
|
||||
}
|
||||
await b.close();
|
||||
})().catch(e => { console.error(e); process.exit(1); });
|
||||
@@ -1,3 +1,9 @@
|
||||
## gates — site gate 19: dashboard pictures in the page's own language (2026-10-08)
|
||||
|
||||
- `site_gates.py` gate 19: every `/assets/dashboard-*-(hu|en).webp` on a page must match the page's language set.
|
||||
Decoy `site/dashboard-picture-wrong-language` (the English home page given `dashboard-start-hu.webp`) convicts with
|
||||
„en/index.html: a hu dashboard picture … on a en page".
|
||||
|
||||
## gates — the decoy suite runs one at a time (2026-10-08, fixed without a row)
|
||||
|
||||
- `test_gate_decoys.py` takes an exclusive `fcntl.flock` on `.git/decoy-suite.lock` before planting anything. Two runs at
|
||||
|
||||
@@ -28,6 +28,7 @@ Gates (all must pass; non-zero exit on any failure):
|
||||
retrieval promise beyond what the Hungarian twin makes
|
||||
17. faq-ld — each FAQ page's FAQPage JSON-LD carries exactly its visible questions and answers
|
||||
18. tail — nothing after </html> (a stray file-dump summary sat visible below technologiak.html)
|
||||
19. dash-lang — a page shows dashboard pictures only in its own language (`dashboard-*-hu.webp` / `-en.webp`)
|
||||
"""
|
||||
import html as _html, io, json, os, re, sys, unicodedata
|
||||
|
||||
@@ -439,8 +440,20 @@ for p, s in pages.items():
|
||||
if i < 0 or s[i + len("</html>"):].strip():
|
||||
fail("%s: text after </html> (%r) — it renders on the page" % (p, s[i + 7:i + 87] if i >= 0 else "no </html>"))
|
||||
|
||||
# gate 19: dashboard pictures in the page's own language (2026-10-08). The dashboard speaks both languages and the
|
||||
# site shows it in each: an English page may not carry a `dashboard-*-hu.webp`, a Hungarian page a `-en.webp`.
|
||||
_DASH_RE = re.compile(r"/assets/dashboard-[a-z0-9-]+?-(hu|en)\.webp")
|
||||
_dash_n = 0
|
||||
for p, s in pages.items():
|
||||
want = lang_of(p)
|
||||
for m in _DASH_RE.finditer(s):
|
||||
_dash_n += 1
|
||||
if m.group(1) != want:
|
||||
fail("%s: a %s dashboard picture (%s) on a %s page — use the page's own language" % (p, m.group(1), m.group(0), want))
|
||||
print(" dashboard pictures: %d references, each in its page's language" % _dash_n)
|
||||
|
||||
if fails:
|
||||
print("\nSITE GATES FAILED: %d problem(s)" % len(fails))
|
||||
sys.exit(1)
|
||||
print("site gates OK — BOM, emoji=0, nav/footer per language, analytics, no CDN, no legacy tokens, no <style>, "
|
||||
"cache-busted assets, twins + hreflang + globe, lang, same apps, no Hungarian in English, FAQ JSON-LD, clean tail")
|
||||
"cache-busted assets, twins + hreflang + globe, lang, same apps, no Hungarian in English, FAQ JSON-LD, clean tail, dashboard pictures per language")
|
||||
|
||||
@@ -82,7 +82,7 @@ COVERS = {
|
||||
"switch at the wrong twin, lang=\"hu\" on an English page, an app missing from one apps page, "
|
||||
"ASCII-only Hungarian in English text and in a script message, a 'please', an English "
|
||||
"retrieval promise the Hungarian does not make, a FAQ JSON-LD drifting from the visible "
|
||||
"answer, and text after </html> — each must convict WITH its own failure line"),
|
||||
"answer, text after </html>, and a Hungarian dashboard picture on an English page — each must convict WITH its own failure line"),
|
||||
"script-tests": ("R-885: FIVE cases in scripts/test_script_tests_gate.py, run from here: a suite that PRINTS "
|
||||
"OK and exits 1 (label without fact), a failing suite three levels deep (scope is a walk), "
|
||||
"an empty scripts/ tree (checked nothing), the genuine article (must pass), the nested mark"),
|
||||
@@ -540,6 +540,10 @@ decoy("site/globe-wrong-order", "site_gates.py",
|
||||
decoy("site/leftover-text-switch", "site_gates.py",
|
||||
replace_in(_EN("apps.html"), '<li class="lang-globe-li">', '<li><a href="/alkalmazasok" lang="hu" hreflang="hu" class="lang-switch">Magyar</a></li><li class="lang-globe-li">'),
|
||||
must='en/apps.html: a leftover text language switch')
|
||||
# the dashboard pictures (2026-10-08): a Hungarian picture copied onto the English home page
|
||||
decoy("site/dashboard-picture-wrong-language", "site_gates.py",
|
||||
replace_in(_EN("index.html"), 'src="/assets/dashboard-start-en.webp"', 'src="/assets/dashboard-start-hu.webp"'),
|
||||
must="en/index.html: a hu dashboard picture (/assets/dashboard-start-hu.webp) on a en page")
|
||||
decoy("site/lang-attr", "site_gates.py",
|
||||
replace_in(_EN("backups.html"), '<html lang="en">', '<html lang="hu">'),
|
||||
must="the English set needs lang='en'")
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<title>Az oldal nem található | Felhom.eu</title>
|
||||
<meta name="robots" content="noindex, follow">
|
||||
<!-- shared assets: bump ?v= together on any site.css/icons.svg change -->
|
||||
<link rel="stylesheet" href="/assets/site.css?v=3">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=4">
|
||||
<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>
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
## 2026-10-08 (afternoon) — the dashboard, shown
|
||||
|
||||
- **A new section after „Mit tud a doboz ma?" / „What the box does today"**: „Így néz ki a vezérlőpult" / „What the
|
||||
Dashboard looks like" — four real screenshots (Launcher, Apps, an app's page, Backup → Apps), each with a one-line
|
||||
caption; the technology page's dashboard card gets the Apps and Backup pictures. Hungarian pages show the Hungarian
|
||||
dashboard, English pages the English one.
|
||||
- Taken on demo-hp's household guest (controller 0.303.0, no warnings, last night's backups OK); 1440 × 900 WebP,
|
||||
31–83 KB each; `loading="lazy"`, `width`/`height` set, each links to its full-size picture (no script).
|
||||
- `site.css`: `.dash-grid` / `.dash-shot` (two per row, one below 700 px); `?v=3` → `?v=4` on all sixteen pages.
|
||||
- Gate 19: a page may only show dashboard pictures in its own language (decoy seen failing first).
|
||||
- Evidence, captions-to-capability rows and the privacy scan: `documentation/audits/website-dashboard-2026-10-08/`.
|
||||
|
||||
## 2026-10-08 — the FAQ's GDPR answer tells the truth about where copies and traffic go (R-900; operator approved the text in chat)
|
||||
|
||||
- `gyik.html` and `en/faq.html`, the GDPR answer, both the visible text and its structured-data copy: the line „az adataid a
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
}
|
||||
</script>
|
||||
<!-- shared assets: bump ?v= together on any site.css/icons.svg change -->
|
||||
<link rel="stylesheet" href="/assets/site.css?v=3">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=4">
|
||||
<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>
|
||||
|
||||
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 33 KiB |
@@ -2056,3 +2056,13 @@ footer p { color: var(--text-2); font-size: 0.9rem; }
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Dashboard pictures (2026-10-08): real screenshots, two per row, one on a phone. A picture links to its
|
||||
full-size file; no lightbox. Hairline border, 2px radius, no shadow. --- */
|
||||
.dash-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; margin: 8px 0 24px; }
|
||||
.dash-shot { margin: 0; }
|
||||
.dash-shot img { display: block; width: 100%; height: auto; border: 1px solid var(--line); border-radius: var(--radius); }
|
||||
.dash-shot a:hover img { border-color: var(--blue); }
|
||||
.dash-shot figcaption { margin-top: 10px; color: var(--text-2); font-size: 0.95rem; line-height: 1.5; }
|
||||
.dash-shot figcaption strong { color: var(--text-1); }
|
||||
@media (max-width: 700px) { .dash-grid { grid-template-columns: minmax(0, 1fr); } }
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
}
|
||||
</script>
|
||||
<!-- shared assets: bump ?v= together on any site.css/icons.svg change -->
|
||||
<link rel="stylesheet" href="/assets/site.css?v=3">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=4">
|
||||
<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>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
}
|
||||
</script>
|
||||
<!-- shared assets: bump ?v= together on any site.css/icons.svg change -->
|
||||
<link rel="stylesheet" href="/assets/site.css?v=3">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=4">
|
||||
<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>
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
}
|
||||
</script>
|
||||
<!-- shared assets: bump ?v= together on any site.css/icons.svg change -->
|
||||
<link rel="stylesheet" href="/assets/site.css?v=3">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=4">
|
||||
<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>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<meta name="twitter:description" content="A question? Write to us: info@felhom.eu">
|
||||
<meta name="twitter:image" content="https://felhom.eu/assets/og-image-en.png">
|
||||
<!-- shared assets: bump ?v= together on any site.css/icons.svg change -->
|
||||
<link rel="stylesheet" href="/assets/site.css?v=3">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=4">
|
||||
<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>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<meta name="twitter:description" content="Download, checksum, and what to check before you install.">
|
||||
<meta name="twitter:image" content="https://felhom.eu/assets/og-image.png">
|
||||
<!-- shared assets: bump ?v= together on any site.css/icons.svg change -->
|
||||
<link rel="stylesheet" href="/assets/site.css?v=3">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=4">
|
||||
<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>
|
||||
|
||||
@@ -363,7 +363,7 @@
|
||||
}
|
||||
</script>
|
||||
<!-- shared assets: bump ?v= together on any site.css/icons.svg change -->
|
||||
<link rel="stylesheet" href="/assets/site.css?v=3">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=4">
|
||||
<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>
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
}
|
||||
</script>
|
||||
<!-- shared assets: bump ?v= together on any site.css/icons.svg change -->
|
||||
<link rel="stylesheet" href="/assets/site.css?v=3">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=4">
|
||||
<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>
|
||||
@@ -151,6 +151,33 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="content-section" id="dashboard">
|
||||
<div class="container">
|
||||
<div class="section-header">
|
||||
<h2>What the <span>Dashboard looks like</span></h2>
|
||||
<p>Real pictures from a Felhom box — click one for the full size</p>
|
||||
</div>
|
||||
<div class="dash-grid">
|
||||
<figure class="dash-shot">
|
||||
<a href="/assets/dashboard-start-en.webp"><img src="/assets/dashboard-start-en.webp" alt="The Dashboard's Launcher: tiles of the apps installed at home" width="1440" height="900" loading="lazy"></a>
|
||||
<figcaption><strong>Launcher</strong> — every app you have, one click away.</figcaption>
|
||||
</figure>
|
||||
<figure class="dash-shot">
|
||||
<a href="/assets/dashboard-apps-en.webp"><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-app-en.webp"><img src="/assets/dashboard-app-en.webp" alt="An app's own page: what it is for, pictures, and the first steps" width="1440" height="900" loading="lazy"></a>
|
||||
<figcaption><strong>An app's page</strong> — what it is for, where your files go, and how to start.</figcaption>
|
||||
</figure>
|
||||
<figure class="dash-shot">
|
||||
<a href="/assets/dashboard-backups-en.webp"><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>
|
||||
</section>
|
||||
|
||||
<section class="content-section alt-bg">
|
||||
<div class="container">
|
||||
<div class="section-header">
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
}
|
||||
</script>
|
||||
<!-- shared assets: bump ?v= together on any site.css/icons.svg change -->
|
||||
<link rel="stylesheet" href="/assets/site.css?v=3">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=4">
|
||||
<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>
|
||||
@@ -163,6 +163,17 @@
|
||||
<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"><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"><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>
|
||||
|
||||
@@ -363,7 +363,7 @@
|
||||
}
|
||||
</script>
|
||||
<!-- shared assets: bump ?v= together on any site.css/icons.svg change -->
|
||||
<link rel="stylesheet" href="/assets/site.css?v=3">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=4">
|
||||
<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>
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
}
|
||||
</script>
|
||||
<!-- shared assets: bump ?v= together on any site.css/icons.svg change -->
|
||||
<link rel="stylesheet" href="/assets/site.css?v=3">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=4">
|
||||
<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>
|
||||
@@ -151,6 +151,33 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="content-section" id="vezerlopult">
|
||||
<div class="container">
|
||||
<div class="section-header">
|
||||
<h2>Így néz ki <span>a vezérlőpult</span></h2>
|
||||
<p>Valódi képek egy Felhom dobozról — kattints rájuk a teljes mérethez</p>
|
||||
</div>
|
||||
<div class="dash-grid">
|
||||
<figure class="dash-shot">
|
||||
<a href="/assets/dashboard-start-hu.webp"><img src="/assets/dashboard-start-hu.webp" alt="A vezérlőpult Indítópultja: az otthon telepített alkalmazások csempéi" width="1440" height="900" loading="lazy"></a>
|
||||
<figcaption><strong>Indítópult</strong> — minden alkalmazásod egy kattintásra.</figcaption>
|
||||
</figure>
|
||||
<figure class="dash-shot">
|
||||
<a href="/assets/dashboard-apps-hu.webp"><img src="/assets/dashboard-apps-hu.webp" alt="Az Alkalmazások oldal: telepített és telepíthető alkalmazások kártyái, állapottal" width="1440" height="900" loading="lazy"></a>
|
||||
<figcaption><strong>Alkalmazások</strong> — telepítés pár kattintással, és látod, mi fut és mi naprakész.</figcaption>
|
||||
</figure>
|
||||
<figure class="dash-shot">
|
||||
<a href="/assets/dashboard-app-hu.webp"><img src="/assets/dashboard-app-hu.webp" alt="Egy alkalmazás saját oldala: mire jó, képek, és az első lépések" width="1440" height="900" loading="lazy"></a>
|
||||
<figcaption><strong>Egy alkalmazás oldala</strong> — mire jó, hova tedd a fájlokat, és hogyan kezdj hozzá.</figcaption>
|
||||
</figure>
|
||||
<figure class="dash-shot">
|
||||
<a href="/assets/dashboard-backups-hu.webp"><img src="/assets/dashboard-backups-hu.webp" alt="A mentések oldala: minden alkalmazás adatbázisának éjszakai mentése, ellenőrizve" width="1440" height="900" loading="lazy"></a>
|
||||
<figcaption><strong>Mentések</strong> — minden éjjel minden alkalmazás adatbázisa mentésre kerül, és ellenőrizzük.</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="content-section alt-bg">
|
||||
<div class="container">
|
||||
<div class="section-header">
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<meta name="twitter:description" content="Kérdésed van? Írj nekünk: info@felhom.eu">
|
||||
<meta name="twitter:image" content="https://felhom.eu/assets/og-image.png">
|
||||
<!-- shared assets: bump ?v= together on any site.css/icons.svg change -->
|
||||
<link rel="stylesheet" href="/assets/site.css?v=3">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=4">
|
||||
<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>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<meta name="twitter:description" content="Letöltés, ellenőrző összeg, és mire figyelj a telepítés előtt.">
|
||||
<meta name="twitter:image" content="https://felhom.eu/assets/og-image.png">
|
||||
<!-- shared assets: bump ?v= together on any site.css/icons.svg change -->
|
||||
<link rel="stylesheet" href="/assets/site.css?v=3">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=4">
|
||||
<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>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<meta name="description" content="Felhom.eu - Szolgáltatások és árak. Otthoni szerver telepítés, üzemeltetés, monitoring és támogatás.">
|
||||
<title>Szolgáltatások - Felhom.eu</title>
|
||||
<!-- shared assets: bump ?v= together on any site.css/icons.svg change -->
|
||||
<link rel="stylesheet" href="/assets/site.css?v=3">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=4">
|
||||
<link rel="icon" type="image/png" href="/assets/logo_favicon_2.svg">
|
||||
<!-- analytics intentionally omitted for draft page -->
|
||||
</head>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
}
|
||||
</script>
|
||||
<!-- shared assets: bump ?v= together on any site.css/icons.svg change -->
|
||||
<link rel="stylesheet" href="/assets/site.css?v=3">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=4">
|
||||
<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>
|
||||
@@ -163,6 +163,17 @@
|
||||
<li>Rendszer monitoring – folyamatos egészségfigyelés, riasztások</li>
|
||||
</ul>
|
||||
|
||||
<div class="dash-grid">
|
||||
<figure class="dash-shot">
|
||||
<a href="/assets/dashboard-apps-hu.webp"><img src="/assets/dashboard-apps-hu.webp" alt="Az Alkalmazások oldal: telepített és telepíthető alkalmazások kártyái, állapottal" width="1440" height="900" loading="lazy"></a>
|
||||
<figcaption><strong>Alkalmazások</strong> — telepítés pár kattintással, és látod, mi fut és mi naprakész.</figcaption>
|
||||
</figure>
|
||||
<figure class="dash-shot">
|
||||
<a href="/assets/dashboard-backups-hu.webp"><img src="/assets/dashboard-backups-hu.webp" alt="A mentések oldala: minden alkalmazás adatbázisának éjszakai mentése, ellenőrizve" width="1440" height="900" loading="lazy"></a>
|
||||
<figcaption><strong>Mentések</strong> — minden éjjel minden alkalmazás adatbázisa mentésre kerül, és ellenőrizzük.</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
<div class="highlight-box">
|
||||
<p><strong>Tökéletes:</strong> Otthoni média szerver, családi felhő, személyes projektek, kis irodai használat.</p>
|
||||
</div>
|
||||
|
||||