From a20d4ab3626a17f15d7cb6efff243cfc38afab80 Mon Sep 17 00:00:00 2001 From: Juan Denis Date: Mon, 19 Jan 2026 10:12:28 -0500 Subject: [PATCH] feat(14): Add Star on GitHub prompt for new users - Add dismissible "Star on GitHub" card in About section - Shows for new users, remembers dismissal in localStorage - Accent-colored design with star icon - Links to github.com/jhd3197/ServerKit - Mobile responsive layout Co-Authored-By: Claude Opus 4.5 --- frontend/src/pages/Settings.jsx | 36 +++++++++++- frontend/src/styles/pages/_settings.less | 75 ++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 1 deletion(-) diff --git a/frontend/src/pages/Settings.jsx b/frontend/src/pages/Settings.jsx index 468a59c5..9f59efbf 100644 --- a/frontend/src/pages/Settings.jsx +++ b/frontend/src/pages/Settings.jsx @@ -3,7 +3,7 @@ import { useAuth } from '../contexts/AuthContext'; import api from '../services/api'; import UsersTab from '../components/settings/UsersTab'; import AuditLogTab from '../components/settings/AuditLogTab'; -import { Github, FileText, HelpCircle, MessageSquare, Bug, Check, Layers, Download, CheckCircle, RefreshCw, ExternalLink } from 'lucide-react'; +import { Github, FileText, HelpCircle, MessageSquare, Bug, Check, Layers, Download, CheckCircle, RefreshCw, ExternalLink, Star, X } from 'lucide-react'; const Settings = () => { const [activeTab, setActiveTab] = useState('profile'); @@ -1647,10 +1647,15 @@ const SystemInfo = () => { ); }; +const STAR_PROMPT_KEY = 'serverkit-star-prompt-dismissed'; + const AboutSection = () => { const [version, setVersion] = useState('...'); const [updateInfo, setUpdateInfo] = useState(null); const [checkingUpdate, setCheckingUpdate] = useState(false); + const [showStarPrompt, setShowStarPrompt] = useState(() => { + return localStorage.getItem(STAR_PROMPT_KEY) !== 'true'; + }); useEffect(() => { const fetchVersion = async () => { @@ -1664,6 +1669,11 @@ const AboutSection = () => { fetchVersion(); }, []); + const dismissStarPrompt = () => { + setShowStarPrompt(false); + localStorage.setItem(STAR_PROMPT_KEY, 'true'); + }; + const checkForUpdate = async () => { setCheckingUpdate(true); try { @@ -1733,6 +1743,30 @@ const AboutSection = () => { + {showStarPrompt && ( +
+ +
+ +
+
+

Enjoying ServerKit?

+

If you find ServerKit useful, consider starring the repository on GitHub. It helps others discover the project!

+ + + Star on GitHub + +
+
+ )} +

Features

    diff --git a/frontend/src/styles/pages/_settings.less b/frontend/src/styles/pages/_settings.less index 34ee04e7..436119ed 100644 --- a/frontend/src/styles/pages/_settings.less +++ b/frontend/src/styles/pages/_settings.less @@ -660,6 +660,81 @@ to { transform: rotate(360deg); } } +// Star Prompt Card +.star-prompt-card { + position: relative; + background: linear-gradient(135deg, @accent-glow 0%, fade(@accent-primary, 8%) 100%); + border: 1px solid fade(@accent-primary, 30%); + border-radius: @radius-lg; + padding: @space-6; + display: flex; + align-items: flex-start; + gap: @space-4; + + .dismiss-btn { + position: absolute; + top: @space-3; + right: @space-3; + background: none; + border: none; + color: @text-tertiary; + cursor: pointer; + padding: @space-1; + border-radius: @radius-sm; + transition: all @transition-fast; + + &:hover { + background: @bg-hover; + color: @text-primary; + } + } + + .star-icon { + flex-shrink: 0; + width: 48px; + height: 48px; + background: linear-gradient(135deg, @warning 0%, darken(@warning, 10%) 100%); + border-radius: @radius-lg; + display: flex; + align-items: center; + justify-content: center; + color: white; + } + + .star-content { + flex: 1; + padding-right: @space-6; + + h4 { + margin: 0 0 @space-2; + font-size: @font-size-md; + font-weight: @font-weight-semibold; + } + + p { + margin: 0 0 @space-4; + font-size: @font-size-sm; + color: @text-secondary; + line-height: @line-height-relaxed; + } + + .btn { + display: inline-flex; + align-items: center; + gap: @space-2; + } + } + + @media (max-width: @breakpoint-sm) { + flex-direction: column; + text-align: center; + + .star-content { + padding-right: 0; + } + } +} + // Feature List .feature-list { list-style: none;