Compare commits

9 Commits
Author SHA1 Message Date
ffaerber 245516f9cb Merge pull request 'About-me page instead of the services list' (#14) from ai/about-me into main
build-and-push / build-and-push (push) Successful in 13s
Reviewed-on: #14
2026-10-28 08:14:49 +01:00
ffaerberandClaude Opus 5.5 e2eb20b3d0 Show only an about-me page, no homelab services
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015XiQYLY5JBuwam5nuVnBfz
2026-10-28 09:14:12 +02:00
ffaerber 837c50588f Merge pull request 'Remove the AI agents' (#13) from ai/remove-agents into main
build-and-push / build-and-push (push) Successful in 13s
Reviewed-on: #13
2026-10-27 19:02:49 +01:00
ffaerberandClaude Opus 5.5 22dadd4fea Remove the AI-agent workflow caller
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015XiQYLY5JBuwam5nuVnBfz
2026-10-27 19:55:55 +02:00
ffaerber 1b6c05d5c0 Merge pull request '@senior: List all homelab services' (#12) from ai/issue-11 into main
build-and-push / build-and-push (push) Successful in 26s
Reviewed-on: #12
2026-07-30 13:30:42 +02:00
senior 19bc3cf991 Address @qa review on PR #12 (issue #11)
- index.html: replace Image() probe with fetch(no-cors) + AbortController
  timeout. fetch resolves for any network response (incl. 4xx/5xx) so
  resolve -> 'up', reject/timeout -> 'down'. Fixes the bug where 401/404
  services were marked green.
- services.json: add Homepage service under 'dev' (was missing; the
  homepage is one of the public homelab services). Now 21 services.
- services.json: fix ethereum category icon (' Ξ' -> 'Ξ') leading space.
- .gitignore (new): ignore /.playwright-mcp/ and services-page.png.
- git rm --cached the three stray dev artifacts so they leave the repo.
2026-07-28 19:06:57 +00:00
senior 3f6a6ac8d2 @senior: issue #11 2026-07-28 18:58:36 +00:00
senior d84002da33 Replace project sections with live Services list
- Add services.json: hand-maintained source of truth with 20 public
  homelab services across 7 categories (edge, observability, media,
  downloads, ethereum, ai, dev), each with name/url/desc/icon.
- Rewrite index.html: Services section rendered client-side from
  services.json with a tiny up/down status probe (green dot = up,
  grey = down/unreachable; graceful fallback on CORS/offline).
  Keep a small Projects section linking the GitHub orgs so the old
  content is not lost.
- Add services grid + status dot styles to styles.css.
- Dockerfile: COPY services.json into the nginx html root.
2026-07-28 18:58:26 +00:00
pm 424fa94e85 Merge pull request '@senior: Layout: replace card grid with a simple list' (#10) from ai/issue-9 into main
build-and-push / build-and-push (push) Successful in 17s
2026-07-08 11:09:03 +02:00
5 changed files with 42 additions and 193 deletions

No files matched your search

-15
View File
@@ -1,15 +0,0 @@
name: ai-agent
run-name: "ai-agent · #${{ github.event.issue.number }}" # quotes required: bare # starts a YAML comment
# Standard caller for the shared AI-agent workflow (gitea/agents). Copy this file VERBATIM into
# any repo that should get the agents — it is identical in every repo. All logic + scripts live in
# agents/.gitea/workflows/; scripts are fetched from @main at run time. The `jobs.agent` wrapper is
# required: a reusable (workflow_call) workflow can only be invoked from a caller job, not top-level.
on:
issue_comment:
types: [created]
issues:
types: [opened]
jobs:
agent:
uses: gitea/agents/.gitea/workflows/agent.yml@main
secrets: inherit
+6
View File
@@ -0,0 +1,6 @@
# Playwright MCP scratch files (local browser sessions)
/.playwright-mcp/
# Local screenshots from manual testing
services-page.png
*.screenshot.png
+1 -1
View File
@@ -1,6 +1,6 @@
# homepage # homepage
Public homepage — Docker image deployed to homepage.ffaerber.duckdns.org Public homepage (about me) — Docker image deployed to ffaerber.com and homepage.ffaerber.duckdns.org
How it ships itself — issue → agent team → PR → QA → autopilot merge → image → swarm deploy — How it ships itself — issue → agent team → PR → QA → autopilot merge → image → swarm deploy —
is documented in [PIPELINE.md](PIPELINE.md). is documented in [PIPELINE.md](PIPELINE.md).
+14 -176
View File
@@ -3,197 +3,36 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="ffaerber — personal projects: CipherDolls, decentralized apps on Gnosis/Ethereum Swarm, self-hosted speech AI, and Ethereum infrastructure."> <meta name="description" content="Felix Faerber — Ethereum infrastructure, dapps and self-hosted AI.">
<title>ffaerber — projects</title> <title>Felix Faerber</title>
<link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="styles.css">
</head> </head>
<body> <body>
<header class="site-header"> <header class="site-header">
<div class="container"> <div class="container">
<h1 class="site-title">ffaerber</h1> <h1 class="site-title">Felix Faerber</h1>
<p class="site-tagline">Personal projects — AI companions, decentralized apps, GPU speech services, Ethereum infra.</p> <p class="site-tagline">Ethereum infrastructure, dapps and self-hosted AI.</p>
</div> </div>
</header> </header>
<main class="container"> <main class="container">
<!-- Section: CipherDolls --> <section class="section" id="about">
<section class="section" id="cipherdolls">
<div class="section-head"> <div class="section-head">
<h2 class="section-title">CipherDolls — AI companion platform</h2> <h2 class="section-title">About me</h2>
<p class="section-lede">What if an AI companion wasn't just an app, but something physical in your room? CipherDolls is my biggest project: an AI companion platform where characters can talk, listen — and live inside real devices.</p>
<a class="section-link" href="https://github.com/cipherdolls" rel="noopener noreferrer" target="_blank">github.com/cipherdolls ↗</a>
</div> </div>
<ul class="projects"> <p class="project-story">I build decentralised apps and the infrastructure under them: Ethereum and
Gnosis nodes, staking and Swarm storage. I also work on self-hosted AI: GPU speech services
<li class="project"> and an AI companion platform.</p>
<h3 class="project-name"><a href="https://github.com/cipherdolls/core" rel="noopener noreferrer" target="_blank">core</a></h3>
<p class="project-story">The brain of the platform: one backend that handles chat, voice, memory, payments and the connection to the physical dolls.</p>
<ul class="tags">
<li>Bun</li><li>Elysia</li><li>Prisma</li><li>PostgreSQL</li><li>Redis</li><li>MQTT</li>
</ul>
</li>
<li class="project">
<h3 class="project-name"><a href="https://github.com/cipherdolls/server" rel="noopener noreferrer" target="_blank">server</a></h3>
<p class="project-story">A slimmed-down core for anyone who just wants to chat with a character — the same architecture, none of the complexity.</p>
<ul class="tags">
<li>Bun</li><li>Elysia</li><li>Prisma</li><li>PostgreSQL</li>
</ul>
</li>
<li class="project">
<h3 class="project-name"><a href="https://github.com/cipherdolls/webapp" rel="noopener noreferrer" target="_blank">webapp</a></h3>
<p class="project-story">The web face of CipherDolls — where you meet the characters.</p>
<ul class="tags">
<li>React Router</li><li>TypeScript</li><li>Tailwind</li>
</ul>
</li>
<li class="project">
<h3 class="project-name"><a href="https://github.com/cipherdolls/stream-player" rel="noopener noreferrer" target="_blank">stream-player</a></h3>
<p class="project-story">Voices need to arrive instantly. This streams the AI's speech to your browser the moment it is generated.</p>
<ul class="tags">
<li>TypeScript</li><li>Redis</li><li>WebSocket</li>
</ul>
</li>
<li class="project">
<h3 class="project-name"><a href="https://github.com/cipherdolls/stream-recorder" rel="noopener noreferrer" target="_blank">stream-recorder</a></h3>
<p class="project-story">The listening half: your voice streams in, gets converted on the fly, and lands with the AI.</p>
<ul class="tags">
<li>TypeScript</li><li>WebSocket</li><li>ffmpeg</li>
</ul>
</li>
<li class="project">
<h3 class="project-name"><a href="https://github.com/cipherdolls/firmware-watcher" rel="noopener noreferrer" target="_blank">firmware-watcher</a></h3>
<p class="project-story">The magic moment: a real device on your desk wakes up, connects, and speaks with the character's voice.</p>
<ul class="tags">
<li>C</li><li>ESP-IDF</li><li>ESP32-S3</li><li>LVGL</li>
</ul>
</li>
<li class="project">
<h3 class="project-name"><a href="https://github.com/cipherdolls/firmware-m5sticks3" rel="noopener noreferrer" target="_blank">firmware-m5sticks3</a></h3>
<p class="project-story">The pocket version: the same companion on a tiny stick with a display and a microphone.</p>
<ul class="tags">
<li>C</li><li>ESP-IDF</li><li>ESP32-S3</li>
</ul>
</li>
</ul>
</section> </section>
<!-- Section: Decentralized apps --> <section class="section" id="projects">
<section class="section" id="dapps">
<div class="section-head"> <div class="section-head">
<h2 class="section-title">Decentralized apps — Gnosis Chain + Ethereum Swarm</h2> <h2 class="section-title">Projects</h2>
<p class="section-lede">Can the web run without servers? These apps are my experiments in building things that nobody can switch off.</p>
</div> </div>
<ul class="projects"> <ul class="orgs">
<li><a href="https://github.com/ffaerber" rel="noopener noreferrer" target="_blank">github.com/ffaerber ↗</a> — dapps, Ethereum infra, GPU speech services</li>
<li class="project"> <li><a href="https://github.com/cipherdolls" rel="noopener noreferrer" target="_blank">github.com/cipherdolls ↗</a> — AI companion platform</li>
<h3 class="project-name"><a href="https://github.com/ffaerber/SwarmChat" rel="noopener noreferrer" target="_blank">SwarmChat</a></h3>
<p class="project-story">I was thinking about how cool it would be to have a web3-based chat system. Is it possible to communicate without any servers? With Swarm, a decentralised technology, this is now possible — messages travel encrypted through the network itself, and your wallet is your identity.</p>
<ul class="tags">
<li>Solidity</li><li>React</li><li>Swarm PSS</li><li>WebRTC</li>
</ul>
</li>
<li class="project">
<h3 class="project-name"><a href="https://github.com/ffaerber/pinkchainsaw" rel="noopener noreferrer" target="_blank">Pink Chainsaw</a></h3>
<p class="project-story">I wanted an imageboard where content can't just disappear. Images live on Swarm, and every post pays a little to keep them alive — good content earns you cheaper posting, bad content gets expensive.</p>
<ul class="tags">
<li>Solidity</li><li>Foundry</li><li>React</li><li>Swarm</li>
</ul>
</li>
<li class="project">
<h3 class="project-name"><a href="https://github.com/ffaerber/freeemarket" rel="noopener noreferrer" target="_blank">FreeeMarket</a></h3>
<p class="project-story">Can you run a marketplace with no company behind it? Anyone opens a shop, buyers pay in stablecoins, and on-chain escrow replaces the middleman. Deliberately fee-free — a farmers' market for the internet.</p>
<ul class="tags">
<li>Solidity</li><li>Gnosis Chain</li><li>Swarm</li>
</ul>
</li>
<li class="project">
<h3 class="project-name"><a href="https://github.com/ffaerber/walletmatrix" rel="noopener noreferrer" target="_blank">WalletMatrix</a></h3>
<p class="project-story">My tokens were scattered across a dozen chains and I could never see the whole picture. So I built a pivot table for your wallet: tokens as rows, chains as columns — drag a cell from one chain to another to bridge.</p>
<ul class="tags">
<li>React</li><li>TypeScript</li><li>Vite</li>
</ul>
</li>
<li class="project">
<h3 class="project-name"><a href="https://github.com/ffaerber/swarm-connect" rel="noopener noreferrer" target="_blank">swarm-connect</a></h3>
<p class="project-story">Every Swarm dApp I built needed the same onboarding dance: wallet, network, Bee node, postage stamp. So I packaged it once — a single React button that walks users through all of it.</p>
<ul class="tags">
<li>React</li><li>wagmi</li><li>npm package</li>
</ul>
</li>
<li class="project">
<h3 class="project-name"><a href="https://github.com/ffaerber/opentab" rel="noopener noreferrer" target="_blank">opentab</a></h3>
<p class="project-story">An experiment with onchain apps on Base.</p>
<ul class="tags">
<li>Next.js</li><li>TypeScript</li>
</ul>
</li>
</ul>
</section>
<!-- Section: AI on GPU -->
<section class="section" id="ai-gpu">
<div class="section-head">
<h2 class="section-title">AI on GPU — self-hosted speech services</h2>
<p class="section-lede">I wanted my projects to hear and speak without sending a single word to the cloud — so these run on my own GPU.</p>
</div>
<ul class="projects">
<li class="project">
<h3 class="project-name"><a href="https://github.com/ffaerber/whisper-cuda" rel="noopener noreferrer" target="_blank">whisper-cuda</a></h3>
<p class="project-story">Speech-to-text on my own GPU: no cloud, no per-minute pricing. Whisper packaged for the RTX 5090 so anything in my homelab can transcribe audio locally.</p>
<ul class="tags">
<li>Python</li><li>FastAPI</li><li>CUDA</li>
</ul>
</li>
<li class="project">
<h3 class="project-name"><a href="https://github.com/ffaerber/kokoro-cuda" rel="noopener noreferrer" target="_blank">kokoro-cuda</a></h3>
<p class="project-story">Giving my projects a voice: a small self-hosted TTS service with 49 voices in 9 languages, fast enough to stream. Type text, hear it instantly.</p>
<ul class="tags">
<li>Python</li><li>FastAPI</li><li>CUDA</li>
</ul>
</li>
<li class="project">
<h3 class="project-name"><a href="https://github.com/ffaerber/voxtral-cuda" rel="noopener noreferrer" target="_blank">voxtral-cuda</a></h3>
<p class="project-story">The newest open speech models are amazing but heavy. This runs Mistral's Voxtral on a local GPU, so state-of-the-art speech stays in my own house.</p>
<ul class="tags">
<li>Python</li><li>vLLM</li><li>CUDA</li>
</ul>
</li>
</ul>
</section>
<!-- Section: Ethereum infrastructure -->
<section class="section" id="eth-infra">
<div class="section-head">
<h2 class="section-title">Ethereum infrastructure</h2>
</div>
<ul class="projects">
<li class="project">
<h3 class="project-name"><a href="https://github.com/ffaerber/stakingtracker" rel="noopener noreferrer" target="_blank">stakingtracker</a></h3>
<p class="project-story">Tax season with an ETH validator used to mean paid APIs and spreadsheets. Now my own beacon node does the work: a small self-hosted app that records rewards daily and prints the tax report.</p>
<ul class="tags">
<li>TypeScript</li><li>Fastify</li><li>SQLite</li>
</ul>
</li>
</ul> </ul>
</section> </section>
@@ -205,7 +44,6 @@
<a href="https://github.com/ffaerber" rel="noopener noreferrer" target="_blank">github.com/ffaerber ↗</a> <a href="https://github.com/ffaerber" rel="noopener noreferrer" target="_blank">github.com/ffaerber ↗</a>
<a href="https://github.com/cipherdolls" rel="noopener noreferrer" target="_blank">github.com/cipherdolls ↗</a> <a href="https://github.com/cipherdolls" rel="noopener noreferrer" target="_blank">github.com/cipherdolls ↗</a>
</nav> </nav>
<p class="footer-meta">Served from a container built in <a href="https://git.ffaerber.duckdns.org/ffaerber/homepage" rel="noopener">ffaerber/homepage</a>.</p>
</div> </div>
</footer> </footer>
</body> </body>
+21 -1
View File
@@ -113,7 +113,7 @@ body {
line-height: 1.65; line-height: 1.65;
} }
/* Tags — small, muted detail */ /* Tags — small, muted detail (kept for any legacy use) */
.tags { .tags {
list-style: none; list-style: none;
margin: 0; margin: 0;
@@ -134,6 +134,26 @@ body {
color: var(--border); color: var(--border);
} }
/* Orgs list (Projects section) */
.orgs {
list-style: none;
margin: 0;
padding: 0;
max-width: 42rem;
}
.orgs li {
padding: 0.7rem 0;
border-bottom: 1px solid var(--border);
font-size: 0.98rem;
}
.orgs li:last-child { border-bottom: none; }
.orgs a {
color: var(--accent);
text-decoration: none;
font-weight: 700;
}
.orgs a:hover { text-decoration: underline; }
/* Footer */ /* Footer */
.site-footer { .site-footer {
margin-top: 3rem; margin-top: 3rem;