feat(frontend): connect Next.js server components to Go backend REST API with resilient fallback

- Implement typed REST API client in refer_landing_page/lib/api.ts
- Support API_BASE_URL environment variable with graceful fallback to static content
- Connect Home page (projects, areas, stats), Members page (active, alumni), Publications (highlights, list, patents), Lectures, and Standardization pages to backend endpoints
- Pass all 12 SSG build, TypeScript, ESLint, and E2E quality gates
This commit is contained in:
2026-08-24 18:40:46 +09:00
parent fb6881070c
commit 9cb6258d3d
10 changed files with 415 additions and 40 deletions
@@ -1,9 +1,15 @@
import React from "react";
import { researchProjects } from "../../content/projects";
import { researchProjects as staticProjects } from "../../content/projects";
import type { ResearchProject } from "../../content/types";
import ProjectPageViewControls from "./ProjectPageViewControls";
export function ProjectPageView() {
const slugs = researchProjects.map((p) => p.slug);
interface ProjectPageViewProps {
projects?: ResearchProject[];
}
export function ProjectPageView({ projects: projectsProp }: ProjectPageViewProps = {}) {
const projects = projectsProp ?? staticProjects;
const slugs = projects.map((p) => p.slug);
const trackId = "research-projects-track";
return (
@@ -21,7 +27,7 @@ export function ProjectPageView() {
</h2>
</div>
<p className="text-xs text-ink-mute font-mono">
{researchProjects.length} core international standardization research projects
{projects.length} core international standardization research projects
</p>
</div>
@@ -34,13 +40,13 @@ export function ProjectPageView() {
aria-label="연구 프로젝트 목록"
className="flex gap-6 overflow-x-auto snap-x snap-mandatory scroll-smooth [scrollbar-width:none] [&::-webkit-scrollbar]:hidden desktop:grid desktop:grid-cols-3 desktop:overflow-visible focus:outline-none focus:ring-1 focus:ring-cobalt/50 rounded"
>
{researchProjects.map((proj, idx) => (
{projects.map((proj, idx) => (
<article
key={proj.slug}
id={`project-${proj.slug}`}
role="group"
aria-roledescription="slide"
aria-label={`${researchProjects.length}개 중 ${idx + 1}번째 프로젝트`}
aria-label={`${projects.length}개 중 ${idx + 1}번째 프로젝트`}
className="snap-start shrink-0 min-w-0 w-full md:w-[calc(50%-12px)] desktop:w-full flex flex-col justify-between bg-paper p-6 rounded-lg border border-line hover:border-cobalt/60 transition-colors space-y-5 break-words [word-break:keep-all]"
>
<div className="space-y-4">