Skip to content
Merged
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
19 changes: 11 additions & 8 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ If MCP is already configured, you have these tools available — no CLI needed:

| Tool | Auth? | Description |
|------|:---:|-------------|
| `graspful_create_academy` | No | Generate academy manifest YAML |
| `graspful_create_academy` | No | Generate academy plan and manifest YAML |
| `graspful_scaffold_course` | No | Generate course YAML skeleton |
| `graspful_fill_concept` | No | Add KPs and problems to a concept |
| `graspful_validate` | No | Validate YAML against schema |
Expand Down Expand Up @@ -70,7 +70,7 @@ This creates an account, org, and API key through browser auth. To use MCP tools

### Step 3: Build a course

The workflow is: scaffold -> fill -> validate -> review -> import.
The workflow is: academy plan -> course graphs -> fill -> validate -> review -> import.

**Before writing any YAML**, follow the detailed runbook in `docs/adding-a-course.md`. Key steps:
1. Gather source material (official docs, syllabi, PDFs — not marketing copy)
Expand All @@ -83,22 +83,25 @@ The workflow is: scaffold -> fill -> validate -> review -> import.
8. Validate and review

```bash
# 1. Scaffold the academy shell
# 1. Scaffold the academy plan
graspful create academy --topic "Your Topic" -o academy.yaml

# 2. Scaffold the first course knowledge graph
# 2. Edit the academy plan until source material, learner promise,
# landing-page proof, and course dependencies are specific.

# 3. Scaffold each course knowledge graph
graspful create course --topic "Your Topic" --hours 10 -o course.yaml

# 3. Fill each concept with knowledge points and problems
# 4. Fill each concept with knowledge points and problems
graspful fill concept course.yaml <concept-id>

# 4. Validate after every edit
# 5. Validate after every edit
graspful validate course.yaml

# 5. Review must score 10/10 to publish
# 6. Review must score 10/10 to publish
graspful review course.yaml

# 6. Import and publish
# 7. Import and publish
graspful import academy.yaml --org <org-slug> --course-dir .
```

Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Graspful is an agent-first academy creation platform. Academies and courses are

## How It Works

1. **Scaffold academy** -- `graspful create academy --topic "CKA Exam"` generates the academy shell
1. **Plan academy** -- `graspful create academy --topic "CKA Exam"` generates the academy layers, course map, and authoring gates
2. **Scaffold courses** -- `graspful create course --topic "Cluster Networking"` generates each course graph
3. **Fill** -- `graspful fill concept course.yaml networking` adds KPs and practice problems
4. **Review** -- `graspful review course.yaml` runs 10 quality checks, including whether problems only assess taught material
Expand All @@ -24,6 +24,7 @@ npx @graspful/cli init
# opens browser auth, then saves an API key locally
graspful register --email you@example.com
graspful create academy --topic "Your Topic" -o academy.yaml
mkdir -p courses
graspful create course --topic "Foundations" -o courses/foundations.yaml
```

Expand Down Expand Up @@ -60,7 +61,7 @@ graspful/
|---------|:---:|-------------|
| `graspful register` | No | Create account + API key via browser auth |
| `graspful login` | No | Authenticate with existing credentials |
| `graspful create academy` | No | Generate academy manifest skeleton |
| `graspful create academy` | No | Generate academy plan and manifest skeleton |
| `graspful create course` | No | Generate course YAML skeleton |
| `graspful create brand` | No | Generate brand YAML with theme presets |
| `graspful fill concept` | No | Add KPs and problems to a concept |
Expand Down Expand Up @@ -99,7 +100,7 @@ Or manually add to your MCP config:
| Tool | Auth? | Description |
|------|:---:|-------------|
| `graspful_scaffold_course` | No | Generate course YAML skeleton |
| `graspful_create_academy` | No | Generate academy manifest scaffold |
| `graspful_create_academy` | No | Generate academy plan and manifest scaffold |
| `graspful_fill_concept` | No | Add KPs and problems to a concept |
| `graspful_validate` | No | Validate YAML against schema |
| `graspful_review_course` | No | Run 10 quality checks, including teaching alignment |
Expand Down
26 changes: 26 additions & 0 deletions apps/site/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { defineConfig, globalIgnores } from "eslint/config";
import nextVitals from "eslint-config-next/core-web-vitals";
import nextTs from "eslint-config-next/typescript";

const eslintConfig = defineConfig([
...nextVitals,
...nextTs,
globalIgnores([
".next/**",
"out/**",
"build/**",
"next-env.d.ts",
"e2e/**",
"src/**/__tests__/**",
]),
{
rules: {
"react-hooks/immutability": "off",
"react-hooks/refs": "off",
"react-hooks/set-state-in-effect": "off",
"react/no-unescaped-entities": "off",
},
},
]);

export default eslintConfig;
32 changes: 32 additions & 0 deletions apps/web/src/app/(marketing)/docs/cli/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,38 @@ export default function CLIReferencePage() {
}`}
/>

<CommandSection
name="graspful create academy"
synopsis={`graspful create academy \\
--topic <topic> \\
[--course <name>] \\
[--version <version>] \\
[-o, --output <file>]`}
description="Generate an academy manifest scaffold with the academy planning layers, course file references, and authoring gates for source material, learner promise, landing-page proof, graph checks, and review before publishing."
options={[
{ flag: "--topic <topic>", description: "Academy topic name (required)" },
{ flag: "--course <name>", description: "Course name to include in dependency order. Repeatable. Defaults to the four academy planning layers." },
{ flag: "--version <version>", description: "Academy version string (default: 2026.1)" },
{ flag: "-o, --output <file>", description: "Output file path (defaults to stdout)" },
]}
examples={[
{
label: "Scaffold a default academy plan",
code: `graspful create academy \\
--topic "AWS Solutions Architect" \\
-o aws-academy.yaml`,
},
{
label: "Scaffold with named courses",
code: `graspful create academy \\
--topic "PostHog TAM" \\
--course "Data Models" \\
--course "Pipeline Reading and Solution Design" \\
-o posthog-tam-academy.yaml`,
},
]}
/>

<CommandSection
name="graspful create course"
synopsis={`graspful create course \\
Expand Down
52 changes: 35 additions & 17 deletions apps/web/src/app/llms-full.txt/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,19 @@ npx @graspful/cli init
# 2. Register to get an API key (required before import/publish)
graspful register

# 3. Scaffold a course from a topic
graspful create course --topic "Linear Algebra"
# 3. Scaffold the academy plan
graspful create academy --topic "Linear Algebra" -o academy.yaml

# 4. Fill in a specific concept with problems
graspful fill concept course.yaml concept-id
# 4. Scaffold each course graph, then fill concepts
mkdir -p courses
graspful create course --topic "Linear Algebra Foundations" -o courses/linear-algebra-foundations.yaml
graspful fill concept courses/linear-algebra-foundations.yaml concept-id

# 5. Review the course (runs 10 quality checks)
graspful review course.yaml
graspful review courses/linear-algebra-foundations.yaml

# 6. Import and publish to an organization
graspful import course.yaml --org my-org --publish
# 6. Import and publish the academy to an organization
graspful import academy.yaml --org my-org --course-dir . --publish
\`\`\`

---
Expand All @@ -55,8 +57,8 @@ graspful import course.yaml --org my-org --publish

| Operation | Auth required? |
|-----------|:-:|
| Scaffold, fill, validate, review, describe, create brand | No |
| Import course, publish course, import brand, list courses | **Yes** |
| Create academy, scaffold course, fill, validate, review, describe, create brand | No |
| Import academy, import course, publish course, import brand, list courses | **Yes** |

---

Expand All @@ -66,13 +68,14 @@ graspful import course.yaml --org my-org --publish
|---------|:---:|-------------|-----------|
| \`graspful init\` | No | Initialize project, browser-auth, and auto-configure MCP | \`--email\`, \`--no-browser\` |
| \`graspful register\` | No | Create account + API key via browser auth | \`--email <email>\`, \`--no-browser\` |
| \`graspful create academy\` | No | Scaffold an academy plan with source, landing-page, graph, and review gates | \`--topic <topic>\`, \`--course <name>\`, \`--version <version>\` |
| \`graspful create course\` | No | Scaffold a new course YAML | \`--topic <topic>\`, \`--hours <n>\`, \`--source <file>\` |
| \`graspful fill concept <yaml> <conceptId>\` | No | Generate knowledge points and problems for a concept | \`--force\` overwrite existing |
| \`graspful validate <yaml>\` | No | Validate course YAML against schema | — |
| \`graspful review <yaml>\` | No | Run all 10 quality checks | \`--fix\` auto-fix issues |
| \`graspful describe <yaml>\` | No | Describe course structure | — |
| \`graspful create brand\` | No | Scaffold a brand YAML | \`--niche <niche>\`, \`--name <name>\`, \`--domain <domain>\`, \`--org <slug>\` |
| \`graspful import <yaml>\` | **Yes** | Import course to platform | \`--org <slug>\`, \`--publish\` |
| \`graspful import <yaml>\` | **Yes** | Import an academy manifest or course to platform | \`--org <slug>\`, \`--publish\`, \`--course-dir <dir>\` |
| \`graspful publish <courseId>\` | **Yes** | Publish an imported course | \`--org <slug>\` |
| \`graspful import-brand <yaml>\` | **Yes** | Import brand config to platform | \`--org <slug>\` |
| \`graspful list courses\` | **Yes** | List courses in an org | \`--org <slug>\` |
Expand All @@ -82,9 +85,15 @@ graspful import course.yaml --org my-org --publish

## MCP Tools

Graspful exposes 10 MCP tools for AI agents. Tools marked (AUTH REQUIRED) need
Graspful exposes 12 MCP tools for AI agents. Tools marked (AUTH REQUIRED) need
an API key in \`GRASPFUL_API_KEY\`.

### graspful_create_academy
Generate an academy manifest with planning layers and authoring gates.
- \`topic\` (string, required) — Academy topic
- \`courseNames\` (string[], optional) — Ordered course names. Defaults to foundations, core structures, operational flows, and applied judgment
- \`version\` (string, optional) — Academy version string

### graspful_scaffold_course
Scaffold a new course YAML from a topic.
- \`topic\` (string, required) — The subject to create a course for
Expand All @@ -110,6 +119,13 @@ Import a course YAML to the Graspful platform. Set \`GRASPFUL_API_KEY\` first if
- \`orgSlug\` (string, required) — Organization slug
- \`publish\` (boolean, optional) — Publish immediately after import

### graspful_import_academy (AUTH REQUIRED)
Import an academy manifest and referenced course YAMLs. Set \`GRASPFUL_API_KEY\` first if not authenticated.
- \`manifestYaml\` (string, required) — Full academy manifest YAML
- \`courseYamls\` (object, required) — Map of course file paths to course YAML strings
- \`org\` (string, required) — Organization slug
- \`publish\` (boolean, optional) — Publish imported courses after import

### graspful_publish_course (AUTH REQUIRED)
Publish an already-imported course. Set \`GRASPFUL_API_KEY\` first if not authenticated.
- \`courseId\` (string, required) — ID of the course to publish
Expand Down Expand Up @@ -358,12 +374,14 @@ Each check returns pass/fail with details. Fix failures before importing.
## Typical Agent Workflow

1. **Register** — Run \`graspful register\` in a terminal to complete browser auth and get an API key. This is required before importing or publishing. Skip if you already have GRASPFUL_API_KEY set.
2. **Scaffold** — Use \`graspful_scaffold_course(topic: "Your Topic", hours: 10)\` to generate the course skeleton.
3. **Fill concepts** — For each concept, call \`graspful_fill_concept(yaml, conceptId)\` to generate knowledge points and problems.
4. **Review** — Call \`graspful_review_course(yaml)\` to run quality checks. Fix any failures.
5. **Import** — Call \`graspful_import_course(yaml, orgSlug, publish: true)\` to push to platform.
6. **Create brand** (optional) — Use \`graspful_create_brand(niche: "Your Niche")\` to generate a white-label site config.
7. **Import brand** (optional) — Use \`graspful_import_brand(yaml, orgSlug)\` to deploy the site.
2. **Plan the academy** — Use \`graspful_create_academy(topic: "Your Topic")\` to generate the academy manifest, planning layers, and authoring gates.
3. **Resolve the plan** — Fill in source material, learner promise, landing-page proof, and course dependencies before writing knowledge points.
4. **Scaffold course graphs** — Use \`graspful_scaffold_course(topic: "Your Course", estimatedHours: 10)\` for each course referenced by the academy.
5. **Fill concepts** — For each concept, call \`graspful_fill_concept(yaml, conceptId)\` to generate knowledge points and problems.
6. **Review** — Call \`graspful_review_course(yaml)\` to run quality checks. Fix any failures.
7. **Import academy** — Call \`graspful_import_academy(manifestYaml, courseYamls, org, publish: true)\` to push the connected product to platform.
8. **Create brand** — Use \`graspful_create_brand(niche: "Your Niche", topic: "Your Topic")\` to generate the landing page config.
9. **Import brand** — Use \`graspful_import_brand(yaml, orgSlug)\` to deploy the site.

### Tips for Agents

Expand Down
1 change: 1 addition & 0 deletions backend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

NODE_ENV=development
PORT=3000
ALLOWED_ORIGINS=http://localhost:3001,http://localhost:3002

# Database (Supabase PostgreSQL)
# Transaction pooler for app queries
Expand Down
20 changes: 18 additions & 2 deletions backend/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,25 @@ async function bootstrap() {
transform: true,
}));

// Static origins from env var (platform hosts, localhost, etc.)
const nodeEnv = config.get<string>('NODE_ENV', 'development');
const defaultLocalOrigins =
nodeEnv === 'production'
? []
: [
'http://localhost:3001',
'http://127.0.0.1:3001',
'http://localhost:3002',
'http://127.0.0.1:3002',
];

// Static origins from env var plus local development app hosts.
const staticOrigins = new Set(
config.get<string>('ALLOWED_ORIGINS')?.split(',').filter(Boolean) ?? [],
[
...defaultLocalOrigins,
...(config.get<string>('ALLOWED_ORIGINS')?.split(',') ?? []),
]
.map((origin) => origin.trim())
.filter(Boolean),
);

// Dynamic CORS: static origins are checked first, then brand domains from DB (cached 5 min)
Expand Down
6 changes: 3 additions & 3 deletions docs/adding-a-course.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Adding a New Course
# Adding a New Academy or Course

End-to-end guide for creating a course YAML and importing it into the platform.
End-to-end guide for planning an academy, creating course YAML, and importing it into the platform.

This document also serves as the agent runbook for new course creation. If an agent is asked to "add a course", "draft a course graph", or "author a course YAML", this is the document it should follow.
This document also serves as the agent runbook for academy and course creation. If an agent is asked to "create an academy", "add a course", "draft a course graph", or "author a course YAML", this is the document it should follow.

## Agent Workflow

Expand Down
53 changes: 52 additions & 1 deletion docs/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Version: 0.1.0

- [1. CLI Reference](#1-cli-reference)
- [Global Options](#global-options)
- [graspful create academy](#graspful-create-academy)
- [graspful create course](#graspful-create-course)
- [graspful create brand](#graspful-create-brand)
- [graspful fill concept](#graspful-fill-concept)
Expand All @@ -19,6 +20,7 @@ Version: 0.1.0
- [graspful login](#graspful-login)
- [graspful register](#graspful-register)
- [2. MCP Tools Reference](#2-mcp-tools-reference)
- [graspful_create_academy](#graspful_create_academy)
- [graspful_scaffold_course](#graspful_scaffold_course)
- [graspful_fill_concept](#graspful_fill_concept)
- [graspful_validate](#graspful_validate)
Expand Down Expand Up @@ -55,6 +57,35 @@ When `--format json` is set, all commands emit structured JSON to stdout and str

---

### `graspful create academy`

Generate an academy plan and manifest scaffold with planning layers and authoring gates.

If no `--course` flags are passed, the scaffold starts with the four default planning layers: foundations, core structures, operational flows, and applied judgment. It also includes an `authoringPlan` block for source material, learner promise, landing-page proof, graph checks, and review before publishing.

**Syntax:**

```
graspful create academy --topic <topic> [options]
```

**Parameters:**

| Flag | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `--topic <topic>` | string | Yes | — | Academy topic name. |
| `--course <name>` | string[] | No | four planning layers | Course name to include in dependency order. Repeatable. |
| `--version <version>` | string | No | `2026.1` | Academy version string. |
| `-o, --output <file>` | string | No | stdout | Output file path. If omitted, YAML is printed to stdout. |

**Example:**

```bash
graspful create academy --topic "PostHog TAM" --course "Data Models" --course "Pipeline Reading" -o academy.yaml
```

---

### `graspful create course`

Generate a course YAML scaffold with placeholder sections and concepts.
Expand Down Expand Up @@ -630,12 +661,30 @@ You're ready. Run: graspful import course.yaml --org alice-org

## 2. MCP Tools Reference

The Graspful MCP server exposes 10 tools over the Model Context Protocol (stdio transport). Server name: `graspful`, version `0.1.0`.
The Graspful MCP server exposes 12 tools over the Model Context Protocol (stdio transport). Server name: `graspful`, version `0.1.0`.

All tools return `{ content: [{ type: "text", text: "..." }], isError?: boolean }`. The `text` field contains either raw YAML or a JSON string depending on the tool.

---

### `graspful_create_academy`

Generate an academy plan and manifest scaffold with planning layers and authoring gates.

If `courseNames` is omitted, the scaffold starts with foundations, core structures, operational flows, and applied judgment. It also returns an `authoringPlan` block for source material, learner promise, landing-page proof, graph checks, and review before publishing.

**Parameters:**

| Name | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `topic` | string | Yes | — | Academy topic name (e.g., "PostHog TAM"). |
| `courseNames` | string[] | No | four planning layers | Ordered course names for the manifest. |
| `version` | string | No | `2026.1` | Academy version string. |

**Returns:** Raw academy manifest YAML string (not JSON-wrapped).

---

### `graspful_scaffold_course`

Generate a course YAML skeleton with sections, concepts, and prerequisite edges.
Expand Down Expand Up @@ -1233,6 +1282,8 @@ Top-level key: `academy`. File: `academy-manifest.schema.ts`.

Used to define a multi-course academy with optional grouping into "parts."

`graspful create academy` also emits an `authoringPlan` block. That block is for agents and humans while drafting: source material, learner promise, landing-page proof, graph checks, and review gates. The import API treats it as authoring metadata and does not persist it.

#### `academy` (required)

| Field | Type | Required | Description |
Expand Down
Loading
Loading