Skip to content
Closed
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
33 changes: 33 additions & 0 deletions apps/website/app/(docs)/docs/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Link from "next/link";
import Image from "next/image";

export default function DocsPage() {
return (
<main className="flex min-h-screen w-full items-center justify-center lg:pl-72">
<div className="space-y-4 text-center">
<h1 className="text-4xl font-bold tracking-tight text-slate-900 dark:text-white">
Future Home of All the Docs
</h1>
<p className="text-lg text-secondary">
For now, here are the{" "}
<Link href={"docs/roam"} className="underline">
Roam Docs{" "}
</Link>
</p>
<div className="mt-8 flex items-center justify-center gap-4">
<button>
<Link href="https://github.com/DiscourseGraphs">
<Image
src="/github.svg"
alt="GitHub"
width={24}
height={24}
className="opacity-80 transition-opacity hover:opacity-100"
/>
</Link>
</button>
</div>
</div>
</main>
);
}
92 changes: 92 additions & 0 deletions apps/website/app/(docs)/docs/roam/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import fs from "fs/promises";
import path from "path";
import { notFound } from "next/navigation";
import { Metadata } from "next";
import { DocsHeader } from "~/components/DocsHeader";
import { Prose } from "~/components/Prose";
import { collectSections } from "~/utils/sections";
import { TableOfContents } from "~/components/TableOfContents";
import { getMarkdownPage } from "~/utils/getMarkdownFile";

type Params = {
params: Promise<{
slug: string;
}>;
};

const PATH = "app/(docs)/docs/roam/pages";
const DIRECTORY = path.join(process.cwd(), PATH);

export default async function Page({ params }: Params) {
try {
const { slug } = await params;
const { data, contentHtml } = await getMarkdownPage({
slug,
directory: DIRECTORY,
});
const tableOfContents = await collectSections(contentHtml);

return (
<>
<div className="min-w-0 max-w-2xl flex-auto px-4 py-8 lg:max-w-none lg:pl-8 lg:pr-0 xl:px-16">
<article className="[&::-webkit-scrollbar]:hidden">
<DocsHeader title={data.title} />
<Prose>
<div dangerouslySetInnerHTML={{ __html: contentHtml }} />
</Prose>
</article>
{/* <PrevNextLinks /> */}
</div>
<TableOfContents tableOfContents={tableOfContents} />
</>
);
} catch (error) {
console.error("Error rendering docs page:", error);
return notFound();
}
}

export async function generateStaticParams() {
try {
const directoryExists = await fs
.stat(DIRECTORY)
.then((stats) => stats.isDirectory())
.catch(() => false);

if (!directoryExists) {
console.log("No docs directory found");
return [];
}

const files = await fs.readdir(DIRECTORY);

return files
.filter((filename) => filename.endsWith(".md"))
.map((filename) => ({
slug: filename.replace(/\.md$/, ""),
}));
} catch (error) {
console.error("Error generating static params:", error);
return [];
}
}

export async function generateMetadata({ params }: Params): Promise<Metadata> {
try {
const { slug } = await params;
const { data } = await getMarkdownPage({
slug,
directory: DIRECTORY,
});

return {
title: data.title,
authors: [{ name: data.author }],
};
} catch (error) {
console.error("Error generating metadata:", error);
return {
title: "Docs",
};
}
}
10 changes: 10 additions & 0 deletions apps/website/app/(docs)/docs/roam/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Layout } from "~/components/Layout";
import { navigation } from "./navigation";

export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return <Layout navigationList={navigation}>{children}</Layout>;
}
80 changes: 80 additions & 0 deletions apps/website/app/(docs)/docs/roam/navigation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { NavigationList } from "~/components/Navigation";

const ROOT = "/docs/roam";

export const navigation: NavigationList = [
{
title: "🏠 Welcome!",
links: [
{ title: "Getting Started", href: `${ROOT}/getting-started` },
{ title: "Installation", href: `${ROOT}/installation` },
],
},
{
title: "🗺️ GUIDES",
links: [
{
title: "Creating Nodes",
href: `${ROOT}/creating-discourse-nodes`,
},
{
title: "Creating Relationships",
href: `${ROOT}/creating-discourse-relationships`,
},
{
title: "Exploring",
href: `${ROOT}/exploring-discourse-graph`,
},
{
title: "Querying",
href: `${ROOT}/querying-discourse-graph`,
},
{
title: "Extending",
href: `${ROOT}/extending-personalizing-graph`,
},
{
title: "Sharing",
href: `${ROOT}/sharing-discourse-graph`,
},
],
},
{
title: "🧱 FUNDAMENTALS",
links: [
{
title: "What is a Discourse Graph?",
href: `${ROOT}/what-is-discourse-graph`,
},
{
title: "Grammar",
href: `${ROOT}/grammar`,
},
],
},
{
title: "🚢 USE CASES",
links: [
{
title: "Literature Reviewing",
href: `${ROOT}/literature-reviewing`,
},
{
title: "Zettelkasten",
href: `${ROOT}/enhanced-zettelkasten`,
},
{
title: "Reading Clubs / Seminars",
href: `${ROOT}/reading-clubs`,
},
{
title: "Lab notebooks",
href: `${ROOT}/lab-notebooks`,
},
{
title: "Product / Research Roadmapping",
href: `${ROOT}/research-roadmapping`,
},
],
},
];
13 changes: 13 additions & 0 deletions apps/website/app/(docs)/docs/roam/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { redirect, notFound } from "next/navigation";
import { navigation } from "./navigation";

export default function Page() {
const firstSection = navigation[0];
const firstLink = firstSection?.links[0];

if (!firstLink?.href) {
notFound();
}

redirect(firstLink.href);
}
27 changes: 27 additions & 0 deletions apps/website/app/(docs)/docs/roam/pages/base-grammar.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
title: "Base Grammar"
date: "2025-01-01"
author: ""
published: true
---

## Base grammar

This is what ships with the extension.

### Nodes

- QUE - Question
- CLM - Claim
- EVD - Evidence
- Source

### Relations

- EVD Informs QUE
- EVD Supports CLM
- EVD Opposes CLM

Motivation for this base grammar is described in this [article](https://oasislab.pubpub.org/pub/54t0y9mk/release/3).

This base grammar may be most useful for projects that interact with empirical evidence where you want to clearly distinguish between theory and evidence, and retain provenance to the source citations if you want to get more context.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
title: "Creating Discourse Nodes"
date: "2025-01-01"
author: ""
published: true
---

The extension makes it easy to factor parts of your notes into formal of a discourse graph (claims, evidence, etc.).

Steps to create a discourse graph node:

1. Select the text you want to turn into a formal discourse graph node
2. Press the trigger hotkey (default is `\`) to open up the Node Menu
3. Press the appropriate shortcut key (e.g., E for Evidence)

The system will create a new page with the text as title, appropriate metadata, and template you have defined.

## Demo

https://www.loom.com/share/471fcf7dc13246439cb35feedb110470

You can customize the template for specific nodes in the Settings Panel.

![](/docs/roam/node-template.png)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
title: "Creating Discourse Relationships"
date: "2025-01-01"
author: ""
published: true
---

One of the main features of the Discourse Graph extension is the ability to **create formal discourse relations between nodes just by writing and outlining!**

The extension has an in-built [grammar](./grammar) that enables it to recognize when certain patterns of writing and outlining are meant to express particular discourse relations (e.g., support, oppose, inform) between discourse nodes. When it recognizes these patterns, it "writes" them to a formal discourse graph data structure, that you can then use to explore or query your discourse graph.

## Stock Patterns

- Take a look at [Relations Patterns](./relations-patterns)

### Verifying relations

You can verify any created relations by checking the [discourse context](./discourse-context) of the claim, evidence, or question page.

Or by running a [query](./querying-discourse-graph) for the specific relation.

## Digging deeper

Want to recognize other patterns that aren't listed here? Or don't like these? You can [change them](./extending-personalizing-graph)! But you might first want to [understand how the grammar works](./grammar).
65 changes: 65 additions & 0 deletions apps/website/app/(docs)/docs/roam/pages/discourse-attributes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
title: "Discourse Attributes"
date: "2025-01-01"
author: ""
published: true
---

- [Discourse Context](./discourse-context)
- [Discourse Context Overlay](./discourse-context-overlay)
- [Discourse Attributes](./discourse-attributes)
- [Node Index](./node-index)

## Define Discourse Attributes

You can define discourse attributes that for each discourse node, which compute a numerical "score" for each instance of the node based on its discourse relations to other nodes. In the extension, we call these **discourse attributes**.

These attributes can be handy for sorting/querying nodes. For instance, if you create a discourse attribute for Claim nodes that is a function of the number of Evidence nodes that Support the Claim, like this:

![](/docs/roam/settings-discourse-attributes.png)

You can add discourse attributes as a column to display and sort/filter by when [Querying your discourse graph](./querying-discourse-graph.md) by adding a `Discourse:{label}` selection.

For example, in the index for Claims, you can return the Evidence attribute as a column (Select), and then sort in descending order by that attribute.

## Basic Discourse Relation Functions

A discourse attribute consists of one or more **discourse functions**, joined by one or more math operations. You can think of the discourse functions as variables that get their value from some discourse relations the node participates in.

Here is the template for each discourse function: `{count:relationName:targetType}`

- `count` is the operation. Atm, this is the only supported operation for basic discourse functions. We also have experimental discourse functions that operate over the discourse attributes of related nodes (see below), which allow for other operations such as `sum` and `average`
- `relationName` is the name of the relation you want to use for the function, such as `Supported By` or `Informed By`
- `targetType` is the name of the type of target of the relation you want to use for the function (since nodes can have relationships of the same name with multiple other nodes, such as `Supported By:Claim` or `Supported By:Evidence`)

Here are some examples:

- `{count:Supported By:Evidence}`
- `{count:Informed By:Source}`
- `{count:Opposed By:Claim}`

You can use basic math operations to combine multiple discourse functions. For example, you might want to combine information across the supporting and opposing relationships to gauge how "robust" a Claim is, and give different weights to support from evidence vs. claims. You could express it like this:

`{count:Supported By:Evidence} + {count:Supported By:Claim}*0.5 - {count:Opposed By:Evidence} - {count:Opposed By:Claim}*0.5`

This function sums up the number of supporting relations and subtracts the number of opposing relations, but gives only half weight (`*0.5`) to supporting/opposing relations from Claims.

## Compound Discourse Functions

We have an experimental feature that allows us to access discourse attributes from related nodes to compute a discourse attribute. This allows us to experiment with more sophisticated ways to reason over our discourse nodes.

For example, if a Claim that only gets direct support from other Claims (e.g., because it is quite general), we might care to distinguish if its supporting Claims are themselves also supported by Evidence.

If each Claim node has a discourse attribute called Evidence that looks like this:

`{count:Supported By:Evidence} - {count:Opposed By:Evidence}`

We can define a compound discourse function that _averages_ over the Evidence attribute of Claims that support the Claim. Like this:

`{average:Supported By:Claim:Evidence}`

The syntax for these compound discourse functions is:

`{operation:relationName:targetType:targetDiscourseAttribute}`

This generalizes the syntax for the basic discourse functions by adding a discourse attribute to access from the targets, and the option of using additional operations than `count` (for now, we only support `sum` and `average`) for the function.
Loading