Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ Flat legacy redirects, such as `/docs/obsidian/<slug>` to `/docs/obsidian/<secti

Use existing Nextra Markdown, MDX, and `nextra/components` features for styling and layout before proposing anything custom. For example, use Nextra callouts, cards, steps, tabs, tables, and file trees when those fit the content.

For discourse candidate tag pills, use the existing global MDX component: `<NodeTag type="clm" />`, `<NodeTag type="evd" />`, or `<NodeTag type="que" />`. Allowed `type` values are `que`, `clm`, `evd`, `src`, `hyp`, `res`, and `iss`. Use a `.mdx` file when a page needs `NodeTag`, and do not add one-off tag styling or CSS.

If the docs need a styling or presentation feature that Nextra does not currently provide, create a separate Linear ticket to add that Nextra functionality. Do not include theme, layout, route, component, or CSS changes in a content-only docs update.

Preferred: Use the `$update-user-docs` skill to update plugin docs. Detailed guidance for plugin docs lives next to the `$update-user-docs` skill:
Expand Down
8 changes: 8 additions & 0 deletions apps/website/app/(nextra)/nextra-css.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
--nextra-content-width: 90rem;
}

.docs-bordered-image {
display: block;
max-width: 100%;
height: auto;
border: 1px solid rgb(203 213 225);
margin-top: 1.25em;
}

.nextra-reset,
.nextra-search-results {
--nextra-primary-hue: 212deg;
Expand Down
57 changes: 57 additions & 0 deletions apps/website/app/components/docs/NodeTag.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import type { CSSProperties, ReactElement, ReactNode } from "react";

const NODE_TAG_COLORS = {
que: "#99890E", // Question
clm: "#7DA13E", // Claim
evd: "#DB134A", // Evidence
src: "#3B82F6", // Source
hyp: "#8CE99A", // Hypothesis
res: "#4DABF7", // Result
iss: "#E599F7", // Issue
} as const;

export type NodeTagType = keyof typeof NODE_TAG_COLORS;

const NODE_TAG_TYPES = Object.keys(NODE_TAG_COLORS) as NodeTagType[];

const isNodeTagType = (type: unknown): type is NodeTagType =>
typeof type === "string" && type in NODE_TAG_COLORS;

const getTextColor = (backgroundColor: string): string => {
const hex = backgroundColor.replace("#", "");
const r = parseInt(hex.slice(0, 2), 16);
const g = parseInt(hex.slice(2, 4), 16);
const b = parseInt(hex.slice(4, 6), 16);

return (0.299 * r + 0.587 * g + 0.114 * b) / 255 > 0.5
? "#000000"
: "#FFFFFF";
};

type NodeTagProps = {
type: NodeTagType;
children?: ReactNode;
};

export const NodeTag = ({ type, children }: NodeTagProps): ReactElement => {
if (!isNodeTagType(type)) {
throw new Error(
`Invalid NodeTag type "${String(type)}". Expected one of: ${NODE_TAG_TYPES.join(", ")}.`,
);
}

const backgroundColor = NODE_TAG_COLORS[type];

const style: CSSProperties = {
backgroundColor,
color: getTextColor(backgroundColor),
padding: "1px 10px",
borderRadius: "999px",
fontSize: "0.85em",
fontWeight: 500,
display: "inline-block",
whiteSpace: "nowrap",
};

return <span style={style}>{children ?? `#${type}-candidate`}</span>;
};
11 changes: 7 additions & 4 deletions apps/website/content/obsidian/use-cases/_meta.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import type { MetaRecord } from "nextra";

const meta: MetaRecord = {
"literature-reviewing": "Literature review",
"research-roadmapping": "Research notes",
"reading-clubs": "Reading clubs and seminars",
"lab-notebooks": "Lab notebooks",
"build-utilize-personal-knowledge-base":
"Build and Utilize a Personal Knowledge Base",
"synthesize-insights-from-literature":
"Synthesize Insights from the Literature",
"share-your-ideas-and-research": "Share your ideas & research",
"track-your-projects-and-experiments": "Track your Projects and Experiments",
"experiment-tracking": "Experiment Tracking",
};

export default meta;
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
---
title: "Build and Utilize a Personal Knowledge Base"
date: "2026-06-29"
author: ""
published: true
---

import Image from "next/image";
import { Callout } from "nextra/components";

## Turn your tsundoku pile into a knowledge base with discourse graphs

<Image
src="/docs/obsidian/tsundoku.png"
alt="tsundoku pile"
width={195}
height={302}
className="docs-bordered-image"
/>

_Candidate for saddest short poem_

Many researchers have established pipeline for accumulating potentially useful evidence and insights, but fewer ways of managing and exploiting these resources.

The [discourse graph protocol](/docs/obsidian/fundamentals/what-is-a-discourse-graph) can be used to drive more intentional note taking and to accentuate serendipitous discovery within existing knowledge bases.

## Startup

If you're already using Obsidian or Roam Research or another PKM platform, your first question might be _"Can I integrate discourse graphs into my existing knowledge base?"_

For Obsidian (& Roam), the answer is **yes**. Your discourse nodes can coexist with your existing graph: the two major considerations for a smooth integration are _organizational preferences_ and _vault size_.

### Vault organization

If you are a **"folder-centric"** Obsidian user, we recommend keeping your discourse graph an folder within your vault.

<Image
src="/docs/obsidian/left-sidebar.png"
alt="left sidebar"
width={330}
height={403}
className="docs-bordered-image"
/>

The Discourse Graph plugin lets you configure a default folder (or per-node-type folders) for discourse nodes in its settings, independent of Obsidian's own "Default location for new notes" setting.

So Obsidian's **"Default location for new notes"** setting (in `Settings → Files & Links`) can control where non-discourse notes go while the plugin routes new nodes to its own folder.

```
vault/
├── Discourse Graph/
│ ├── Questions/
│ ├── Claims/
│ └── Evidence/
└── Notes/ ← regular notes land here
```

As you convert more of your existing notes to discourse nodes via the plugin's **"Convert note to discourse node"** command, move these notes to the configured discourse folder.

If you're a **"graph-centric"** vault user, following Obsidian wiki-linking and discourse graph [relation-creating](/docs/obsidian/core-features/creating-discourse-relationships) practices will allow you to navigate a vault of arbitrary size without getting lost in unrelated material.

As you build out your graph, your discourse nodes will begin to form "paths of desire" around the central Questions in your vault.

<Image
src="/docs/obsidian/graph-view02.png"
alt="graph view"
width={971}
height={924}
className="docs-bordered-image"
/>

<Callout type="info" emoji="💡">
**Graph Gardening:** Add a random note picker to your vault to get in the
habit of reviewing older notes for potential conversion to discourse nodes.
</Callout>

### Managing a large vault

"Vanilla" Obsidian accommodates very large vaults with very few issues. Vault size usually only becomes a problem when you're running many script-heavy plugins at once.
If you're an Obsidian power user you may already be using a plugin like [Dataview](https://blacksmithgu.github.io/obsidian-dataview/) to run queries over your vault. The discourse graph plugin uses [Datacore](https://github.com/blacksmithgu/datacore) to power its queries, which is even more performant in large vaults than Dataview. These two plugins can both be used in the same vault, but we recommend keeping an eye on your plugin count to optimize vault load time.

## Transforming existing notes into discourse nodes

You can transform a variety of file types into discourse nodes:

- [readwise](https://readwise.io/) snippets
- [memex](https://memex.garden/) imports
- screenshots
- captures from the [Obsidian web clipper](https://obsidian.md/clipper).
- articles from [Zotero](/docs/obsidian/use-cases/synthesize-insights-from-literature), etc.

As long as it can be referenced (`[filename]`) in a markdown file with the appropriate frontmatter, it can be part of your discourse graph.

<Image
src="/docs/obsidian/clipping01.png"
alt="Obsidian web clipper"
width={853}
height={713}
className="docs-bordered-image"
/>

_This web clipping has been converted into a Source_

<Image
src="/docs/obsidian/img-clm02.png"
alt="image to CLM"
width={773}
height={864}
className="docs-bordered-image"
/>

_This web screenshot has been converted into a Claim_

### Best practices for node conversion

The goal of transforming a **note** into a dg **node** is to preserve as much context and information as possible while orienting the content toward the questions animating your research -- or at least positioning it so that it suggests additional discourse nodes.

First, paraphrase the key insight of the note and record the source of the insight. This paraphrase is your new discourse node/filename. The rest of the note will become a **Source** node where the remaining note text can be retained as additional context for the insight. You might extract several discourse nodes or [candidate nodes](/docs/obsidian/core-features/node-tags) from a single web-clipped article, but breaking it out into a single DG node + SRC is enough to get started.

<Image
src="/docs/obsidian/clm-clip02.png"
alt="claim"
width={744}
height={832}
className="docs-bordered-image"
/>

_CLM node with SRC node attributing a blog_

In the above image, you can see the a second related Claim and its Source has already been extracted from the same web clipping. If you decide to pursue this topic further, you've already identified another Source node to investigate (Klein _et al._)

Adding `[[wiki-links]]` to key terms will keep your new node in conversation with the rest of your vault as you build your graph. This can help you to find appropriate [discourse relations](/docs/obsidian/core-features/creating-discourse-relationships) later.

<Image
src="/docs/obsidian/src-node-clip.png"
alt="source"
width={517}
height={759}
className="docs-bordered-image"
/>

_This SRC node from a web clipping is linked to the rest of the vault_

As you go through your vault, you might find that certain sources are accumulating multiple mentions in your graph. Identifying especially productive sources can help you to decide how to allocate your attention.

Of course you may be the author of many of the original notes in your vault -- in that case, we suggest retaining the relevant contextual information on the QUE/CLM/EVD node itself -- but remember to create a Source node for yourself!

<Image
src="/docs/obsidian/drmanhattan.png"
alt="self-cite"
width={640}
height={801}
className="docs-bordered-image"
sizes="350px"
style={{ width: 350 }}
/>

### Progressive formalization

The goal is to gradually convert most of your existing notes into a graph of interlinked CLM, QUE, or EVD nodes.

You can jumpstart the process by identifying [candidate nodes](/docs/obsidian/core-features/node-tags) in your existing notes, and revisiting these notes to decide which nodes should be promoted to full-fledged discourse nodes. The trigger for such a promotion is identifying their relevance to one of your research questions, or finding a potential [discourse relation](/docs/obsidian/core-features/creating-discourse-relationships) elsewhere in your graph.

<Image
src="/docs/obsidian/graph-view01.png"
alt="the graph"
width={786}
height={795}
className="docs-bordered-image"
/>

_So much room for activities!_

## Creating new discourse nodes

Build out your discourse graph by reading with an eye to capturing information relevant to your current questions or that inspires new questions.

<Image
src="/docs/obsidian/new-node01.png"
alt="web clipping"
width={498}
height={668}
className="docs-bordered-image"
/>

_Here's a [web clipping](https://obsidian.md/clipper) captured with an eye to turning it into a CLM node - the Obsidian web clipper helpfully captures the source in the frontmatter_

<Image
src="/docs/obsidian/new-node02.png"
alt="claim node"
width={544}
height={772}
className="docs-bordered-image"
/>

_... and here's the CLM node. Note that it's linked to 3 sources: one named after the article url where the full text is captured, one to the author, & one to the author's institution -- this reflects the organizational preferences of the vault owner; a single SRC node can contain all this information_

This habit of intentional reading is a great way to nudge yourself toward [contributing to the public conversation](/docs/obsidian/use-cases/share-your-ideas-and-research).

<Image
src="/docs/obsidian/cat-meme.png"
alt="you should start a blog"
width={454}
height={327}
className="docs-bordered-image"
/>

If you're using a highlighter like [memex](memex.garden) or the [Obsidian web clipper](https://obsidian.md/clipper), you can

1. highlight the relevant text
2. bring it into your vault via the tool's import feature or copy-paste
3. Select `Convert into` from the file window menu to turn it into a discourse node

<Image
src="/docs/obsidian/convert-menu.png"
alt="convert menu"
width={1016}
height={843}
className="docs-bordered-image"
/>

<Image
src="/docs/obsidian/memex-res.png"
alt="memex highlight"
width={771}
height={413}
className="docs-bordered-image"
/>

_Result node spotted in the wild_

Similarly, plugins like [Zotsidian](https://github.com/Qiwei-Zhao/zotsidian) enable you to import items from your reference manager pre-formatted as Sources.

<Image
src="/docs/obsidian/zot-import.png"
alt="readymade Source"
width={776}
height={889}
className="docs-bordered-image"
/>

After you've captured capture a few ideas, you can mark those that you might want to add to your graph later as [candidate nodes](/docs/obsidian/core-features/node-tags). The _progressive formalization_ ethos of the discourse graph protocol also applies to the process of deciding how to direct your attention: you can have a number of leads on potential projects active at once, and decide which ones to curate further later.

<Image
src="/docs/obsidian/bullet-journal.png"
alt="bullet journal"
width={763}
height={384}
className="docs-bordered-image"
/>

_Bullet Journal with candidate nodes in a [Daily Notes](https://obsidian.md/help/plugins/daily-notes) page_

## What else would you like to do?

- [Synthesize Insights from the Literature](/docs/obsidian/use-cases/synthesize-insights-from-literature)
- [Track your Projects and Experiments](/docs/obsidian/use-cases/track-your-projects-and-experiments)
- [Share your ideas & research](/docs/obsidian/use-cases/share-your-ideas-and-research)
Loading