diff --git a/package.json b/package.json
index 09abc7c1..fe148350 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,8 @@
"scripts": {
"dev": "next dev",
"build": "next build",
- "start": "next start",
+ "postbuild": "mkdir -p .next/standalone/.next/static && cp -r .next/static/* .next/standalone/.next/static/ 2>/dev/null; true",
+ "start": "node .next/standalone/server.js",
"prisma:generate": "prisma generate",
"typecheck": "tsc --noEmit --incremental false",
"biome:check": "biome check --write .",
diff --git a/src/app/(site)/login/page.tsx b/src/app/(site)/login/page.tsx
index e90fdf04..af098b43 100644
--- a/src/app/(site)/login/page.tsx
+++ b/src/app/(site)/login/page.tsx
@@ -11,17 +11,19 @@ import { resolveHotelName } from "@/lib/hotel-name";
import { siteSettings } from "@/lib/services/site-settings";
import { ThemeSwitcher } from "@/components/theme-switcher";
import { LanguageSwitcher } from "@/components/language-switcher";
+import { Reveal } from "@/components/motion-reveal";
export default async function LoginPage() {
const t = await getTranslations("pages.login");
const th = await getTranslations("header");
- const [hotelName, imagerRaw, cfg] = await Promise.all([
+ const [hotelName, imagerRaw, cfg, discordUrl] = await Promise.all([
resolveHotelName(),
siteSettings.get(
"habbo_imaging_url",
"https://www.habbo.com/habbo-imaging/avatarimage",
),
captchaConfig(),
+ siteSettings.get("radio_social_discord", ""),
]);
const imager = imagerRaw ?? "https://www.habbo.com/habbo-imaging/avatarimage";
const nonce = (await headers()).get("x-nonce") ?? undefined;
@@ -47,31 +49,41 @@ export default async function LoginPage() {
]);
return (
-
-
-
-
-
- {hotelName}
-
+
+ {/* ── Top Bar ── */}
+
+
+
+
+
+ {hotelName}
+
+
+ {discordUrl && (
+
+
+
+ )}
-
+
+
{/* Left panel */}
@@ -114,7 +126,7 @@ export default async function LoginPage() {
{t("welcomeBack")}
@@ -129,21 +141,21 @@ export default async function LoginPage() {
{recentUsers.length > 0 && (
-
-
- {th("online", { count: online, hotel: "" }).trim()}
-
+
+
+ {th("online", { count: online, hotel: "" }).trim()}
+
+
+
{recentUsers.map((u) => (
))}
+
)}
{latestUsers.length > 0 && (
-
- ✨ Newest citizens
-
+
+
+ Newest citizens
+
+
+
{latestUsers.map((u) => (
))}
+
)}
@@ -232,40 +247,38 @@ export default async function LoginPage() {
{/* Right: form */}
-
-
-
+
+
+
+
{t("title")}
-
- {t("subtitle")}
-
-
-
+
+
+ {t("subtitle")}
+
+
+
+
+
);
}
diff --git a/src/app/(site)/page.tsx b/src/app/(site)/page.tsx
index 7af17264..198a1657 100644
--- a/src/app/(site)/page.tsx
+++ b/src/app/(site)/page.tsx
@@ -57,7 +57,9 @@ async function getHotelData() {
.catch(() => []),
]);
- return { hotelName, imager, online, users, rooms, articles, recentUsers, recentPhotos, latestUsers };
+ const discordUrl = await siteSettings.get("radio_social_discord", "");
+
+ return { hotelName, imager, online, users, rooms, articles, recentUsers, recentPhotos, latestUsers, discordUrl };
}
export default async function Home() {
@@ -66,7 +68,7 @@ export default async function Home() {
const tp = await getTranslations("pages.home");
const th = await getTranslations("header");
- const { hotelName, imager, online, users, rooms, articles, recentUsers, recentPhotos, latestUsers } = await getHotelData();
+ const { hotelName, imager, online, users, rooms, articles, recentUsers, recentPhotos, latestUsers, discordUrl } = await getHotelData();
const captcha = await captchaConfig();
const nonce = (await headers()).get("x-nonce") ?? undefined;
@@ -84,7 +86,7 @@ export default async function Home() {
}}>
+ {discordUrl && (
+
+
+
+ )}
@@ -137,7 +144,7 @@ export default async function Home() {
{tp("welcome", { hotelName })}
@@ -196,8 +203,8 @@ export default async function Home() {
{[
- { value: online.toLocaleString(), label: tp("statsOnline"), icon: "/assets/images/icons/navigation/home.png" },
- { value: users.toLocaleString(), label: tp("statsCitizens"), icon: "/assets/images/icons/navigation/me.png" },
+ { value: online.toLocaleString(), label: tp("statsOnline"), icon: "/assets/images/icons/online-friends.png" },
+ { value: users.toLocaleString(), label: tp("statsCitizens"), icon: "/assets/images/icons/friends.png" },
{ value: rooms.toLocaleString(), label: tp("statsRooms"), icon: "/assets/images/icons/catalog.png" },
].map((s) => (
-
+
{tp("register")}
@@ -331,7 +338,7 @@ export default async function Home() {
+
+ →
+
{[
- { img: "/assets/images/icons/star.gif", title: tp("featuresAvatar"), desc: tp("featuresAvatarDesc") },
+ { img: "/assets/images/icons/navigation/me.png", title: tp("featuresAvatar"), desc: tp("featuresAvatarDesc") },
{ img: "/assets/images/icons/catalog.png", title: tp("featuresFurniture"), desc: tp("featuresFurnitureDesc") },
{ img: "/assets/images/icons/navigation/community.png", title: tp("featuresCommunity"), desc: tp("featuresCommunityDesc") },
{ img: "/assets/images/icons/navigation/bb.png", title: tp("featuresGames"), desc: tp("featuresGamesDesc") },
].map((f) => (
+ {/* ── Client / Play ── */}
+
+
+
+
+
+
+ {th("nitroClient")}
+
+
+ {tp("welcomeBody")}
+
+
+
+
+ {th("nitroClient")}
+
+
+
+
+
{/* ── Online users ── */}
{recentUsers.length > 0 && (
-
-
- {tp("recentUsers")}
-
+
+
+
+ {tp("recentUsers")}
+
+
+
+ {tp("allNews")}
+
@@ -469,7 +522,7 @@ export default async function Home() {
borderColor: "color-mix(in srgb, var(--color-primary) 15%, transparent)",
}}
>
-
+
{tp("joinNow", { hotelName })}
diff --git a/src/app/(site)/register/page.tsx b/src/app/(site)/register/page.tsx
index c0fe8229..6daee9b1 100644
--- a/src/app/(site)/register/page.tsx
+++ b/src/app/(site)/register/page.tsx
@@ -11,17 +11,19 @@ import { resolveHotelName } from "@/lib/hotel-name";
import { siteSettings } from "@/lib/services/site-settings";
import { ThemeSwitcher } from "@/components/theme-switcher";
import { LanguageSwitcher } from "@/components/language-switcher";
+import { Reveal } from "@/components/motion-reveal";
export default async function RegisterPage() {
const th = await getTranslations("header");
const tpr = await getTranslations("pages.register");
- const [hotelName, imagerRaw, cfg] = await Promise.all([
+ const [hotelName, imagerRaw, cfg, discordUrl] = await Promise.all([
resolveHotelName(),
siteSettings.get(
"habbo_imaging_url",
"https://www.habbo.com/habbo-imaging/avatarimage",
),
captchaConfig(),
+ siteSettings.get("radio_social_discord", ""),
]);
const imager = imagerRaw ?? "https://www.habbo.com/habbo-imaging/avatarimage";
const nonce = (await headers()).get("x-nonce") ?? undefined;
@@ -47,31 +49,41 @@ export default async function RegisterPage() {
]);
return (
-
-
-
-
-
- {hotelName}
-
+
+ {/* ── Top Bar ── */}
+
+
+
+
+
+ {hotelName}
+
+
+ {discordUrl && (
+
+
+
+ )}
-
+
+
{/* Left panel */}
@@ -113,7 +125,7 @@ export default async function RegisterPage() {
{tpr("title")} — {hotelName}
@@ -128,21 +140,21 @@ export default async function RegisterPage() {
{recentUsers.length > 0 && (
-
-
- {tpr("whoIsOnline")}
-
+
+
+ {tpr("whoIsOnline")}
+
+
+
{recentUsers.map((u) => (
))}
+
)}
{latestUsers.length > 0 && (
-
- ✨ Newest citizens
-
+
+
+ Newest citizens
+
+
+
{latestUsers.map((u) => (
))}
+
)}
@@ -241,29 +256,25 @@ export default async function RegisterPage() {
{/* Right: form */}
-
-
-
+
- {tpr("title")}
-
+
+
+ {tpr("title")}
+
+
+
+
+
);
}