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} + + {hotelName} + +
+ {discordUrl && ( + + Discord + + )}
-
+
+
{/* 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() { }}>
{hotelName}
+ {discordUrl && ( + + Discord + + )}
@@ -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) => (
Register
- + {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} + + {hotelName} + +
+ {discordUrl && ( + + Discord + + )}
-
+
+
{/* 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")} +

+
+

{tpr("subtitle")}

-
+
+
); }