Cursor BYOK 프론트엔드은(는) 무엇을 하나요?
apps/desktop에 이미 존재하는 컴포넌트 및 테마 시스템 위에 구축합니다. Tauri HTTP 경계를 유지하며, 프론트엔드 관리 기능은 /__byok-api__/api를 호출하고 IPC 비즈니스 API를 추가하지 않습니다.
데스크톱 HTTP 통신
- Rust 관리 서버를 데스크톱 UI의 단일 HTTP 오리진으로 취급합니다. 기본 WebView와 브라우저에서 열린 상세 페이지는
http://127.0.0.1:<dynamic-port>/__byok-api__/를 사용해야 하며,tauri://localhost에서 메인 UI를 로드하거나 두 번째 프론트엔드 오리진을 노출하지 마십시오. - 모든 프론트엔드 관리 요청을
/__byok-api__/api에 상대 경로로 만듭니다.apiOrigin을 발견, 삽입, 유지 또는 전달하지 말고, 고정 포트에서 관리 URL을 구성하지 마십시오. /__byok-api__/네임스페이스를 이 경계를 위해 예약하십시오:/__byok-api__/api/*는 Rust 관리 API에서 로컬로 처리됩니다.- 다른
/__byok-api__/*경로는 프론트엔드 문서, 에셋, 모듈 및 개발 리소스입니다.
- 프로덕션에서는 Tauri의
frontendDist에 의해 임베드된 프론트엔드를 Rust 서버를 통해 제공합니다. 두 번째 프론트엔드 리소스 세트를 번들링하거나 복사하는 대신 Tauri의 에셋 리졸버를 재사용하십시오. - 개발 중에는 Rust 서버가 비-API
/__byok-api__/*요청을 Vite로 역방향 프록시하도록 합니다. 요청 경로와 쿼리 문자열을 유지하십시오. Vite가 관리 API 요청을 Rust로 프록시하도록 구성하지 마십시오. - Vite의 기본 경로를
/__byok-api__/로 구성하여 생성된 에셋, 모듈 임포트 및 개발 클라이언트 URL이 예약된 네임스페이스 아래에 유지되도록 합니다. - 개발 Vite 서버를 Rust 프록시 대상과 호환되는 명시적 루프백 주소에 바인딩하십시오.
localhost가 동일한 IP 패밀리로 해석된다고 가정하지 마십시오. - 외부 상세 페이지를 일반 루프백 HTTP URL과 해시 라우트로 엽니다. 페이지와 API가 동일 오리진이므로 Tauri URL 해결 방법, API 오리진 쿼리 매개변수 또는 CORS에 의존하는 브라우저 흐름을 추가하지 마십시오.
- 터미널 열기, 트레이 통합 또는 운영 체제 작업과 같은 네이티브 데스크톱 기능에만 Tauri 명령을 사용하십시오. HTTP 비즈니스 API에 대한 IPC 미러를 만들지 마십시오.
컴포넌트 경계
- Provider, Model, Call, Usage 및 영구 설정 상태를 프레젠테이션 컴포넌트 외부에 유지하십시오.
- 컴포넌트가 비즈니스 스냅샷을 수신하고 액션을 디스패치하도록 합니다. 로컬 React 상태는 포커스, 열림 상태, 드래그 상태 및 입력 초안과 같은 일시적인 UI 동작에만 허용됩니다.
- 페이지, 레이아웃, 차트, 폼 및 재사용 가능한 컨트롤을 집중된 컴포넌트로 분할하십시오. 전체 기능 세트를
App.tsx에 모으지 마십시오. App.tsx를 라우트 구성 루트로 유지하십시오.
페이지 레이아웃
- 모든 전체 높이 페이지를
components/layout/PageLayout.tsx로 빌드하십시오. 그리드 행으로 페이지 셸을 수동으로 만들지 마십시오. - 생성, 가져오기, 내보내기, 필터링, 정렬 및 보기 옵션과 같은 페이지 수준 명령 및 컨트롤을
PageActions를 통해 공유 페이지 액션 영역에 배치하십시오. 편집 및 삭제와 같이 하나의 구체적인 목록 항목을 대상으로 하는 작업만 해당 항목의 행 내부에 유지하십시오. 페이지 콘텐츠 내에 중복 액션 바 또는 패널 헤더 컨트롤을 추가하지 마십시오. - 데이터 테이블 또는 플랫 데이터 목록 위에 제목 영역을 렌더링하지 마십시오. 컨텍스트를 위해 페이지 제목을 사용하고, 테이블 헤더에 열 레이블을 유지하며, 페이지 수준 컨트롤을
PageActions에 배치하고, 제목이 없는Card로 테이블을 감쌉니다. 그룹화된 부모-자식 보기에서 부모 데이터를 식별하는 계층 레이블은 테이블 제목이 아닙니다. - 기본 스크롤 뷰포트를 전체 높이로 유지하고
position: relative로 설정하며, 페이지 제목과 액션 영역을 그 위에 절대적으로 배치하십시오. - 스크롤 콘텐츠에
padding-top으로 절대 제목/액션 영역을 예약하고, 스크롤 뷰포트 자체를 단축하거나 오프셋하여 예약하지 마십시오. - 메뉴 Card를 고정하고 콘텐츠 영역의
margin-left로 예약하십시오. Header, 메뉴 및 콘텐츠를 플로우 그리드에 배치하지 마십시오. - 외부 간격을 만들기 위해 자식 또는 섹션 패딩을 사용하지 마십시오. 형제 간에는 flex/grid 갭을 사용하고, 컨테이너 경계에는 마진 또는 고정 오프셋을 사용하십시오. 스크롤 콘텐츠 상단 패딩은 절대 제목/액션 오버레이에만 예약됩니다.
- 다음 불변 속성을 가진 수직 flex 레이아웃을 사용하십시오:
- Header:
flex: 0 0 auto. - Footer:
flex: 0 0 auto. - Content:
flex: 1 1 auto,min-height: 0,overflow: hidden.
- Header:
- Header와 Footer를 스크롤 뷰포트 외부에 유지하십시오. 콘텐츠에 따라 커지거나 작아지면 안 됩니다.
- macOS, Windows 및 Linux 창 모서리 안전 영역 변수를 네이티브 둥근 모서리에 들어갈 수 있는 가장자리 크롬에만 적용하십시오.
- macOS 트래픽 라이트 공간과 상단 고정 드래그 스트립을 대화형 컨트롤 없이 유지하십시오.
- 사용자가 작업을 수행하거나 상태를 해석하는 데 도움이 되지 않는 장식용 브랜드 텍스트와 설명문을 피하십시오.
타이포그래피
- SCSS로 컴포넌트 스타일을 작성하고 모든
font-size를src/styles/_typography.scss에서 가져오십시오. SCSS, React 스타일 또는 차트 옵션에서 글꼴 크기를 하드코딩하지 마십시오. - 일반 UI 텍스트와 일반 제목(제목 표시줄, 패널, 카드 및 섹션 제목 포함)에는
base를 사용하십시오. 요소가h1또는h2라고 해서 글꼴을 키우지 마십시오. - 보조 정보에만
xs를 사용하십시오. 명시적으로 큰 표시 제목에만lg를 예약하고, 일상적인 제목에 사용하지 마십시오. - 스케일을 변경한 후 원시 숫자 글꼴 크기뿐만 아니라 모든 타이포그래피 토큰 사용을 감사하십시오.
스크롤 및 가상화
- 세로로 스크롤되는 페이지 콘텐츠에는
components/layout/VirtualPage.tsx를 사용하십시오. - 커질 수 있는 데이터 컬렉션 및 메뉴에는
components/virtual/VirtualList.tsx를 사용하십시오. ScrollArea를 가상 스크롤 구현이 소유한 저수준 프리미티브로 취급하십시오. 페이지 또는 레이아웃에서 직접ScrollArea를 가져오지 마십시오.- 스크롤 가장자리 그림자에 전역
scroll-shadow-top및scroll-shadow-bottom마스크를 사용하십시오. 스크롤 콘텐츠 삽입이 절대 오버레이를 예약하는 경우 상단 그림자 거리를 해당padding-top과 동일한 CSS 변수에서 가져오십시오. - 비목록 페이지를 측정 가능한 최상위 가상 섹션의 짧은 시퀀스로 모델링하십시오.
- 문서 스크롤, 네이티브 페이지
overflow: auto또는 중첩된 세로 스크롤 컨테이너를 사용하지 마십시오. - 가상 뷰포트의 모든 flex/grid 조상이
min-height: 0을 가지고 뷰포트에 명시적인 제한 높이가 있는지 확인하십시오.
라우팅 및 페이지
- Tauri 호환성을 위해
HashRouter를 사용하십시오. /를 통계 대시보드로 유지하고 모든 기본 페이지를 공유AppLayout의 영구 메뉴를 통해 노출하십시오.- 기본 페이지에 최상위 라우트를 사용하십시오:
/,/providers,/models,/calls,/settings. - 별도의 Home 및 Settings 셸을 만들거나 Home 전환 컨트롤을 추가하지 마십시오.
- 라우트 콘텐츠를 창 Header 및 Footer와 독립적으로 유지하십시오.
차트
components/charts/EChart.tsx를 통해 ECharts를 사용하십시오.- 필요한 ECharts Core 차트, 컴포넌트 및 렌더러만 등록하십시오.
- 차트 컴포넌트를 선언적으로 유지하십시오: 도메인 데이터를 수락하고 데이터를 가져오거나 유지하지 않고 옵션을 구성합니다.
ResizeObserver가 레이아웃 컨테이너와 함께 차트 크기를 조정하고 마운트 해제 시 인스턴스를 폐기하도록 하십시오.
검증
apps/desktop에서 실행:
npm run check
npm run tauri:build -- --debug --no-bundle
Header와 Footer가 고정되어 있고, 가상 콘텐츠 뷰포트만 스크롤되며, 최소 창 크기에서 설정 탐색이 계속 가능하고, macOS 컨트롤이 둥근 모서리 및 트래픽 라이트 안전하지 않은 영역 외부에 있는지 확인하십시오.