Remove coming-soon; redirect site hosts to website app.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-09-07 21:00:23 +03:30
co-authored by Cursor
parent 18b29f5b62
commit 1041ab20c5
7 changed files with 18 additions and 237 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
NEXT_PUBLIC_API_URL=http://api.mana-collection.com:3002/api/v1
NEXT_PUBLIC_STORE_URL=http://store.mana-collection.com:3000
NEXT_PUBLIC_STORE_URL=http://store.mana-collection.com:3001
NEXT_PUBLIC_SITE_URL=http://mana-collection.com:3000
+3 -2
View File
@@ -11,8 +11,9 @@ Shared Next.js app for **store admin** and **customer** account UI.
| URL | App |
|-----|-----|
| http://store.mana-collection.com:3000 | Store dashboard |
| http://customer.mana-collection.com:3000 | Customer (same app) |
| http://mana-collection.com:3000 | Website (coming soon) |
| http://store.mana-collection.com:3001 | Store dashboard |
| http://customer.mana-collection.com:3001 | Customer (same app) |
| http://api.mana-collection.com:3002/api/v1 | Backend API |
```bash
+2 -2
View File
@@ -3,9 +3,9 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev -H 0.0.0.0 -p 3000",
"dev": "next dev -H 0.0.0.0 -p 3001",
"build": "next build",
"start": "next start -H 0.0.0.0 -p 3000",
"start": "next start -H 0.0.0.0 -p 3001",
"lint": "eslint"
},
"dependencies": {
-87
View File
@@ -1,87 +0,0 @@
import type { Metadata } from "next";
import Image from "next/image";
import ManaLogo from "@/components/ui/ManaLogo";
export const metadata: Metadata = {
title: "به‌زودی | مانا کالکشن",
description: "فروشگاه آنلاین مانا کالکشن به‌زودی در دسترس خواهد بود.",
};
const STORE_LOGIN =
process.env.NEXT_PUBLIC_STORE_URL?.replace(/\/$/, "") ||
"http://store.mana-collection.com:3000";
export default function ComingSoonPage() {
return (
<main className="coming-soon relative min-h-dvh overflow-hidden bg-[#f7f7f5] text-ink">
{/* dir=ltr keeps content on visual left, image on visual right */}
<div dir="ltr" className="grid min-h-dvh grid-cols-1 lg:grid-cols-2">
{/* Content — left */}
<section className="relative order-2 flex min-h-[52dvh] flex-col lg:order-1 lg:min-h-dvh">
<div className="mana-canvas absolute inset-0" aria-hidden />
<div
dir="rtl"
className="relative z-10 flex flex-1 flex-col px-7 py-8 sm:px-12 sm:py-10 lg:px-16 lg:py-14"
>
<header className="coming-soon-seq coming-soon-seq-1 flex shrink-0 justify-center">
<ManaLogo
href=""
width={400}
priority
showTagline
variant="white"
blackBg
className="w-[400px] max-w-[min(400px,100%)]"
/>
</header>
<div className="flex flex-1 flex-col items-center justify-center py-12 text-center sm:py-16">
<div className="max-w-md">
<p
dir="ltr"
className="coming-soon-seq coming-soon-seq-2 mb-4 font-display text-sm tracking-[0.2em] text-muted sm:text-base"
>
Coming soon
</p>
<h1 className="coming-soon-seq coming-soon-seq-3 mb-5 text-4xl leading-tight text-ink sm:text-5xl">
به‌زودی
</h1>
<p className="coming-soon-seq coming-soon-seq-4 text-sm leading-8 text-muted sm:text-base sm:leading-8">
در این آدرس میزبان شما خواهیم بود.
</p>
</div>
</div>
<footer className="coming-soon-seq coming-soon-seq-5 shrink-0 pt-6">
<div className="flex flex-wrap items-center justify-between gap-4">
<p className="text-xs leading-6 text-muted">
حساب دارید؟ وارد شوید.
</p>
<a
href={`${STORE_LOGIN}/login`}
className="coming-soon-login inline-flex items-center justify-center border border-ink bg-ink px-7 py-2.5 text-sm text-white transition-colors hover:bg-white hover:text-ink"
>
ورود
</a>
</div>
</footer>
</div>
</section>
{/* Image — right */}
<aside className="coming-soon-seq-image relative order-1 min-h-[42dvh] overflow-hidden lg:order-2 lg:min-h-dvh">
<Image
src="/images/image1.jpg"
alt="مانا کالکشن"
fill
priority
sizes="(max-width: 1024px) 100vw, 50vw"
className="coming-soon-image object-cover object-center"
/>
<div className="pointer-events-none absolute inset-0 bg-gradient-to-l from-transparent via-transparent to-black/10" />
</aside>
</div>
</main>
);
}
-123
View File
@@ -35,129 +35,6 @@ body {
font-family: var(--font-montserrat), system-ui, sans-serif;
}
/* Soft paper atmosphere + scattered random dots */
@keyframes coming-soon-rise {
from {
opacity: 0;
transform: translateY(22px);
filter: blur(6px);
}
to {
opacity: 1;
transform: translateY(0);
filter: blur(0);
}
}
@keyframes coming-soon-panel {
from {
opacity: 0;
transform: translateX(24px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes coming-soon-drift {
0% {
transform: scale(1) translate3d(0, 0, 0);
}
100% {
transform: scale(1.06) translate3d(-0.8%, 0.5%, 0);
}
}
@keyframes coming-soon-line {
from {
transform: scaleX(0);
opacity: 0;
}
to {
transform: scaleX(1);
opacity: 1;
}
}
@keyframes coming-soon-glow {
0%,
100% {
box-shadow: 0 0 0 0 rgba(10, 10, 10, 0);
}
50% {
box-shadow: 0 0 0 4px rgba(10, 10, 10, 0.06);
}
}
.coming-soon-seq {
opacity: 0;
animation: coming-soon-rise 0.95s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
.coming-soon-seq-1 {
animation-delay: 0.12s;
}
.coming-soon-seq-2 {
animation-delay: 0.38s;
}
.coming-soon-seq-3 {
animation-delay: 0.58s;
}
.coming-soon-seq-4 {
animation-delay: 0.78s;
}
.coming-soon-seq-5 {
animation-delay: 1s;
}
.coming-soon-seq-5 {
position: relative;
}
.coming-soon-seq-5::before {
content: "";
position: absolute;
top: 0;
inset-inline: 0;
height: 1px;
background: var(--line);
transform-origin: center;
animation: coming-soon-line 0.7s cubic-bezier(0.16, 1, 0.3, 1) 1.05s both;
}
.coming-soon-seq-image {
opacity: 0;
animation: coming-soon-panel 1.1s ease-out 0.05s forwards;
}
.coming-soon-image {
transform: scale(1);
animation: coming-soon-drift 20s ease-in-out 1.2s alternate infinite both;
will-change: transform;
}
.coming-soon-login {
animation: coming-soon-glow 2.4s ease-in-out 1.6s 2;
}
@media (prefers-reduced-motion: reduce) {
.coming-soon-seq,
.coming-soon-seq-image,
.coming-soon-image,
.coming-soon-seq-5::before,
.coming-soon-login {
animation: none !important;
opacity: 1 !important;
filter: none !important;
transform: none !important;
}
}
.mana-canvas,
.auth-canvas {
background:
+4 -14
View File
@@ -4,12 +4,7 @@ import { useEffect } from "react";
import { usePathname, useRouter } from "next/navigation";
import { useAuth } from "@/lib/auth";
const PUBLIC_PATHS = ["/login", "/coming-soon"];
const WEBSITE_HOSTS = new Set([
"mana-collection.com",
"www.mana-collection.com",
]);
const PUBLIC_PATHS = ["/login"];
export default function RequireStoreAuth({
children,
@@ -20,14 +15,9 @@ export default function RequireStoreAuth({
const pathname = usePathname();
const router = useRouter();
const host =
typeof window !== "undefined"
? window.location.hostname.toLowerCase()
: "";
const onWebsite = WEBSITE_HOSTS.has(host);
const isPublic =
onWebsite ||
PUBLIC_PATHS.some((p) => pathname === p || pathname.startsWith(`${p}/`));
const isPublic = PUBLIC_PATHS.some(
(p) => pathname === p || pathname.startsWith(`${p}/`),
);
useEffect(() => {
if (loading || isPublic) return;
+8 -8
View File
@@ -5,6 +5,10 @@ const WEBSITE_HOSTS = new Set([
"www.mana-collection.com",
]);
const SITE_ORIGIN =
process.env.NEXT_PUBLIC_SITE_URL?.replace(/\/$/, "") ||
"http://mana-collection.com:3000";
export function middleware(request: NextRequest) {
const host = request.headers.get("host")?.split(":")[0]?.toLowerCase() ?? "";
if (!WEBSITE_HOSTS.has(host)) {
@@ -21,15 +25,11 @@ export function middleware(request: NextRequest) {
return NextResponse.next();
}
if (pathname === "/coming-soon") {
return NextResponse.next();
}
const url = request.nextUrl.clone();
url.pathname = "/coming-soon";
return NextResponse.redirect(url);
return NextResponse.redirect(new URL(pathname || "/", SITE_ORIGIN));
}
export const config = {
matcher: ["/((?!_next/static|_next/image|.*\\.(?:svg|png|jpg|jpeg|gif|webp|woff|woff2|otf|ttf)$).*)"],
matcher: [
"/((?!_next/static|_next/image|.*\\.(?:svg|png|jpg|jpeg|gif|webp|woff|woff2|otf|ttf)$).*)",
],
};