Overview
Knowledge kept as linked notes is only useful if the links can be seen and followed. Parallelepiped opens any folder of Markdown files as a vault and keeps the files themselves as the only source of truth: there is no proprietary format and no import step. On top of them it builds an index of links, tags and text, and uses it for backlinks, search and a 3D graph that can be rotated, zoomed and hovered to light up a note's connections. It can also read a code repository and generate a linked map of its modules, so a project without documentation can be explored the same way. It is an original personal project, not a fork of an existing application.
My contribution
I am the sole author. I designed the module boundaries and wrote the Go backend — vault, notes, index, file watcher and the structural import — with the SQLite schema and its migrations; the TypeScript frontend with the editor, the context column and the 3D graph, including the neuron geometry and its rendering optimisations; the light and dark themes and the app icon; and the Makefile, tests and architecture documentation.
The project exercises two things I care about: a layered modular monolith applied outside the HTTP world, and interactive graphics that stay fast without giving up how they look.
Architecture
One executable. The frontend runs in the system's WebView2 and calls the Go backend through Wails bindings. The backend is a modular monolith: five business modules, each split into handler, service, model, repository and DTO, with cross-cutting concerns in a separate platform layer. Modules talk to each other only through small interfaces defined by the consumer.
internal/modules,
internal/platform and frontend/src directories.
Code layout
main.gois the composition root: it builds the repositories, services and handlers and binds them to Wails.internal/modulesholds vault, notes, index, watcher and brain, each with handler, service, model, repository and DTO.internal/platformholds the error catalogue, field validation, database, logging and the desktop bridge.migrations/keeps the versioned index schema at the root, embedded in the binary.frontend/srcseparates the views (tree, tabs, editor, context, graph) from the API client and the shared colour and theme modules.
Stack
- Backend: Go with Wails v2, a pure-Go SQLite driver with FTS5, and fsnotify for the folder watcher.
- Frontend: TypeScript and Vite, CodeMirror 6 for the editor.
- Graph: 3d-force-graph on three.js, with custom neuron geometry and a bloom pass in the dark theme.
- Interface: an original layout with a light and a dark theme, folder colours shared by every view.
- Delivery: a single executable built from a Makefile, with an optional NSIS installer.
Engineering decisions
Three decisions that shaped the project, each with the alternative considered and what it costs.
1. The files are the source of truth; the database is a cache
- Decision:
- notes are ordinary
.mdfiles written atomically (temporary file, then rename). The SQLite index of links, tags and text lives outside the vault and can be deleted and rebuilt from the files at any time; if an index update fails after a save, the save stands and the failure is logged. - Alternative:
- store the notes in the database and export Markdown on demand.
- Reason:
- the user's notes stay readable and editable with any tool, under any version control, without the app. Because the index is derived and single-user, its migrations can safely run when it is opened — a deliberate exception to the usual rule, documented in the architecture notes.
- Limitation:
- the index can briefly disagree with the disk, and anything outside the files — such as the layout of the graph — is not stored with the notes.
2. Recognise the app's own writes by content hash, not by a time window
- Decision:
- the watcher waits for each path to be quiet for 300 ms, then reads it from disk. It keeps the hash of the content it last indexed; when the disk holds exactly that content, the event came from the app itself and is dropped.
- Alternative:
- ignore every event for a short time after the app saves a note.
- Reason:
- a time window either swallows a real external edit made just after a save or lets the app's own save trigger a reindex. Comparing content has no window: an outside edit is always picked up, and the app's own saves never cause extra work.
- Limitation:
- removed or renamed folders, and lost events, still fall back to rebuilding the whole vault index.
3. Make the graph faster without changing a pixel
- Decision:
- the graph renders on demand — while the layout settles, the camera moves or the pointer is active — and pauses after 1.5 seconds of inactivity. Hovering a neuron restyles only the fibres that touch it and the one hovered before, updating their meshes in place.
- Alternative:
- simplify the scene — merge the fibres into flat lines or drop the tube geometry — to cut the cost.
- Reason:
- the visual style is the point of the feature, and a simplified version was rejected as soon as it was seen. The library re-created every link on each hover; restyling only the affected ones took a hover on a vault of about 860 links from roughly 150 ms to 7 ms, and the result was checked to be identical to the library's own output.
- Limitation:
- the optimisation depends on internals of the graph library, so upgrading it needs that equivalence check repeated.
Quality, safety and cost
Everything below is in the public repository and can be checked against the source. The measured figures come from a single development machine and are not a guarantee for other hardware.
Tests
- 13 Go test files with 49 test functions across the models, services and repositories of every module.
- They cover link parsing, the index queries, the watcher's debounce and write ledger, and the structural import's analysis and re-import rules.
make checkrunsgo vet, the Go tests and the TypeScript type check.
Safety of the user's notes
- Deleting a note moves it to a
.trashfolder inside the vault, with the date in the name; the app never deletes a file permanently. - The structural import only overwrites notes it generated itself, marked in their front matter; the “Minhas anotações” (my notes) section of each generated note survives every re-import.
- Errors cross to the frontend in one envelope with a code and field messages; internal details stay in the log.
Footprint
- A single executable of about 18 MB, with no runtime to install on Windows 11, which ships WebView2.
- The graph stops drawing while it is idle or hidden, and draws at the screen's native resolution without supersampling.
- Hovering a neuron costs about 7 ms on a vault of about 860 links.
Results and limitations
What exists today is a working application: tabs and an editor with link autocompletion; a context column
with a 2D mini-map of the note's neighbourhood, backlinks, outgoing links and tags; full-text search;
folder colours shared by every view; a 3D graph with a graph-only mode; light and dark themes; an index
kept in step with edits made outside the app; and a structural import that turns a code repository into
linked notes inside its own docs/ folder.
Stated limitations
- Only Windows 11 has been verified. Wails can target other systems, but no other platform has been built or tested.
- Renaming a note does not rewrite the links that point to it, and there is no rendered live preview yet; both are next on the roadmap, with sandboxed WebAssembly plugins after them.
- The structural import is static. It reads packages, exported symbols and imports for Go and relative imports for TypeScript and JavaScript; it does not understand what the code does.
- The executable is not code-signed, so SmartScreen may warn on first run.
- There is no real-world usage data. This is a personal project; I am not claiming users, downloads or adoption.
Explore
The repository is public and includes the README with the build instructions, the architecture document, and the contributing guide, code of conduct and security policy.
The repository documentation and the application interface are in Portuguese. The video and screenshots use a fictional demo vault.
Gallery
Captures of the demo vault — select an image to enlarge it and browse the gallery.
The 3D graph in graph-only mode: each note is a neuron, coloured by folder and sized by its links.
A note with its context: neighbourhood mini-map, backlinks, outgoing links and tags.
The same graph in the light theme.
The editor in the light theme, after a link was added with autocompletion.