Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
30d3b5a
generated adr for other sitebuilders to use
LinKCoding Aug 18, 2026
ddff7ff
working starlight site with a few pages set up
LinKCoding Aug 19, 2026
9152d38
update server
LinKCoding Aug 20, 2026
93c6d4c
testing astro coding editor
LinKCoding Aug 24, 2026
3408c31
add custom theme
LinKCoding Aug 24, 2026
b7eabcd
add styling for the theme
LinKCoding Aug 24, 2026
72aba1d
merge main and resolve conflict
LinKCoding Aug 25, 2026
2e6de1f
update adr
LinKCoding Aug 26, 2026
9b6b22d
working buttons pages
LinKCoding Aug 26, 2026
9032bba
updated Actions components
LinKCoding Aug 26, 2026
5abaa02
updated Actions components
LinKCoding Aug 26, 2026
0221b2b
updated containers pages
LinKCoding Aug 26, 2026
7fa40c4
forms pages
LinKCoding Aug 26, 2026
6f2072a
revisit feedback and add navigation
LinKCoding Aug 26, 2026
aa3b519
overlay and data display pages
LinKCoding Aug 27, 2026
2773e42
update List
LinKCoding Aug 27, 2026
d87d2ed
update media + assets and typography
LinKCoding Aug 27, 2026
e4cd874
add utilities pages and update headings
LinKCoding Aug 27, 2026
ab68dd7
update Reference and Concept pages
LinKCoding Aug 27, 2026
0302003
update guides
LinKCoding Aug 27, 2026
d3e9c2c
ported over gamut writing guide and audited pages for writing guide s…
LinKCoding Aug 28, 2026
b925832
renamed patterns to usage examples
LinKCoding Aug 28, 2026
0f6d42b
undo Popover heading change
LinKCoding Aug 28, 2026
be2f3bc
touch-ups while auditing
LinKCoding Aug 31, 2026
eb98a83
update astro to 7 and include sidebar plugin
LinKCoding Sep 1, 2026
e5f3d00
update reference => foundations and updated layout to have foundation…
LinKCoding Sep 1, 2026
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
2 changes: 1 addition & 1 deletion .claude/skills/gamut-create-skill/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ For skills covering a concept rather than a single component (e.g. `gamut-color-

---

## Reference skills by type
## Prop Reference skills by type

| Type | Skill | Read it for |
| ---------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------- |
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ tmp
dist/storybook
dist/docs

# Astro / Starlight build
packages/starlight/dist
packages/starlight/.astro

# NX
dist/out-tsc
*.tsbuildinfo
Expand Down
153 changes: 153 additions & 0 deletions docs/adr/0001-documentation-site-information-architecture.md

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,15 @@
"@types/react-test-renderer": "^18.2.0",
"@typescript-eslint/utils": "^8.57.0",
"axios": "1.14.0",
"cookie": "^2.0.1",
"error-ex": "1.3.4",
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"scripts": {
"build": "nx run-many --target=build --all",
"build-all": "yarn build",
"build-docs-site": "nx run starlight:build",
"build-storybook": "nx run styleguide:build-storybook",
"build:graph": "nx graph",
"clean-builds": "nx run-many --target=clean --all",
Expand All @@ -137,6 +139,7 @@
"prepare": "husky",
"prettier": "prettier --ignore-path .prettierignore \"./**/*.{mdx,js,ts,tsx,json,css,scss}\"",
"start": "yarn && yarn start:storybook",
"start:docs": "nx run starlight:dev",
"start:storybook": "nx storybook styleguide",
"test": "nx run-many --target=test --all",
"test:storybook": "nx run styleguide:storybook-test",
Expand Down
165 changes: 165 additions & 0 deletions packages/starlight/astro.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import react from '@astrojs/react';
import starlight from '@astrojs/starlight';
import { defineConfig } from 'astro/config';
import liveCode from 'astro-live-code';
import starlightSidebarTopics from 'starlight-sidebar-topics';

// Sidebar structure follows docs/adr/0001-documentation-site-information-architecture.md.
// Top level maps to Diátaxis modes: Getting started (tutorials), Guides (how-to),
// Components + Reference (reference), Concepts (explanation).
// Each top-level section is its own topic (starlight-sidebar-topics), so its
// sidebar replaces the others instead of all five being stacked in one long list.
export default defineConfig({
site: 'https://gamut.codecademy.com',
server: {
port: 3333,
},
vite: {
ssr: {
// CommonJS modules imported with named imports inside @codecademy/gamut.
// Vite must bundle (rather than externalize) them during dev SSR to
// generate the named-export interop; without this the dev server fails
// with "[vite] Named export '…' not found".
noExternal: ['react-use'],
},
},
integrations: [
react(),
liveCode(),
starlight({
title: 'Gamut',
description: "Codecademy's design system for the web",
social: [
{
icon: 'github',
label: 'GitHub',
href: 'https://github.com/Codecademy/gamut',
},
],
editLink: {
baseUrl:
'https://github.com/Codecademy/gamut/edit/main/packages/starlight/',
},
customCss: ['./src/styles/gamut-core-theme.css'],
plugins: [
starlightSidebarTopics(
[
{
label: 'Getting started',
icon: 'rocket',
link: '/getting-started/installation/',
items: [{ autogenerate: { directory: 'getting-started' } }],
},
{
label: 'Guides',
icon: 'open-book',
link: '/guides/',
items: [{ autogenerate: { directory: 'guides' } }],
},
{
label: 'Foundations',
icon: 'information',
link: '/foundations/',
items: [{ autogenerate: { directory: 'foundations' } }],
},
{
label: 'Components',
icon: 'puzzle',
link: '/components/',
items: [
{
label: 'Overview',
slug: 'components',
},
{
label: 'Actions',
items: [
{ autogenerate: { directory: 'components/actions' } },
],
},
{
label: 'Containers',
items: [
{ autogenerate: { directory: 'components/containers' } },
],
},
{
label: 'Inputs & forms',
items: [
{
autogenerate: {
directory: 'components/inputs-and-forms',
},
},
],
},
{
label: 'Navigation',
items: [
{ autogenerate: { directory: 'components/navigation' } },
],
},
{
label: 'Feedback',
items: [
{ autogenerate: { directory: 'components/feedback' } },
],
},
{
label: 'Status',
items: [{ autogenerate: { directory: 'components/status' } }],
},
{
label: 'Overlays',
items: [
{ autogenerate: { directory: 'components/overlays' } },
],
},
{
label: 'Data display',
items: [
{
autogenerate: { directory: 'components/data-display' },
},
],
},
{
label: 'Typography',
items: [
{ autogenerate: { directory: 'components/typography' } },
],
},
{
label: 'Media & assets',
items: [
{
autogenerate: {
directory: 'components/media-and-assets',
},
},
],
},
{
label: 'Utilities',
items: [
{ autogenerate: { directory: 'components/utilities' } },
],
},
],
},
{
label: 'Concepts',
icon: 'document',
link: '/concepts/',
items: [{ autogenerate: { directory: 'concepts' } }],
},
],
{
// The splash-template homepage has no topic of its own.
exclude: ['/'],
}
),
],
}),
],
});
34 changes: 34 additions & 0 deletions packages/starlight/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "@codecademy/gamut-docs",
"description": "Gamut documentation site (Astro + Starlight)",
"version": "0.1.0",
"dependencies": {
"@astrojs/react": "^6.0.4",
"@astrojs/starlight": "^0.41.9",
"@codecademy/gamut": "workspace:*",
"@codecademy/gamut-icons": "workspace:*",
"@codecademy/gamut-styles": "workspace:*",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"astro": "^7.2.6",
"astro-live-code": "^0.0.6",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"starlight-sidebar-topics": "^0.8.0"
},
"devDependencies": {
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1"
},
"license": "MIT",
"private": true,
"repository": "git@github.com:Codecademy/gamut.git",
"scripts": {
"build": "astro build",
"check": "astro check",
"dev": "astro dev",
"preview": "astro preview",
"start": "astro dev"
},
"type": "module"
}
32 changes: 32 additions & 0 deletions packages/starlight/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "starlight",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/starlight/src",
"projectType": "application",
"tags": [],
"targets": {
"dev": {
"executor": "nx:run-commands",
"options": {
"cwd": "packages/starlight",
"command": "astro dev"
}
},
"build": {
"executor": "nx:run-commands",
"outputs": ["{projectRoot}/dist"],
"options": {
"cwd": "packages/starlight",
"command": "astro build"
}
},
"preview": {
"executor": "nx:run-commands",
"dependsOn": ["build"],
"options": {
"cwd": "packages/starlight",
"command": "astro preview"
}
}
}
}
29 changes: 29 additions & 0 deletions packages/starlight/src/components/FigmaEmbed.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
/**
* Embeds a Figma frame via Embed Kit 2.0 (embed.figma.com). Static HTML —
* no client JS. The target file must be shared as "anyone with the link can
* view" for anonymous visitors to see it; otherwise the iframe shows a
* Figma login wall. Keep a node-id in the URL so the embed opens zoomed to
* the relevant frame instead of the entire file.
*/
interface Props {
/** Full Figma URL, including node-id for a specific frame */
url: string;
height?: string;
}

const { url, height = '28rem' } = Astro.props;

const embedUrl = new URL(
url.replace(/www\.figma\.com\/(file|design)\//, 'embed.figma.com/design/')
);
embedUrl.searchParams.set('embed-host', 'gamut-docs');
---

<iframe
src={embedUrl.href}
title="Figma design"
loading="lazy"
allowfullscreen
style={`width: 100%; height: ${height}; border: 1px solid var(--sl-color-gray-5); border-radius: 0.5rem; margin: 1rem 0;`}
></iframe>
45 changes: 45 additions & 0 deletions packages/starlight/src/components/StoryEmbed.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
/**
* A component page's Reference section (per
* docs/adr/0001-documentation-site-information-architecture.md §3) embeds
* this rather than re-authoring variants/accessibility/props/playground
* content: an iframe onto a live Storybook story canvas, paired with a link
* to open that same story directly in Storybook. Storybook stays the single
* source of truth for that content — this is a durable part of the site's
* architecture, not a stopgap pending further migration.
*
* Requires the Storybook deployment to remain live at gamut.codecademy.com.
*/
interface Props {
/** Storybook story id, e.g. "atoms-buttons-fillbutton--default" */
id: string;
height?: string;
}

const { id, height = '10rem' } = Astro.props;

const storybookOrigin = 'https://gamut.codecademy.com';
const src = `${storybookOrigin}/iframe.html?id=${id}&viewMode=story`;

// Storybook ids are "<title>--<story-name>"; the docs page for the whole
// story group lives at "<title>--docs".
const storyGroupId = id.slice(0, id.lastIndexOf('--'));
const docsHref = `${storybookOrigin}/?path=/docs/${storyGroupId}--docs`;
---

<div style="margin: 1rem 0;">
<iframe
src={src}
title={`Storybook example: ${id}`}
loading="lazy"
style={`width: 100%; height: ${height}; display: block; border: 1px solid var(--sl-color-gray-5); border-radius: 0.5rem 0.5rem 0 0; background: white;`}
></iframe>
<a
href={docsHref}
target="_blank"
rel="noreferrer"
style="display: block; padding: 0.5rem 0.75rem; font-size: var(--sl-text-sm); border: 1px solid var(--sl-color-gray-5); border-top: none; border-radius: 0 0 0.5rem 0.5rem; background: var(--sl-color-bg-inline-code); color: var(--sl-color-text-accent);"
>
Open full story in Storybook →
</a>
</div>
7 changes: 7 additions & 0 deletions packages/starlight/src/content.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { docsLoader } from '@astrojs/starlight/loaders';
import { docsSchema } from '@astrojs/starlight/schema';
import { defineCollection } from 'astro:content';

export const collections = {
docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
};
Loading