-
+
Devpulse Leaderboards
diff --git a/app/components/auth/ForgotPassword.tsx b/app/components/auth/ForgotPassword.tsx
index 24242ac..af9b4a9 100644
--- a/app/components/auth/ForgotPassword.tsx
+++ b/app/components/auth/ForgotPassword.tsx
@@ -29,7 +29,7 @@ export default function ForgotPassword() {
href="/"
className="flex items-center gap-3 w-fit hover:opacity-80 transition"
>
-
+
Devpulse
@@ -95,7 +95,7 @@ export default function ForgotPassword() {
href="/"
className="lg:hidden flex items-center justify-center gap-3 mb-10"
>
-
+
Devpulse
diff --git a/app/components/auth/Login.tsx b/app/components/auth/Login.tsx
index ee265b7..fdcf7e2 100644
--- a/app/components/auth/Login.tsx
+++ b/app/components/auth/Login.tsx
@@ -29,7 +29,7 @@ export default function Login() {
href="/"
className="flex items-center gap-3 w-fit hover:opacity-80 transition"
>
-
+
Devpulse
@@ -94,7 +94,7 @@ export default function Login() {
href="/"
className="lg:hidden flex items-center justify-center gap-3 mb-10"
>
-
+
Devpulse
diff --git a/app/components/auth/Signup.tsx b/app/components/auth/Signup.tsx
index a2d1351..13bd702 100644
--- a/app/components/auth/Signup.tsx
+++ b/app/components/auth/Signup.tsx
@@ -29,7 +29,7 @@ export default function Signup() {
href="/"
className="flex items-center gap-3 w-fit hover:opacity-80 transition"
>
-
+
Devpulse
@@ -94,7 +94,7 @@ export default function Signup() {
href="/"
className="lg:hidden flex items-center justify-center gap-3 mb-10"
>
-
+
Devpulse
diff --git a/app/components/auth/VerifyEmail.tsx b/app/components/auth/VerifyEmail.tsx
index 7c79f34..669ee40 100644
--- a/app/components/auth/VerifyEmail.tsx
+++ b/app/components/auth/VerifyEmail.tsx
@@ -75,7 +75,7 @@ export default function VerifyEmail({
error: "Failed to resend. Please try again.",
});
- verifyEmailPromise.then(() => {
+ verifyEmailPromise.finally(() => {
setLoading(false);
});
};
@@ -91,7 +91,7 @@ export default function VerifyEmail({
href="/"
className="flex items-center gap-3 w-fit hover:opacity-80 transition"
>
-
+
Devpulse
@@ -157,7 +157,7 @@ export default function VerifyEmail({
href="/"
className="lg:hidden flex items-center justify-center gap-3 mb-10"
>
-
+
Devpulse
diff --git a/app/components/auth/VerifyWakatime.tsx b/app/components/auth/VerifyWakatime.tsx
index 674af20..e3818c8 100644
--- a/app/components/auth/VerifyWakatime.tsx
+++ b/app/components/auth/VerifyWakatime.tsx
@@ -57,21 +57,22 @@ export default function VerifyWakatime() {
toast.promise(verifyWakatimePromise, {
pending: "Verifying...",
- success: {
- render() {
- router.push("/d");
-
- return "Verification successful!";
- },
- },
+ success: "Verification successful!",
error: {
render({ data }) {
- setLoading(false);
const err = data as Error;
return err?.message || "Failed to verify. Please try again.";
},
},
});
+
+ verifyWakatimePromise
+ .then(() => {
+ router.push("/d");
+ })
+ .finally(() => {
+ setLoading(false);
+ });
};
return (
@@ -85,7 +86,7 @@ export default function VerifyWakatime() {
href="/"
className="flex items-center gap-3 w-fit hover:opacity-80 transition"
>
-
+
Devpulse
@@ -151,7 +152,7 @@ export default function VerifyWakatime() {
href="/"
className="lg:hidden flex items-center justify-center gap-3 mb-10"
>
-
+
Devpulse
diff --git a/app/components/auth/form/LoginForm.tsx b/app/components/auth/form/LoginForm.tsx
index 496ce44..1a0780b 100644
--- a/app/components/auth/form/LoginForm.tsx
+++ b/app/components/auth/form/LoginForm.tsx
@@ -81,16 +81,19 @@ export default function LoginForm() {
success: "Login successful! Redirecting...",
error: {
render({ data }) {
- setLoading(false);
const err = data as Error;
return err?.message || "Failed to login. Please try again.";
},
},
});
- loginPromise.then(() => {
- router.push(redirectTo);
- });
+ loginPromise
+ .then(() => {
+ router.push(redirectTo);
+ })
+ .finally(() => {
+ setLoading(false);
+ });
};
return (
diff --git a/app/components/auth/form/ResetPasswordForm.tsx b/app/components/auth/form/ResetPasswordForm.tsx
index 8bac0bb..497fd97 100644
--- a/app/components/auth/form/ResetPasswordForm.tsx
+++ b/app/components/auth/form/ResetPasswordForm.tsx
@@ -74,26 +74,24 @@ export default function ResetPasswordForm() {
toast.promise(updatePasswordPromise, {
pending: "Resetting password...",
- success: {
- render() {
- setLoading(false);
- setPassword("");
- setConfirmPassword("");
- return "Password updated! You can log in now.";
- },
- },
+ success: "Password updated! You can log in now.",
error: {
render({ data }) {
- setLoading(false);
const err = data as Error;
return err?.message || "Failed to reset password. Please try again.";
},
},
});
- updatePasswordPromise.then(() => {
- router.replace("/login");
- });
+ updatePasswordPromise
+ .then(() => {
+ setPassword("");
+ setConfirmPassword("");
+ router.replace("/login");
+ })
+ .finally(() => {
+ setLoading(false);
+ });
};
return (
diff --git a/app/components/auth/form/SignupForm.tsx b/app/components/auth/form/SignupForm.tsx
index ee55275..4309605 100644
--- a/app/components/auth/form/SignupForm.tsx
+++ b/app/components/auth/form/SignupForm.tsx
@@ -86,22 +86,22 @@ export default function SignupForm() {
toast.promise(signUp, {
pending: "Creating account...",
- success: {
- render() {
- setLoading(false);
- router.push(`/verify-email?email=${encodeURIComponent(email)}`);
-
- return "Please check your email to verify your account.";
- },
- },
+ success: "Please check your email to verify your account.",
error: {
render({ data }) {
- setLoading(false);
const err = data as Error;
return err?.message || "Failed to sign up. Please try again.";
},
},
});
+
+ signUp
+ .then(() => {
+ router.push(`/verify-email?email=${encodeURIComponent(email)}`);
+ })
+ .finally(() => {
+ setLoading(false);
+ });
};
return (
diff --git a/app/components/auth/form/UpdatePasswordForm.tsx b/app/components/auth/form/UpdatePasswordForm.tsx
index 9e8cb93..c3ccc87 100644
--- a/app/components/auth/form/UpdatePasswordForm.tsx
+++ b/app/components/auth/form/UpdatePasswordForm.tsx
@@ -69,20 +69,18 @@ export default function UpdatePasswordForm() {
toast.promise(updateUserPasswordPromise, {
pending: "Updating password...",
- success: {
- render() {
- setLoading(false);
- return "Password updated!";
- },
- },
+ success: "Password updated!",
error: {
render({ data }) {
- setLoading(false);
const err = data as Error;
return err?.message || "Failed to update password. Please try again.";
},
},
});
+
+ updateUserPasswordPromise.finally(() => {
+ setLoading(false);
+ });
};
return (
diff --git a/app/components/common/NavProfileDropdown.tsx b/app/components/common/NavProfileDropdown.tsx
index 32bb460..94b27bb 100644
--- a/app/components/common/NavProfileDropdown.tsx
+++ b/app/components/common/NavProfileDropdown.tsx
@@ -72,7 +72,7 @@ export default function NavProfileDropdown({
setProfileOpen(false)}
>
@@ -144,7 +144,7 @@ export default function NavProfileDropdown({
{type === "navbar" && (
setProfileOpen(false)}
>
diff --git a/app/components/dashboard/Navbar.tsx b/app/components/dashboard/Navbar.tsx
index 78c9232..b950cc2 100644
--- a/app/components/dashboard/Navbar.tsx
+++ b/app/components/dashboard/Navbar.tsx
@@ -184,7 +184,7 @@ export default function DashboardLayout({
>
diff --git a/app/components/dashboard/Settings/Profile.tsx b/app/components/dashboard/Settings/Profile.tsx
index b34088b..64f0d49 100644
--- a/app/components/dashboard/Settings/Profile.tsx
+++ b/app/components/dashboard/Settings/Profile.tsx
@@ -22,7 +22,7 @@ export default function UserProfile({ user }: { user: UserShape }) {
const [loading, setLoading] = useState(false);
const [isEditing, setIsEditing] = useState(false);
const { badWords } = useBadWords();
- const preferredAvatar = user.image || "/logo.svg";
+ const preferredAvatar = user.image || "/apple-touch-icon.png";
const isEdited = name.trim() !== originalName.trim();
@@ -65,19 +65,21 @@ export default function UserProfile({ user }: { user: UserShape }) {
success: "Profile updated!",
error: {
render({ data }) {
- setLoading(false);
const err = data as Error;
return err?.message || "Failed to update profile. Please try again.";
},
},
});
- updateUserProfile.then(() => {
- setLoading(false);
- setOriginalName(sanitizedName);
- setName(sanitizedName);
- setIsEditing(false);
- });
+ updateUserProfile
+ .then(() => {
+ setOriginalName(sanitizedName);
+ setName(sanitizedName);
+ setIsEditing(false);
+ })
+ .finally(() => {
+ setLoading(false);
+ });
}
return (
diff --git a/app/components/dashboard/Settings/ResetPassword.tsx b/app/components/dashboard/Settings/ResetPassword.tsx
index 6c40e0c..274a3fd 100644
--- a/app/components/dashboard/Settings/ResetPassword.tsx
+++ b/app/components/dashboard/Settings/ResetPassword.tsx
@@ -67,15 +67,9 @@ export default function ResetPassword({ email }: { email: string }) {
toast.promise(resetUserPasswordPromise, {
pending: "Sending reset email...",
- success: {
- render() {
- setLoading(false);
- return "Reset email sent!";
- },
- },
+ success: "Reset email sent!",
error: {
render({ data }) {
- setLoading(false);
const err = data as Error;
return (
err?.message || "Failed to send reset email. Please try again."
@@ -83,6 +77,10 @@ export default function ResetPassword({ email }: { email: string }) {
},
},
});
+
+ resetUserPasswordPromise.finally(() => {
+ setLoading(false);
+ });
};
return (
diff --git a/app/components/layout/Nav.tsx b/app/components/layout/Nav.tsx
index 0a2f4dd..d16a3a5 100644
--- a/app/components/layout/Nav.tsx
+++ b/app/components/layout/Nav.tsx
@@ -14,7 +14,7 @@ export default async function Nav() {
className="flex items-center gap-3 hover:opacity-80 transition"
data-aos="fade-down"
>
-
+
Devpulse
diff --git a/app/components/leaderboard/Header.tsx b/app/components/leaderboard/Header.tsx
index 7778873..4fef554 100644
--- a/app/components/leaderboard/Header.tsx
+++ b/app/components/leaderboard/Header.tsx
@@ -36,7 +36,7 @@ export default function LeaderboardHeader({
-
+
Devpulse
diff --git a/app/layout.tsx b/app/layout.tsx
index 591c14e..96c67f9 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -83,7 +83,7 @@ export async function generateMetadata(): Promise {
},
{
rel: "icon",
- url: "/favicon.png",
+ url: "/favicon-32x32.png",
},
],
};
@@ -104,16 +104,52 @@ export default function RootLayout({
data-scroll-behavior="smooth"
>
+
+
+
+
+
+
+
+
+
+
+
{children}
+
+
{isProduction && (
<>
diff --git a/app/page.tsx b/app/page.tsx
index fde4032..43c256f 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -110,7 +110,7 @@ export default async function Home() {
"@type": "Organization",
name: "Devpulse",
url: "https://devpulse.hallofcodes.org",
- logo: "https://devpulse.hallofcodes.org/favicon.png",
+ logo: "https://devpulse.hallofcodes.org/favicon-32x32.png",
},
};
@@ -138,26 +138,12 @@ export default async function Home() {
{/* Hero Section */}
-
+
{/* Left text */}
-
-
- Star on GitHub
-
-
Measure your
@@ -166,7 +152,7 @@ export default async function Home() {
Turn your daily coding activity into competitive, shareable
@@ -176,21 +162,33 @@ export default async function Home() {
@@ -233,7 +231,9 @@ export default async function Home() {
-
TypeScript
+
+ TypeScript
+
28h 40m
@@ -304,15 +304,12 @@ export default async function Home() {
className="max-w-7xl mx-auto px-6 py-24 lg:py-32 relative z-10"
>
-
+
Everything you need to grow.
Devpulse integrates seamlessly with your tools to provide
@@ -384,7 +381,7 @@ function FeatureCard({
return (
diff --git a/ecosystem.config.js b/ecosystem.config.js
new file mode 100644
index 0000000..21de3d7
--- /dev/null
+++ b/ecosystem.config.js
@@ -0,0 +1,16 @@
+module.exports = {
+ apps: [
+ {
+ name: "devpulse",
+ script: "./node_modules/next/dist/bin/next",
+ args: "start",
+ instances: "max",
+ exec_mode: "cluster",
+ max_memory_restart: "1G",
+ env: {
+ NODE_ENV: "production",
+ PORT: 3000,
+ },
+ },
+ ],
+};
diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png
new file mode 100644
index 0000000..f524cdc
Binary files /dev/null and b/public/android-chrome-192x192.png differ
diff --git a/public/android-chrome-512x512.png b/public/android-chrome-512x512.png
new file mode 100644
index 0000000..308f154
Binary files /dev/null and b/public/android-chrome-512x512.png differ
diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png
new file mode 100644
index 0000000..099d9eb
Binary files /dev/null and b/public/apple-touch-icon.png differ
diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png
new file mode 100644
index 0000000..91ccf8e
Binary files /dev/null and b/public/favicon-16x16.png differ
diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png
new file mode 100644
index 0000000..40a19a0
Binary files /dev/null and b/public/favicon-32x32.png differ
diff --git a/public/favicon.ico b/public/favicon.ico
index 7283b9d..e2585f0 100644
Binary files a/public/favicon.ico and b/public/favicon.ico differ
diff --git a/public/favicon.png b/public/favicon.png
deleted file mode 100644
index 33ac00f..0000000
Binary files a/public/favicon.png and /dev/null differ
diff --git a/public/images/devpulse.cover.png b/public/images/devpulse.cover.png
index 194f982..0456ce3 100644
Binary files a/public/images/devpulse.cover.png and b/public/images/devpulse.cover.png differ
diff --git a/public/logo.svg b/public/logo.svg
deleted file mode 100644
index 97569ec..0000000
--- a/public/logo.svg
+++ /dev/null
@@ -1,33 +0,0 @@
-
diff --git a/public/robots.txt b/public/robots.txt
index 7442891..eb4eb9c 100644
--- a/public/robots.txt
+++ b/public/robots.txt
@@ -9,4 +9,4 @@ Allow: /join$
Disallow: /join/
Disallow: /reset-password/
-Sitemap: https://www.hallofcodes.org/sitemap.xml
+Sitemap: https://devpulse.hallofcodes.org/sitemap.xml
diff --git a/public/site.webmanifest b/public/site.webmanifest
new file mode 100644
index 0000000..45dc8a2
--- /dev/null
+++ b/public/site.webmanifest
@@ -0,0 +1 @@
+{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
\ No newline at end of file