No description
  • TypeScript 83%
  • CSS 14.6%
  • JavaScript 2.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
tyange 2907a9b231
All checks were successful
Deploy Static Export / deploy (push) Successful in 4m9s
재배포: CMS intro 최신 본문으로 다시 빌드
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AJWzL4gjz131fLkSr3Y8gX
2026-10-11 08:58:41 +09:00
.forgejo/workflows Forgejo 워크플로 SSH 배포 secrets 이름 통일 2026-09-06 08:04:45 +09:00
.vscode 포스트 링크 연결 및 oxfmt 포매터 추가 2026-04-06 01:11:59 +09:00
public feat: Next.js에서 SolidStart 2로 마이그레이션 2026-09-05 12:02:54 +09:00
src 폰트: optional 되돌리고 메트릭 매칭 폴백으로 FOUT 무해화 2026-09-08 13:22:09 +09:00
.gitignore feat: Next.js에서 SolidStart 2로 마이그레이션 2026-09-05 12:02:54 +09:00
.oxfmtrc.json 포스트 링크 연결 및 oxfmt 포매터 추가 2026-04-06 01:11:59 +09:00
AGENTS.md dev 서버 전용 페이지 전환 버그 문서화 2026-09-06 08:48:31 +09:00
bun.lock Kobalte(헤드리스 UI) 정식 도입 — Switch/Select/Dialog 프리뷰 2026-09-06 08:48:50 +09:00
CLAUDE.md Initial commit from Create Next App 2026-03-30 19:59:00 +09:00
eslint.config.js feat: Next.js에서 SolidStart 2로 마이그레이션 2026-09-05 12:02:54 +09:00
package.json Kobalte(헤드리스 UI) 정식 도입 — Switch/Select/Dialog 프리뷰 2026-09-06 08:48:50 +09:00
README.md ci: self-hosted:host 러너 라벨에 맞춰 워크플로 조정 2026-09-05 14:59:57 +09:00
tsconfig.json feat: Next.js에서 SolidStart 2로 마이그레이션 2026-09-05 12:02:54 +09:00
vite.config.ts Kobalte(헤드리스 UI) 정식 도입 — Switch/Select/Dialog 프리뷰 2026-09-06 08:48:50 +09:00

tyange-dev

tyange-dev는 tyange-cms-api에서 포트폴리오 문서와 개발 글을 받아 보여주는 개인 개발자 사이트입니다.
단순 소개 페이지보다, 블로그·CMS·API·대시보드로 이어지는 tyange 운영 흐름의 공개 진입점을 목표로 합니다.

프로젝트 목적

  • 포트폴리오와 경력 정보를 하나의 정적 사이트로 제공
  • tyange-cms-api에 저장된 포트폴리오 문서와 dev 태그 글을 공개 화면에 반영
  • 개인 프로젝트 전반의 구조와 맥락을 한 화면에서 읽히도록 정리

현재 제공 기능

  • CMS API 포트폴리오 문서(intro, career, featured_projects)를 단일 페이지에 Bento Grid로 렌더링
  • dev 태그 글 목록 조회 및 상세 페이지 (/posts/[post_id])
  • Intro 섹션 마크다운 렌더링 (raw HTML + sanitize)
  • 작업 섹션 4그룹(inert / CMS 시스템 / 개인 사이트 / 기타) 카드 레이아웃
  • GitHub 저장소 링크 자동 인식 및 아이콘 처리
  • Promise.allSettled로 포트폴리오/글 API 조회를 독립 실패 처리 (한쪽이 죽어도 나머지는 렌더)
  • 정적 export 기반 배포 — 서버 없이도 홈↔글 상세 클라이언트 사이드 전환(전체 새로고침 없음) 지원

기술 스택

  • Runtime / Package Manager: Bun
  • Framework: SolidStart 2 (@solidjs/start, Vite 네이티브, nitro 프리셋 static으로 순수 정적 export)
  • UI: Solid 1.x, Tailwind CSS 4
  • Design System: @tyange-labs/design-system — 색상·타이포·간격 등 시맨틱 토큰(--tl-*)을 git 의존성으로 가져와 씀. 라이트/다크는 dark-auto.css로 OS 설정을 따름
  • Markdown: unified 파이프라인 (remark-parse + remark-gfm → rehype-raw + rehype-sanitize + rehype-shiki) — CMS에 저장된 마크다운 본문을 raw HTML 허용 + XSS 방지 상태로 렌더. 동적 import()로만 불러와 클라이언트 번들에 섞여 들어가지 않는다(자세한 이유는 AGENTS.md)
  • Icons: simple-icons (GitHub SVG 인라인)
  • Fonts: Pretendard subset (woff2) + Monaspace Neon, font-display: swap
  • Data Source: tyange-cms-api
  • Deployment: GitHub Actions + static export(SCP)

환경 변수 예시

.env.local

CMS_API_BASE_URL=https://tyange.com/api/cms

로컬 개발

bun install
bun dev

기본 개발 서버는 http://localhost:3000에서 실행됩니다.

정적 빌드

bun run build

정적 export 결과물은 .output/public/ 디렉터리에 생성됩니다.

배포

배포 워크플로는 .forgejo/workflows/deploy.yml에 있습니다(Forgejo Actions — .github/workflows가 아니다. GitHub Actions 마켓플레이스 액션도 DEFAULT_ACTIONS_URL 기본값이 data.forgejo.org라 uses:를 전부 https://github.com/... 완전한 URL로 써야 한다).

전제 조건:

  • git.tyange.com에 Forgejo Actions runner가 self-hosted:host 라벨로 구동 중이어야 함(Docker 없이 러너를 띄우는 서버에서 직접 실행 — 격리 없음). forgejo-runner daemon --url ... --uuid ... --token-url ... --label self-hosted:host
  • 저장소 Settings → Units → Overview에서 Actions 체크박스가 켜져 있어야 함 (러너가 있어도 이게 꺼져 있으면 워크플로를 안 읽는다)
  • 러너 실행 환경에 @tyange-labs/design-system(git+ssh 의존성)을 내려받을 수 있는 SSH 키가 있어야 함 — 아래 DESIGN_SYSTEM_DEPLOY_KEY secret 참고

필수 Forgejo Actions secrets (저장소 Settings → Actions → Secrets):

  • HOST
  • USER_NAME
  • PRIVATE_SSH_KEY
  • DESIGN_SYSTEM_DEPLOY_KEY — git.tyange.com의 design-system 저장소를 읽을 수 있는 SSH 개인키(읽기 전용 deploy key 권장)

필수 Forgejo Actions variables:

  • DEPLOY_PATH

선택 Forgejo Actions variable:

  • CMS_API_BASE_URL

주요 설계 결정

  • 정적 export(nitro static 프리셋): 포트폴리오 콘텐츠는 빌드 시점에만 확정되면 충분하므로 Node 서버를 두지 않고 순수 SSG로 처리한다. vite.config.ts가 빌드 시점에 dev 태그 글 id를 CMS에서 가져와 프리렌더 대상 라우트로 명시하고(crawlLinks도 안전망으로 병행), 각 라우트 컴포넌트는 query() + createAsync()로 그 데이터를 받는다.
  • tyange-cms-api를 브라우저가 직접 호출하지 않는다: 그 API는 Origin 헤더가 붙은 요청을 자기 도메인이어도 전부 403으로 막는다. 그래서 src/routes/api/home.json.ts, src/routes/api/posts/[id].ts 같은 파일 기반 API 라우트를 두고, 빌드 시 nitro가 이 경로들을 정적 JSON 파일로 구워낸다. 클라이언트 사이드 이동에서는 이 정적 파일만 fetch()한다(Next의 페이지별 정적 데이터 방식과 동일한 원리). 자세한 경위는 AGENTS.md 참고.
  • Promise.allSettled로 장애 격리: 포트폴리오 API와 dev 태그 글 조회를 독립적으로 수행해, 하나가 실패해도 나머지 섹션은 정상 렌더한다.
  • unified 마크다운 파이프라인: CMS 본문에 raw HTML(예: 커스텀 div, 임베드)을 허용하기 위해 rehype-raw를 통과시키되, 직후 rehype-sanitize로 XSS 차단한다. 코드 하이라이트는 shiki로 서버(프리렌더)에서만 미리 렌더한다 — 동적 import()로 감싸 클라이언트 번들에는 아예 포함되지 않는다.
  • Bento Grid 레이아웃: "작업" 섹션은 hero(featured_projects[0], CMS에서 순서로 제어) + 2×N 그리드(CMS 시스템, 개인 사이트, 기타)로 구성해 중요도에 따른 시각적 우선순위를 준다.
  • 폰트 최적화: Pretendard는 한국어 subset만 woff2로 번들하고 font-display: swap으로 첫 텍스트 페인트 지연을 막는다. next/font/local이 하던 등록을 src/app.css의 수동 @font-face로 대체했다.
  • 디자인 시스템 토큰으로 전면 교체: 기존에 하드코딩돼 있던 black/white 및 그 위에 얹은 불투명도(text-black/56 등)를 @tyange-labs/design-system의 시맨틱 토큰(text-tl-fg, bg-tl-surface, border-tl-border 등)으로 바꿨다. 불투명도 계층은 tl-fg/tl-bg 위에 그대로 유지해(text-tl-fg/56) 기존의 세밀한 명암 단계를 잃지 않으면서도 라이트/다크 전환에 자동으로 대응하게 했다. Tailwind Typography(prose)는 다크에서 무시되는 자체 색을 쓰므로 dark:prose-invert를 반드시 같이 켠다.