feat(settings): prominent sponsor banner on General tab

Matomo shows only 1.18% of website visitors reach /sponsors despite
      29% hitting /installation. The ask was discoverable on the marketing
      site but invisible in-app where users actually live.

      Full-width gradient banner sits above the three-column layout on the
      default landing tab and links to bambuddy.cool/sponsors.html with a
      ?from=app-settings tracking param so conversion lift is measurable
      in Matomo. Three new sponsors.* keys translated to all 11 locales.
This commit is contained in:
maziggy
2026-06-28 12:38:11 +02:00
13 changed files with 108 additions and 1 deletions
+1
View File
@@ -156,6 +156,7 @@ Optional but recommended — drop the [`slicer-api/` Compose stack](slicer-api/R
- Skip objects during print
- AMS slot RFID re-read
- **AMS slot Load / Unload from the printer card** — Hover any AMS slot or external spool, click the menu button, and load that tray or unload the currently-loaded one without going to the touchscreen; supports dual-extruder H2D (Ext-L / Ext-R drive their own nozzle)
- **AMS Filament Backup status + control** — Mirrors BambuStudio's per-printer "AMS Filament Backup" auto-switch (when a spool runs out, the printer rolls over to a same-material spool in another slot). A small badge in the Filaments section header on each printer card shows the live state (blue circular-arrow icon = ON, dim = OFF, "?" = A1 family with no `cfg` field yet); click to toggle. State syncs in real time whether you toggled from Bambuddy, BambuStudio, or the printer's touchscreen. Bambuddy's **Prefer Lowest Remaining Filament** sort now respects this setting — when Backup is OFF the dispatcher skips the prefer-lowest sort entirely so it won't reach for a near-empty spool the printer can't roll off of.
- AMS slot configuration (model-filtered presets, K profiles, color picker, pre-population for configured slots)
- AMS info card (hover for serial number, firmware version) with custom friendly names that persist across printers
- **AMS remote drying** — Start, monitor, and stop drying sessions for AMS 2 Pro and AMS-HT directly from the Printers page with filament-based temperature/duration presets, optional spool rotation; automatic PSU detection and HMS power error reporting
+7
View File
@@ -3605,6 +3605,13 @@ export default {
architecture: 'Architektur',
},
// Sponsor surface (System page)
sponsors: {
sectionTitle: 'Unabhängig & von der Community finanziert',
tagline: 'Bambuddy ist kostenlos und bleibt es, weil Menschen es freiwillig unterstützen. Kein VC, kein Cloud-Zwang.',
viewSupporters: 'Unterstützer ansehen',
},
// Library (K Profiles)
library: {
title: 'Filament-Bibliothek',
+7
View File
@@ -3617,6 +3617,13 @@ export default {
architecture: 'Architecture',
},
// Sponsor surface (System page)
sponsors: {
sectionTitle: 'Independent & community-funded',
tagline: 'Bambuddy is free and stays that way because people choose to support it. No VC, no cloud lock-in.',
viewSupporters: 'View supporters',
},
// Library (K Profiles)
library: {
title: 'Filament Library',
+7
View File
@@ -3608,6 +3608,13 @@ export default {
architecture: 'Arquitectura',
},
// Sponsor surface (System page)
sponsors: {
sectionTitle: 'Independiente y financiado por la comunidad',
tagline: 'Bambuddy es gratuito y seguirá siéndolo porque hay quien decide apoyarlo. Sin VC, sin dependencia de la nube.',
viewSupporters: 'Ver patrocinadores',
},
// Library (K Profiles)
library: {
title: 'Biblioteca de filamentos',
+7
View File
@@ -3594,6 +3594,13 @@ export default {
architecture: 'Architecture',
},
// Sponsor surface (System page)
sponsors: {
sectionTitle: 'Indépendant & financé par la communauté',
tagline: 'Bambuddy est gratuit et le reste parce que des personnes choisissent de le soutenir. Pas de VC, pas de verrouillage cloud.',
viewSupporters: 'Voir les soutiens',
},
// Library (K Profiles)
library: {
title: 'Bibliothèque Filament',
+7
View File
@@ -3593,6 +3593,13 @@ export default {
architecture: 'Architettura',
},
// Sponsor surface (System page)
sponsors: {
sectionTitle: 'Indipendente e finanziato dalla community',
tagline: 'Bambuddy è gratuito e resta tale perché qualcuno sceglie di sostenerlo. Niente VC, niente lock-in cloud.',
viewSupporters: 'Vedi i sostenitori',
},
// Library (K Profiles)
library: {
title: 'Libreria filamenti',
+7
View File
@@ -3605,6 +3605,13 @@ export default {
architecture: 'アーキテクチャ',
},
// Sponsor surface (System page)
sponsors: {
sectionTitle: '独立・コミュニティ運営',
tagline: 'Bambuddyは無料で、これからも無料です。支援してくださる方々のおかげで、VCもクラウドロックインもありません。',
viewSupporters: 'サポーター一覧',
},
// Library (K Profiles)
library: {
title: 'フィラメントライブラリ',
+5
View File
@@ -3404,6 +3404,11 @@ export default {
platform: '플랫폼',
architecture: '아키텍처'
},
sponsors: {
sectionTitle: '독립적·커뮤니티 후원',
tagline: 'Bambuddy는 무료이며, 자발적으로 후원하는 사용자 덕분에 계속 무료로 유지됩니다. VC도 없고, 클라우드 종속도 없습니다.',
viewSupporters: '후원자 보기'
},
library: {
title: '필라멘트 라이브러리',
addFilament: '필라멘트 추가',
+7
View File
@@ -3593,6 +3593,13 @@ export default {
architecture: 'Arquitetura',
},
// Sponsor surface (System page)
sponsors: {
sectionTitle: 'Independente e financiado pela comunidade',
tagline: 'O Bambuddy é gratuito e continua assim porque há quem escolha apoiá-lo. Sem VC, sem dependência de nuvem.',
viewSupporters: 'Ver apoiadores',
},
// Library (K Profiles)
library: {
title: 'Biblioteca de Filamentos',
+7
View File
@@ -3594,6 +3594,13 @@ export default {
architecture: 'Mimari',
},
// Sponsor yüzeyi (Sistem sayfası)
sponsors: {
sectionTitle: 'Bağımsız ve topluluk destekli',
tagline: 'Bambuddy ücretsizdir ve böyle kalır çünkü insanlar onu desteklemeyi seçer. VC yok, bulut bağımlılığı yok.',
viewSupporters: 'Destekçileri görüntüle',
},
// Kütüphane (K Profilleri)
library: {
title: 'Filament Kütüphanesi',
+7
View File
@@ -3593,6 +3593,13 @@ export default {
architecture: '架构',
},
// Sponsor surface (System page)
sponsors: {
sectionTitle: '独立运营·社区支持',
tagline: 'Bambuddy 完全免费,并将持续免费——这要感谢主动支持的用户。没有风投,也没有云端绑定。',
viewSupporters: '查看支持者',
},
// Library (K Profiles)
library: {
title: '耗材库',
+7
View File
@@ -3593,6 +3593,13 @@ export default {
architecture: '架構',
},
// Sponsor surface (System page)
sponsors: {
sectionTitle: '獨立運作·社群支持',
tagline: 'Bambuddy 完全免費,並將持續免費——感謝主動支持的使用者。沒有創投,也沒有雲端綁定。',
viewSupporters: '查看支持者',
},
// Library (K Profiles)
library: {
title: '耗材庫',
+32 -1
View File
@@ -1,5 +1,5 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { Loader2, Plus, Plug, AlertTriangle, RotateCcw, Bell, Download, RefreshCw, ExternalLink, Globe, Droplets, Thermometer, FileText, Edit2, Send, CheckCircle, XCircle, History, Trash2, Zap, TrendingUp, Calendar, DollarSign, Power, PowerOff, Key, Copy, Database, X, Shield, Printer, Cylinder, Wifi, Home, Video, Users, Lock, Unlock, ChevronDown, Save, Mail, Flame, Layers, ListOrdered, Code, Search, Scale, Settings as SettingsIcon, ScanEye, Cog, QrCode } from 'lucide-react';
import { Loader2, Plus, Plug, AlertTriangle, RotateCcw, Bell, Download, RefreshCw, ExternalLink, Globe, Droplets, Thermometer, FileText, Edit2, Send, CheckCircle, XCircle, History, Trash2, Zap, TrendingUp, Calendar, DollarSign, Power, PowerOff, Key, Copy, Database, X, Shield, Printer, Cylinder, Wifi, Home, Video, Users, Lock, Unlock, ChevronDown, Save, Mail, Flame, Layers, ListOrdered, Code, Search, Scale, Settings as SettingsIcon, ScanEye, Cog, QrCode, Heart } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { api } from '../api/client';
@@ -1459,6 +1459,36 @@ export function SettingsPage() {
</nav>
<div className="flex-1 min-w-0">
{activeTab === 'general' && (
<>
{/* Sponsor banner — prominent independence callout */}
<a
href="https://bambuddy.cool/sponsors.html?from=app-settings"
target="_blank"
rel="noopener noreferrer"
className="group block mb-4 lg:mb-6 rounded-xl border border-bambu-green/30 bg-gradient-to-br from-bambu-green/15 via-bambu-green/5 to-transparent hover:border-bambu-green/50 hover:from-bambu-green/20 transition-colors"
>
<div className="flex flex-col md:flex-row items-start md:items-center gap-4 p-4 md:p-5">
<div className="p-3 rounded-lg bg-bambu-green/20 text-bambu-green flex-shrink-0">
<Heart className="w-6 h-6" />
</div>
<div className="flex-1 min-w-0">
<p className="text-base font-semibold text-white">
{t('sponsors.sectionTitle', 'Independent & community-funded')}
</p>
<p className="text-sm text-bambu-gray mt-0.5">
{t(
'sponsors.tagline',
'Bambuddy is free and stays that way because people choose to support it. No VC, no cloud lock-in.'
)}
</p>
</div>
<div className="flex items-center gap-2 px-4 py-2 rounded-lg bg-bambu-green/20 text-bambu-green group-hover:bg-bambu-green/30 text-sm font-medium whitespace-nowrap self-start md:self-auto">
{t('sponsors.viewSupporters', 'View supporters')}
<ExternalLink className="w-4 h-4" />
</div>
</div>
</a>
<div className="flex flex-col lg:flex-row gap-4 lg:gap-6">
{/* Left Column - General Settings */}
<div className="space-y-3 flex-1 lg:max-w-xl">
@@ -2551,6 +2581,7 @@ export function SettingsPage() {
<ExternalLinksSettings />
</div>
</div>
</>
)}
{/* Network Tab */}