AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기data sharing
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗This is a Next.js project bootstrapped with create-next-app.
Copy your Supabase project's URL and anon key into .env.local (placeholders are there by default):
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
Run the development server:
npm run dev
Open http://localhost:3000 with your browser to see the result.
This milestone proves out the signaling layer (Supabase Realtime Broadcast) that
Milestone 2 will layer WebRTC on top of. No RTCPeerConnection code exists yet —
two tabs just exchange arbitrary broadcast messages over a shared room channel.
lib/supabase.ts — Supabase client singletonlib/roomId.ts — generates a 6-character, unambiguous room codehooks/useSignalingChannel.ts — subscribes to room-<id> and exposes
sendMessage, onMessage, status, and disconnectapp/page.tsx — sender/create-room viewapp/join/page.tsx — receiver/join-room view/join), paste the room ID, and click
Join.<id>". Tab A should flip from
"Waiting for peer..." to "Peer connected" shortly after./join and re-enter the same room ID — it should
reconnect successfully and Tab A should see "Peer connected" fire again./join and enter a made-up/invalid room ID. This
should not crash the app — it will report as "connected" to an empty
channel (see note below), since Supabase Realtime channels don't require
a room to be pre-created. If Supabase itself is unreachable (bad URL/key,
network issue), the status will show a clear "Connection error" state
instead of hanging on "Connecting...".Note on room validity: Supabase Realtime broadcast channels are created implicitly on subscribe — there's no server-side concept of a room "existing" yet. So joining a room nobody created will still show as "connected," it just won't receive any messages. Real room-existence validation (e.g. a
roomstable, or Presence to detect whether the sender is actually there) is deferred to Milestone 6 — see the comment inhooks/useSignalingChannel.ts.
This milestone adds the actual WebRTC layer on top of Milestone 1's signaling.
An RTCPeerConnection is established using the existing Supabase signaling
channel to exchange the SDP offer/answer and ICE candidates, resulting in an
open RTCDataChannel between the two browsers. Once that DataChannel opens,
the signaling channel is disconnected — everything after that is direct
peer-to-peer, no server involved.
lib/webrtc-config.ts — RTCConfiguration with a public STUN server (no
TURN yet — see Milestone 6)hooks/usePeerConnection.ts — wraps useSignalingChannel to run the
offer/answer/ICE handshake and exposes connectionState, sendData,
onData, disconnectapp/page.tsx / app/join/page.tsx — updated to use usePeerConnection
instead of raw signaling broadcasts for the test message boxNote on STUN-only connectivity: only a public STUN server is configured right now. If either side is behind a strict/symmetric NAT or a corporate firewall, the handshake can hit a "Connection failed" state — that's expected until Milestone 6 adds a TURN server.
This milestone replaces the Milestone 2 raw test-string box with a real chat feature: a typed, extensible message protocol over the DataChannel, a proper chat UI, and a clear "connection lost" state if the peer drops mid-chat.
lib/messageTypes.ts — ChatMessage / DataChannelMessage discriminated
union sent over the wire (JSON-stringified in, JSON-parsed + narrowed by
type out); more variants (file-meta, file-chunk, ...) get added here in
Milestone 4hooks/useChat.ts — wraps a usePeerConnection result into
messages / sendMessage(), with sent messages added optimistically and
unrecognized incoming message types ignored (logged, not thrown)components/ChatPanel.tsx — scrollable message list (sender/receiver
bubbles, timestamps, auto-scroll, empty state), input that's disabled
whenever connectionState !== 'connected', and a banner when the
connection is lost mid-chatapp/page.tsx / app/join/page.tsx — render <ChatPanel /> below the
existing connection status indicatorroomId exists, with input disabled until the status reads "Connected
(P2P)".This milestone adds chunked file transfer on the same DataChannel chat already uses, with backpressure handling so large files don't blow up browser memory, and SHA-256 checksum verification so silent corruption on a large transfer gets caught instead of ignored.
lib/messageTypes.ts — adds FileMeta / FileChunk / FileComplete to
DataChannelMessage. Chunks stay base64-in-JSON (not raw binary frames)
to keep one consistent message format with chat on the same channel —
documented tradeoff, see the file header comment in
hooks/useFileTransfer.tshooks/usePeerConnection.ts — gained isOpen(), getBufferedAmount(),
and waitForBufferedAmountBelow(threshold) so a chunked sender can pace
itself against RTCDataChannel.bufferedAmount instead of flooding the
channelhooks/useFileTransfer.ts — sendFile(file) chunks at 16KB, pausing
whenever bufferedAmount exceeds 1MB until the channel's
bufferedamountlow event fires; computes a whole-file SHA-256 and sends
it in file-complete. On receive, chunks are reassembled by index into a
Blob, re-hashed, and compared against the sender's checksum — a
mismatch (or a dropped connection mid-transfer) marks the transfer
failed rather than silently accepting bad datacomponents/FileTransferPanel.tsx — file picker, per-transfer progress
bars (sending/receiving), and download links for completed filescomponents/SessionPanels.tsx — tabs Chat/Files above ChatPanel and
FileTransferPanel; both stay mounted (just hidden) when switching tabs
so neither chat history nor in-flight transfer progress resetsapp/page.tsx / app/join/page.tsx — render <SessionPanels /> instead
of <ChatPanel /> directlybufferedAmount backpressure is actually pausing sends.To learn more about Next.js, take a look at the following resources:
The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.