This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
CodeHelp is an Astro-based static site serving as a community-driven resource portal (codehelp.io). It aggregates curated links for developers, designers, and marketers across learning materials and development tools.
- Framework: Astro 5 with React 18 integration
- Language: JavaScript/JSX (Astro components + React islands)
- Styling: CSS (global) + styled-components (legacy page styles)
- State Management: nanostores (theme/dark mode)
- Deployment: Netlify (automatic on git push to master)
- Node: v20+ (set in
.nvmrcandnetlify.toml)
| Command | Purpose |
|---|---|
npm run dev |
Start Astro dev server on localhost:4321 with hot reload |
npm run build |
Build production site to /dist |
npm run preview |
Serve the built site locally for testing |
npm run clean |
Remove dist and .astro cache directories |
npm run format |
Format all code with Prettier (2-space, single quotes) |
src/
├── pages/ # File-based routing (Astro auto-creates routes)
│ ├── index.astro # Homepage (/)
│ ├── learning.astro # /learning resources page
│ ├── resources.astro # /resources development tools page
│ └── 404.astro # Not found page
│
├── layouts/
│ └── Layout.astro # Main HTML wrapper (head, analytics, theme script)
│
├── components/ # Reusable components (dual Astro + JSX pattern)
│ ├── Header/ # Logo and navigation (.astro + .jsx)
│ ├── Nav/ # Main nav links + Discord popup modal (.jsx only)
│ ├── Footer/ # Footer with links (.astro + .jsx)
│ ├── Sidebar/ # Category navigation with anchor links (.astro + .jsx)
│ ├── DataList/ # Maps data array -> Resource cards (.astro + .jsx)
│ ├── Resource/ # Individual resource card (.astro + .jsx)
│ ├── PageTitle/ # Page heading component (.astro + .jsx)
│ └── ThemeToggle/ # Dark/light mode switcher (.jsx only)
│
├── stores/
│ └── themeStore.js # nanostores atom for theme state, syncs to localStorage
│
├── utils/
│ └── theme-script.js # Inline script to prevent FOUC on page load
│
├── data/ # Static JSON data (no database)
│ ├── resources.json # Development tools/frameworks organized by category
│ └── learning.json # Learning materials organized by category
│
├── styles/ # Global CSS
│ ├── global.css # Theme variables, layout, typography
│ ├── normalize.css # CSS reset
│ └── fonts.css # Custom font declarations (Apercu Mono Pro)
│
└── assets/ # Static files
├── styles/ # Legacy styled-components page styles
├── fonts/ # Custom font files (.woff, .woff2)
└── images/ # PNG, SVG assets
Most components have dual implementations:
.component.astro— server-rendered Astro component (preferred for static content).component.jsx— React component (used for interactive islands like Nav, ThemeToggle)
Page rendering:
- Pages (
.astro) import static JSON fromsrc/data/ - Pass data to
Sidebar(category filters) andDataList(resource cards) - Sidebar renders anchor links for category navigation
- DataList maps array -> Resource components (individual cards)
- Layout.astro wraps all pages with head metadata, analytics, and theme initialization
Data shape (JSON structure):
{
"resources": [
{
"label": {
"id": "guides-info",
"name": "General Guides & Information",
"categories": [
{
"category": {
"id": "web-development",
"name": "Web Development",
"resources": [
{
"name": "MDN Web Docs",
"description": "...",
"url": "https://..."
}
]
}
}
]
}
}
]
}- Global CSS in
src/styles/global.csswith CSS custom properties (--color__background,--color__text, etc.) - Theme controlled via
data-themeattribute on<html>element - Legacy styled-components in
src/assets/styles/pages/for page-level styles - Responsive design: CSS media queries
Theme (nanostores):
- Defined in
src/stores/themeStore.jsusing nanostoresatom - Persists to localStorage, syncs to
document.documentElement.dataset.theme - React components access via
@nanostores/react(useStore) - FOUC prevention via inline script in Layout.astro (
src/utils/theme-script.js)
| Integration | Purpose |
|---|---|
@astrojs/react |
React component islands |
@astrojs/sitemap |
Auto-generated sitemap.xml |
@astrojs/partytown |
Google Analytics in web worker (off main thread) |
| File | Notes |
|---|---|
astro.config.mjs |
Integrations, site URL, image service, static output |
.nvmrc |
Node version (v20) |
.prettierrc |
Enforce 2-space indentation, single quotes, no semicolons, trailing commas |
.eslintrc |
ESLint configuration |
netlify.toml |
Build command, publish dir (dist), Node version, redirects |
.env.development/.env.production |
Google Analytics ID (PUBLIC_GA_ID) |
- Astro components for static content, React for interactivity
- styled-components for legacy page styles (in
src/assets/styles/pages/) - File naming:
ComponentName.component.astro/ComponentName.component.jsx
- Always use lowercase unless referencing case-sensitive items (component names, file paths, variable names, etc.)
- Write comments declaratively and directly, like a commit message
- Focus on the "why" rather than obvious "what"
- Examples:
// toggle dark mode theme in localStorage// map categories to sidebar navigation links
- Edit
src/data/resources.jsonorsrc/data/learning.json - Follow existing category/resource structure
- Run
npm run devto see changes (hot reload works)
- Create
.astrofile insrc/pages/(Astro auto-routes by filename) - Import and use
Layout.astroas the wrapper - Pass
titleanddescriptionprops to Layout for head metadata
/* use CSS custom properties that change with data-theme */
.my-element {
background: var(--color__background);
color: var(--color__text);
}// react components can read theme from nanostores
import { useStore } from '@nanostores/react'
import { themeStore } from '../stores/themeStore'
const MyComponent = () => {
const theme = useStore(themeStore)
// ...
}- Dev:
npm run dev-> localhost:4321 - Production:
npm run build-> outputs/distwith static assets - Netlify: Builds and deploys on git push to master
- Live site: https://codehelp.io
- ESLint: Configured via
.eslintrc - Prettier: Auto-format with
npm run format
- Data is static JSON — no database or API backend
- Theme switching is client-side only (nanostores + localStorage)
- Analytics via Google Analytics loaded through Partytown (web worker)
- Static output mode (
output: 'static'in astro.config.mjs)