TreeMap
무료 오픈소스 디스크 사용량 시각화 도구로, 사각형 트리맵·중복 파일 탐색·디스크 가득 예측·정리 시 파일을 휴지통으로만 이동한다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Keep track of ideas for research and analysis. Made for Sloan Venture Capital Internship
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
A board for organizing a hierarchical field — medical technology, in the case it
was built for — into an outline of concepts. Each concept holds a markdown
description, links, attached files, and an optional colour, and can branch into
subconcepts.
Boards live in Supabase, scoped to a workspace, so they follow you between
machines. Signing in gives you a workspace of your own straight away; an admin
who reads across it is someone you invite afterwards, if you want one at all.
Made for the Sloan Venture Capital internship.
.env.local needs the project's URL and publishable key:README 전문 보기 ↗A board for organizing a hierarchical field — medical technology, in the case it was built for — into an outline of concepts. Each concept holds a markdown description, links, attached files, and an optional colour, and can branch into subconcepts.
Boards live in Supabase, scoped to a workspace, so they follow you between machines. Signing in gives you a workspace of your own straight away; an admin who reads across it is someone you invite afterwards, if you want one at all.
Made for the Sloan Venture Capital internship.
npm install
npm run dev
.env.local needs the project's URL and publishable key:
NEXT_PUBLIC_SUPABASE_URL=https://<project>.supabase.co
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_...
Both are safe in the browser — every table and every stored file is gated by row-level security, so the key grants nothing on its own.
In the Supabase dashboard, Authentication → URL Configuration has to list
http://localhost:3000/auth/confirm** as a redirect URL (plus the same for the
deployed origin), or the sign-in link will bounce. The trailing ** matters:
the link carries a ?next= path so a sign-in that started on another page — the
agent consent screen, say — lands back on it.
Sign-in is passwordless: you enter an email, Supabase sends a link, and opening it signs you in. There is no password to set or reset.
Nothing stands between that and a board. The first page load calls
ensure_placement, which puts the account in a workspace named after it — or,
if an invitation was already addressed to that email, in the workspace that sent
it. Either way you arrive as a user, with somewhere to put boards.
| User | Admin | |
|---|---|---|
| Own boards | creates, edits, deletes | — |
| Other members' boards | not visible | read-only |
| Members and invitations | — | manages |
You are never made an admin by your own hand; someone invites you as one.
Admins can't write to boards. Not "the buttons are hidden": can_write_board
in the database refuses any insert, update, or delete from an admin, so the
read-only board view is a reflection of the rule rather than the rule itself.
That also means an admin has no boards of their own and no "New project" button.
Share in the projects toolbar invites someone by email, as an admin who can
read every board in the workspace or as a user who keeps their own. That control
belongs to the workspace's owner — the account it was provisioned for, kept in
organizations.owner_id — so being invited into someone else's workspace does
not let you widen who sees it. An admin can invite too, that being the role's
job, and the owner sees and can revoke every pending invitation in their own
workspace.
Invitations are addressed to an email, not handed out as codes. Invite
[email protected]; when that person signs in with that address, placement
puts them in the workspace.
If the invitation arrives after they already have a workspace of their own, a bar on the projects screen offers to take it. Accepting moves the account and drops the workspace it left — so it only goes through when that workspace is empty, with no boards and nobody else in it.
| Action | How |
|---|---|
| Pan | Drag empty canvas |
| Zoom | Scroll wheel (anchors on the cursor) |
| Re-frame the tree | Fit in the header |
| Open a concept | Click its node |
| Rename the board | Edit the title in the header |
| Add a subconcept | + on a node, or Add subconcept in the panel |
| Add a top-level concept | Add root concept in the header |
| Collapse a branch | The chevron under a node; the count beside it is what's hidden |
| Colour a concept | Pick a swatch in the panel, or the crossed circle to clear it |
| Attach files | Drop them on the panel's file area, or click to browse |
| Reference another concept | Type @ in a description and pick from the list (↑/↓, Enter) |
| Jump to a referenced concept | Click its chip in the description |
| Show or hide reference arrows | References in the header |
Subconcepts stack vertically under their parent, so a plain branch reads top to bottom as one column. A subconcept that has children of its own claims the rest of that column for them, and the sibling after it starts a fresh column alongside — so A with subconcepts B and C, where B has a subconcept D, lays out as the B–D stack with C beside it.
The board keeps itself framed while you build. Once you pan or zoom it leaves the view alone until you press Fit.
A reference is stored in the description as a markdown link to
#concept:<id>, so it follows the concept through renames and shows its
current name. With References on, each one is drawn as an arrow from the
concept that mentions it to the concept it names. Selecting a node brings its
own arrows forward. An arrow whose end is folded away under a collapsed branch
points at that branch instead, dashed. A reference to a deleted concept stays in
the text, crossed out. The toggle is remembered per board, in this browser.
Edits to the name, description, and links autosave about half a second after you stop typing; the panel header shows the save state. Deleting a concept also deletes everything beneath it, along with their attachments, and asks first.
| Table | Holds |
|---|---|
organizations | One workspace, and the account it was provisioned for |
profiles | One row per account, mirrored from auth.users by a trigger |
organization_invites | Pending invitations, keyed on email |
ensure_placement() | Puts a new account in a workspace; idempotent |
boards | One board, owned by one profile |
concepts | The tree; parent_id defines it, sort_order orders siblings |
concept_files | Attachment metadata |
References between concepts have no table of their own: they're read out of the
descriptions (lib/references.ts), so the arrows can never disagree with the text.
Attachments themselves go in the private board-files bucket under
<board id>/<concept id>/<file>; the bucket's policies read that first path
segment to decide who may touch the object. Nothing is publicly addressable, so
opening a file mints a short-lived signed URL.
Deleting a concept cascades to its descendants and their file rows in Postgres. Stored objects don't cascade, so the app removes those explicitly first.
/api/mcp is a Model Context Protocol server,
so Claude and other agents can read boards and edit them on your behalf:
summarize a board, check it for inconsistencies, add sources to a concept,
write up a new one.
Adding it. In claude.ai or Claude Desktop: Settings → Connectors → Add
custom connector, URL https://<your deployment>/api/mcp. In Claude Code:
claude mcp add --transport http brain-board https://<your deployment>/api/mcp.
Either one opens a browser to sign in (the usual email link) and asks you to
allow access.
What it can do. Read every board your account can open, including text attachments; create concepts, edit names, descriptions, tags and links, and move concepts. It can't delete anything, create boards, or upload files. It acts as you, under the same row-level security as the board, so an admin's agent is read-only too. A board that's already open needs a refresh to show its changes.
| Tool | Does |
|---|---|
list_boards | Boards you can open, with their tags |
get_board | The whole outline plus every concept's details |
get_concept | One concept, its place in the tree, and its references |
search_concepts | Text search over names and descriptions |
read_file | Contents of a text attachment (up to 512 KB) |
create_concept | New concept under a parent, or at the top level |
update_concept | Name, description, tag, or links |
add_links | Appends links, skipping URLs already there |
move_concept | Re-parent or reorder |
One-time setup (Supabase dashboard, Authentication → OAuth Server):
/oauth/consent, with the site URL pointing
at the deployment.Sign-in is Supabase's: the agent is sent there by
/.well-known/oauth-protected-resource, Supabase sends the browser to
/oauth/consent to ask, and the token it issues is your own session JWT.
Nothing new is stored in the app, and there are no extra environment variables.
To poke at it locally, run npx @modelcontextprotocol/inspector and connect to
http://localhost:3000/api/mcp.
Earlier versions kept each concept as a markdown file in a folder on disk. To lift one of those folders into a board:
SUPABASE_SERVICE_ROLE_KEY=... node scripts/import-vault.mjs \
--vault "C:\path\to\vault" --owner [email protected] --name "Board name"
The account must already exist and hold a workspace, which happens on its first
page load — so sign in and open the app once first. The service role key bypasses row-level security — which is the point,
since the importer writes rows on someone else's behalf — so pass it on the
command line and keep it out of .env.local, which the app loads.
| Path | Purpose |
|---|---|
proxy.ts | Refreshes the session, bounces signed-out traffic to /login |
lib/supabase/* | The clients: browser, server, proxy, and bearer token (MCP) |
lib/auth.ts | Resolving the signed-in viewer, placing it; the gate every page calls |
lib/boards.ts | Server-side reads for the projects and board screens |
lib/client.ts | Browser-side board, concept, and file writes |
lib/mapping.ts | Postgres rows ↔ the shapes the UI renders |
lib/tree.ts | Flat concept list → forest |
lib/layout-tree.ts | Outline layout: node placement, connector and reference-arrow routing |
lib/references.ts | The @ reference link format, and the graph read out of descriptions |
lib/colors.ts | The sixteen concept pastels |
lib/concept-writes.ts | Concept write details shared by the browser and the MCP server |
lib/mcp/* | MCP tools and the text they render boards as |
app/api/mcp/route.ts | The MCP endpoint; verifies the bearer token |
app/oauth/consent/ | Where you allow or deny an agent |
app/actions.ts | Server Actions: sign out, invitations |
components/board-canvas.tsx | Pan, zoom, edges, node placement |
components/side-panel.tsx | The editor |
Writes go straight from the browser to Postgres rather than through a route handler. There's no API layer to enforce anything, because row-level security already does — a hand-rolled request reaches exactly what the UI could. The MCP endpoint is the one route handler that writes, and it holds to the same rule: it queries with the caller's token, never a service key.
search_concepts)