| title | README |
|---|
A Jekyll-based knowledge base with an interactive hypertext graph. Write notes in Markdown, link them with [[wikilinks]], and browse the result as a force-directed graph in the browser. Inspired by Foam.
Preview: https://yjmantilla.github.io/jekyll-hypertext-network/
- Python 3 (
pyyaml— install withpip install pyyaml) - Ruby + Bundler (
gem install github-pagesorbundle install)
bash make.shThis runs two steps in sequence:
python gen_static_data.py— scans all Markdown files, builds the graph JSON, and populates_data/anddirs/.bundle exec jekyll serve— builds the site and serves it athttp://localhost:4000.
You must re-run gen_static_data.py any time you add, remove, or rename a note file.
Create .md files in the notes/ folder (or any category folder you add). Each file must have YAML front matter with at least a title:
---
title: My Note
---
Content goes here. Link to another note with [[other-note-filename]].- Links use the filename without extension:
[[node1]]links tonotes/node1.md. - If the referenced file does not exist, the link points to
stub.mdinstead. - Filenames must be unique across the entire repo (even across subdirectories).
Obsidian Clipper can clip web pages as Markdown files directly into a folder. Point it at the sources/ directory to save articles, pages, and excerpts as notes you can then link with [[wikilinks]].
To add a new category (e.g. books/):
-
Create the folder and put your
.mdfiles in it. -
Create a listing page at
dirs/books.md:*Note that i think this might be automated in gen_static_data.py
--- title: Books --- <ul> {% for item in site.data.books-list %} <li><a href="{{ item._link }}">{{ item.title }}</a></li> {% endfor %} </ul>
-
Register it in
gencfg.ymlundercollect_stuff:collect_stuff: - ['notes', '.md'] - ['sources', '.md'] - ['books', '.md'] # add this line - ['dirs', '.md', ['dirs']]
-
Run
gen_static_data.pyagain — it will create_data/books-list.ymland regenerate the graphs.
If you want the
booksdirectory node itself excluded from the graph (likenotesandsourcesare), add'books'toignore_eqingencfg.yml.
| Field | Description |
|---|---|
GRAPHS_URL_RULE |
[from, to] substitution applied to file paths when building node URLs for the graph JSON. Default converts ./ to ./../ so paths are correct relative to the graphs/ folder. |
SUBDIRS_URL_RULE |
Same substitution for subdirectory graph variants. |
out_extension |
Extension appended to node URLs. Empty string means URLs have no extension (Jekyll serves them without .html). |
BEGIN / END |
Delimiters wrapping the autogenerated link-reference block at the bottom of each .md file. These allow [[wikilinks]] to render as proper Markdown links in standard editors. |
ignore_in |
Directory name fragments to skip when scanning for files (e.g. _site, .github). Any path containing one of these strings is excluded. |
ignore_eq |
Node IDs to drop from the graph entirely (exact match). Useful for category folders like notes and sources that would otherwise appear as ghost nodes. |
ignored_attributes |
Front matter keys excluded from the ontology file (attributes.md). |
ignored_substring |
Front matter keys whose names contain any of these substrings are excluded from the ontology. |
ontology_name |
Filename (without .md) for the generated attribute ontology page. |
ontology_only_ignore |
Additional keys excluded only in the ontology (not from the graph). |
collect_stuff |
List of [folder, extension] (or [folder, extension, ignore_list]) entries. For each entry the script creates _data/<folder>-list.yml and regenerates dirs/<folder>.md. |
jekyll-hypertext-network/
├── notes/ # Your knowledge base notes
├── sources/ # Curated external content
├── dirs/ # Category listing pages (some auto-generated)
├── graphs/ # Graph viewer pages + generated JSON
│ ├── graph.json # (generated) flat graph
│ └── graph-subdirs.json # (generated) graph with categories
├── _data/ # (generated) YAML lists for Jekyll templates
├── _includes/ # JS graph component and feature loaders
├── attributes.md # (generated) ontology of all front matter values
├── stub.md # Fallback page for broken links
├── gencfg.yml # Configuration for gen_static_data.py
├── gen_static_data.py # Static data generation script
└── make.sh # Build + serve shortcut
- Filenames are unique across all directories (e.g.
notes/a.mdandsources/a.mdcannot coexist). - Notes are at most one subdirectory deep:
root/subdir/note.mdis fine, deeper is not. - Every note has front matter with at least
title. - Do not use
[[double brackets]]in text unless it is meant as a wikilink. - Use this repo as a template rather than forking it — GitHub limits forks per account.
- For pasting images in VSCode, vscode-paste-image is recommended (configure the image output path to
assets/).
---
title: My Note Title
type: concept # concept | paper | method | person | question | project | log
tags: [tag1, tag2]
status: stub # stub | draft | note | evergreen
------
title: My Note Title
type: paper
tags: [tag1, tag2]
status: note
source: https://doi.org/... # URL, DOI, or citation
authors: [Author A, Author B]
year: 2024
venue: Nature # journal or conference
read: reading # unread | reading | read | reviewed
---| Field | Used in | Values / notes |
|---|---|---|
title |
all | Required. Displayed in graph and search. |
type |
all | concept, paper, method, person, question, project, log |
tags |
all | Freeform list. Drives clustering in the graph. |
status |
all | stub → draft → note → evergreen |
source |
academic | URL, DOI, or free-text citation. |
authors |
academic | List of author names. |
year |
academic | Publication year (integer). |
venue |
academic | Journal name or conference acronym. |
read |
academic | unread, reading, read, reviewed |
categoryis auto-derived from the directory — do not set it manually.created/modifieddates are omitted intentionally — git history is the source of truth.- Any field you add consistently becomes a filterable attribute in the knowledge graph (via
attributes.md).