Furry-Community mit Gallery, Profilen und Feed. 18+.
Translation pending
SocialTypeScript · JavaScriptGitHub @Kitsulife2601OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
Furry-Community mit vertikalem Bilder-Feed (wie TikTok), Gallery, Personensuche, Profilen, Uploads, Likes, Folgen und Meldungen. Nur für Erwachsene: Profile werden nur mit einem Geburtsdatum angelegt, das 18+ ergibt. FSK-18-Bilder sind für alle unkenntlich, die sich nicht in unserem Discord verifiziert haben. Der Server schickt ihnen nur eine 16-Pixel-Vorschau, die verschwommen angezeigt wird — das echte Bild verlässt den Server nie, es lässt sich also auch nicht per Browser „entblurren“.Read the full README ↗
Furry-Community mit vertikalem Bilder-Feed (wie TikTok), Gallery, Personensuche, Profilen, Uploads, Likes, Folgen und Meldungen. Nur für Erwachsene: Profile werden nur mit einem Geburtsdatum angelegt, das 18+ ergibt.
FSK-18-Bilder sind für alle unkenntlich, die sich nicht in unserem Discord verifiziert haben. Der Server schickt ihnen nur eine 16-Pixel-Vorschau, die verschwommen angezeigt wird — das echte Bild verlässt den Server nie, es lässt sich also auch nicht per Browser „entblurren“.
Stack: TanStack Start (React 19, Router, Query), Tailwind v4, Better Auth, Postgres (Neon in Produktion, eingebettetes PGLite lokal), Deployment auf Vercel.
npm ci
npm run dev # http://localhost:8080 — ohne DATABASE_URL läuft PGLite im Speicher
| Befehl | Zweck |
|---|---|
npm run build | Produktions-Build + Datenbank-Migrationen (mit DATABASE_URL) |
npm run typecheck | TypeScript prüfen |
npm run lint | ESLint |
npm test | Unit-Tests |
migrations/ SQL-Schema, wird beim Build (Neon) bzw. Start (PGLite) angewendet
0001_auth.sql Better-Auth-Tabellen (nicht von Hand ändern)
0002_schema.sql profiles, posts, likes, follows + Beispieldaten
0003_reports.sql Meldungen zu Bildern
0004_fsk18.sql FSK-18-Markierung, Vorschaubild, Discord-Verknüpfung
public/seed/ Beispielbilder der Seed-Profile
src/routes/ Seiten (dateibasiertes Routing)
__root.tsx HTML-Gerüst, 18+-Abfrage, Provider
login.tsx Anmelden / Registrieren
impressum.tsx Impressum (Platzhalter ausfüllen!)
datenschutz.tsx Datenschutzerklärung (Vorlage)
_app.tsx App-Layout mit Navigation + Onboarding-Gate
_app/index.tsx „Für dich“-Feed
_app/explore.tsx Gallery + Profilliste
_app/upload.tsx Bild hochladen
_app/profile.tsx Eigenes Profil
_app/u.$handle.tsx Fremdes Profil
_app/settings.tsx Profil, Portrait, Hintergrund, FSK-18-Freischaltung, Abmelden
api/discord/ Discord-Login (start.ts), Rückkehr mit Rollenprüfung (callback.ts)
und der Verifizierungs-Bot (interactions.ts)
src/components/ UI-Bausteine (Feed-Karte, Grid, Viewer, Melden-Dialog, …)
src/lib/vela/ Fachlogik: Server-Funktionen, Typen, Alter, Hintergründe, Cache
discord.ts Discord-OAuth, Rollenprüfung und Nachprüfung per Bot
discord-bot.ts Verifizierungs-Bot: Panel, private Kanäle, Freischalten
src/lib/auth/ Better Auth + Middleware (vorkonfiguriert)
src/lib/db.ts Datenbankzugang (Neon oder PGLite)
Alle schreibenden Server-Funktionen in src/lib/vela/server.ts laufen über
authMiddleware und prüfen serverseitig, dass ein volljähriges Profil existiert.
Anmelden geht per E-Mail, Google und Discord. Die Vercel-Adresse der Seite wird automatisch erkannt; eine eigene Domain funktioniert ebenfalls.
| Variable | Inhalt |
|---|---|
BETTER_AUTH_SECRET | Pflicht. Zufälliger Schlüssel, mind. 32 Zeichen (z. B. von generate-secret.vercel.app/32). Ohne ihn gehen Anmeldungen zufällig verloren. |
SITE_URL | Empfohlen bei eigener Domain, z. B. https://furry-gallery.de |
GOOGLE_CLIENT_ID | optional: ist voreingestellt |
GOOGLE_CLIENT_SECRET | Google-Anmeldung |
Discord-Anmeldung nutzt dieselben DISCORD_CLIENT_ID / DISCORD_CLIENT_SECRET wie die
Verifizierung (siehe unten). Ein Anmelde-Button erscheint nur, wenn seine Zugangsdaten
gesetzt sind.
Google: In der Google Cloud Console
→ Anmeldedaten erstellen → OAuth-Client-ID → Webanwendung. Unter Autorisierte
Weiterleitungs-URIs https://DEINE-DOMAIN/api/auth/callback/google eintragen. Den
OAuth-Zustimmungsbildschirm auf Extern stellen und veröffentlichen, sonst können sich nur
Testnutzer*innen anmelden.
Discord: Im Developer Portal unter OAuth2 → Redirects zusätzlich
https://DEINE-DOMAIN/api/auth/callback/discord eintragen.
Euer Discord-Bot verifiziert Mitglieder und gibt ihnen eine Rolle (z. B. „18+ verifiziert“). Die Webseite prüft nur, ob jemand diese Rolle auf eurem Server hat.
https://DEINE-DOMAIN/api/discord/callback eintragen.DISCORD_BOT_TOKEN. Damit
prüft die Seite alle 6 Stunden nach, ob die Rolle noch da ist — wird sie entzogen, sind
die Bilder wieder gesperrt. Der Bot braucht dafür den Server Members Intent.| Variable | Inhalt |
|---|---|
DISCORD_CLIENT_ID | optional: Application ID (ist voreingestellt) |
DISCORD_CLIENT_SECRET | Client Secret |
DISCORD_GUILD_ID | optional: Server-ID (ist voreingestellt) |
DISCORD_VERIFIED_ROLE_ID | optional: Verifiziert-Rolle (ist voreingestellt) |
DISCORD_BOT_TOKEN | optional: Bot-Token für die Nachprüfung |
DISCORD_INVITE_URL | optional: Einladungslink, wird in den Einstellungen gezeigt |
DISCORD_REDIRECT_URI | optional: nur nötig, wenn die Domain automatisch falsch erkannt wird |
Tokens und Secrets niemals in den Code oder ins Repository schreiben — nur in Vercel.
Ein Discord-Konto kann nur ein Profil freischalten. Als FSK 18 markieren kann jedes Mitglied sein eigenes Bild; die Uploader*innen sehen ihre eigenen Bilder immer.
Der Bot läuft in der Webseite mit (Discord schickt Klicks und Befehle an
/api/discord/interactions) — es muss also kein eigener Bot-Prozess rund um die Uhr laufen.
/verify-panel (nur mit „Server verwalten“) postet das Panel mit Verifizieren-Button
in den Verifizierungs-Kanal.verify-<name>, den nur das
Mitglied, das Team und der Bot sehen. Pro Mitglied höchstens einer.Voreingestellt (in src/lib/vela/discord-bot.ts, per Umgebungsvariable änderbar):
| Was | ID | Variable zum Überschreiben |
|---|---|---|
| Server | 1553802179431899266 | DISCORD_GUILD_ID |
| Kanal für das Panel | 1553814568852136097 | DISCORD_VERIFY_CHANNEL_ID |
| Kategorie für Kanäle | 1553815320202973281 | DISCORD_VERIFY_CATEGORY_ID |
| Verifiziert-Rolle | 1553830873365872680 | DISCORD_VERIFIED_ROLE_ID |
| Application ID | 1553811273165307995 | DISCORD_CLIENT_ID |
| Public Key | 5e09597b…405b889b05 | DISCORD_PUBLIC_KEY |
Einrichtung:
DISCORD_MOD_ROLE_ID
(Rolle, die freischalten darf und im Kanal angepingt wird). DISCORD_BOT_TOKEN ist hier
Pflicht.https://DEINE-DOMAIN/api/discord/interactions eintragen und speichern. Discord prüft die
Adresse; dabei registriert die Seite automatisch den Befehl /verify-panel.bot und
applications.commands). Die Bot-Rolle muss in der Rollenliste über der
Verifiziert-Rolle stehen./verify-panel ausführen.Achtung: Mit gesetzter Interactions Endpoint URL bekommt ein anderswo laufendes Bot-Programm mit demselben Token keine Befehle und Button-Klicks mehr.
/admin (Pfote oben rechts): Meldungen, FSK-18-Freigaben, Feedback, Updates,
Sperren. Admin ist, wer auf dem Discord-Server die Rolle Owner (1553843194993582253)
oder Fluff Admin (1553862150710239345) hat und Discord verknüpft bzw. sich damit
angemeldet hat — oder dessen Handle in ADMIN_HANDLES steht (Standard: kitsulife). Die
Rollen zählen auch im Bot als Team; ändern über DISCORD_ADMIN_ROLE_IDS./web-freischalten profil:<handle> und /web-sperren profil:<handle> schalten
FSK 18 auf der Webseite von Hand frei bzw. wieder ab (Mods). Nach dem Deploy einmal
/api/discord/interactions im Browser öffnen, damit neue Befehle angemeldet werden.Der Feed richtet sich nach Likes: Bilder, die Mitglieder mit ähnlichem Geschmack geliked haben
(„wer mag, was du magst, mag auch …“), kommen nach vorn. Dazu zählen Accounts, deren Bilder man
liked (×3), kommentiert (×4) oder ansieht (×1, Bild ≥ 1,5 s im Blick), ein Bonus für gefolgte
Accounts sowie Beliebtheit und Frische. Schon Gesehenes und Geliktes rutscht nach hinten. Gäste
sehen neu + beliebt. Die Gewichte stehen in listFeed (src/lib/vela/server.ts).
Kategorien dienen nur noch dem Filter in der Gallery.
Jede Meldung auf der Webseite postet der Bot in #meldungen in der Kategorie „🚩 Meldungen“
(legt er beim ersten Mal selbst an, nur fürs Team sichtbar): Bild (FSK 18 als Spoiler),
Uploader, Melder*in, Uhrzeit, Begründung und Details — mit Buttons Bild löschen,
Verwerfen und Uploader sperren. Der Bot braucht dafür „Kanäle verwalten“.
Videos (MP4, WebM, MOV, bis 50 MB) liegen im Vercel-Blob-Speicher, Bilder weiter in der Datenbank.
Einmalig einrichten: Vercel → Projekt → Storage → Create → Blob → mit dem Projekt
verbinden (setzt BLOB_READ_WRITE_TOKEN) → neu deployen. Ohne Token können nur Bilder hochgeladen
werden. Das Standbild (Poster) wird im Browser erzeugt; für FSK-18-Videos bekommen nicht
verifizierte Besucher nur die unkenntliche 16-px-Vorschau, nie die Video-Adresse.
Die Befehle funktionieren ohne. Für den grünen Online-Status muss ein kleines Programm dauerhaft laufen (eigener PC, Raspberry Pi, kleiner Server):
DISCORD_BOT_TOKEN=... npm run bot:online
[Platzhalter] in
src/routes/impressum.tsx und src/routes/datenschutz.tsx.reports, z. B.
select r.*, p.image_url from reports r join posts p on p.id = r.post_id order by r.created_at desc;