Custom app launcher, browser home page, and service monitor. cute.haus
homelab react typescript
0

Configure Feed

Select the types of activity you want to include in your feed.

reorganize apps, add community infra

Aly Raffauf (Jul 2, 2026, 1:11 PM EDT) 60042ccf 797e0078

+37 -20
+6 -3
src/App.tsx
··· 5 5 import { Weather } from "./components/Weather"; 6 6 import { SearchBar } from "./components/SearchBar.tsx"; 7 7 import { apps } from "./data/apps"; 8 + import { communityInfra } from "./data/communityInfra"; 8 9 import { privateApps } from "./data/privateApps"; 9 10 import { websites } from "./data/websites"; 10 11 ··· 33 34 </div> 34 35 </div> 35 36 37 + <h2 className="section-heading mt-10 mb-3">Community Apps+Infra</h2> 38 + <ServiceGrid services={communityInfra} columns={4} /> 39 + <h2 className="section-heading mt-10 mb-3">Webpages</h2> 40 + <ServiceGrid services={websites} columns={3} /> 36 41 <h2 className="section-heading mt-10 mb-3">Apps</h2> 37 42 <ServiceGrid services={apps} columns={4} /> 38 - <h2 className="section-heading mt-10 mb-3">Private Apps</h2> 43 + <h2 className="section-heading mt-10 mb-3">Homelab</h2> 39 44 <ServiceGrid services={privateApps} columns={4} /> 40 - <h2 className="section-heading mt-10 mb-3">Webpages</h2> 41 - <ServiceGrid services={websites} columns={2} /> 42 45 </Layout> 43 46 ); 44 47 }
+5 -6
src/data/apps.ts
··· 6 6 url: "https://id.cute.haus/", 7 7 icon: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/pocket-id.png", 8 8 }, 9 - { name: "atbbs", url: "https://atbbs.xyz/" }, 9 + { 10 + name: "Jellyfin", 11 + url: "https://jellyfin.cute.haus", 12 + icon: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/jellyfin.png", 13 + }, 10 14 { 11 15 name: "Plex", 12 16 url: "https://plex.cute.haus/", ··· 41 45 name: "Forĝejo", 42 46 url: "https://git.aly.codes/", 43 47 icon: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/forgejo.png", 44 - }, 45 - { 46 - name: "aly.social", 47 - url: "https://pds.cute.haus", 48 - icon: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/bluesky.png", 49 48 }, 50 49 { 51 50 name: "Vaultwarden",
+16
src/data/communityInfra.ts
··· 1 + import type { Service } from "../types"; 2 + 3 + export const communityInfra: Service[] = [ 4 + { name: "atbbs", url: "https://atbbs.xyz/" }, 5 + { name: "morsels.blue", url: "https://morsels.blue/" }, 6 + { 7 + name: "aly.social", 8 + url: "https://pds.cute.haus", 9 + icon: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/bluesky.png", 10 + }, 11 + { 12 + name: "slingshot", 13 + url: "https://slingshot.cute.haus", 14 + icon: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/bluesky.png", 15 + }, 16 + ];
-5
src/data/privateApps.ts
··· 2 2 3 3 export const privateApps: Service[] = [ 4 4 { 5 - name: "Jellyfin", 6 - url: "https://jellyfin.cute.haus", 7 - icon: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/jellyfin.png", 8 - }, 9 - { 10 5 name: "Sonarr", 11 6 url: "https://sonarr.narwhal-snapper.ts.net/", 12 7 icon: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/sonarr.png",
+10 -6
src/index.ts
··· 1 1 import { serve } from "bun"; 2 2 import index from "./index.html"; 3 - import { privateApps } from "./data/privateApps"; 4 - import { websites } from "./data/websites"; 5 3 6 4 let hnCache: { stories: any[]; fetchedAt: number } | null = null; 7 5 let lobstersCache: { stories: any[]; fetchedAt: number } | null = null; ··· 87 85 } 88 86 89 87 async function checkStatuses( 90 - items: { name: string; url: string; healthUrl?: string; goodStatuses?: number[] }[], 88 + items: { 89 + name: string; 90 + url: string; 91 + healthUrl?: string; 92 + goodStatuses?: number[]; 93 + }[], 91 94 ) { 92 95 const results = await Promise.all( 93 96 items.map(async (item) => { ··· 97 100 signal: AbortSignal.timeout(3000), 98 101 }); 99 102 const status = response.status; 100 - const online = "goodStatuses" in item 101 - ? item.goodStatuses!.includes(status) 102 - : status < 500; 103 + const online = 104 + "goodStatuses" in item 105 + ? item.goodStatuses!.includes(status) 106 + : status < 500; 103 107 return { name: item.name, online }; 104 108 } catch { 105 109 return { name: item.name, online: false };