Contributing Guide

Help build EngPath

You don't need to know React. Every contribution area is a TypeScript data file — add a roadmap domain, write a mindset article, or list an open source project.

Quick Start

Three steps to your first PR

01

Fork the repository

Fork citraFebriawirti/EngPath on GitHub, clone it locally, and create a new branch from main.

02

Pick what to add

Choose a contribution area below. Each area is a TypeScript data file — no component work required.

03

Open a pull request

Push your branch and open a PR against main. Keep PRs focused — one contribution area per PR.

A

Roadmap Domain

Add a new career domain

A roadmap domain is a TypeScript object that describes a career path: its metadata, color, and an array of skill nodes. Once you create the file and register it in the index, it automatically appears on the roadmap listing page.

1

Create the domain file

Create a new folder under src/content/roadmap/ and add an index.ts file following the RoadmapDomain type.

// src/content/roadmap/your-domain/index.ts
import type { RoadmapDomain } from "@/content/roadmap/types";

export const yourDomain: RoadmapDomain = {
  slug: "your-domain",
  label: "Your Domain",
  flag: "Specialization",      // "Core" | "Specialization" | "Domain"
  shortDesc: "Short description shown on roadmap cards.",
  longDesc: "Longer description displayed on the domain page.",
  color: "#F59E0B",
  bg: "rgba(245,158,11,0.10)",
  meta: { nodes: 0, hours: 0 }, // update after adding nodes
  nodes: [
    {
      id: "yd-first-skill",    // prefix id with your domain abbreviation
      title: "Your First Skill",
      type: "core",            // "core" | "optional"
      level: 1,                // 1=Foundation 2=Intermediate 3=Advanced 4=Expert
      description: "What this skill covers and why it matters.",
      tags: ["tag1", "tag2"],
      resources: [
        { label: "Resource Name", href: "https://example.com" },
      ],
    },
  ],
};
2

Register the domain

Open src/content/roadmap/index.ts and add your domain to the imports and the roadmapDomains array. That's it — the page renders automatically.

// src/content/roadmap/index.ts  — two changes required

// 1. Add the import (alphabetical order preferred)
import { yourDomain } from "./your-domain";

// 2. Add to the domains array
export const roadmapDomains: RoadmapDomain[] = [
  backend, frontend, devops, mobile, security,
  data, qa, dba, business,
  yourDomain, // ← add here
];
B

Mindset Article

Write a mindset article

Articles are written with a structured block format — no MDX, no markdown files, just TypeScript. Each block is typed so you always know exactly what fields are required. Three registrations are needed across two files.

1

Create the article content file

Create src/content/mindset/your-article/index.ts and fill in the MindsetArticleContent shape. Available block kinds: p, h2, h3, callout, list, quote, code, conversation, takeaways, refs.

// src/content/mindset/your-article/index.ts
import type { MindsetArticleContent } from "@/content/mindset";

export const yourArticle: MindsetArticleContent = {
  slug: "your-article",        // must match folder name
  title: "Your Article Title",
  excerpt: "One-sentence summary shown on listing cards.",
  category: "Thinking Models", // use existing or add a new one
  readMin: 7,
  color: "#4F8EF7",
  bg: "rgba(79,142,247,0.10)",
  featured: false,             // set true to highlight on the listing page
  iconName: "Target",          // any valid Lucide icon name
  lead: "Opening paragraph shown at the top of the article.",
  blocks: [
    { kind: "h2", text: "First Section Heading" },
    { kind: "p",  text: "Paragraph text here." },
    {
      kind: "callout",
      variant: "insight",      // "insight" | "warning" | "tip"
      title: "Key Insight",
      body: "Callout body text.",
    },
    { kind: "list", style: "bullet", items: ["Item 1", "Item 2"] },
    { kind: "takeaways", items: ["Main takeaway 1", "Main takeaway 2"] },
  ],
};
2

Register in the content index

Import your article in src/content/mindset/index.ts and add it to the internal articles array. This is what the slug-based article page uses to resolve content.

// src/content/mindset/index.ts  — add import + register

// 1. Add the import
import { yourArticle } from "./your-article";

// 2. Add to the articles array
const articles: MindsetArticleContent[] = [
  firstPrinciplesArticle,
  systemsThinkingArticle,
  // ... existing articles ...
  yourArticle, // ← add here
];
3

Add display metadata for the listing page

Add a lightweight entry to the articles array in src/app/mindset/data.ts. This drives the card grid on the mindset listing page.

// src/app/mindset/data.ts  — add display metadata

export const articles: MindsetArticle[] = [
  // ... existing entries ...
  {
    slug: "your-article",      // must match content file slug
    title: "Your Article Title",
    excerpt: "One-sentence summary.",
    category: "Thinking Models",
    readMin: 7,
    iconName: "Target",
    color: "#4F8EF7",
    bg: "rgba(79,142,247,0.10)",
    featured: false,
  },
];
C

Open Source Project

List an open source project

The simplest contribution — add one object to a single array. The project will appear on the open source page, sorted and filtered by difficulty automatically.

1

Add the project to the data array

Open src/app/opensource/data.ts and append an object to the projects array. The difficulty level controls which section it appears in on the page.

// src/app/opensource/data.ts  — add to the projects array

export const projects: OsProject[] = [
  // ... existing projects ...
  {
    name: "your-project",
    fullName: "Your Project Full Name",
    description: "One to two sentences describing what the project does.",
    stars: 0,
    forks: 0,
    lang: "TypeScript",
    langColor: "#3178C6",
    difficulty: "Beginner",    // "Beginner" | "Intermediate" | "Advanced"
    category: "Tooling",       // e.g. "API", "CLI", "UI", "Data", "Tooling"
    tags: ["tag1", "tag2"],
    // href: "/opensource/your-project", // optional: internal detail page
    // githubUrl: "https://github.com/org/repo", // optional: external GitHub
  },
];

Tip

The href field links to an internal detail page (/opensource/[slug]), while githubUrl links directly to the GitHub repository. Both are optional — you can provide one, both, or neither and only include the card metadata.

Before You Submit

PR guidelines

Run through this checklist before opening your pull request to keep the review process fast.

Build passes

Run npm run build locally — zero TypeScript errors before opening a PR.

One area per PR

Don't mix roadmap + article changes in the same PR. Keep scope small and reviewable.

Follow naming conventions

Use kebab-case for all folder and file names (e.g. my-new-article/index.ts).

Fill all required fields

Every field in the TypeScript type is required unless explicitly marked optional.

At least one resource per node

Each roadmap skill node should link to at least one learning resource.

Article length

Aim for 6–12 minute reads. Use blocks: h2, p, callout, list, takeaways.

Get Started

Ready to open your first PR?

Fork the repo, pick an area above, and open a pull request. The maintainers are friendly and will help you get merged.