Skip to content

Commit 3549599

Browse files
devRavitclaude
andcommitted
feat: resume 명령어 및 브랜딩 업데이트
- resume 명령어 추가 (vim 스타일 이력서 뷰어) - VimViewer 컴포넌트 구현 (j/k, ↑/↓, PgUp/Dn, Home/End 키보드 네비게이션) - 한글 입력 상태에서도 단축키 동작하도록 e.code 사용 - 회사명 브랜드 컬러 그라데이션 적용 (NOL Universe, 미네르바소프트) - 파비콘 추가 ({/} 코드 아이콘) - 메타데이터 업데이트 (title: ravit.run) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent a356a72 commit 3549599

4 files changed

Lines changed: 267 additions & 4 deletions

File tree

app/icon.svg

Lines changed: 3 additions & 0 deletions
Loading

app/layout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import type { Metadata } from 'next'
22
import './globals.css'
33

44
export const metadata: Metadata = {
5-
title: 'Pixel',
6-
description: 'Pixel - Frontend for Stash',
5+
title: 'ravit.run',
6+
description: 'RAVIT - Backend Developer',
77
}
88

99
export default function RootLayout({

app/page.tsx

Lines changed: 248 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ function StatusIndicator({ onClick }: { onClick?: () => void }) {
3636

3737
const BRAND_COLORS: Record<string, string | [string, string]> = {
3838
'Nol Universe': ['#3549FF', '#5085FF'],
39+
'미네르바소프트': ['#3B82F6', '#EF4444'],
3940
'Kotlin': '#7F52FF',
4041
'C#': '#68217A',
4142
'TypeScript': '#3178C6',
@@ -101,6 +102,239 @@ interface HistoryEntry {
101102
isTyping?: boolean
102103
}
103104

105+
// Vim-style Resume Viewer
106+
function VimViewer({ onClose }: { onClose: () => void }) {
107+
const contentRef = useRef<HTMLDivElement>(null)
108+
const containerRef = useRef<HTMLDivElement>(null)
109+
110+
// Focus container on mount
111+
useEffect(() => {
112+
containerRef.current?.focus()
113+
}, [])
114+
115+
const handleKeyDown = (e: React.KeyboardEvent) => {
116+
// e.code는 물리적 키 위치 (한영 상관없이 동작)
117+
if (e.code === 'KeyQ' || e.key === 'Escape') {
118+
e.preventDefault()
119+
onClose()
120+
} else if ((e.code === 'KeyJ' || e.key === 'ArrowDown') && contentRef.current) {
121+
e.preventDefault()
122+
contentRef.current.scrollBy({ top: 80, behavior: 'smooth' })
123+
} else if ((e.code === 'KeyK' || e.key === 'ArrowUp') && contentRef.current) {
124+
e.preventDefault()
125+
contentRef.current.scrollBy({ top: -80, behavior: 'smooth' })
126+
} else if (e.code === 'KeyD' && e.ctrlKey && contentRef.current) {
127+
e.preventDefault()
128+
contentRef.current.scrollBy({ top: 300, behavior: 'smooth' })
129+
} else if (e.code === 'KeyU' && e.ctrlKey && contentRef.current) {
130+
e.preventDefault()
131+
contentRef.current.scrollBy({ top: -300, behavior: 'smooth' })
132+
} else if (e.code === 'KeyG' && !e.shiftKey && contentRef.current) {
133+
e.preventDefault()
134+
contentRef.current.scrollTo({ top: 0, behavior: 'smooth' })
135+
} else if (e.code === 'KeyG' && e.shiftKey && contentRef.current) {
136+
e.preventDefault()
137+
contentRef.current.scrollTo({ top: contentRef.current.scrollHeight, behavior: 'smooth' })
138+
} else if (e.key === 'PageDown' && contentRef.current) {
139+
e.preventDefault()
140+
contentRef.current.scrollBy({ top: 300, behavior: 'smooth' })
141+
} else if (e.key === 'PageUp' && contentRef.current) {
142+
e.preventDefault()
143+
contentRef.current.scrollBy({ top: -300, behavior: 'smooth' })
144+
} else if (e.key === 'Home' && contentRef.current) {
145+
e.preventDefault()
146+
contentRef.current.scrollTo({ top: 0, behavior: 'smooth' })
147+
} else if (e.key === 'End' && contentRef.current) {
148+
e.preventDefault()
149+
contentRef.current.scrollTo({ top: contentRef.current.scrollHeight, behavior: 'smooth' })
150+
}
151+
}
152+
153+
return (
154+
<div
155+
ref={containerRef}
156+
tabIndex={0}
157+
onKeyDown={handleKeyDown}
158+
className="absolute inset-0 z-10 flex flex-col bg-[#0d1117] font-mono text-sm outline-none"
159+
>
160+
{/* Vim Header */}
161+
<div className="flex items-center justify-between border-b border-[#30363d] bg-[#161b22] px-4 py-2">
162+
<span className="text-[#8b949e]">resume.md</span>
163+
<span className="text-[#8b949e]">[readonly]</span>
164+
</div>
165+
166+
{/* Content */}
167+
<div ref={contentRef} className="flex-1 overflow-y-auto scrollbar-terminal p-4 sm:p-6">
168+
{/* Header */}
169+
<div className="mb-6">
170+
<h1 className="text-2xl font-bold text-[#58a6ff]"># RAVIT</h1>
171+
<p className="mt-1 text-[#8b949e]">Backend Developer · 5+ years experience</p>
172+
</div>
173+
174+
{/* Experience */}
175+
<div className="mb-6">
176+
<h2 className="mb-3 text-lg font-semibold text-[#7ee787]">## Experience</h2>
177+
178+
{/* Nol Universe */}
179+
<div className="mb-4 border-l-2 border-[#238636] pl-4">
180+
<div className="flex flex-wrap items-center gap-2">
181+
<span
182+
className="font-semibold"
183+
style={{
184+
background: 'linear-gradient(135deg, #3549FF, #5085FF)',
185+
WebkitBackgroundClip: 'text',
186+
WebkitTextFillColor: 'transparent',
187+
}}
188+
>
189+
NOL Universe
190+
</span>
191+
<span className="text-[#8b949e]">(구 인터파크)</span>
192+
<span className="rounded bg-[#238636] px-2 py-0.5 text-xs text-white">current</span>
193+
</div>
194+
<div className="mt-1 text-[#8b949e]">Backend Developer · 2022.04 ~ present</div>
195+
<ul className="mt-2 space-y-1 text-[#c9d1d9]">
196+
<li><span className="text-[#8b949e]">-</span> 패키지 투어 서비스 백엔드 개발</li>
197+
<li><span className="text-[#8b949e]">-</span> Spring Boot, Kotlin, MSSQL 기반 시스템 구축</li>
198+
<li><span className="text-[#8b949e]">-</span> 예약/결제 시스템 설계 및 운영</li>
199+
<li><span className="text-[#8b949e]">-</span> 레거시 .NET 시스템 유지보수</li>
200+
</ul>
201+
</div>
202+
203+
{/* Minerva Soft */}
204+
<div className="mb-4 border-l-2 border-[#30363d] pl-4">
205+
<div className="flex flex-wrap items-center gap-2">
206+
<span
207+
className="font-semibold"
208+
style={{
209+
background: 'linear-gradient(135deg, #3B82F6, #EF4444)',
210+
WebkitBackgroundClip: 'text',
211+
WebkitTextFillColor: 'transparent',
212+
}}
213+
>
214+
미네르바소프트
215+
</span>
216+
</div>
217+
<div className="mt-1 text-[#8b949e]">사원 · 2020.09 ~ 2022.03</div>
218+
<ul className="mt-2 space-y-1 text-[#c9d1d9]">
219+
<li><span className="text-[#8b949e]">-</span> 플랫폼 개발 및 응용 프로그램 개발</li>
220+
<li><span className="text-[#8b949e]">-</span> 동의서 인식기 API Backend (Manager-Agent 병렬처리)</li>
221+
<li><span className="text-[#8b949e]">-</span> 통합 모듈 플랫폼 관리 서비스 (Blazor, Socket)</li>
222+
<li><span className="text-[#8b949e]">-</span> SQL 구문 분석기 개발 (Oracle, MSSQL, MySQL, PostgreSQL)</li>
223+
</ul>
224+
</div>
225+
226+
{/* KITA */}
227+
<div className="mb-4 border-l-2 border-[#30363d] pl-4">
228+
<div className="flex flex-wrap items-center gap-2">
229+
<span className="font-semibold text-[#c9d1d9]">한국무역협회 KITA 아카데미</span>
230+
</div>
231+
<div className="mt-1 text-[#8b949e]">프리랜서 · 2020.05 ~ 2020.08</div>
232+
<ul className="mt-2 space-y-1 text-[#c9d1d9]">
233+
<li><span className="text-[#8b949e]">-</span> LMS 관리 Web 프로그램 개발</li>
234+
</ul>
235+
</div>
236+
</div>
237+
238+
{/* Skills */}
239+
<div className="mb-6">
240+
<h2 className="mb-3 text-lg font-semibold text-[#7ee787]">## Skills</h2>
241+
242+
<div className="space-y-3">
243+
<div>
244+
<span className="text-[#ffa657]">Languages:</span>
245+
<div className="mt-1 flex flex-wrap gap-2">
246+
<span className="rounded bg-[#7F52FF]/20 px-2 py-1 text-xs text-[#7F52FF]">Kotlin</span>
247+
<span className="rounded bg-[#68217A]/20 px-2 py-1 text-xs text-[#68217A]">C#</span>
248+
<span className="rounded bg-[#3178C6]/20 px-2 py-1 text-xs text-[#3178C6]">TypeScript</span>
249+
<span className="rounded bg-[#b07219]/20 px-2 py-1 text-xs text-[#b07219]">Java</span>
250+
</div>
251+
</div>
252+
253+
<div>
254+
<span className="text-[#ffa657]">Frameworks:</span>
255+
<div className="mt-1 flex flex-wrap gap-2">
256+
<span className="rounded bg-[#6DB33F]/20 px-2 py-1 text-xs text-[#6DB33F]">Spring Boot</span>
257+
<span className="rounded bg-[#512BD4]/20 px-2 py-1 text-xs text-[#512BD4]">.NET / Blazor</span>
258+
<span className="rounded bg-[#ffffff]/20 px-2 py-1 text-xs text-[#ffffff]">Next.js</span>
259+
</div>
260+
</div>
261+
262+
<div>
263+
<span className="text-[#ffa657]">Database:</span>
264+
<div className="mt-1 flex flex-wrap gap-2">
265+
<span className="rounded bg-[#CC2927]/20 px-2 py-1 text-xs text-[#CC2927]">MSSQL</span>
266+
<span className="rounded bg-[#47A248]/20 px-2 py-1 text-xs text-[#47A248]">MongoDB</span>
267+
<span className="rounded bg-[#4479A1]/20 px-2 py-1 text-xs text-[#4479A1]">MySQL</span>
268+
<span className="rounded bg-[#F80000]/20 px-2 py-1 text-xs text-[#F80000]">Oracle</span>
269+
</div>
270+
</div>
271+
272+
<div>
273+
<span className="text-[#ffa657]">DevOps:</span>
274+
<div className="mt-1 flex flex-wrap gap-2">
275+
<span className="rounded bg-[#2496ED]/20 px-2 py-1 text-xs text-[#2496ED]">Docker</span>
276+
<span className="rounded bg-[#2088FF]/20 px-2 py-1 text-xs text-[#2088FF]">GitHub Actions</span>
277+
<span className="rounded bg-[#ffffff]/20 px-2 py-1 text-xs text-[#ffffff]">Vercel</span>
278+
</div>
279+
</div>
280+
</div>
281+
</div>
282+
283+
{/* Education */}
284+
<div className="mb-6">
285+
<h2 className="mb-3 text-lg font-semibold text-[#7ee787]">## Education</h2>
286+
<div className="space-y-2">
287+
<div className="border-l-2 border-[#30363d] pl-4">
288+
<div className="font-semibold text-[#c9d1d9]">가천대학교</div>
289+
<div className="text-[#8b949e]">컴퓨터공학과 졸업 · 2010.03 ~ 2020.02</div>
290+
</div>
291+
<div className="border-l-2 border-[#30363d] pl-4">
292+
<div className="font-semibold text-[#c9d1d9]">SC IT MASTER</div>
293+
<div className="text-[#8b949e]">일본 IT 전문인재 양성 부트캠프 · 2019.03 ~ 2019.12</div>
294+
</div>
295+
</div>
296+
</div>
297+
298+
{/* Certifications */}
299+
<div className="mb-6">
300+
<h2 className="mb-3 text-lg font-semibold text-[#7ee787]">## Certifications</h2>
301+
<div className="space-y-1 text-[#c9d1d9]">
302+
<div><span className="text-[#8b949e]">-</span> JLPT N1</div>
303+
</div>
304+
</div>
305+
306+
{/* Links */}
307+
<div className="mb-6">
308+
<h2 className="mb-3 text-lg font-semibold text-[#7ee787]">## Links</h2>
309+
<div className="space-y-1 text-[#58a6ff]">
310+
<div><span className="text-[#8b949e]"></span> github.com/devRavit</div>
311+
<div><span className="text-[#8b949e]"></span> ravit.run</div>
312+
</div>
313+
</div>
314+
</div>
315+
316+
{/* Vim Footer */}
317+
<div className="border-t border-[#30363d] bg-[#161b22] px-4 py-2">
318+
<div className="flex flex-wrap items-center justify-between gap-2 text-xs text-[#8b949e]">
319+
<span className="hidden sm:inline">
320+
<span className="text-[#ffa657]">↑↓</span> scroll
321+
<span className="mx-2">·</span>
322+
<span className="text-[#ffa657]">PgUp/Dn</span> page
323+
<span className="mx-2">·</span>
324+
<span className="text-[#ffa657]">Home/End</span> top/bottom
325+
<span className="mx-2">·</span>
326+
<span className="text-[#ffa657]">q</span> quit
327+
</span>
328+
<button onClick={onClose} className="text-[#ffa657] hover:text-[#c9d1d9] sm:hidden">
329+
[tap to close]
330+
</button>
331+
<span>:q</span>
332+
</div>
333+
</div>
334+
</div>
335+
)
336+
}
337+
104338
const AboutJson = () => (
105339
<pre className="mt-1 text-xs leading-relaxed sm:text-sm">
106340
<code>
@@ -119,7 +353,7 @@ const AboutJson = () => (
119353
</pre>
120354
)
121355

122-
type CommandResult = React.ReactNode | 'OPEN_GITHUB' | 'OPEN_WORK' | 'CLEAR' | 'FETCH_STATUS'
356+
type CommandResult = React.ReactNode | 'OPEN_GITHUB' | 'OPEN_WORK' | 'CLEAR' | 'FETCH_STATUS' | 'OPEN_RESUME'
123357

124358
const COMMANDS: Record<string, { description: string; action: () => CommandResult }> = {
125359
'help': {
@@ -130,6 +364,7 @@ const COMMANDS: Record<string, { description: string; action: () => CommandResul
130364
<div className="ml-2 mt-1">
131365
<div><span className="text-[#79c0ff]">help</span> Show this help message</div>
132366
<div><span className="text-[#79c0ff]">whoami</span> Display current user</div>
367+
<div><span className="text-[#79c0ff]">resume</span> View resume (vim mode)</div>
133368
<div><span className="text-[#79c0ff]">status</span> Check system status</div>
134369
<div><span className="text-[#79c0ff]">open --github</span> Open GitHub profile</div>
135370
<div><span className="text-[#79c0ff]">open --work</span> Open work project</div>
@@ -142,6 +377,10 @@ const COMMANDS: Record<string, { description: string; action: () => CommandResul
142377
description: 'Display current user',
143378
action: () => <div className="text-[#8b949e]">ravit</div>,
144379
},
380+
'resume': {
381+
description: 'View resume',
382+
action: () => 'OPEN_RESUME',
383+
},
145384
'status': {
146385
description: 'Check system status',
147386
action: () => 'FETCH_STATUS',
@@ -169,6 +408,7 @@ export default function Home() {
169408
const [commandHistory, setCommandHistory] = useState<string[]>([])
170409
const [historyIndex, setHistoryIndex] = useState(-1)
171410
const [isLoading, setIsLoading] = useState(false)
411+
const [showVim, setShowVim] = useState(false)
172412
const terminalRef = useRef<HTMLDivElement>(null)
173413
const inputRef = useRef<HTMLInputElement>(null)
174414

@@ -284,6 +524,9 @@ export default function Home() {
284524
setIsLoading(false)
285525
} else if (result === 'CLEAR') {
286526
setHistory([])
527+
} else if (result === 'OPEN_RESUME') {
528+
setHistory(prev => [...prev, { command: cmd, output: <div className="text-[#8b949e]">Opening resume.md...</div> }])
529+
setShowVim(true)
287530
} else {
288531
setHistory(prev => [...prev, { command: cmd, output: result }])
289532
}
@@ -416,7 +659,10 @@ export default function Home() {
416659
{/* Terminal Section */}
417660
<section className="flex h-screen flex-col pt-[57px]">
418661
{/* Terminal Window - Full screen on mobile */}
419-
<div className="flex min-h-0 flex-1 flex-col bg-[#161b22] sm:m-6 sm:rounded-lg sm:border sm:border-[#30363d] sm:shadow-2xl">
662+
<div className="relative flex min-h-0 flex-1 flex-col bg-[#161b22] sm:m-6 sm:rounded-lg sm:border sm:border-[#30363d] sm:shadow-2xl">
663+
{/* Vim Viewer Overlay */}
664+
{showVim && <VimViewer onClose={() => { setShowVim(false); inputRef.current?.focus() }} />}
665+
420666
{/* Terminal Header */}
421667
<div className="flex items-center gap-2 border-b border-[#30363d] bg-[#21262d] px-3 py-2 sm:px-4 sm:py-3">
422668
<div className="h-2.5 w-2.5 rounded-full bg-[#ff5f56] sm:h-3 sm:w-3" />

docs/CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@
44

55
<!-- CHANGELOG_START -->
66

7+
## v0.0.8
8+
`2025.12.03 01:30`
9+
10+
resume 명령어 및 브랜딩 업데이트
11+
12+
- `resume` 명령어 추가 (vim 스타일 이력서 뷰어)
13+
- VimViewer 컴포넌트 구현 (j/k, ↑/↓, PgUp/Dn, Home/End 키보드 네비게이션)
14+
- 한글 입력 상태에서도 단축키 동작하도록 `e.code` 사용
15+
- 회사명 브랜드 컬러 그라데이션 적용 (NOL Universe, 미네르바소프트)
16+
- 파비콘 추가 (`{/}` 코드 아이콘)
17+
- 메타데이터 업데이트 (title: ravit.run, description 변경)
18+
19+
---
20+
721
## v0.0.7
822
`2025.11.30 16:30`
923

0 commit comments

Comments
 (0)