Compare commits

...
9 Commits
15 changed files with 2753 additions and 2407 deletions

No files matched your search

-3
View File
@@ -1,3 +0,0 @@
{
"presets": ["next/babel"]
}
+19 -1
View File
@@ -46,6 +46,24 @@ jobs:
-
name: Check files
uses: pre-commit/action@v3.0.1
-
name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
run_install: false
-
name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
-
name: Install dependencies
run: pnpm install
-
name: Lint frontend
run: pnpm run lint
build:
name: Docker Build & Push
@@ -127,7 +145,7 @@ jobs:
REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }}
# https://github.com/docker/setup-qemu-action#about
# platforms: linux/amd64,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/mips64le,linux/mips64,linux/arm/v7,linux/arm/v6
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6
platforms: linux/amd64,linux/arm64
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
+6 -5
View File
@@ -1,7 +1,7 @@
# syntax = docker/dockerfile:latest
# Install dependencies only when needed
FROM docker.io/node:18-alpine AS deps
FROM docker.io/node:22-alpine AS deps
WORKDIR /app
@@ -17,7 +17,7 @@ RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm f
RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm install -r --offline
# Rebuild the source code only when needed
FROM docker.io/node:18-alpine AS builder
FROM docker.io/node:22-alpine AS builder
WORKDIR /app
ARG BUILDTIME
@@ -33,7 +33,7 @@ RUN npm run telemetry \
&& NEXT_PUBLIC_BUILDTIME=$BUILDTIME NEXT_PUBLIC_VERSION=$VERSION NEXT_PUBLIC_REVISION=$REVISION npm run build
# Production image, copy all the files and run next
FROM docker.io/node:18-alpine AS runner
FROM docker.io/node:22-alpine AS runner
LABEL org.opencontainers.image.title "Homepage"
LABEL org.opencontainers.image.description "A self-hosted services landing page, with docker and service integrations."
LABEL org.opencontainers.image.url="https://github.com/gethomepage/homepage"
@@ -41,7 +41,7 @@ LABEL org.opencontainers.image.documentation='https://github.com/gethomepage/hom
LABEL org.opencontainers.image.source='https://github.com/gethomepage/homepage'
LABEL org.opencontainers.image.licenses='Apache-2.0'
ENV NODE_ENV production
ENV NODE_ENV=production
WORKDIR /app
@@ -56,7 +56,8 @@ COPY --link --chmod=755 docker-entrypoint.sh /usr/local/bin/
RUN apk add --no-cache su-exec
ENV PORT 3000
ENV HOSTNAME=::
ENV PORT=3000
EXPOSE $PORT
HEALTHCHECK --interval=10s --timeout=3s --start-period=20s \
+1 -1
View File
@@ -38,7 +38,7 @@ With features like quick search, bookmarks, weather support, a wide range of int
- **Fast** - The site is statically generated at build time for instant load times.
- **Secure** - All API requests to backend services are proxied, keeping your API keys hidden. Constantly reviewed for security by the community.
- **For Everyone** - Images built for AMD64, ARM64, ARMv7, and ARMv6.
- **For Everyone** - Images built for AMD64, ARM64.
- **Full i18n** - Support for over 40 languages.
- **Service & Web Bookmarks** - Add custom links to the homepage.
- **Docker Integration** - Container status and stats. Automatic service discovery via labels.
+1 -1
View File
@@ -19,7 +19,7 @@ Allowed fields: `["uptime", "wan", "lan", "lan_users", "lan_devices", "wlan", "w
!!! hint
If you enter e.g. incorrect credentials and receive an "API Error", you may need to recreate the container to clear the cache.
If you enter e.g. incorrect credentials and receive an "API Error", you may need to recreate the container or restart the service to clear the cache.
```yaml
widget:
+1484 -844
View File
File diff suppressed because it is too large. Load diff
+11 -11
View File
@@ -10,7 +10,7 @@
"telemetry": "next telemetry disable"
},
"dependencies": {
"@headlessui/react": "^1.7.18",
"@headlessui/react": "^1.7.19",
"@kubernetes/client-node": "^0.17.1",
"cal-parser": "^1.0.2",
"classnames": "^2.5.1",
@@ -24,22 +24,22 @@
"luxon": "^3.5.0",
"memory-cache": "^0.2.0",
"minecraft-ping-js": "^1.0.2",
"next": "^12.3.4",
"next": "^15.0.3",
"next-i18next": "^12.1.0",
"ping": "^0.4.4",
"pretty-bytes": "^6.1.1",
"raw-body": "^3.0.0",
"react": "^18.3.1",
"react-dom": "^18.2.0",
"react-dom": "^18.3.1",
"react-i18next": "^11.18.6",
"react-icons": "^5.4.0",
"recharts": "^2.12.6",
"recharts": "^2.12.7",
"rrule": "^2.8.1",
"swr": "^1.3.0",
"systeminformation": "^5.24.3",
"tough-cookie": "^4.1.3",
"urbackup-server-api": "^0.52.1",
"winston": "^3.11.0",
"tough-cookie": "^4.1.4",
"urbackup-server-api": "^0.8.9",
"winston": "^3.13.0",
"xml-js": "^1.6.11"
},
"devDependencies": {
@@ -47,15 +47,15 @@
"autoprefixer": "^10.4.20",
"eslint": "^8.57.1",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-next": "^14.2.3",
"eslint-config-next": "^14.2.4",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-jsx-a11y": "^6.9.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.37.3",
"eslint-plugin-react-hooks": "^4.6.2",
"postcss": "^8.4.47",
"prettier": "^3.2.5",
"postcss": "^8.4.48",
"prettier": "^3.3.2",
"tailwind-scrollbar": "^3.0.5",
"tailwindcss": "^3.4.17",
"typescript": "^5.6.3"
+1154 -1472
View File
File diff suppressed because it is too large. Load diff
+48 -48
View File
@@ -64,7 +64,7 @@
"up": "Up",
"down": "INACTIF",
"wait": "Veuillez patienter",
"empty_data": "Statut sous-système inconnu"
"empty_data": "Statut du sous-système inconnu"
},
"docker": {
"rx": "Rx",
@@ -84,17 +84,17 @@
},
"ping": {
"error": "Erreur",
"ping": "Ping",
"down": "Down",
"up": "Up",
"ping": "Latence",
"down": "Bas",
"up": "Haut",
"not_available": "Non disponible"
},
"siteMonitor": {
"http_status": "Statut HTTP",
"error": "Erreur",
"response": "Réponse",
"down": "Down",
"up": "Up",
"down": "Bas",
"up": "Haut",
"not_available": "Non disponible"
},
"emby": {
@@ -144,8 +144,8 @@
"uptime": "Démarré depuis",
"maxDown": "Max. Bas",
"maxUp": "Max. Haut",
"down": "Down",
"up": "Up",
"down": "Bas",
"up": "Haut",
"received": "Reçu",
"sent": "Envoyé",
"externalIPAddress": "IP externe"
@@ -173,11 +173,11 @@
"plex_connection_error": "Vérifier la connexion à Plex"
},
"omada": {
"connectedAp": "AP connectés",
"activeUser": "Équipts actifs",
"connectedAp": "APs connectées",
"activeUser": "Périphériques actifs",
"alerts": "Alertes",
"connectedGateway": "Passerelles connectées",
"connectedSwitches": "Switches connectés"
"connectedSwitches": "Switchs connectés"
},
"nzbget": {
"rate": "Débit",
@@ -213,11 +213,11 @@
"seed": "Seed"
},
"qnap": {
"cpuUsage": "Cpu",
"memUsage": "Mém",
"systemTempC": "Temp",
"poolUsage": "Pool",
"volumeUsage": "Volume",
"cpuUsage": "Utilisation CPU",
"memUsage": "Utilisation MÉM",
"systemTempC": "Temp. système",
"poolUsage": "Utilisation de la pool",
"volumeUsage": "Utilisation du volume",
"invalid": "Invalide"
},
"deluge": {
@@ -302,7 +302,7 @@
"speedtest": {
"upload": "Envoi",
"download": "Récep.",
"ping": "Ping"
"ping": "Latence"
},
"portainer": {
"running": "Démarré",
@@ -349,8 +349,8 @@
"tdarr": {
"queue": "En attente",
"processed": "Traité",
"errored": "En erreur",
"saved": "Libéré"
"errored": "Erroné",
"saved": "Enregistré"
},
"traefik": {
"routers": "Routeurs",
@@ -376,7 +376,7 @@
"gotify": {
"apps": "Applis",
"clients": "Clients",
"messages": "Msg"
"messages": "Messages"
},
"prowlarr": {
"enableIndexers": "Indexeur",
@@ -387,7 +387,7 @@
},
"jackett": {
"configured": "Configuré",
"errored": "En erreur"
"errored": "Erroné"
},
"strelaysrv": {
"numActiveSessions": "Sessions",
@@ -461,10 +461,10 @@
"0-night": "Ciel clair",
"1-day": "Principalement ensoleillé",
"1-night": "Principalement clair",
"2-day": "Partiellement couvert",
"2-night": "Partiellement couvert",
"3-day": "Couvert",
"3-night": "Couvert",
"2-day": "Partiellement nuageux",
"2-night": "Partiellement nuageux",
"3-day": "Nuageux",
"3-night": "Nuageux",
"45-day": "Brumeux",
"45-night": "Brumeux",
"48-day": "Brumeux",
@@ -489,8 +489,8 @@
"66-night": "Pluie verglaçante",
"67-day": "Pluie verglaçante",
"67-night": "Pluie verglaçante",
"71-day": "Neige légère",
"71-night": "Neige légère",
"71-day": "Légères chutes de neige",
"71-night": "Légères chutes de neige",
"73-day": "Neige",
"73-night": "Neige",
"75-day": "Neige abondante",
@@ -521,15 +521,15 @@
"up_to_date": "À jour",
"child_bridges": "Child Bridges",
"child_bridges_status": "{{ok}}/{{total}}",
"up": "Up",
"up": "Haut",
"pending": "En attente",
"down": "Down"
"down": "Bas"
},
"healthchecks": {
"new": "Nouveau",
"up": "Up",
"up": "Haut",
"grace": "En Période de Grâce",
"down": "Down",
"down": "Bas",
"paused": "En Pause",
"status": "Statut",
"last_ping": "Dernier Ping",
@@ -632,8 +632,8 @@
},
"octoprint": {
"printer_state": "Statut",
"temp_tool": "Tool T°",
"temp_bed": "Bed T°",
"temp_tool": "Temp. de l'outil",
"temp_bed": "Temp. du lit",
"job_completion": "Achèvement"
},
"cloudflared": {
@@ -644,8 +644,8 @@
"load": "Charge moy.",
"memory": "Util. Mém.",
"wanStatus": "Statut WAN",
"up": "Up",
"down": "Down",
"up": "Haut",
"down": "Bas",
"temp": "T°",
"disk": "Util. Disque",
"wanIP": "IP WAN"
@@ -754,9 +754,9 @@
"booksDuration": "Durée"
},
"homeassistant": {
"people_home": "People Home",
"people_home": "Personne à la maison",
"lights_on": "Lumières allumées",
"switches_on": "Commutateur On"
"switches_on": "Interrupteurs allumés"
},
"whatsupdocker": {
"monitoring": "Conteneurs",
@@ -800,8 +800,8 @@
"currentPlayers": "Joueurs actuels",
"players": "Joueurs",
"maxPlayers": "Joueurs max",
"bots": "Bots",
"ping": "Ping"
"bots": "Robots",
"ping": "Latence"
},
"urbackup": {
"ok": "Ok",
@@ -826,8 +826,8 @@
"openwrt": {
"uptime": "Démarré depuis",
"cpuLoad": "Charge moyenne CPU (5 min)",
"up": "Up",
"down": "Down",
"up": "Haut",
"down": "Bas",
"bytesTx": "Transmis",
"bytesRx": "Reçu"
},
@@ -840,9 +840,9 @@
"sitesDown": "Hors ligne",
"paused": "En Pause",
"notyetchecked": "Non vérifié",
"up": "Up",
"up": "Haut",
"seemsdown": "Semble hors ligne",
"down": "Down",
"down": "Bas",
"unknown": "Inconnu"
},
"calendar": {
@@ -912,7 +912,7 @@
},
"crowdsec": {
"alerts": "Alertes",
"bans": "Exclusions"
"bans": "Bannissements"
},
"wgeasy": {
"connected": "Connecté",
@@ -927,12 +927,12 @@
"banned": "Banni"
},
"myspeed": {
"ping": "Ping",
"ping": "Latence",
"download": "Récep.",
"upload": "Envoi"
},
"stocks": {
"stocks": "Actions",
"stocks": "Stocks",
"loading": "Chargement",
"open": "Ouvert - Marché américain",
"closed": "Fermé - marché américain",
@@ -981,8 +981,8 @@
"beszel": {
"name": "Nom",
"systems": "Systèmes",
"up": "Up",
"down": "Down",
"up": "Haut",
"down": "Bas",
"paused": "En Pause",
"pending": "En attente",
"status": "Statut",
+16 -16
View File
@@ -311,13 +311,13 @@
},
"suwayomi": {
"download": "下载",
"nondownload": "Non-Downloaded",
"nondownload": "未下载",
"read": "已读",
"unread": "未读",
"downloadedread": "Downloaded & Read",
"downloadedunread": "Downloaded & Unread",
"nondownloadedread": "Non-Downloaded & Read",
"nondownloadedunread": "Non-Downloaded & Unread"
"downloadedread": "已下载 & 已读",
"downloadedunread": "已下载 & 未读",
"nondownloadedread": "未下载 & 已读",
"nondownloadedunread": "未下载 & 未读"
},
"tailscale": {
"address": "地址",
@@ -980,7 +980,7 @@
},
"beszel": {
"name": "Name",
"systems": "Systems",
"systems": "系统",
"up": "Up",
"down": "Down",
"paused": "暂停",
@@ -989,26 +989,26 @@
"updated": "已升级",
"cpu": "CPU",
"memory": "内存",
"disk": "Disk",
"network": "NET"
"disk": "磁盘",
"network": "网络"
},
"argocd": {
"apps": "应用程序",
"synced": "Synced",
"outOfSync": "Out Of Sync",
"synced": "已同步",
"outOfSync": "未同步",
"healthy": "健康",
"degraded": "Degraded",
"progressing": "Progressing",
"degraded": "已降级",
"progressing": "进行中",
"missing": "丢失",
"suspended": "Suspended"
"suspended": "已停用"
},
"spoolman": {
"loading": "正在加载"
},
"gitlab": {
"groups": "Groups",
"groups": "群组",
"issues": "问题",
"merges": "Merge Requests",
"projects": "Projects"
"merges": "合并请求",
"projects": "项目"
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
import { useContext } from "react";
import Image from "next/future/image";
import Image from "next/image";
import { SettingsContext } from "utils/contexts/settings";
import { ThemeContext } from "utils/contexts/theme";
+2 -2
View File
@@ -1,6 +1,6 @@
import { useTranslation } from "next-i18next";
import useSWR from "swr";
import { compareVersions } from "compare-versions";
import { compareVersions, validate } from "compare-versions";
import { MdNewReleases } from "react-icons/md";
export default function Version() {
@@ -44,7 +44,7 @@ export default function Version() {
</a>
)}
</span>
{version === "main" || version === "dev" || version === "nightly"
{!validate(version)
? null
: releaseData &&
latestRelease &&
+5
View File
@@ -67,3 +67,8 @@ dialog ::-webkit-scrollbar {
.chart + .chart {
margin-top: 2em;
}
.service-container + .chart {
margin-top: 2.5rem;
margin-bottom: .5rem;
}
+1 -1
View File
@@ -79,7 +79,7 @@ export default async function genericProxyHandler(req, res, map) {
error: {
message: "HTTP Error",
url: sanitizeErrorURL(url),
resultData: Buffer.isBuffer(resultData) ? Buffer.from(resultData).toString() : resultData,
data: Buffer.isBuffer(resultData) ? Buffer.from(resultData).toString() : resultData,
},
});
}
+4 -1
View File
@@ -29,10 +29,13 @@ export default function Component({ service }) {
);
}
// broken by evcc v0.133.0 https://github.com/evcc-io/evcc/commit/9dcb1fa0a7c08dd926b79309aa1f676a5fc6c8aa
const gridPower = stateData.result.gridPower ?? stateData.result.grid?.power ?? 0;
return (
<Container service={service}>
<Block label="evcc.pv_power" value={`${toKilowatts(t, stateData.result.pvPower)} ${t("evcc.kilowatt")}`} />
<Block label="evcc.grid_power" value={`${toKilowatts(t, stateData.result.gridPower)} ${t("evcc.kilowatt")}`} />
<Block label="evcc.grid_power" value={`${toKilowatts(t, gridPower)} ${t("evcc.kilowatt")}`} />
<Block label="evcc.home_power" value={`${toKilowatts(t, stateData.result.homePower)} ${t("evcc.kilowatt")}`} />
<Block
label="evcc.charge_power"