diff --git a/frontend/app/(main)/admin/BestPracticesAnnouncementPanel.tsx b/frontend/app/(main)/admin/BestPracticesAnnouncementPanel.tsx
new file mode 100644
index 00000000..0ed66dd9
--- /dev/null
+++ b/frontend/app/(main)/admin/BestPracticesAnnouncementPanel.tsx
@@ -0,0 +1,226 @@
+"use client";
+
+import React, { useState } from "react";
+import {
+ Activity,
+ CheckCircle2,
+ Trophy,
+ Heart,
+ Sparkles,
+ Star,
+ ExternalLink,
+} from "lucide-react";
+import { sendBestPracticesAnnouncement } from "@/lib/api";
+import { toast } from "@/lib/toast";
+import { cn } from "@/lib/utils";
+
+export default function BestPracticesAnnouncementPanel() {
+ const [subject, setSubject] = useState("");
+ const [ctaUrl, setCtaUrl] = useState("");
+ const [testEmail, setTestEmail] = useState("");
+ const [sendToAll, setSendToAll] = useState(false);
+ const [sending, setSending] = useState(false);
+
+ const effectiveSubject =
+ subject.trim() || "Koder — Discover Best Practices: See how top developers solve problems";
+
+ const canSend = sendToAll || testEmail.trim().length > 0;
+
+ const handleSend = async () => {
+ if (!sendToAll && !testEmail.trim()) {
+ toast.error("Enter a test email or enable Send to all.");
+ return;
+ }
+
+ setSending(true);
+
+ const frontendBase = window.location.origin;
+ let finalCta = ctaUrl.trim();
+ if (!finalCta) {
+ finalCta = `${frontendBase}/home?bp_tab=all`;
+ } else if (finalCta.startsWith("/")) {
+ finalCta = `${frontendBase}${finalCta}`;
+ }
+
+ const payload = {
+ subject: effectiveSubject,
+ cta_url: finalCta,
+ test_email: testEmail.trim() || undefined,
+ send_to_all: sendToAll,
+ };
+
+ const res = await sendBestPracticesAnnouncement(payload);
+ setSending(false);
+
+ if (!res.success) {
+ toast.error(res.error?.message || "Failed to send announcement.");
+ return;
+ }
+
+ const attempted = res.data?.attempted ?? 0;
+ const sent = res.data?.sent ?? 0;
+ const failed = res.data?.failed ?? 0;
+
+ if (sendToAll) {
+ toast.success(
+ `Best Practices announcement queued to ${attempted} users; ${sent} sent, ${failed} failed.`,
+ );
+ } else {
+ toast.success(`Test email sent to ${testEmail.trim()}.`);
+ }
+ };
+
+ return (
+
+
+
+
+
+
+
+ Best Practices Announcement
+
+
+ Send an introductory email about the Best Practices feature with live stats and solution previews.
+
+
+
+
+
+
+ Subject
+ setSubject(event.target.value)}
+ placeholder="Koder — Discover Best Practices: See how top developers solve problems"
+ className="w-full bg-brand-charcoal-base border border-brand-charcoal-border rounded-xl px-3 py-2 text-sm text-brand-offwhite focus:outline-none focus:border-brand-muted-gold"
+ />
+
+
+
+ CTA URL (optional)
+ setCtaUrl(event.target.value)}
+ placeholder="Leave blank to use /home?bp_tab=all"
+ className="w-full bg-brand-charcoal-base border border-brand-charcoal-border rounded-xl px-3 py-2 text-sm text-brand-offwhite focus:outline-none focus:border-brand-muted-gold font-mono"
+ />
+
+
+
+
+ Test email address
+ setTestEmail(event.target.value)}
+ placeholder="admin@example.com"
+ className="w-full bg-brand-charcoal-base border border-brand-charcoal-border rounded-xl px-3 py-2 text-sm text-brand-offwhite focus:outline-none focus:border-brand-muted-gold"
+ />
+
+
+ setSendToAll(event.target.checked)}
+ className="h-4 w-4 rounded border-brand-charcoal-border bg-brand-charcoal-base text-brand-muted-gold focus:ring-brand-muted-gold"
+ />
+ Send to all users
+
+
+
+
+
+ {sendToAll
+ ? "This email will be delivered to all registered users with an email address."
+ : "Enter a test email to send a single preview email."}
+
+
+ {sending ? (
+
+ ) : (
+
+ )}
+ {sending ? "Sending..." : "Send announcement"}
+
+
+
+ {/* Email preview */}
+
+
+
+
+ Email preview
+
+
+ {effectiveSubject}
+
+
+
+
+ Feature announcement
+
+
+
+
+ {/* Stats preview */}
+
+
+ {/* Feature cards preview */}
+
+ {[
+ { icon: Heart, label: "Community Solutions", color: "bg-amber-100" },
+ { icon: Sparkles, label: "AI-Powered Code Analysis", color: "bg-purple-100" },
+ { icon: Star, label: "How to Get Featured", color: "bg-yellow-100" },
+ ].map(({ icon: Icon, label, color }) => (
+
+ ))}
+
+
+
+
+
+ {ctaUrl.trim() || "https://.../home?bp_tab=all"}
+
+
+
+
+
+
+ );
+}
diff --git a/frontend/app/(main)/admin/page.tsx b/frontend/app/(main)/admin/page.tsx
index 9965e6e6..5c63b3d9 100644
--- a/frontend/app/(main)/admin/page.tsx
+++ b/frontend/app/(main)/admin/page.tsx
@@ -71,6 +71,7 @@ import PendingContributions from "./PendingContributions";
import FeedbackPanel from "./FeedbackPanel";
import BroadcastPanel from "./BroadcastPanel";
import EmailBroadcastPanel from "./EmailBroadcastPanel";
+import BestPracticesAnnouncementPanel from "./BestPracticesAnnouncementPanel";
import ProblemEditPanel from "./ProblemEditPanel";
import ProblemReports from "./ProblemReports";
import UserVerificationPanel from "./UserVerificationPanel";
@@ -1293,6 +1294,13 @@ export default function AdminDashboard() {
+ {/* Best Practices Announcement */}
+
+
{/* Broadcasts */}
diff --git a/frontend/app/(main)/home/page.tsx b/frontend/app/(main)/home/page.tsx
index 54da4ac2..813fbfbe 100644
--- a/frontend/app/(main)/home/page.tsx
+++ b/frontend/app/(main)/home/page.tsx
@@ -14,7 +14,6 @@ import {
Trophy,
ArrowLeft,
BookOpen,
- FlaskConical,
} from "lucide-react";
import { LanguageLogo } from "@/components/LanguageLogo";
import GoogleLinkBanner from "@/components/GoogleLinkBanner";
@@ -589,17 +588,6 @@ export default function Dashboard() {
)}
>
- ) : user?.role !== "admin" ? (
-
-
-
- Best Practices — Coming Soon
-
- This feature is in private beta and currently available to administrators only.
- Stay tuned for the public release.
-
-
-
) : (
{
+ const timer = setTimeout(() => {
+ textareaRef.current?.focus({ preventScroll: true });
+ }, 320);
+ return () => clearTimeout(timer);
+ }, []);
+
const submit = () => {
if (!question.trim() || loading) return;
onSend();
@@ -39,7 +50,6 @@ export function ChatComposer({