diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..db9c5ea
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,5 @@
+FROM nginx:alpine
+LABEL maintainer="services-homepage"
+COPY . /usr/share/nginx/html
+EXPOSE 80
+CMD ["nginx", "-g", "daemon off;"]
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..0b1f272
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,13 @@
+version: '3.8'
+services:
+ services-homepage:
+ build: .
+ container_name: services-homepage
+ ports:
+ - "8088:80"
+ restart: unless-stopped
+ logging:
+ driver: json-file
+ options:
+ max-size: "5m"
+ max-file: "2"
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..a90f356
--- /dev/null
+++ b/index.html
@@ -0,0 +1,105 @@
+
+
+
+
+
+ Services Homepage
+
+
+
+
+
+
+
+
+
+ Notes
+
+ - If any service is behind a reverse proxy or uses host networking, the path/host may differ.
+ - Edit
services.xml in this repo to add/remove links.
+
+
+
+
+
+
+
+
diff --git a/logos/aurcache.svg b/logos/aurcache.svg
new file mode 100644
index 0000000..f0eaa90
--- /dev/null
+++ b/logos/aurcache.svg
@@ -0,0 +1,5 @@
+
diff --git a/logos/default.svg b/logos/default.svg
new file mode 100644
index 0000000..fea15a7
--- /dev/null
+++ b/logos/default.svg
@@ -0,0 +1,4 @@
+
diff --git a/logos/filebrowser.svg b/logos/filebrowser.svg
new file mode 100644
index 0000000..2855131
--- /dev/null
+++ b/logos/filebrowser.svg
@@ -0,0 +1,4 @@
+
diff --git a/logos/gitea.svg b/logos/gitea.svg
new file mode 100644
index 0000000..da3a821
--- /dev/null
+++ b/logos/gitea.svg
@@ -0,0 +1,4 @@
+
diff --git a/logos/homeassistant.svg b/logos/homeassistant.svg
new file mode 100644
index 0000000..720b0ee
--- /dev/null
+++ b/logos/homeassistant.svg
@@ -0,0 +1,4 @@
+
diff --git a/logos/jellyfin.svg b/logos/jellyfin.svg
new file mode 100644
index 0000000..04f0e76
--- /dev/null
+++ b/logos/jellyfin.svg
@@ -0,0 +1,4 @@
+
diff --git a/logos/kiwix.svg b/logos/kiwix.svg
new file mode 100644
index 0000000..2c72d24
--- /dev/null
+++ b/logos/kiwix.svg
@@ -0,0 +1,4 @@
+
diff --git a/logos/nextcloud.svg b/logos/nextcloud.svg
new file mode 100644
index 0000000..65b9f36
--- /dev/null
+++ b/logos/nextcloud.svg
@@ -0,0 +1,5 @@
+
diff --git a/logos/picoshare.svg b/logos/picoshare.svg
new file mode 100644
index 0000000..1b55266
--- /dev/null
+++ b/logos/picoshare.svg
@@ -0,0 +1,6 @@
+
diff --git a/logos/portainer.svg b/logos/portainer.svg
new file mode 100644
index 0000000..e5ac341
--- /dev/null
+++ b/logos/portainer.svg
@@ -0,0 +1,4 @@
+
diff --git a/logos/tdarr.svg b/logos/tdarr.svg
new file mode 100644
index 0000000..6c7c764
--- /dev/null
+++ b/logos/tdarr.svg
@@ -0,0 +1,4 @@
+
diff --git a/logos/transmission.svg b/logos/transmission.svg
new file mode 100644
index 0000000..3219899
--- /dev/null
+++ b/logos/transmission.svg
@@ -0,0 +1,4 @@
+
diff --git a/logos/uptime-kuma.svg b/logos/uptime-kuma.svg
new file mode 100644
index 0000000..80a1f8d
--- /dev/null
+++ b/logos/uptime-kuma.svg
@@ -0,0 +1,5 @@
+
diff --git a/services.xml b/services.xml
new file mode 100644
index 0000000..b6f9549
--- /dev/null
+++ b/services.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/styles.css b/styles.css
new file mode 100644
index 0000000..0dbd485
--- /dev/null
+++ b/styles.css
@@ -0,0 +1,19 @@
+/* Minimal, responsive grid layout */
+:root{
+ --bg:#0f1720;--card:#0b1220;--accent:#4f46e5;--muted:#94a3b8;color-scheme: dark;
+}
+*{box-sizing:border-box}
+html,body{height:100%;margin:0;font-family:Inter,Segoe UI,Roboto,Arial,sans-serif;background:linear-gradient(180deg,#071020 0%,#0b1220 100%);color:#e6eef8}
+header{padding:24px 20px;text-align:center}
+header h1{margin:0;font-size:28px}
+.subtitle{color:var(--muted);margin-top:6px}
+main{max-width:1100px;margin:18px auto;padding:12px}
+.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px}
+.card{display:flex;align-items:center;justify-content:center;padding:18px;border-radius:10px;background:linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01));text-decoration:none;color:inherit;border:1px solid rgba(255,255,255,0.03);font-weight:600;transition:transform .12s ease,box-shadow .12s ease}
+.card:hover{transform:translateY(-6px);box-shadow:0 10px 30px rgba(15,20,32,0.6)}
+.card .logo{width:36px;height:36px;margin-right:12px;flex:0 0 36px}
+.card .label{flex:1;text-align:left}
+.notes{margin-top:18px;background:rgba(255,255,255,0.02);padding:12px;border-radius:8px;color:var(--muted)}
+footer{padding:12px 20px;text-align:center;color:var(--muted);font-size:12px}
+
+@media (max-width:420px){.card{padding:14px;font-size:14px}}