Synaplan
Open-source AI platform for companies: self-hosted AI agents, GDPR-compliant chatbot widget, RAG knowledge base, WhatsApp and Outlook AI, MCP, multi-model routing. Docker, Kubernetes or hosted in Germ
4인 리서치 그룹의 주간 세미나 워크스페이스
Translation pending
BusinessTypeScript · JavaScriptGitHub @csm-krOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗최근 변경: 업데이트 노트 · 개발 검증: 테스트 환경
AI 연결: 사이드바 상태 점에서 Codex·Claude Code별 모델·effort와 설치 앱 버전·업데이트를 확인한다. 연결 설정 UX, 계약 ADR-028, 검증 phase 20을 따른다.
4인 리서치랩 협업 앱(웹). 한국어 UI. 이 패키지는 개발자가 실제 코드베이스에서 재구축할 수 있도록 디자인을 문서화한다.
하박조팽(HaBakJoPaeng — 네 멤버 하수현·박진희·조성민·팽진욱)은 매주 토요일 세미나를 진행하는 소규모 리서치 그룹을 위한 비공개 워크스페이스다. 이 제품은 그룹이 매주 수행하는 네 가지 일을 하나로 묶는다:
이것은 한 그룹을 위한 단일 테넌트 도구이지 다중 조직 SaaS가 아니다. 톤은 따뜻하고 격식 없는 한국어다("리서치는 혼자 하는 게 아니야").
아래는 실제 구동 중인 앱(모두의모임 / 하박조팽 워크스페이스)의 화면이다. 브랜드 카피는 모두의모임(모모), 코드·DB·URL 식별자는 hapark/하박조팽으로 유지한다.
논문·발표 자료 퀵 카드, 최근 활동, 현재 팀과 멤버 목록.
매주 토요일 발표 순번, 발표자 로테이션, 발표자/일반 불참 벌금 설정.
업로드된 논문(연구/재구현 두 관점 분석)과 슬라이드 수가 함께 쌓이는 발표 자료.
LiveKit 기반 다자간 화상 룸. 라이브가 없을 때의 빈 상태 — 시작하면 모두에게 알림이 가고 룸이 열린다.
src/의 파일들은 HTML/React-via-Babel로 만든 디자인 레퍼런스다 — 의도한 모습과 동작을 보여주는 클릭 가능한 프로토타입이다. 출시할 프로덕션 코드가 아니다. 브라우저 내 Babel 설정, window.* 전역, 인라인 JSX <script type="text/babel"> 로딩은 모두 프로토타입을 위한 편의 장치다.
작업은 타깃 코드베이스 환경에서 그곳의 확립된 패턴(실제 번들러, 컴포넌트 라이브러리, 라우터, 실제 상태 관리, 실제 비디오 SDK, 실제 PDF 파이프라인)을 사용해 이 디자인들을 재현하는 것이다. 아직 코드베이스가 없다면, 컴포넌트 라이브러리(예: Radix/shadcn)를 곁들인 모던 React + TypeScript + Vite 스택이 여기 있는 것과 깔끔하게 대응된다.
고충실도. 최종 색상, 타이포그래피, 간격, 레이아웃, 카피, 빈 상태, 인터랙션 상태가 모두 프로토타입에 명세되어 존재한다. UI는 충실하게 재현하되, 프로토타입 메커니즘(브라우저 Babel, 목 window 데이터, 가짜 미디어 스트림)은 프로덕션 동등물로 교체한다.
| 프로토타입 메커니즘 | 교체 대상 |
|---|---|
@babel/standalone로 브라우저에서 JSX 트랜스파일 | 실제 빌드(Vite/Next) |
data.js의 window.PAPERS, window.TEAM, window.SCHEDULE 등 | API + 타입드 모델 / DB |
useDetailState / useAnState / useMeetState (로컬 useState) | 실제 상태 + 서버 영속화 |
<image-slot> 웹 컴포넌트(드래그앤드롭 플레이스홀더) | 실제 이미지 업로드 / 렌더링된 PDF figure |
getUserMedia 프리뷰 타일, 타인용 정적 아바타 | LiveKit(SFU) — 참가자별 입장 토큰으로 같은 룸에 접속해 다자간 비디오 타일·화면공유(ADR-019, Cloudflare Stream Live 대체). 앱은 토큰 발급·권한 체크·룸 정리만 담당 |
Tweaks 패널(tweaks-panel.jsx) | 제거 — 제품 기능이 아니라 디자인 탐색 도구 |
싱글 페이지 앱. app.jsx가 screen 문자열과 작은 switch 라우터를 보유한다. 화면들:
| 화면 키 | 컴포넌트 | 라우트 의도 |
|---|---|---|
auth | AuthScreen (screens-auth.jsx) | 로그인 / 가입 히어로 |
dashboard | DashboardScreen (screens-main.jsx) | 홈 |
library | LibraryScreen (screens-main.jsx) | 논문 목록 |
paper | PaperDetailScreen (screens-detail.jsx) | 한 논문의 분석 |
presentations | PresentationsScreen (screens-presentations.jsx) | 발표 자료 목록 |
presentation | PresentationView (screens-detail.jsx) | 한 자료 + 댓글 |
schedule | ScheduleScreen (screens-schedule.jsx) | 스케쥴 |
team | TeamScreen (screens-main.jsx) | 팀 관리 |
meeting | MeetingScreen (meeting.jsx) | 세미나 라이브 |
ideas | 아이디어 보드 | 아이디어 |
profile | ProfileScreen (screens-main.jsx) | 설정 |
(화면별이 아니라) 앱 레벨로 끌어올려야 하는 상태:
live: boolean — 지금 세미나가 라이브인가? 사이드바 LIVE 배지, 대시보드 배너, 그리고 미팅 룸 vs. 빈 상태를 좌우한다. MeetingScreen에서 라이브를 시작/종료하면 onSetLive를 통해 위로 흘러간다.theme, collapsed(사이드바), uploadOpen, 현재 screen + 파라미터.count/unread 배지를 가지며, meeting 항목은 live === true일 때만 깜빡이는 LIVE 알약을 표시한다.<Topbar crumbs={[...]} actions={...} />로 사용한다.내비 순서: 홈 · 논문 · 발표 자료 · 아이디어 · 스케쥴 · 팀 관리 · 세미나 라이브.
스플릿 히어로. 좌측 = 브랜드 패널: 워드마크 "하박조팽", 태그라인 "리서치는 혼자 하는 게 아니야.", 서브 카피, 그리고 4개 항목 기능 목록(세미나 라이브 / 논문 분석 관리 / 자료 관리 / 스케쥴 관리) — 각각 아이콘 타일 + 제목 + 한 줄 설명. 우측 = 로그인/가입 폼. 빠른 "social-btn" 항목은 데모 멤버로 로그인한다.
live일 때만 렌더링. 미팅으로 연결된다.{icon, label, count, desc}..paper-row): 종류 태그, 제목, 저자, 업로더 아바타, 날짜. 클릭 → paper.헤더: 브레드크럼(발표 자료 → 논문), 제목, 저자/메타. 상단바 액션 = 단일 "원문 PDF" 다운로드 버튼(arXiv 및 공유 버튼은 제거됨). 탭 바 없음.
헤더 아래에 전체 폭의 AnalysisView(analyzer.jsx)가 자리한다. 구성:
🔬 연구 분석 ⇄ 🛠️ 재구현 분석, 그리고 활성 관점을 설명하는 한 줄 힌트.Figure 분석은 두 관점 모두의 하단에 고정 — 관점별이 아니라 공통이다. 각 figure 카드는 "원문 PDF p.N에서 추출" 출처 배지, 추출된 figure용 <image-slot>, 캡션, 그리고 설명(해석) 줄을 표시한다. 프로덕션에서는 자동 또는 사람이 작성한 설명과 함께 PDF에서 추출/렌더링된 실제 figure다.{sectionId, lens}로 스코프된다 — 단 Figure 노트는 관점 공통(lens: "any")이다. 노트는 삭제 가능하다.layout prop으로 레이아웃 변형(stack / grid / toc)이 존재한다; toc는 고정된 섹션 점프 사이드바를 추가한다.
자료 목록(개수 "14개"). 상세 = 자료 뷰어 + @멘션과 반응이 있는 댓글 스레드.
보드의 단일 컬럼. 핵심 모델: 월별 계획, store[${year}-${month}] = { weeks, saved }로 저장.
월별 세 가지 상태:
일정 짜기(또는 수정)가 해당 월 토요일들의 초안을 만든다(순번은 직전 계획이 끝난 지점부터 이어짐). 각 행은 편집 가능: 확정 체크박스, 시간 입력, 발표자 선택, 주제 텍스트 입력. 고정된 편집 바가 "확정 N/M"과 취소 / 저장을 표시한다.페이지의 다른 보드들: 벌금 설정(발표자 불참 벌금, 일반 불참 벌금 — 둘 다 편집 가능), 로테이션(하수현 → 박진희 → 조성민 → 팽진욱), 연도별 멤버 현황 표(참여 / 불참 / 누적 벌금 / 납부 / 미납, 편집 가능한 벌금 금액으로부터 재계산).
!live일 때 빈 상태: 중앙 정렬 "진행 중인 라이브가 없습니다", 라이브 시작하기(주요) + 스케줄 보기, 그리고 "다음 세미나" 칩. 라이브 시작은 onSetLive(true)를 호출한다.live일 때 룸: 비디오 그리드(자기 타일은 getUserMedia 사용; 타인은 아바타 타일), 발표자 스포트라이트, 컨트롤 바(마이크/카메라/공유), 그리고 종료(라이브 종료 → onSetLive(false), 트랙 중지, 홈 복귀)와 나가기(종료하지 않고 퇴장)가 있는 헤더.프로필 필드, 알림 토글, 테마, 법적 링크.
onNavigate(screen, params); 브레드크럼과 사이드바 모두 호출한다.onToast(message).CURRENT_USER로 작성자 표기.papers + analyses(연구/재구현 구조화 필드, 페이지 참조 및 해석이 있는 figure들){paperId, sectionId, lens, author, title, body}로 키잉되는 sectionNotespresentations + comments(스레드형, @멘션, 반응){year, month}로 키잉되는 schedule → weeks [{week, date, time, presenter, topic, confirmed, status, presId}]; 순번 포인터fines(presenterFine, absentFine) + 멤버별 출석/납부 장부team 멤버 + 역할 + 대기 중인 초대liveSession(단일 boolean/객체: active, presenter, participants)모든 토큰은 src/styles.css에 CSS 커스텀 프로퍼티(:root + [data-theme="dark"])로 존재한다. 정확한 값은 거기서 가져온다 — 주요 계열:
--accent(따뜻한 테라코타/오렌지, 브랜드 액센트), --accent-soft, --accent-faint; 표면 --bg, --bg-subtle, --bg-elevated, --bg-active, --bg-hover; 텍스트 --fg, --fg-muted, --fg-subtle, --fg-faint; --border, --border-strong; 상태 --online, --busy. 역할/상태 배지는 oklch(...) 틴트를 사용한다(예: 게스트 배지, 벌금 점). 다크 테마 오버라이드 포함.--r-xs, --r-sm, --r-md, --r-lg.--shadow-lg(메뉴/팝오버).--font-mono. 제목 .h1/.h2; 본문 13–14px; 작은/메타 11–12px.gap 사용.<Icon name="…" /> 컴포넌트(인라인 SVG 세트) — 곳곳에서 참조되는 이름들(video, play, calendar, users, sparkles, download, plus, x, chevron-* 등). 사용하는 아이콘 라이브러리에 매핑(Lucide가 거의 전부 커버).<Avatar user={…} />를 통한 이니셜/색상 타일 생성.<image-slot> 플레이스홀더(src/image-slot.js).index.html — 엔트리; React 18.3.1 + Babel standalone를 로드한 뒤 아래 모든 JSX/JS 로드.styles.css — 모든 스타일링 + 디자인 토큰.data.js — 목 데이터 + window 전역 + find* 헬퍼(형식화할 데이터 모델).app.jsx — 라우터, 앱 레벨 상태(live 포함), 화면 switch.shell.jsx — 사이드바 + 상단바.screens-auth.jsx — 로그인/히어로.screens-main.jsx — 대시보드, 라이브러리, 팀, 프로필.screens-detail.jsx — 논문 상세, PresentationView, 업로드 모달.analyzer.jsx — AnalysisView(관점, 섹션, figure, 섹션별 노트).screens-presentations.jsx — 발표 자료 목록.screens-schedule.jsx — 스케줄(빈/편집/확정 + 벌금 + 순번 + 통계).meeting.jsx — 세미나 라이브(빈 상태 + 룸).legal.jsx — 약관/개인정보 페이지.image-slot.js — figure 플레이스홀더 웹 컴포넌트.tweaks-panel.jsx — 디자인 탐색 전용; 포팅하지 말 것.제품 명세는 PRD.md를, 단계별 플로우는 UX_FLOWS.md를 참조한다.
웹의 AI 연결에서 이 PC의 CLI를 연결한다. 최초 설치·6자리 확인 이후 같은 웹 세션·팀·기기는 전용 링크로 다시 실행한다. 설정 화면에서 실제 모델·팀 논문을 선택해 질문한다. 실제 화면·검증 HTML 보고서, 동작·설치 빌드·검증, UX 시연, 하네스 상태를 참조한다. 운영 DB와 설치 파일 배포는 검토 상태를 확인한 뒤 반영한다.
업로드는 원문 준비까지만 진행해 AI 호출이 없다. 본문이 준비되면 PC·실제 모델을 명시적으로 선택해 논문 분석을 시작한다. Inngest가 로컬 실행 결과를 회수해 JSON·페이지·원문 인용을 검증하고 최신 요청의 두 관점 결과만 저장한다. 연구/repro 관점과 공통 Figure 하단은 유지하며 논문 상세에 AI 탭·사이드패널을 추가하지 않는다.
별도 메뉴 /ai-chat에서 자료 없이 개인 대화를 시작하고 후속 질문을 이어간다. 입력창의 @로 같은 팀 논문·발표 자료를 합계 10개까지 질문마다 선택하며, 지난 질문의 자료 기록은 보존한다. 자료 준비는 Inngest에서 처리한다. 부분 답변·중지·연결 끊김을 구분하고 대화 기록과 현재 PC 실행 권한을 분리한다. 목록 최근 100개·상세 50턴, 모델 문맥은 완료된 최근 8턴·원문 합계 20만 자이며 생략 여부를 표시한다. 현재 CLI는 텍스트 전용으로 Figure는 본문·캡션 기반 추론, 외부 저장소는 미검증이다. Gemini·다른 CLI·원격 유료 API로 자동 대체하지 않는다.
소스 3f16685의 CI 39033348260에서 웹 946개·실제 PostgreSQL 16 동시성 13개·Chromium 8개·HTTP 쿠키 회수·3 OS native/패키징을 통과했다. 합성 2쪽 PDF의 실제 Codex 구조화 분석은 형식 안내 수정 뒤 1회 성공했으며 이전 형식 거절 2회와 구분한다. 운영 DB·서명 배포는 아직 미완료다. 기존 연결 5개 테이블 이후 연구 대화 테이블·추가 컬럼을 수동 적용해야 한다. 화면과 검증 HTML, 제품 범위, ADR-026, API, 스키마·운영 적용 순서, 검증 하네스를 참조한다.
/presentations/new에서 논문 읽기 → 발표 방향 2~3개 → 한 질문씩 대화 → 목차 합의 → 원문 Figure·표·설명 도식 → 대화 수정 → HTML/PDF 검수·명시적 팀 등록으로 이어진다. 제작 계약, ADR-031/032와 운영 반영 기록을 따른다. 스키마·최신 AI 브릿지·Inngest를 준비한 뒤 AGENT_TASKS_ENABLED=1로 켠다.