Files
netrunner-landing/app/[lang]/page.tsx
T
nineap 899c54e1fc Unify auth with backend cookie sessions; add dev-deploy pipeline
Auth: drop localStorage session token entirely, talk to netrunner-backend
via credentials:"include" HttpOnly cookies shared over the common parent
domain, and redirect to the account subdomain (ЛК) after login instead of
a dead local /profile route.

Config: NEXT_PUBLIC_* values used by client components (API_URL,
ACCOUNT_ORIGIN, BOT_USERNAME, PB_URL) get inlined into the JS bundle at
image build time and can't be overridden by docker-compose environment at
container start. Moved these reads into server components (page.tsx) and
thread them down as props, so one built image can genuinely serve both
prod and dev by config alone.

CI/CD: split the old single auto-deploy-to-prod workflow into build.yml
(build+push on every push to main) and deploy.yml with deploy-dev (auto,
same VPS as netrunner-backend's dev environment) and deploy-prod (manual
dispatch only) — mirrors netrunner-backend's pipeline shape. Added
docker-compose.dev-remote.yml pointing at the dev backend.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 15:26:28 +07:00

66 lines
3.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Suspense } from "react";
import dynamic from "next/dynamic";
import { getDictionary } from "@/lib/dictionaries";
import { Hero } from "@/components/sections/Hero";
import { Features } from "@/components/sections/Features";
const SectionSkeleton = () => (
<div className="h-[500px] w-full animate-pulse bg-card/20 rounded-3xl my-10" />
);
// Тяжёлые интерактивные секции (framer-motion анимации, клиентские запросы к PocketBase,
// realtime-подписки) грузятся через next/dynamic, а не обычным import, чтобы не раздувать
// первый JS-бандл главной страницы: Hero и Features рендерятся сразу (статично, легче),
// а Pricing/FAQ/TerminalGuestbook/BlogPreview подгружаются отдельными чанками с плейсхолдером
// SectionSkeleton, пока грузится JS.
const Pricing = dynamic(
() => import("@/components/sections/Pricing").then((mod) => mod.Pricing),
{ loading: () => <SectionSkeleton /> },
);
const FAQ = dynamic(
() => import("@/components/sections/Faq").then((mod) => mod.FAQ),
{ loading: () => <SectionSkeleton /> },
);
const TerminalGuestbook = dynamic(
() =>
import("@/components/sections/TerminalGuestbook").then(
(mod) => mod.TerminalGuestbook,
),
{ loading: () => <SectionSkeleton /> },
);
const BlogPreview = dynamic(() =>
import("@/components/sections/BlogPreview").then((mod) => mod.BlogPreview),
);
export default async function Home({
params,
}: {
params: Promise<{ lang: string }>;
}) {
const { lang } = await params;
const dict = await getDictionary(lang);
// Читаем PB_PUBLIC_URL, а не NEXT_PUBLIC_PB_URL: Next.js статически подставляет
// NEXT_PUBLIC_*-переменные везде, где они встречаются в коде (в т.ч. внутри серверных
// компонентов), на этапе `next build` — так что чтение NEXT_PUBLIC_PB_URL здесь давало бы
// то же самое собранное-в-образ значение, что и в клиентском бандле. PB_PUBLIC_URL —
// обычная (не NEXT_PUBLIC_) переменная, поэтому читается по-настоящему заново при каждом
// запросе (см. подробный комментарий в app/[lang]/auth/auth-client.tsx про ACCOUNT_ORIGIN).
const pbUrl =
process.env.PB_PUBLIC_URL || "https://netrunner-vpn.com/cms-api";
return (
<>
<Hero dict={dict.hero} lang={lang} />
<Features dict={dict.features} />
<Pricing dict={dict.pricing} lang={lang} pbUrl={pbUrl} />
<FAQ dict={dict.faq} lang={lang} />
<TerminalGuestbook dict={dict.guestbook} pbUrl={pbUrl} />
<Suspense fallback={<SectionSkeleton />}>
<BlogPreview lang={lang} dict={dict.blog} />
</Suspense>
</>
);
}