vccs
Vue 3용 차트 컴포넌트 모음, Recharts에서 포팅
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
An open-source, collective library of regenerative research — a bibliography anyone
can add to, a shared vocabulary that keeps it coherent, and a constellation map that
shows what sits near what.
Curated by Malina Dabrowska. Contributions welcome.
There is no build step and no dependency tree — the whole platform is Node's standard
library plus the browser. npm start is the entire install story. Node 22.5 or newer
is required, for the built-in node:sqlite.README 전문 보기 ↗An open-source, collective library of regenerative research — a bibliography anyone can add to, a shared vocabulary that keeps it coherent, and a constellation map that shows what sits near what.
Curated by Malina Dabrowska. Contributions welcome.
git clone https://github.com/mmalinadabrowska/regenerative-atlas.git
cd regenerative-atlas
npm run seed # build data/atlas.db from the starter bibliography
npm start # http://localhost:4321
There is no build step and no dependency tree — the whole platform is Node's standard
library plus the browser. npm start is the entire install story. Node 22.5 or newer
is required, for the built-in node:sqlite.
A bibliography. Paste a link on /add. The server goes and reads it — DOIs
through doi.org's citation API, everything else scraped for citation_*, Open Graph
and Dublin Core metadata — and hands back a filled-in form. You correct what it got
wrong and say where the piece sits. Submitting the same link twice does not make a
second entry; the two sets of tags are merged, because two people finding the same
paper is a signal rather than a collision.
A tagging system. Tags are free — anyone can coin one — but a curated core of
sixty holds the middle. Every tag written by a contributor is slugified and run
through an alias table before it is stored, so Circular Economy, circularity and
cradle to cradle all arrive at the same node instead of splitting the map three
ways. Tags carry a facet — theme, location, material, method, scale, format, or open —
which decides how hard they pull on the map. Themes hold territory; formats only tint
it; a location pulls on nothing at all.
A place for everything. Where a piece of work is grounded is a tag like any other
underneath, and nothing like one to read. Denmark files a source under Europe as well,
so asking the library for a region is a plain tag match and still finds the work filed
under a country inside it; a country the vocabulary does not name folds to its region
rather than being lost. A submission that names no place is filed as global — the work
that reads the same anywhere — so no source falls out of the location filter. Places
are never drawn on the map: an island is a subject, and a continent is not one.
A map. /map opens on the tags alone — ink blots clustered into islands by what
they are filed alongside. Open one and the graph rearranges around it: the tag at the
centre, everything filed under it on a ring, the kinship between those pieces drawn.
Open one of those pieces and it rearranges again, its tags fanned to one side and the
research it sits beside to the other. Click the empty ground to come back.
Two kinds of node:
Two kinds of line:
Kin lines are deliberately sparse. A graph that connects everything says nothing.
Names arrive with the zoom. Fully out, only the tags that actually organise the library are named and no titles are shown at all; each step closer lowers the bar on tags and lets more of each title through. The thresholds are relative to the zoom that fits the whole map, so a library of thirty and a library of three thousand both open as territory.
Clusters form on the tags first, by label propagation over their co-occurrence
graph, normalised by cosine so a tag like materials — which half the library carries
— cannot swallow everything it touches. Tag communities are more stable than source
communities and they name themselves, which matters on a map you have to read.
A source then joins the community its tags vote for, weighted by inverse document
frequency: a source tagged mycelium is placed by that, not by also being tagged
materials.
Kinship between two sources is the cosine of their IDF-weighted tag vectors. Cosine rather than Jaccard on purpose — a thoroughly tagged source should not be punished for the tags it does not share, and two pieces meeting on one uncommon tag should still find each other. Each source keeps only its strongest few lines, and any source with no line at all gets its single best candidate, so nothing well-tagged floats alone.
All of it is deterministic. The same library draws the same map.
server/
index.js http server, router, static files
api.js request handlers, validation, JSON and BibTeX export
db.js SQLite schema and queries
graph.js clustering and the constellation payload
metadata.js reading a link, and the SSRF guard around doing so
vocabulary.js the curated tags and their aliases
seed.js loads data/seed.json
public/
index.html the landing constellation and the way in to the map
images/hero.svg the landing drawing, generated by scripts/draw-hero.mjs
map/index.html the constellation
themes/index.html keyword search and the vocabulary as an index
add/index.html submission
about/index.html what the Atlas is
js/ink.js the drawing hand — every mark on the site comes from here
js/constellation.js force simulation and canvas renderer
scripts/
check-links.js walks every URL in the library and reports what has rotted
draw-hero.mjs redraws the landing constellation (`npm run draw`)
test/ 63 tests, `npm test`
data/seed.json the starter bibliography
Everything the pages use is public and unauthenticated for reading.
| Method | Path | Does |
|---|---|---|
GET | /api/sources?tag=&q=&limit=&offset= | List sources; repeat or comma-separate tag to intersect |
GET | /api/graph?tag=&q=&tags=off | The constellation: nodes, links, clusters |
GET | /api/tags | Tags in use, with counts, grouped by facet |
GET | /api/vocabulary | The curated core and its facets |
GET | /api/stats | Counts and the five most recent additions |
GET | /api/export.json | The whole library as JSON |
GET | /api/export.bib | The whole library as BibTeX |
POST | /api/describe | {url} → what that link says about itself |
POST | /api/sources | {url, title, tags[], …} → adds a source |
Both POST routes are rate-limited per address. POST /api/describe makes the server
fetch a URL a stranger supplied, so it resolves the host first and refuses private,
loopback and link-local addresses.
Through the site is the intended way — /add, paste, check, tag.
To propose entries as a pull request instead, add them to data/seed.json and run
npm run reset. Please run npm run check-seed first: link rot is what kills a
bibliography, and a reference nobody can open is not a reference.
To read or correct the whole library at once, npm run library:export writes it to
data/library.csv (with the tag vocabulary in data/vocabulary.csv). Edit it in any
spreadsheet, save it as CSV UTF-8 in the same place, and npm run library:import checks
every row and writes the changes back to data/seed.json — listing each one, and writing
nothing if any row is wrong. Then npm run reset, npm run build-static, and
npm run supabase-sql, pasting supabase/replace-library.sql into Supabase.
The starter links are unverified. They were written from knowledge of the field, not checked against the live web, so some will have moved or rotted.
npm run check-seedreports what is unreachable and what has redirected; fixing those is a good first contribution.
Both are post-binary faces from the Bye Bye Binary collective:
Both complete upstream packages are bundled under public/fonts/, sources and
documentation included, because their licence asks for whole folders rather than lone font
files. They are not under this project's MIT licence, and one of their conditions —
placing yourself on a donation scale — is not something a repository can discharge for
you. Read public/fonts/README.md before deploying the Atlas
anywhere, and the CUTE text bundled alongside each face.
Deleting either directory breaks nothing; the stacks fall back to EB Garamond and Century Gothic. The Atlas is just less itself.
npm run build-static bakes the read endpoints into public/data/snapshot.json and
writes dist/atlas.html, the map as one self-contained file — styles, scripts, fonts
and library all inlined, nothing to fetch. Open that file on any device, or drop
public/ on any static host: js/api.js falls back to the snapshot whenever the API
is not there, so the map, the themes index and search all work. Adding does not, and
says so — a snapshot has nowhere to write to.
Rebuild the snapshot whenever the library changes; it is committed, so a static deploy needs no build step of its own.
Every page but the landing one is a folder with an index.html in it — map/, add/,
themes/, about/ — so that /map/ is a real path on any host that has ever served a
website, rather than a rewrite rule you have to remember to add. GitHub Pages, Netlify,
Cloudflare Pages, an S3 bucket and python3 -m http.server all serve it the same way,
and so does server/index.js. 404.html is picked up as the not-found page by most of
them without being asked.
The site can be served as files, and a folder of files cannot be added to. So
the one thing it cannot do by itself is done by four small functions in
api/ — the same validator, the same vocabulary, no framework — and
what comes through them is queued rather than published: written to a
submissions table in the Supabase project, announced to the curator by email,
and put on the map only by a decision.
a submission on /api/sources written to the submissions
the website ───▶ on the host ───▶ queue, and nowhere else
│
▼
on the map at the the scheduled one email, one link, one
next publish ◀─── publish rebuilds ◀── page with two buttons
the snapshot
The review link carries a token that is a key to one submission and to nothing else — it cannot list the queue, read another entry, or touch the library — and the decision is a POST rather than a link, because inboxes are full of scanners that open every URL in a message.
It is all opt-in: with no Supabase project the form says so plainly instead of
swallowing a contribution, and with no mail key the queue still fills, it just
fills quietly. docs/submissions.md is the setup, end
to end, and /api/health on the deployed site says in booleans which halves are
wired up.
Put it behind a reverse proxy and give it a persistent volume for data/.
PORT=4321 HOST=0.0.0.0 ATLAS_DB=/var/lib/atlas/atlas.db node server/index.js
ATLAS_DB sets the database path, ATLAS_FETCH_TIMEOUT the link-lookup timeout in
milliseconds. The database is a single SQLite file; back it up by copying it.
The Atlas runs on a SQLite file and needs nothing else. Point it at a Supabase project and that project becomes the durable copy — the place the research lives, outliving any one machine and readable by anything else you point at it — while SQLite stays the working copy the map is drawn from. Every read the map makes is synchronous, and a map that waits on the network for each of them is not a map you can drag, so the two are kept in step rather than swapped:
There is no client library, only fetch against PostgREST, which is the API Supabase
already exposes — so the install story is the same as it ever was.
Setting it up is walked through step by step in docs/supabase.md,
which offers two routes: filling a project from the browser alone — paste
supabase/schema.sql then supabase/seed.sql
into the SQL editor, no terminal and no keys handled — or connecting a running Atlas so
that new sources go up as they arrive.
The short version: run supabase/schema.sql once in the project's
SQL editor, then put two values in a .env file next to package.json:
SUPABASE_URL=https://<project-ref>.supabase.co
SUPABASE_SERVICE_ROLE_KEY=<the service role key>
The service role key writes and must never reach a browser — that machine and nowhere
else. The anon key can only read, and is the one to hand to anything public. .env is
git-ignored and .env.example shows the shape; it is read automatically,
and anything already set in the environment wins over it, which is how a hosted server
should be configured.
npm run supabase check # does the project answer, and are the tables there
npm run supabase push # send this machine's library up — the first fill
npm run supabase pull # bring the project's library down
With the variables unset none of this runs and nothing changes.
See CONTRIBUTING.md, and docs/design-notes.md for why the map looks the way it does.
Code is MIT. Bibliographic records — titles, links, tags — are offered under CC0; the
works they point at remain with their authors. The bundled typefaces are not MIT —
see public/fonts/README.md.