From 61fa2267a80a432a3f00a0a1fee1c21a47014183 Mon Sep 17 00:00:00 2001
From: Manthan Terse
Date: Thu, 7 May 2026 12:21:25 +0530
Subject: [PATCH] Add proper empty state before username input
---
app/customize/page.tsx | 104 +++++++++++++++++++++++++++++------------
app/page.test.tsx | 15 +++++-
app/page.tsx | 65 +++++++++++++++++++-------
3 files changed, 135 insertions(+), 49 deletions(-)
diff --git a/app/customize/page.tsx b/app/customize/page.tsx
index b2d7caa..4bd0181 100644
--- a/app/customize/page.tsx
+++ b/app/customize/page.tsx
@@ -139,7 +139,7 @@ function HexInput({
// ─── Main Page ────────────────────────────────────────────────────────────────
export default function CustomizePage() {
- const [username, setUsername] = useState('jhasourav07');
+ const [username, setUsername] = useState('');
const [theme, setTheme] = useState('dark');
const [bgHex, setBgHex] = useState('');
const [accentHex, setAccentHex] = useState('');
@@ -147,13 +147,17 @@ export default function CustomizePage() {
const [scale, setScale] = useState('linear');
const [speed, setSpeed] = useState('8s');
const [copied, setCopied] = useState(false);
+ const trimmedUsername = username.trim();
+ const hasUsername = trimmedUsername.length > 0;
// ── buildQueryParams ──────────────────────────────────────────────────────
const buildQueryParams = useCallback(() => {
const params = new URLSearchParams();
- params.set('user', username || 'jhasourav07');
+ if (hasUsername) {
+ params.set('user', trimmedUsername);
+ }
const hasCustomColors = bgHex || accentHex || textHex;
@@ -169,13 +173,15 @@ export default function CustomizePage() {
if (speed !== '8s') params.set('speed', speed);
return params.toString();
- }, [username, theme, bgHex, accentHex, textHex, scale, speed]);
+ }, [hasUsername, trimmedUsername, theme, bgHex, accentHex, textHex, scale, speed]);
const queryString = buildQueryParams();
const previewSrc = `/api/streak?${queryString}`;
const markdownSnippet = ``;
const copyMarkdown = () => {
+ if (!hasUsername) return;
+
navigator.clipboard.writeText(markdownSnippet);
setCopied(true);
setTimeout(() => setCopied(false), 3000);
@@ -417,20 +423,51 @@ export default function CustomizePage() {
{/* Scanning line effect behind image */}
- {/* eslint-disable-next-line @next/next/no-img-element */}
-
+ {hasUsername ? (
+ <>
+ {/* eslint-disable-next-line @next/next/no-img-element */}
+
+ >
+ ) : (
+
+
+
+ Enter a GitHub username to preview
+
+
+ The live badge preview will appear here once a username is added.
+
+
+ )}
- Preview updates on every change · Hosted badge is cached at UTC midnight
+ {hasUsername
+ ? 'Preview updates on every change · Hosted badge is cached at UTC midnight'
+ : 'Add a username to enable live preview and Markdown export'}
@@ -443,10 +480,13 @@ export default function CustomizePage() {
{copied ? (
@@ -490,7 +530,9 @@ export default function CustomizePage() {
- {markdownSnippet}
+ {hasUsername
+ ? markdownSnippet
+ : ''}
@@ -507,19 +549,21 @@ export default function CustomizePage() {
Active Parameters
- {queryString.split('&').map((pair) => {
- const [k, v] = pair.split('=');
- return (
-
- {decodeURIComponent(k)}
- =
- {decodeURIComponent(v)}
-
- );
- })}
+ {(hasUsername ? queryString.split('&') : ['user=your-github-username']).map(
+ (pair) => {
+ const [k, v] = pair.split('=');
+ return (
+
+ {decodeURIComponent(k)}
+ =
+ {decodeURIComponent(v)}
+
+ );
+ }
+ )}
diff --git a/app/page.test.tsx b/app/page.test.tsx
index eceae04..69151af 100644
--- a/app/page.test.tsx
+++ b/app/page.test.tsx
@@ -67,11 +67,18 @@ describe('LandingPage', () => {
expect(screen.getByText(/Contribution Story/i)).toBeDefined();
});
- it('renders the input field with default username', () => {
+ it('renders the input field empty by default', () => {
render( );
const input = screen.getByPlaceholderText('Enter GitHub Username') as HTMLInputElement;
expect(input).toBeDefined();
- expect(input.value).toBe('jhasourav07');
+ expect(input.value).toBe('');
+ });
+
+ it('renders an empty state before a username is entered', () => {
+ render( );
+
+ expect(screen.getByText('Enter a GitHub username to preview')).toBeDefined();
+ expect(screen.queryByTestId('next-image')).toBeNull();
});
it('updates the username when input changes', () => {
@@ -88,6 +95,8 @@ describe('LandingPage', () => {
it('handles copying to clipboard and showing the SuccessGuide', async () => {
render( );
+ const input = screen.getByPlaceholderText('Enter GitHub Username') as HTMLInputElement;
+ fireEvent.change(input, { target: { value: 'jhasourav07' } });
const copyButton = screen.getByText('Copy Link').closest('button');
fireEvent.click(copyButton!);
@@ -120,6 +129,8 @@ describe('LandingPage', () => {
it('can dismiss the SuccessGuide', async () => {
render( );
+ const input = screen.getByPlaceholderText('Enter GitHub Username') as HTMLInputElement;
+ fireEvent.change(input, { target: { value: 'jhasourav07' } });
// Trigger copy to show guide
const copyButton = screen.getByText('Copy Link').closest('button');
diff --git a/app/page.tsx b/app/page.tsx
index c4cdb84..6c5fa5d 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -65,14 +65,18 @@ const Icons = {
};
export default function LandingPage() {
- const [username, setUsername] = useState('jhasourav07');
+ const [username, setUsername] = useState('');
const [copied, setCopied] = useState(false);
const guideRef = useRef(null);
+ const trimmedUsername = username.trim();
+ const hasUsername = trimmedUsername.length > 0;
- const badgeUrl = `/api/streak?user=${username}`;
- const markdown = ``;
+ const badgeUrl = `/api/streak?user=${trimmedUsername}`;
+ const markdown = ``;
const copyToClipboard = () => {
+ if (!hasUsername) return;
+
navigator.clipboard.writeText(markdown);
setCopied(true);
setTimeout(() => {
@@ -124,7 +128,12 @@ export default function LandingPage() {
{copied ? (
@@ -149,8 +158,16 @@ export default function LandingPage() {
{
+ if (!hasUsername) e.preventDefault();
+ }}
+ className={`relative flex min-w-[160px] items-center justify-center gap-2 overflow-hidden rounded-xl border px-6 py-3.5 text-sm font-semibold transition-all duration-200 active:scale-[0.98] ${
+ hasUsername
+ ? 'border-[rgba(255,255,255,0.15)] bg-transparent text-white hover:bg-white/5'
+ : 'border-[rgba(255,255,255,0.08)] bg-white/[0.02] text-white/35'
+ }`}
>
Watch Dashboard
@@ -160,16 +177,30 @@ export default function LandingPage() {
-
+ {hasUsername ? (
+
+ ) : (
+
+
+
+
+
+ Enter a GitHub username to preview
+
+
+ Your 3D contribution monolith will appear here as soon as you add a username.
+
+
+ )}
@@ -180,7 +211,7 @@ export default function LandingPage() {
{copied && (
setCopied(false)}
/>
)}