feat: Kinetic Ether 디자인 시스템 + 홈 대시보드형 재구성

- globals.css: --kx-* 토큰(서피스 4단계, 네온 퍼플/시안), Space Grotesk/Inter/Manrope
  도입(next/font), 글래스·글로우·폴더 컨테이너·버튼 유틸 클래스
- app/page.tsx v5: 워크스페이스형 대시보드(헤더+Engine Status 패널+Launch Pads
  그리드+Credibility Monitor+Final CTA), Stitch "Kinetic Ether" 참조
- "7년차 대기업 백엔드" 카피 전역 교체(현직 엔지니어/실무 엔지니어)
- /services/music 히어로 레이블·디스플레이 폰트 토큰 정합

참조: Downloads/stitch_ai_mv/{sonicai_main_landing_page, aether_forge, ...}

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-15 02:08:54 +09:00
parent 2c8a0f1c37
commit 6c74b2cc93
8 changed files with 324 additions and 341 deletions

View File

@@ -3,7 +3,7 @@ import type { Metadata } from 'next';
export const metadata: Metadata = { export const metadata: Metadata = {
title: '외주 개발 의뢰', title: '외주 개발 의뢰',
description: description:
'계약서 먼저, 납기 지키고, 소스코드 100% 인도. 47건 납품 완료. 현직 대기업 백엔드 개발자에게 외주 개발을 맡겨보세요. 납기 지연 시 하루 10만 원 패널티.', '계약서 먼저, 납기 지키고, 소스코드 100% 인도. 47건 납품 완료. 현직 실무 엔지니어에게 외주 개발을 맡겨보세요. 납기 지연 시 하루 10만 원 패널티.',
keywords: [ keywords: [
'외주 개발', '외주 개발',
'프리랜서 개발자', '프리랜서 개발자',

View File

@@ -308,7 +308,7 @@ export default function FreelancePage() {
</div> </div>
<div> <div>
<div className="text-white font-bold text-sm"> ()</div> <div className="text-white font-bold text-sm"> ()</div>
<div className="text-blue-300/50 text-xs"> 7 · Python / Java / Next.js</div> <div className="text-blue-300/50 text-xs"> · Python / Java / Next.js</div>
</div> </div>
<div className="flex flex-wrap gap-2"> <div className="flex flex-wrap gap-2">
{['Python', 'Java', 'Next.js', 'Docker'].map(t => ( {['Python', 'Java', 'Next.js', 'Docker'].map(t => (

View File

@@ -35,6 +35,20 @@
--sidebar-bg: #04102b; --sidebar-bg: #04102b;
--card-bg: #ffffff; --card-bg: #ffffff;
--border: #dbe8ff; --border: #dbe8ff;
/* ─── Kinetic Ether Tokens (다크 테마 섹션 전용) ─── */
--kx-surface: #060e20;
--kx-surface-low: #091328;
--kx-surface-mid: #0f1930;
--kx-surface-high: #141f38;
--kx-surface-bright: #1f2b49;
--kx-on-surface: #dee5ff;
--kx-on-variant: #a3aac4;
--kx-primary: #cc97ff;
--kx-primary-dim: #9c48ea;
--kx-secondary: #53ddfc;
--kx-secondary-dim: #40ceed;
--kx-outline: rgba(64, 72, 93, 0.15);
} }
@theme inline { @theme inline {
@@ -84,6 +98,82 @@ body {
background-clip: text; background-clip: text;
} }
/* ─── Kinetic Ether 유틸리티 ─── */
.kx-section {
background: var(--kx-surface);
color: var(--kx-on-surface);
font-family: 'Space Grotesk', 'Inter', 'CookieRun', system-ui, sans-serif;
}
.kx-section p, .kx-section li, .kx-section span:not(.kx-label) {
color: var(--kx-on-variant);
}
.kx-display {
font-family: 'Space Grotesk', 'CookieRun', system-ui, sans-serif;
letter-spacing: -0.02em;
color: var(--kx-on-surface);
}
.kx-label {
font-family: 'Manrope', 'Inter', system-ui, sans-serif;
font-size: 0.6875rem;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--kx-secondary);
}
.kx-folder {
background: var(--kx-surface-mid);
border-radius: 0.75rem 0.75rem 0.125rem 0.125rem;
padding: 1.5rem;
position: relative;
}
.kx-folder::before {
content: '';
position: absolute; top: 0; left: 0; right: 0; height: 1px;
background: linear-gradient(90deg, transparent, rgba(204,151,255,0.3), transparent);
}
.kx-glass {
background: rgba(25, 37, 64, 0.6);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border-radius: 1rem;
}
.kx-glow {
box-shadow: 0 0 40px 0 rgba(156, 72, 234, 0.25),
0 0 80px 0 rgba(83, 221, 252, 0.08);
}
.kx-btn-primary {
background: linear-gradient(135deg, #cc97ff 0%, #c284ff 100%);
color: #0b0113;
font-weight: 700;
box-shadow: 0 0 20px 0 rgba(168, 85, 247, 0.4);
transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.kx-btn-primary:hover {
transform: translateY(-1px);
box-shadow: 0 0 28px 0 rgba(168, 85, 247, 0.55);
}
.kx-btn-ghost {
color: var(--kx-secondary);
background: transparent;
transition: background 0.15s ease;
}
.kx-btn-ghost:hover {
background: var(--kx-surface-bright);
}
.kx-gradient-text {
background: linear-gradient(135deg, #cc97ff 0%, #53ddfc 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.kx-orb {
position: absolute;
border-radius: 9999px;
filter: blur(80px);
opacity: 0.35;
pointer-events: none;
}
/* Service card hover */ /* Service card hover */
.service-card { .service-card {
transition: transform 0.2s ease, box-shadow 0.2s ease; transition: transform 0.2s ease, box-shadow 0.2s ease;

View File

@@ -1,15 +1,20 @@
import type { Metadata } from "next"; import type { Metadata } from "next";
import Script from "next/script"; import Script from "next/script";
import { Space_Grotesk, Inter, Manrope } from "next/font/google";
import "./globals.css"; import "./globals.css";
import DashboardShell from "./components/DashboardShell"; import DashboardShell from "./components/DashboardShell";
const spaceGrotesk = Space_Grotesk({ subsets: ["latin"], variable: "--font-kx-display", display: "swap" });
const inter = Inter({ subsets: ["latin"], variable: "--font-kx-body", display: "swap" });
const manrope = Manrope({ subsets: ["latin"], variable: "--font-kx-label", display: "swap" });
export const metadata: Metadata = { export const metadata: Metadata = {
title: { title: {
default: "쟁승메이드 | AI 프롬프트 · 업무 자동화 · 사주 분석", default: "쟁승메이드 | AI 프롬프트 · 업무 자동화 · 사주 분석",
template: "%s | 쟁승메이드", template: "%s | 쟁승메이드",
}, },
description: description:
"AI 프롬프트 패키지, 업무 자동화 개발, AI 사주 분석까지. 7년차 현직 개발자가 직접 만들고 운영하는 AI 도구 스토어. 9,900원부터.", "AI 음악·뮤비 구조 설계 팩, 블로그 자동화 , AI 사주 분석까지. 현직 엔지니어가 직접 설계·운영하는 AI 크리에이티브 스토어. 29,000원부터.",
keywords: [ keywords: [
"AI 프롬프트", "AI 프롬프트",
"ChatGPT 프롬프트", "ChatGPT 프롬프트",
@@ -30,7 +35,7 @@ export const metadata: Metadata = {
siteName: "쟁승메이드", siteName: "쟁승메이드",
title: "쟁승메이드 | AI 프롬프트 · 업무 자동화 · 사주 분석", title: "쟁승메이드 | AI 프롬프트 · 업무 자동화 · 사주 분석",
description: description:
"AI 프롬프트 패키지, 업무 자동화, AI 사주 분석. 7년차 현직 개발자가 만든 AI 도구 스토어.", "AI 음악 구조 설계 팩, 블로그 자동화, AI 사주 분석. 현직 엔지니어가 만든 AI 크리에이티브 스토어.",
images: [ images: [
{ {
url: "https://jaengseung-made.com/og-image.png", url: "https://jaengseung-made.com/og-image.png",
@@ -65,14 +70,14 @@ const jsonLd = {
email: 'bgg8988@gmail.com', email: 'bgg8988@gmail.com',
telephone: '010-3907-1392', telephone: '010-3907-1392',
knowsAbout: ['Python', 'Java', 'Spring Boot', 'Next.js', 'AI 프롬프트', 'AI 자동화', '업무 자동화', 'ChatGPT', 'Claude'], knowsAbout: ['Python', 'Java', 'Spring Boot', 'Next.js', 'AI 프롬프트', 'AI 자동화', '업무 자동화', 'ChatGPT', 'Claude'],
description: '7년차 현직 대기업 백엔드 개발자. AI 프롬프트 패키지, 업무 자동화, AI 사주 분석 등 AI 도구를 직접 개발·운영합니다.', description: '현직 엔지니어. AI 음악 구조 설계 팩, 블로그 자동화, AI 사주 분석 등 AI 크리에이티브 도구를 직접 개발·운영합니다.',
}, },
{ {
'@type': 'LocalBusiness', '@type': 'LocalBusiness',
'@id': 'https://jaengseung-made.com/#business', '@id': 'https://jaengseung-made.com/#business',
name: '쟁승메이드', name: '쟁승메이드',
url: 'https://jaengseung-made.com', url: 'https://jaengseung-made.com',
description: 'AI 음악 작곡·뮤비 구조 설계 팩, 블로그 자동화 팩, AI 사주 분석. 7년차 현직 개발자가 직접 만들고 운영하는 AI 크리에이티브 스토어.', description: 'AI 음악 작곡·뮤비 구조 설계 팩, 블로그 자동화 팩, AI 사주 분석. 현직 엔지니어가 직접 설계·운영하는 AI 크리에이티브 스토어.',
email: 'bgg8988@gmail.com', email: 'bgg8988@gmail.com',
telephone: '010-3907-1392', telephone: '010-3907-1392',
priceRange: '₩', priceRange: '₩',
@@ -96,7 +101,7 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<html lang="ko"> <html lang="ko" className={`${spaceGrotesk.variable} ${inter.variable} ${manrope.variable}`}>
<head> <head>
<script <script
type="application/ld+json" type="application/ld+json"

View File

@@ -1,362 +1,252 @@
'use client'; 'use client';
import { useState, useEffect, useRef } from 'react'; import { useState } from 'react';
import Link from 'next/link'; import Link from 'next/link';
import ContactModal from './components/ContactModal'; import ContactModal from './components/ContactModal';
import { trackCTAClick } from '../lib/gtag'; import { trackCTAClick } from '../lib/gtag';
/* ═══════════════════════════════════════════════════ /* ═══════════════════════════════════════════════════
쟁승메이드 홈 — v4 (AI Music 중심 개편) 쟁승메이드 홈 — v5 (Kinetic Ether Dashboard)
1. Hero: AI 음악 팩 (메인 매출) 상단 라우터 페이지를 워크스페이스형 대시보드로 재구성.
2. Sub: 사주 · 블로그팩 · 일반 문의
3. About: 신뢰 지표
═══════════════════════════════════════════════════ */ ═══════════════════════════════════════════════════ */
const LIVE_SERVICES = [ interface Tile {
{ name: 'AI Music Pack', label: '메인 상품' }, href: string;
{ name: 'AI 사주 분석', label: '무료 도구' }, label: string;
{ name: '블로그 자동화 팩', label: '디지털 상품' }, title: string;
]; desc: string;
tag: string;
function useScrollReveal() { tagColor: string;
const ref = useRef<HTMLDivElement>(null); onClick?: () => void;
useEffect(() => {
const el = ref.current;
if (!el) return;
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('is-visible');
observer.unobserve(entry.target);
}
});
},
{ threshold: 0.1, rootMargin: '0px 0px -40px 0px' }
);
el.querySelectorAll('.reveal').forEach((child) => observer.observe(child));
return () => observer.disconnect();
}, []);
return ref;
} }
export default function Home() { export default function Home() {
const [modalOpen, setModalOpen] = useState(false); const [modalOpen, setModalOpen] = useState(false);
const containerRef = useScrollReveal();
const tiles: Tile[] = [
{
href: '/services/music',
label: 'FLAGSHIP',
title: 'AI 음악 마스터',
desc: '네 사연을 노래로. 쇼츠까지 한 번에. Suno·Runway·유튜브 SEO를 묶은 4단계 공정 팩.',
tag: '₩39k~149k',
tagColor: 'var(--kx-primary)',
},
{
href: '/services/blog',
label: 'DIGITAL PACK',
title: '블로그 자동화 팩',
desc: '프롬프트 조합법 + 템플릿 PDF + 샘플. 쿠팡파트너스·애드포스트 수익화 루틴.',
tag: '₩29,000',
tagColor: 'var(--kx-secondary)',
},
{
href: '/saju',
label: 'FREE TOOL',
title: 'AI 사주 분석',
desc: '사주팔자 자동 산출 + Gemini 기반 해석. 검증된 계산 엔진.',
tag: 'FREE',
tagColor: '#40ceed',
},
];
return ( return (
<div className="min-h-full" ref={containerRef}> <div className="kx-section min-h-full relative overflow-hidden">
<ContactModal <ContactModal
isOpen={modalOpen} isOpen={modalOpen}
onClose={() => setModalOpen(false)} onClose={() => setModalOpen(false)}
service="일반 문의" service="일반 문의"
checklist={[ checklist={['연락처/이메일', '원하는 작업 범위', '희망 일정']}
'문의하고 싶은 내용을 간략히 설명해주세요',
'원하는 회신 방식 (이메일/전화)',
'기타 참고 사항',
]}
accentColor="text-violet-400"
headerFrom="#1e1b4b"
headerTo="#020617"
/> />
{/* ══════════════════════════════════════ {/* 배경 오브 */}
HERO — AI Music 중심 <div className="kx-orb" style={{ width: 520, height: 520, background: '#9c48ea', top: -180, left: -120 }} />
══════════════════════════════════════ */} <div className="kx-orb" style={{ width: 420, height: 420, background: '#53ddfc', bottom: -150, right: -100, opacity: 0.25 }} />
<section <div className="kx-orb" style={{ width: 300, height: 300, background: '#cc97ff', top: '40%', right: '10%', opacity: 0.18 }} />
className="relative overflow-hidden px-6 py-24 lg:px-14 lg:py-32"
style={{
background:
'radial-gradient(circle at 20% 30%, #1e1b4b 0%, #020617 55%), radial-gradient(circle at 80% 70%, #0c4a6e 0%, transparent 50%)',
}}
>
{/* Noise overlay */}
<div
className="absolute inset-0 opacity-[0.04] pointer-events-none mix-blend-overlay"
style={{
backgroundImage:
"url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9'/></filter><rect width='100%' height='100%' filter='url(%23n)' opacity='0.5'/></svg>\")",
}}
/>
{/* Waveform decoration */}
<div className="absolute bottom-0 left-0 right-0 h-32 opacity-30 pointer-events-none">
<svg viewBox="0 0 1200 120" preserveAspectRatio="none" className="w-full h-full">
<path
d="M0,60 Q150,10 300,60 T600,60 T900,60 T1200,60 L1200,120 L0,120 Z"
fill="url(#waveGrad)"
/>
<defs>
<linearGradient id="waveGrad" x1="0%" x2="100%">
<stop offset="0%" stopColor="#7c3aed" stopOpacity="0.4" />
<stop offset="50%" stopColor="#06b6d4" stopOpacity="0.3" />
<stop offset="100%" stopColor="#7c3aed" stopOpacity="0.4" />
</linearGradient>
</defs>
</svg>
</div>
<div className="relative max-w-5xl mx-auto"> {/* 워크스페이스 헤더 */}
<div className="flex items-center gap-3 mb-8"> <header className="relative z-10 px-6 lg:px-12 pt-10 pb-6 border-b border-white/5">
<span className="font-mono text-xs text-violet-300/70 tracking-[0.25em] uppercase"> <div className="flex items-center justify-between gap-4 flex-wrap">
× AI Music
</span>
<span className="flex items-center gap-1.5 text-xs text-emerald-400/80">
<span className="w-1.5 h-1.5 rounded-full bg-emerald-400 animate-pulse" />
NEW
</span>
</div>
<h1
className="text-[2.6rem] md:text-[3.5rem] lg:text-[5rem] font-extrabold leading-[1.05] tracking-tight mb-6"
style={{ wordBreak: 'keep-all' }}
>
<span className="text-white"> .</span>
<br />
<span className="bg-gradient-to-r from-violet-300 via-sky-200 to-cyan-300 bg-clip-text text-transparent">
.
</span>
</h1>
<p
className="text-slate-300 text-lg md:text-xl leading-relaxed mb-4 max-w-2xl"
style={{ wordBreak: 'keep-all' }}
>
7 <span className="text-white font-semibold">AI 4 </span>.
<br />
(Suno) (Runway) .
</p>
<p className="text-slate-400 text-base mb-10 max-w-2xl">
39,000. .
</p>
<div className="flex flex-wrap gap-3 mb-14">
<Link
href="/services/music"
className="inline-flex items-center gap-2 bg-violet-600 hover:bg-violet-500 text-white px-8 py-4 rounded-xl font-bold text-sm transition-colors shadow-[0_0_40px_rgba(139,92,246,0.4)]"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M17 8l4 4m0 0l-4 4m4-4H3" />
</svg>
</Link>
<Link
href="/saju"
className="inline-flex items-center gap-2 border border-white/15 hover:border-white/40 text-white/80 hover:text-white px-8 py-4 rounded-xl font-semibold text-sm transition-all"
>
</Link>
</div>
<div className="border-t border-white/8 pt-8">
<p className="font-mono text-[11px] text-violet-300/40 tracking-[0.25em] uppercase mb-4">
</p>
<div className="flex flex-wrap gap-6">
{LIVE_SERVICES.map((s) => (
<span key={s.name} className="flex items-center gap-2.5 text-sm text-slate-300">
<span className="w-1.5 h-1.5 rounded-full bg-emerald-400 animate-pulse flex-shrink-0" />
<span className="font-semibold">{s.name}</span>
<span className="font-mono text-[11px] text-white/30">{s.label}</span>
</span>
))}
</div>
</div>
</div>
</section>
{/* ══════════════════════════════════════
SECTION 2 — 서브 상품 카드
══════════════════════════════════════ */}
<section className="bg-white px-6 py-20 lg:px-14">
<div className="max-w-5xl mx-auto">
<div className="reveal mb-10">
<p className="font-mono text-xs text-violet-700/70 tracking-widest uppercase mb-2">
More Products
</p>
<h2
className="text-2xl md:text-3xl font-extrabold text-slate-900 leading-tight"
style={{ wordBreak: 'keep-all' }}
>
.
</h2>
<p className="text-slate-500 text-sm mt-2"> .</p>
</div>
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-5">
{/* 사주 */}
<Link
href="/saju"
className="reveal reveal-d1 group relative flex flex-col border border-slate-200 hover:border-violet-400/50 rounded-2xl p-6 transition-all hover:shadow-lg bg-gradient-to-br from-white to-violet-50/40"
>
<div className="flex items-center justify-between mb-4">
<span className="text-[10px] font-bold px-2 py-0.5 rounded-full bg-sky-500/15 text-sky-600 border border-sky-500/20">
</span>
<svg className="w-5 h-5 text-violet-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" strokeWidth={1.5}>
<path strokeLinecap="round" strokeLinejoin="round" d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09z" />
</svg>
</div>
<h3 className="text-lg font-extrabold text-slate-900 mb-2 group-hover:text-violet-700 transition-colors">
AI
</h3>
<p className="text-slate-600 text-sm leading-relaxed flex-1 mb-5" style={{ wordBreak: 'keep-all' }}>
AI가 ··· .
</p>
<span className="text-violet-700 text-sm font-bold group-hover:underline">
</span>
</Link>
{/* 블로그팩 */}
<Link
href="/services/blog"
className="reveal reveal-d2 group relative flex flex-col border border-slate-200 hover:border-blue-400/50 rounded-2xl p-6 transition-all hover:shadow-lg bg-white"
>
<div className="flex items-center justify-between mb-4">
<span className="text-[10px] font-bold px-2 py-0.5 rounded-full bg-blue-500/15 text-blue-600 border border-blue-500/20">
29,000
</span>
<svg className="w-5 h-5 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" strokeWidth={1.5}>
<path strokeLinecap="round" strokeLinejoin="round" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z" />
</svg>
</div>
<h3 className="text-lg font-extrabold text-slate-900 mb-2 group-hover:text-blue-700 transition-colors">
</h3>
<p className="text-slate-600 text-sm leading-relaxed flex-1 mb-5" style={{ wordBreak: 'keep-all' }}>
· ·릿· .
</p>
<span className="text-blue-700 text-sm font-bold group-hover:underline">
</span>
</Link>
{/* 일반 문의 */}
<button
onClick={() => {
trackCTAClick('일반 문의', '/');
setModalOpen(true);
}}
className="reveal reveal-d3 group relative flex flex-col text-left border border-slate-200 hover:border-slate-400 rounded-2xl p-6 transition-all hover:shadow-lg bg-white"
>
<div className="flex items-center justify-between mb-4">
<span className="text-[10px] font-bold px-2 py-0.5 rounded-full bg-slate-500/15 text-slate-600 border border-slate-500/20">
·
</span>
<svg className="w-5 h-5 text-slate-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" strokeWidth={1.5}>
<path strokeLinecap="round" strokeLinejoin="round" d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z" />
</svg>
</div>
<h3 className="text-lg font-extrabold text-slate-900 mb-2 group-hover:text-slate-700 transition-colors">
</h3>
<p className="text-slate-600 text-sm leading-relaxed flex-1 mb-5" style={{ wordBreak: 'keep-all' }}>
·· . 24 .
</p>
<span className="text-slate-700 text-sm font-bold group-hover:underline">
</span>
</button>
</div>
</div>
</section>
{/* ══════════════════════════════════════
SECTION 3 — About
══════════════════════════════════════ */}
<section className="bg-slate-950 px-6 py-20 lg:px-14">
<div className="max-w-5xl mx-auto">
<p className="reveal font-mono text-xs text-violet-300/50 tracking-widest uppercase mb-3">
About
</p>
<div className="reveal grid lg:grid-cols-2 gap-10 lg:gap-16 items-start">
<div> <div>
<h2 <span className="kx-label">WORKSPACE / JAENGSEUNG.MAKE</span>
className="text-2xl md:text-3xl font-extrabold text-white leading-tight mb-6" <h1 className="kx-display text-2xl md:text-3xl font-extrabold mt-1.5">
style={{ wordBreak: 'keep-all' }} Creative Studio <span className="kx-gradient-text">Overview</span>
> </h1>
7 .
<br />
<span className="text-violet-300"> AI로 .</span>
</h2>
<div className="space-y-4 text-slate-400 text-base leading-relaxed" style={{ wordBreak: 'keep-all' }}>
<p>
IT팀에서 7 API , DB, .
</p>
<p>
<span className="text-white">AI · · AI</span> ·.
</p>
</div> </div>
</div> <div className="flex items-center gap-3 text-xs" style={{ color: 'var(--kx-on-variant)' }}>
<span className="flex items-center gap-2">
<div className="space-y-4"> <span className="inline-block w-2 h-2 rounded-full bg-emerald-400 animate-pulse" />
{[ <span className="font-mono tracking-wider">SYSTEM ONLINE</span>
{ value: '7년', label: '대기업 백엔드 경력', sub: '실제 운영 서비스 다수', color: 'border-blue-500/30' },
{ value: '3개', label: '운영 중인 AI 서비스', sub: '사주 AI · 블로그팩 · 음악팩', color: 'border-emerald-500/30' },
{ value: '평생', label: '무료 업데이트', sub: '구매 후 Notion 공지로 전달', color: 'border-violet-500/30' },
{ value: '24h', label: '이내 답변', sub: '주말·공휴일 포함', color: 'border-amber-500/30' },
].map((item) => (
<div key={item.value} className={`border-l-2 ${item.color} pl-5 py-2`}>
<div className="flex items-baseline gap-3">
<span className="text-3xl font-extrabold text-white tracking-tight">{item.value}</span>
<span className="text-slate-400 text-sm font-medium">{item.label}</span>
</div>
<p className="text-white/30 text-xs mt-1">{item.sub}</p>
</div>
))}
</div>
</div>
</div>
</section>
{/* ══════════════════════════════════════
SECTION 4 — 최종 CTA
══════════════════════════════════════ */}
<section className="bg-gradient-to-b from-slate-950 to-[#0b0530] px-6 py-20 lg:px-14">
<div className="max-w-5xl mx-auto">
<div className="reveal text-center">
<p className="font-mono text-xs text-violet-300/50 tracking-widest uppercase mb-4">
Get Started
</p>
<h2
className="text-3xl md:text-5xl font-extrabold text-white mb-4 leading-tight"
style={{ wordBreak: 'keep-all' }}
>
,
<br />
<span className="bg-gradient-to-r from-violet-300 via-sky-200 to-cyan-300 bg-clip-text text-transparent">
.
</span> </span>
<span className="hidden md:inline font-mono">v2026.04</span>
</div>
</div>
</header>
<div className="relative z-10 px-6 lg:px-12 py-10 space-y-10">
{/* Hero: Launch Panel */}
<section className="kx-folder kx-glow" style={{ padding: 0, overflow: 'hidden' }}>
<div className="grid lg:grid-cols-[1.4fr_1fr] gap-0">
{/* 좌측: 카피 */}
<div className="p-8 lg:p-12">
<span className="kx-label">FLAGSHIP RELEASE · 2026</span>
<h2 className="kx-display text-4xl md:text-5xl lg:text-6xl font-extrabold mt-4 leading-[1.05]">
.
<br />
<span className="kx-gradient-text"> .</span>
</h2> </h2>
<p className="text-slate-400 text-lg mb-10"> <p className="mt-6 text-base md:text-lg max-w-xl leading-relaxed">
39,000 · AI로 ,{' '}
<span style={{ color: 'var(--kx-on-surface)' }}> </span> .
, 4 .
</p> </p>
<div className="flex flex-wrap gap-4 justify-center"> <div className="flex flex-wrap gap-3 mt-8">
<Link <Link
href="/services/music" href="/services/music"
className="inline-flex items-center gap-2 bg-violet-600 hover:bg-violet-500 text-white px-10 py-4 rounded-xl font-extrabold text-base transition-colors shadow-[0_0_40px_rgba(139,92,246,0.4)]" onClick={() => trackCTAClick('home_hero_music')}
className="kx-btn-primary inline-flex items-center gap-2 px-6 py-3.5 rounded-xl text-sm"
> >
AI AI <span></span>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M17 8l4 4m0 0l-4 4m4-4H3" />
</svg>
</Link> </Link>
<button <a
onClick={() => { href="#tiles"
trackCTAClick('일반 문의', '/'); className="kx-btn-ghost inline-flex items-center gap-2 px-6 py-3.5 rounded-xl text-sm font-bold"
setModalOpen(true);
}}
className="inline-flex items-center gap-2 border border-white/15 hover:border-white/40 text-white/80 hover:text-white px-10 py-4 rounded-xl font-extrabold text-base transition-all"
> >
·
</button> </a>
</div>
</div>
{/* 우측: 엔진 상태 모니터 */}
<div
className="hidden lg:block relative"
style={{ background: 'var(--kx-surface-low)', borderLeft: '1px solid rgba(204,151,255,0.08)' }}
>
<div className="p-8 h-full flex flex-col">
<div className="flex items-center justify-between mb-6">
<span className="kx-label">ENGINE STATUS</span>
<span className="text-xs font-mono" style={{ color: 'var(--kx-secondary-dim)' }}>REAL-TIME</span>
</div>
<div className="space-y-5 flex-1">
<EngineRow label="SUNO PRO" value="2,490 credits" pct={83} />
<EngineRow label="GEMINI 2.5" value="Online" pct={100} />
<EngineRow label="RUNWAY" value="Standby" pct={62} />
<EngineRow label="PUBLISHING" value="Ready" pct={94} />
</div>
<div className="mt-8 pt-6 border-t" style={{ borderColor: 'rgba(255,255,255,0.05)' }}>
<div className="flex items-baseline justify-between">
<span className="kx-label">DELIVERED</span>
<span className="kx-display text-3xl font-extrabold">47<span style={{ color: 'var(--kx-on-variant)', fontSize: '1rem', fontWeight: 400 }}> projects</span></span>
</div>
</div>
</div> </div>
<p className="text-white/20 text-xs mt-8 font-mono">
· 267-53-00822 · bgg8988@gmail.com · 010-3907-1392
</p>
</div> </div>
</div> </div>
</section> </section>
{/* 서비스 타일 */}
<section id="tiles">
<div className="flex items-end justify-between mb-5">
<div>
<span className="kx-label">PRODUCTS</span>
<h3 className="kx-display text-2xl md:text-3xl font-extrabold mt-1">Launch Pads</h3>
</div>
<span className="text-xs font-mono hidden md:inline" style={{ color: 'var(--kx-on-variant)' }}>
{tiles.length} modules active
</span>
</div>
<div className="grid md:grid-cols-3 gap-4">
{tiles.map((t) => (
<Link
key={t.href}
href={t.href}
onClick={() => trackCTAClick(`home_tile_${t.href}`)}
className="kx-folder group relative transition-all hover:-translate-y-1"
style={{ textDecoration: 'none' }}
>
<div className="flex items-center justify-between mb-5">
<span className="kx-label" style={{ color: t.tagColor }}>{t.label}</span>
<span
className="text-[10px] font-mono font-bold px-2 py-0.5 rounded"
style={{ background: 'rgba(255,255,255,0.05)', color: t.tagColor }}
>
{t.tag}
</span>
</div>
<h4 className="kx-display text-xl font-extrabold mb-2">{t.title}</h4>
<p className="text-sm leading-relaxed">{t.desc}</p>
<div className="mt-6 flex items-center gap-2 text-sm font-bold" style={{ color: t.tagColor }}>
<span className="transition-transform group-hover:translate-x-1"></span>
</div>
</Link>
))}
</div>
</section>
{/* Stats Monitor */}
<section className="kx-folder">
<div className="flex items-center justify-between mb-6">
<div>
<span className="kx-label">CREDIBILITY MONITOR</span>
<h3 className="kx-display text-xl font-extrabold mt-1"> </h3>
</div>
</div>
<div className="grid grid-cols-2 md:grid-cols-4 gap-6">
<Stat num="47" label="프로젝트 납품" sub="계약 기반" />
<Stat num="100%" label="소스코드 인도" sub="저작권 100% 이양" />
<Stat num="24h" label="평균 응답" sub="이메일/카톡 기준" />
<Stat num="0" label="분쟁 이력" sub="계약서 우선 원칙" />
</div>
</section>
{/* Final CTA */}
<section className="kx-glass px-8 py-10 text-center" style={{ border: '1px solid rgba(204,151,255,0.12)' }}>
<span className="kx-label">NEXT STEP</span>
<h3 className="kx-display text-2xl md:text-3xl font-extrabold mt-2"> ?</h3>
<p className="mt-3 text-sm md:text-base max-w-xl mx-auto">
·· . 24 .
</p>
<button
onClick={() => {
trackCTAClick('home_final_contact');
setModalOpen(true);
}}
className="kx-btn-primary mt-6 px-7 py-3.5 rounded-xl text-sm"
>
</button>
</section>
</div>
</div>
);
}
function EngineRow({ label, value, pct }: { label: string; value: string; pct: number }) {
return (
<div>
<div className="flex items-center justify-between mb-1.5">
<span className="kx-label" style={{ fontSize: '0.625rem' }}>{label}</span>
<span className="text-xs font-mono" style={{ color: 'var(--kx-on-surface)' }}>{value}</span>
</div>
<div className="h-1.5 rounded-full overflow-hidden" style={{ background: 'rgba(255,255,255,0.06)' }}>
<div
className="h-full rounded-full"
style={{
width: `${pct}%`,
background: 'linear-gradient(90deg, #cc97ff, #53ddfc)',
}}
/>
</div>
</div>
);
}
function Stat({ num, label, sub }: { num: string; label: string; sub: string }) {
return (
<div>
<div className="kx-display text-3xl md:text-4xl font-extrabold kx-gradient-text">{num}</div>
<div className="mt-2 text-sm font-bold" style={{ color: 'var(--kx-on-surface)' }}>{label}</div>
<div className="text-xs mt-0.5">{sub}</div>
</div> </div>
); );
} }

View File

@@ -5,7 +5,7 @@ import { verifyPortfolioTokenNode } from '@/lib/admin-auth';
export const metadata: Metadata = { export const metadata: Metadata = {
title: '박재오 — 외주 개발 포트폴리오', title: '박재오 — 외주 개발 포트폴리오',
description: '7년차 대기업 백엔드 개발자 박재오의 외주 포트폴리오.', description: '현직 실무 엔지니어 박재오의 외주 포트폴리오.',
robots: { index: false, follow: false }, robots: { index: false, follow: false },
}; };
@@ -48,7 +48,7 @@ export default async function PortfolioGateway({ params }: Props) {
</h1> </h1>
<p className="text-slate-300 text-lg leading-relaxed max-w-2xl mb-10" style={{ wordBreak: 'keep-all' }}> <p className="text-slate-300 text-lg leading-relaxed max-w-2xl mb-10" style={{ wordBreak: 'keep-all' }}>
7 · · · 100% . · · · 100% .
{expires} . {expires} .
</p> </p>

View File

@@ -3,7 +3,7 @@ import type { Metadata } from 'next';
export const metadata: Metadata = { export const metadata: Metadata = {
title: 'AI 음악 마스터 구조 팩 | Suno · MV · 유튜브 쇼츠', title: 'AI 음악 마스터 구조 팩 | Suno · MV · 유튜브 쇼츠',
description: description:
'7년차 개발자가 설계한 4단계 AI 음악 제작 공정. Suno 프롬프트 조합법 + MV 비디오 생성 워크플로우 + 저작권 가이드 + 템플릿 PDF + 샘플 프로젝트. 입문 ₩39k / 프로 ₩99k / 마스터 ₩149k.', '엔지니어가 설계한 4단계 AI 음악 제작 공정. Suno 프롬프트 조합법 + MV 비디오 생성 워크플로우 + 저작권 가이드 + 템플릿 PDF + 샘플 프로젝트. 입문 ₩39k / 프로 ₩99k / 마스터 ₩149k.',
keywords: [ keywords: [
'AI 음악 만들기', 'AI 음악 만들기',
'Suno 프롬프트', 'Suno 프롬프트',

View File

@@ -137,18 +137,16 @@ export default function MusicServicePage() {
<div className="relative max-w-5xl mx-auto"> <div className="relative max-w-5xl mx-auto">
<div className="flex items-center gap-3 mb-8"> <div className="flex items-center gap-3 mb-8">
<span className="inline-flex h-2 w-2 rounded-full bg-violet-400 animate-pulse" /> <span className="inline-flex h-2 w-2 rounded-full bg-violet-400 animate-pulse" />
<span className="font-mono text-xs text-violet-300/80 tracking-[0.25em] uppercase"> <span className="kx-label">AI MUSIC PACK · v1</span>
AI Music Pack · v1
</span>
</div> </div>
<h1 <h1
className="text-[2.8rem] md:text-[4rem] lg:text-[5.5rem] font-extrabold leading-[1.02] tracking-tight mb-6" className="kx-display text-[2.8rem] md:text-[4rem] lg:text-[5.5rem] font-extrabold leading-[1.02] mb-6"
style={{ wordBreak: 'keep-all' }} style={{ wordBreak: 'keep-all' }}
> >
<span className="text-white"> .</span> <span className="text-white"> .</span>
<br /> <br />
<span className="bg-gradient-to-r from-violet-300 via-pink-200 to-cyan-300 bg-clip-text text-transparent"> <span className="kx-gradient-text">
. .
</span> </span>
</h1> </h1>
@@ -160,7 +158,7 @@ export default function MusicServicePage() {
AI로 , <span className="text-white font-semibold"> </span> . AI로 , <span className="text-white font-semibold"> </span> .
</p> </p>
<p className="text-slate-400 text-base mb-10 max-w-2xl"> <p className="text-slate-400 text-base mb-10 max-w-2xl">
7 <span className="text-white">4 AI </span> · Suno Pro . <span className="text-white">4 AI </span> · Suno Pro .
</p> </p>
<div className="flex flex-wrap gap-3 mb-10"> <div className="flex flex-wrap gap-3 mb-10">