This repository holds the course curriculum for GraphAcademy.
This repository uses docker-compose to create a local server using the latest production build of the GraphAcademy website (repo here). The docker image is stored on AWS ECR, so you will need credentials - talk to Adam.
-
Clone this repository
-
Install the AWS CLI
-
Run
aws configureto configure the AWS CLI -
Log in to docker using the credentials above:
aws ecr get-login-password --region us-east-1 | docker login -u AWS --password-stdin 715633473519.dkr.ecr.us-east-1.amazonaws.com
-
Install the dependencies using NPM
npm install
-
You will need to create a
.envfile in the project root with Auth0 configuration. You can get an example file from Adam or Martin.-
NEO4J_HOST -
NEO4J_USERNAME -
NEO4J_PASSWORD -
AUTH0_CLIENT_ID -
AUTH0_CLIENT_SECRET -
AUTH0_ISSUER_BASE_URL -
CDN_URL
-
-
Run
npm run devto start the server-
The local server will be available at http://localhost:3000
-
A Neo4j instance will be available on http://localhost:7474
-
A process will listen for changes in the
asciidoc/folder and sync the content to Neo4j
-
If you are using VS Code, you can use the devcontainer to run the application in a container.
You will need the Dev Containers extension installed and Docker running.
When the devcontainer is started, it will:
-
Install all dependencies
-
Start the GraphAcademy application and Neo4j database.
You can run the content update and sync by running the following command in a terminal:
npm run dev:watchAll content lives in the asciidoc/ directory. As you modify the content, a process will sync the course structure to Neo4j.
-
categories/- Category information (see Category Structure below) -
courses/- All courses are organised into the own folder structure with modules and lessons -
emails/- The emails sent to users on enrolment, completion and a reminder email when the user has been inactive for 7 days -
languages/- i18n phrases for courses in languages other than English. -
pages/- "CMS" content displayed throughout the website, for example the/certifications/page -
shared/- Content shared across courses -
statuses/- Meta data around course statuses
When a PR with a label (e.g. Release) is merged, course metadata is posted to Asana and Slack using the combined config in config/promo/ (e.g. release.json). The file has asana.destinations (project/section/assignee GIDs) and slack.channels.
Build a destination from an Asana URL (paste the board URL, section name, and assignee name; the script looks up GIDs and prints JSON for your config):
npm run asana:url-to-destination -- \
--url "https://app.asana.com/.../project/123/list/456" \
--section "Marquee Assets in Production" \
--assignee "Greg Posten" \
--name "Marquee Production"Other Asana helpers:
-
npm run asana:list-sections — <project_gid>– list section GIDs for a board -
npm run asana:list-assignees — --project <project_gid>– list user GIDs (for assignee) -
ASANA_CONFIG=release npm run release:asana — <course_slug>– post one course’s metadata to Asana locally
Slack promotion and review:
-
npm run release:slack — <course_slug>– post the release promo to Slack (template:asciidoc/shared/release/release.adoc, channels:config/promo/release.json) -
npm run review:slack — <course_slug>– post an SME review request to#graphacademy(template:asciidoc/shared/release/sme-review.adoc, channels:config/promo/sme-review.json); also triggered automatically when thesme-reviewlabel is applied to a PR -
Set
SLACK_BOT_TOKENin.env(Bot User OAuth Token withchat:writeandchannels:historyscopes)
Managing Slack messages posted by the bot:
Find the channel ID in Slack by right-clicking the channel and selecting View channel details.
# List recent bot messages in a channel
npm run slack:list-messages -- --channel <channel_ID>
# Narrow results by count or keyword
npm run slack:list-messages -- --channel <channel_ID> --limit 20 --search "aura-agents"
# Delete a specific message (copy the timestamp from the list output)
npm run slack:delete-message -- --channel <channel_ID> --ts <timestamp>
# Dry-run to confirm before deleting
npm run slack:delete-message -- --channel <channel_ID> --ts <timestamp> --dry-runFull flow (config files, workflow trigger, finding GIDs) is documented in the Releasing courses module in the How We Teach course.
asciidoc
+ courses/
+ {course-slug}/ - Course Folder
+ badge.svg - SVG badge used across the site
| overview.adoc - Course meta data and content used on the course overview page
+ modules/ - Each course is split into modules
+ {module-slug}/
| overview.adoc
+ lessons/ - A module is split into lessons
+ {lesson-slug}/
| lesson.adoc
+ questions/ - A lesson can be optional, otherwise will have questions.
| question-1.adoc
| question-2.adocCategories are defined as .adoc files in asciidoc/categories/.
Courses are assigned to categories via the :categories: attribute in course.adoc:
:categories: developer:1, context-engineer:3, coredbEach entry is a category slug with an optional display order (slug:order).
The order controls where the course appears within that category’s listing.
Five top-level parent categories organise everything else. The website queries these parents directly — never the parents themselves, only their children.
| Slug | Status | Purpose |
|---|---|---|
|
active |
Groups courses by role.
Children: |
|
active |
Curated start-to-finish learning progressions.
Children: |
|
disabled |
The four learning-path cards shown on the GraphAcademy homepage, in order.
Children: |
|
disabled |
Internal classifications required on every course.
Children: |
|
disabled |
Localised landing pages.
Children: |
The following attributes are available on a category .adoc file:
| Attribute | Required | Description |
|---|---|---|
|
No |
Comma-separated list of parent slugs with optional order ( |
|
No |
Short description shown on category cards. |
|
No |
Button label for homepage and path cards (e.g. |
|
No |
Override URL for the category card link. |
|
No |
Rendering hint for the website.
Values: |
|
No |
Certification slug or name that learners can expect to earn by completing this path. |
|
No |
Short display name used where space is limited. |
|
No |
Redirect the category page to another URL. |
|
No |
|
|
No |
BCP 47 language code (e.g. |
Every course must include at least one internal classification in its :categories: attribute.
This is enforced by the tests/categories.test.js test suite.
| Slug | Use for |
|---|---|
|
Core Neo4j database courses (Cypher, modeling, importing, application development, administration) |
|
Graph Data Science courses |
|
Generative AI and GraphRAG courses |
Workshops are instructor-led courses that are designed to be delivered in a classroom setting. They should not be used for self-study. The following workshops are available:
-
Zero to Production Hands-On Workshop (
workshop-zero) (2 hours)
Go from Zero to Production with Neo4j, Aura, and AI Agents. -
Introduction to Graph Databases Workshop (
workshop-fundamentals) (2 hours)
Learn about Graph theory, Neo4j fundamentals, and how to read and write data using Cypher. -
Importing Data into Neo4j Workshop (
workshop-importing) (2 hours)
Learn how to import your data into Neo4j using the Data Importer, including data modeling, indexes, and constraints. -
Modeling and Importing Data into Neo4j Workshop (
workshop-modeling) (2 hours)
Import the Northwind dataset into Neo4j and learn data modeling fundamentals by building a product recommendation engine. -
Neo4j Management, Optimization, and Refactoring Workshop (
workshop-optimization) (4 hours)
Learn how to manage Neo4j Aura databases, optimize Cypher queries for better performance, and refactor graph models for maintainability and efficiency.
-
Graph Data Science in Practice (
workshop-gds) (4 hours)
Learn to apply graph algorithms to real-world business problems, including community detection and fraud detection.
-
Neo4j and Generative AI Workshop (
workshop-genai) (3 hours)
Learn how Neo4j and GraphRAG can support your Generative AI projects, covering knowledge graph construction, vector search, and conversational agents.
A suite of tests have been setup to ensure courses meet the right standard.
To open the test suite run:
npm run testThis will open up a UI. Select E2E testing > Chrome and then select the course.
To create a test for your course, you can copy one of the existing files in the cypress/e2e folder to cypress/e2e/{slug}.cy.js and then change line 6 to cy.getCourseDetails('{slug}')/
You can run QA tests for all courses by running:
npm run test:qaYou can run QA tests for specific courses by setting the COURSES environment variable:
COURSES=fundamentals,aura npm run test:qaYou can use Cursor to run automated QA checks on the course content.
Cursor prompts are stored in the .cursor/ folder.
To run the checks against a specific course , use the following commands:
@review-lesson-content.mdc for @genai-graphrag-python
run and fix COURSES=graphrag-python npm run test qa
@technical-lesson-review.mdc
@review-course.mdcMake sure to install the neo4j documentation MCP server by running the following command:
npm install neo4j-driverUse built-in docs-mcp server to fact check the course content.
npm run mcp:docsOr preview the server with MCP Inspector:
npm run mcp:docs:inspectAdd the following to your .cursor/mcp.json file:
{
"mcpServers": {
"docs-mcp": {
"type": "stdio",
"command": "npx",
"args": [
"tsx",
"/path/to/courses/src/mcp/docs-mcp/index.ts"
]
}
}
}To create a new course or modify an existing course, please create a new branch and make your changes.
Once you have finished, create a new PR and add adam-cowley as a reviewer.
git checkout -b new-course mkdir asciidoc/courses/new-course/ echo "= New Course\n:status: draft" > asciidoc/courses/new-course/course.adoc
git add asciidoc/courses/new-course/ git commit -m "Added new course" git push --set-upstream origin new-course
Before creating the PR, please rebase your branch on the main branch.
git fetch origin main git rebase main
When you create a PR, select the correct template:
The checklist must be completed before the PR can be merged.
When a new application server is created, the latest tagged version of this repository is downloaded by the server.
You can use the npm version command to create a new tag. First, run a git pull --tags to get the latest commits and tags from the server, then run the npm version command to create a new tag. Once you are done, run git push --tags.
git pull --tags origin main npm version patch git push --tags origin main
-
npm version patch- To be used when minor fixes are made to an existing course -
npm version minor- To be used when a new course is released -
npm version major- To be used when a major change is made to the repository - for example, multiple course changes, or addition of a new category
To link certifications from the certifications repository, create a symlink:
ln -s ../certifications/asciidoc/certifications/neo4j-certification asciidoc/certifications/neo4j-certificationAdditional documentation is located in the Docs folder.