Contributor guide

Help build the community

Everything you need to add a lesson, translate content, suggest a resource, or improve the code.

Step 01

Start here

Ways to contribute

There are four main ways to help — pick whatever fits your time and skills:

  • Write or fix a lesson — improve wording, fix errors, or add a whole new lesson (Markdown, no coding needed).
  • Translate — bring a lesson or the UI into one of the site's languages.
  • Suggest a resource — share a great docs page, course, tool, or community. Open an issue and we'll add it.
  • Improve the code — fix a bug, refine the UI, or add a feature via a pull request.

Everything goes through GitHub — the site is fully static, so every change is a file in the repo.

Step 02

Beginner

Local setup

You'll need Node.js 20+ and pnpm. Then:

# 1. Fork the repo on GitHub, then clone your fork
git clone https://github.com/<you>/CRM-Analytics-Academy.git
cd CRM-Analytics-Academy

# 2. Install dependencies
pnpm install

# 3. Start the dev server → http://localhost:3000
pnpm dev

Before committing, always run the two checks (there's no test runner):

pnpm lint       # eslint
pnpm typecheck  # vue-tsc

Tip: if the docs sidebar ever looks empty in dev, the local content database went stale. Fix it with rm -rf .data && pnpm dev.

Step 03

No code

Writing a lesson

Lessons are plain Markdown under content/<locale>/<module>/<lesson>.md. English lives in content/en/. The number prefixes set the order:

content/en/
  1.foundations/
    1.index.md
    2.data-and-datasets.md
  5.saql/
    1.index.md
    2.filter-and-group.md

To add a lesson, create a new file with the next number in a module (e.g. content/en/5.saql/5.window-functions.md), start with a top-level heading, and write in Markdown. Use ## for sections — they become the table of contents. Keep it practical and example-led.

To fix a small typo, just use the “Edit this page” link at the bottom of any lesson — it opens a GitHub edit form.

Step 04

No code

Lesson frontmatter

Each lesson starts with a YAML frontmatter block:

---
title: SAQL Basics
description: A one-line summary used for SEO, the OG image, and AI search.
# Optional — embed a clip of a YouTube video at the top of the lesson:
video:
  id: dQw4w9WgXcQ
  start: 120
  end: 480
# Optional — model Q&A rendered after the body (also emitted as FAQ schema):
interview:
  - q: "What does the load statement do in SAQL?"
    a: "It loads a dataset into the query as the starting stream."
---

# SAQL Basics

Your content here…

title and description are required; video and interview are optional. A new top-level module also needs a .navigation.yml (with title and an icon) and a new section in the llms config in nuxt.config.ts.

Step 05

No code

Translations

The site ships in 12 languages: English (default), Spanish, French, German, Portuguese, Japanese, Chinese, Hindi, Arabic, Russian, Bengali, and Urdu. Arabic and Urdu render right-to-left.

You do not translate by hand. Write the lesson in English only. When it lands on main, a GitHub Action runs it through LibreTranslate and commits content/<locale>/… for all eleven other languages. Code blocks, SAQL, links, frontmatter keys and product names are protected and come through untouched.

content/en/5.saql/1.index.md   →   automatically →   content/es/5.saql/1.index.md
                                                content/ar/5.saql/1.index.md
                                                … and nine more

To run it yourself: pnpm translate (only changed files), or pnpm translate --locales=es,fr.

Machine translation is a starting point, not the finish line. If a sentence reads badly in your language, edit that locale's file directly and open a pull request — the pipeline only overwrites a file when its English source changes, so your fix survives.

UI strings live in i18n/locales/<lang>.json. Add new strings to en.json only; the same run fills in the other eleven and leaves existing translations alone.

Step 06

No code

Submitting a dashboard

Built a CRM Analytics dashboard you're proud of? Add it to the Showcase. It's one markdown file in content/showcase/ plus a screenshot in public/showcase/ — no database, no account, the pull request review is the moderation.

What makes an entry worth reading is not the screenshot, it's the working out: which KPIs you put on it, the formula behind each one, and why you measured it that way. Say what went wrong too — the gotcha you hit is usually the most useful part.

---
title: "Pipeline Health"
description: "One-screen read on coverage, slippage and win rate."
image: "/showcase/pipeline-health.png"
author: "Your Name"
authorUrl: "https://github.com/yourhandle"
domain: "Sales"              # Sales | Service | Marketing | Finance | …
difficulty: "Intermediate"   # Beginner | Intermediate | Advanced
datasets: ["Opportunity", "User"]
kpis:
  - name: "Win Rate"
    formula: "count() [IsWon] / count() [IsClosed]"
    note: "Closed-only denominator, or the rate drifts all quarter."
recipe:
  - step: "Build at opportunity grain"
    detail: "Account and Owner as lookups — never join line items here."
techniques: ["Dataflow", "Faceting", "Conditional Formatting"]
---

Your write-up goes here.

domain, difficulty and techniques drive the filters on the showcase page, so reuse existing values where they fit. Everything except title, description, image and author is optional.

Sanitise the screenshot first. Blur or fake customer names, revenue figures and user names — the repository is public.

Step 07

No code

Suggesting resources

Found a helpful link (docs, course, tool, community)? Open an issue with the title, URL, and a one-line description. Once accepted it's added to the curated list in app/pages/resources.vue and appears on the Resources page. Comfortable with a pull request? Add the entry yourself — it's a single line in that array.

Step 08

Intermediate

Code contributions

The stack is Nuxt 4 · Nuxt Content · Nuxt UI v4 · Tailwind CSS 4. Key folders:

  • content/ — the lessons (Markdown).
  • app/pages/, app/components/, app/composables/ — the app UI.
  • server/routes/raw/ — the raw-markdown surface for AI agents and crawlers.

Style rules are enforced by ESLint: no trailing commas, 1TBS braces, 2-space indent, and one interface member per line. Run pnpm lint --fix to auto-format. Match the surrounding code's conventions.

Step 09

Reference

Tech stack

The whole site is open source — here's what powers it:

  • Nuxt 4 (Vue 3 + Nitro) — the framework, SSR + prerendering
  • Nuxt Content 3 — lessons authored in Markdown, served from SQLite
  • Nuxt UI v4 + Tailwind CSS 4 — components and styling
  • @nuxtjs/i18n — 8 languages
  • GitHub Pages + GitHub Actions — hosting and CI (auto-deploy on push to main)

Also in the box: nuxt-og-image (social cards), nuxt-llms (machine-readable docs), and structured data for SEO.

There is no database and no accounts — every page is prerendered at build time from Markdown. If you're curious about the data model the site used to run on, see dbms.md in the repo.

Step 10

Beginner

Opening a pull request

  1. Branch off main: git checkout -b fix/typo-in-saql
  2. Make your change and preview it with pnpm dev.
  3. Verify: pnpm lint and pnpm typecheck both pass.
  4. Commit with a clear message and push to your fork.
  5. Open a PR against main, describing what changed and why.

A maintainer will review, suggest tweaks if needed, and merge. Once merged, the GitHub Actions workflow builds the site and publishes it to GitHub Pages automatically.

Step 11

Anytime

Getting help

Stuck or have an idea? Open an issue or a discussion on GitHub. First-time contributors are very welcome — no contribution is too small.