diff --git a/.dockerignore b/.dockerignore index 6d1f51a..0cbb973 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,3 +4,4 @@ node_modules dist dist-ssr compose.yml +src/config.json \ No newline at end of file diff --git a/.gitignore b/.gitignore index 767e2f7..2a199e2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ node_modules .DS_Store dist -dist-ssr \ No newline at end of file +dist-ssr +src/config.json \ No newline at end of file diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..b286616 --- /dev/null +++ b/compose.yml @@ -0,0 +1,8 @@ +services: + homepage: + image: jordanroher/starbase-80 + ports: + - 4173:4173 + volumes: + - ./config.json:/app/src/config.json + - ./icons:/app/public/icons # or wherever, JSON icon paths are relative to /app/public diff --git a/dockerfile b/dockerfile index c674408..1a6cf46 100644 --- a/dockerfile +++ b/dockerfile @@ -1,4 +1,4 @@ -FROM node +FROM node18:alpine WORKDIR /app @@ -7,7 +7,7 @@ RUN npm i COPY . . -RUN npm run build +ENV NODE_ENV production EXPOSE 4173 diff --git a/package.json b/package.json index b06b6db..704873f 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "dev": "vite", "build": "tsc && vite build", - "start": "vite preview" + "start": "npm run build && vite preview" }, "dependencies": { "@types/react-dom": "^18.0.11", diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index 6ef539b..0000000 Binary files a/public/favicon.ico and /dev/null differ diff --git a/public/icons/archivebox.jpg b/public/icons/archivebox.jpg deleted file mode 100644 index 01cd12e..0000000 Binary files a/public/icons/archivebox.jpg and /dev/null differ diff --git a/public/icons/authelia.png b/public/icons/authelia.png deleted file mode 100644 index f3b58b7..0000000 Binary files a/public/icons/authelia.png and /dev/null differ diff --git a/public/icons/calibre.png b/public/icons/calibre.png deleted file mode 100644 index 05a95e0..0000000 Binary files a/public/icons/calibre.png and /dev/null differ diff --git a/public/icons/ghost.jpg b/public/icons/ghost.jpg deleted file mode 100644 index 7aa1ed5..0000000 Binary files a/public/icons/ghost.jpg and /dev/null differ diff --git a/public/icons/gitea.svg b/public/icons/gitea.svg deleted file mode 100644 index 5fe2981..0000000 --- a/public/icons/gitea.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/public/icons/home-assistant.svg b/public/icons/home-assistant.svg deleted file mode 100644 index 7856cf1..0000000 --- a/public/icons/home-assistant.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/public/icons/jellyfin.svg b/public/icons/jellyfin.svg deleted file mode 100644 index fcbc0ce..0000000 --- a/public/icons/jellyfin.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/public/icons/mastodon.jpg b/public/icons/mastodon.jpg deleted file mode 100644 index 7e829e6..0000000 Binary files a/public/icons/mastodon.jpg and /dev/null differ diff --git a/public/icons/mealie.jpg b/public/icons/mealie.jpg deleted file mode 100644 index 3b6a63e..0000000 Binary files a/public/icons/mealie.jpg and /dev/null differ diff --git a/public/icons/metube.jpg b/public/icons/metube.jpg deleted file mode 100644 index 7decf6e..0000000 Binary files a/public/icons/metube.jpg and /dev/null differ diff --git a/public/icons/miniflux.jpg b/public/icons/miniflux.jpg deleted file mode 100644 index 4cb5277..0000000 Binary files a/public/icons/miniflux.jpg and /dev/null differ diff --git a/public/icons/n8n.jpg b/public/icons/n8n.jpg deleted file mode 100644 index 80ed356..0000000 Binary files a/public/icons/n8n.jpg and /dev/null differ diff --git a/public/icons/portainer.png b/public/icons/portainer.png deleted file mode 100644 index da7b6fd..0000000 Binary files a/public/icons/portainer.png and /dev/null differ diff --git a/public/icons/router.png b/public/icons/router.png deleted file mode 100644 index 7bb37ed..0000000 Binary files a/public/icons/router.png and /dev/null differ diff --git a/public/icons/standardnotes.png b/public/icons/standardnotes.png deleted file mode 100644 index 086da5a..0000000 Binary files a/public/icons/standardnotes.png and /dev/null differ diff --git a/public/icons/synology.png b/public/icons/synology.png deleted file mode 100644 index 7277471..0000000 Binary files a/public/icons/synology.png and /dev/null differ diff --git a/public/icons/vaultwarden.svg b/public/icons/vaultwarden.svg deleted file mode 100644 index b0b1347..0000000 --- a/public/icons/vaultwarden.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/public/icons/vscode.jpg b/public/icons/vscode.jpg deleted file mode 100644 index 2a5edc9..0000000 Binary files a/public/icons/vscode.jpg and /dev/null differ diff --git a/public/icons/wallabag.png b/public/icons/wallabag.png deleted file mode 100644 index dbab6bc..0000000 Binary files a/public/icons/wallabag.png and /dev/null differ diff --git a/public/icons/wikijs.svg b/public/icons/wikijs.svg deleted file mode 100644 index 17557f3..0000000 --- a/public/icons/wikijs.svg +++ /dev/null @@ -1,291 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/public/icons/woodpecker.jpg b/public/icons/woodpecker.jpg deleted file mode 100644 index 78753f0..0000000 Binary files a/public/icons/woodpecker.jpg and /dev/null differ diff --git a/public/starbase-80.png b/public/starbase-80.png deleted file mode 100644 index d053089..0000000 Binary files a/public/starbase-80.png and /dev/null differ diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..e42dcbf --- /dev/null +++ b/readme.md @@ -0,0 +1,75 @@ +# Starbase 80 + +A nice looking homepage for Docker containers or any other services and links. + +No actual integration with Docker. Loads instantly. + +If you make a change to the config JSON, restart this container and refresh. + +Provide your own icons. + +# Docker compose + +```yaml +services: + homepage: + image: jordanroher/starbase-80 + ports: + - 4173:4173 + volumes: + - ./config.json:/app/src/config.json + - ./icons:/app/public/icons # or wherever, JSON icon paths are relative to /app/public +``` + +# config.json format + +```json +[ + { + "category": "Services", + "services": [ + { + "name": "Archivebox", + "uri": "https://archivebox.mywebsite.com", + "description": "Backup webpages", + "icon": "/icons/archivebox.jpg" + }, + { + "name": "Authelia", + "uri": "https://auth.mywebsite.com", + "description": "Authentication", + "icon": "/icons/authelia.png" + }, + { + "name": "Calibre", + "uri": "https://calibre.mywebsite.com", + "description": "eBook library", + "icon": "/icons/calibre.png" + } + ] + }, + { + "category": "Devices", + "services": [ + { + "name": "Router", + "uri": "http://192.168.1.1/", + "description": "Netgear Orbi", + "icon": "/icons/router.png" + }, + { + "name": "Home Assistant", + "uri": "http://homeassistant.local:8123/", + "description": "Home automation", + "icon": "/icons/home-assistant.svg" + }, + { + "name": "Synology", + "uri": "http://synology:5000", + "description": "Network storage", + "icon": "/icons/synology.png" + } + ] + } +] +``` diff --git a/src/components/icon.tsx b/src/components/icon.tsx index d2f6d24..d63213e 100644 --- a/src/components/icon.tsx +++ b/src/components/icon.tsx @@ -1,6 +1,5 @@ import React from "react"; import { is } from "../shared/is"; -import { IIcon } from "../shared/types"; const iconColors = [ "blue", @@ -25,7 +24,7 @@ const getIconColor = (index: number) => `bg-${iconColors[iconColors.length % ind interface IProps { index: number; - icon?: IIcon; + icon?: string; uri?: string; } @@ -45,12 +44,12 @@ export const Icon: React.FunctionComponent = ({ uri, icon, index }) => { if (!is.null(uri)) { return ( - + ); } - return ; + return ; }; interface IIconBlankProps { @@ -68,18 +67,14 @@ const IconBlank: React.FunctionComponent = ({ index }) => { }; interface IIconBaseProps { - icon: IIcon; - index: number; + icon: string; } -const IconBase: React.FunctionComponent = ({ icon, index }) => { - const { href, alt, title } = icon; - +const IconBase: React.FunctionComponent = ({ icon }) => { return ( {alt} ); diff --git a/src/config/services.json b/src/config/services.json deleted file mode 100644 index 9356e4f..0000000 --- a/src/config/services.json +++ /dev/null @@ -1,180 +0,0 @@ -[ - { - "category": "Services", - "services": [ - { - "name": "Archivebox", - "uri": "https://archivebox.starbase80.dev", - "description": "Backup webpages", - "icon": { - "href": "/icons/archivebox.jpg" - } - }, - { - "name": "Authelia", - "uri": "https://auth.starbase80.dev", - "description": "Authentication", - "icon": { - "href": "/icons/authelia.png" - } - }, - { - "name": "Calibre", - "uri": "https://calibre.starbase80.dev", - "description": "eBook library", - "icon": { - "href": "/icons/calibre.png" - } - }, - { - "name": "Gitea", - "uri": "https://git.starbase80.dev", - "description": "Code hosting", - "icon": { - "href": "/icons/gitea.svg" - } - }, - { - "name": "Jellyfin", - "uri": "https://jellyfin.starbase80.dev", - "description": "Media server", - "icon": { - "href": "/icons/jellyfin.svg" - } - }, - { - "name": "Mastodon", - "uri": "https://notclickable.social", - "description": "NotClickable.social", - "icon": { - "href": "/icons/mastodon.jpg" - } - }, - { - "name": "Mealie", - "uri": "https://mealie.starbase80.dev", - "description": "Recipe manager", - "icon": { - "href": "/icons/mealie.jpg" - } - }, - { - "name": "N8N", - "uri": "https://n8n.starbase80.dev", - "description": "Workflow automation", - "icon": { - "href": "/icons/n8n.jpg" - } - }, - { - "name": "MeTube", - "uri": "https://metube.starbase80.dev", - "description": "Archive YouTube", - "icon": { - "href": "/icons/metube.jpg" - } - }, - { - "name": "Miniflux", - "uri": "https://miniflux.starbase80.dev", - "description": "RSS server", - "icon": { - "href": "/icons/miniflux.jpg" - } - }, - { - "name": "Portainer", - "uri": "https://portainer.starbase80.dev", - "description": "Docker management", - "icon": { - "href": "/icons/portainer.png" - } - }, - { - "name": "Roher Twins", - "uri": "https://rohertwins.starbase80.dev", - "description": "Weekly newsletter", - "icon": { - "href": "/icons/ghost.jpg" - } - }, - { - "name": "Roher Wiki", - "uri": "https://roherwiki.starbase80.dev", - "description": "Family wiki", - "icon": { - "href": "/icons/wikijs.svg" - } - }, - { - "name": "Standard Notes", - "uri": "https://standardnotes.starbase80.dev", - "description": "Knowledge base", - "icon": { - "href": "/icons/standardnotes.png" - } - }, - { - "name": "Vaultwarden", - "uri": "https://vaultwarden.starbase80.dev", - "description": "Password manager", - "icon": { - "href": "/icons/vaultwarden.svg" - } - }, - { - "name": "Visual Studio Code", - "uri": "https://vscode.starbase80.dev", - "description": "Code editor", - "icon": { - "href": "/icons/vscode.jpg" - } - }, - { - "name": "Wallabag", - "uri": "https://wallabag.starbase80.dev", - "description": "Read later", - "icon": { - "href": "/icons/wallabag.png" - } - }, - { - "name": "Woodpecker", - "uri": "https://woodpecker.starbase80.dev", - "description": "Continuous integration", - "icon": { - "href": "/icons/woodpecker.jpg" - } - } - ] - }, - { - "category": "Devices", - "services": [ - { - "name": "Router", - "uri": "http://192.168.1.1/", - "description": "Netgear Orbi", - "icon": { - "href": "/icons/router.png" - } - }, - { - "name": "Home Assistant", - "uri": "http://homeassistant.local:8123/", - "description": "Home automation", - "icon": { - "href": "/icons/home-assistant.svg" - } - }, - { - "name": "Synology", - "uri": "http://synology:5000", - "description": "Network storage", - "icon": { - "href": "/icons/synology.png" - } - } - ] - } -] diff --git a/src/main.tsx b/src/main.tsx index bc7da11..b1a3187 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -5,6 +5,6 @@ import "./tailwind.css"; ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( - + ); diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 6a63271..91591a0 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,7 +1,7 @@ import React from "react"; import { Header } from "../components/header"; import { ServiceCatalogs } from "../components/service-catalogs"; -import userServices from "../config/services.json"; +import userServices from "../config.json"; import { IServiceCatalog } from "../shared/types"; interface IProps { diff --git a/src/shared/types.ts b/src/shared/types.ts index fc01a9a..5219bf0 100644 --- a/src/shared/types.ts +++ b/src/shared/types.ts @@ -8,11 +8,5 @@ export interface IService { uri: string; description?: string; - icon?: IIcon; -} - -export interface IIcon { - href: string; - title?: string; - alt?: string; + icon?: string; } diff --git a/vite.config.ts b/vite.config.ts index 3ce47f6..238a40d 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -8,7 +8,7 @@ export default defineConfig({ watch: { usePolling: true, }, - host: true, // needed for the Docker Container port mapping to work + host: true, strictPort: true, port: 4173, },