diff --git a/.claude/agents/keyser.md b/.claude/agents/keyser.md new file mode 120000 index 0000000..3fea496 --- /dev/null +++ b/.claude/agents/keyser.md @@ -0,0 +1 @@ +../workflow/agents/keyser.md \ No newline at end of file diff --git a/.claude/agents/landa.md b/.claude/agents/landa.md new file mode 120000 index 0000000..8fb0ab1 --- /dev/null +++ b/.claude/agents/landa.md @@ -0,0 +1 @@ +../workflow/agents/landa.md \ No newline at end of file diff --git a/.claude/agents/morpheus.md b/.claude/agents/morpheus.md new file mode 120000 index 0000000..4af2a8e --- /dev/null +++ b/.claude/agents/morpheus.md @@ -0,0 +1 @@ +../workflow/agents/morpheus.md \ No newline at end of file diff --git a/.claude/agents/oracle.md b/.claude/agents/oracle.md new file mode 120000 index 0000000..63209e6 --- /dev/null +++ b/.claude/agents/oracle.md @@ -0,0 +1 @@ +../workflow/agents/oracle.md \ No newline at end of file diff --git a/.claude/agents/saul.md b/.claude/agents/saul.md new file mode 120000 index 0000000..a3613c5 --- /dev/null +++ b/.claude/agents/saul.md @@ -0,0 +1 @@ +../workflow/agents/saul.md \ No newline at end of file diff --git a/.claude/agents/vincent.md b/.claude/agents/vincent.md new file mode 120000 index 0000000..bdf7401 --- /dev/null +++ b/.claude/agents/vincent.md @@ -0,0 +1 @@ +../workflow/agents/vincent.md \ No newline at end of file diff --git a/.claude/agents/wolf.md b/.claude/agents/wolf.md new file mode 120000 index 0000000..037d6e2 --- /dev/null +++ b/.claude/agents/wolf.md @@ -0,0 +1 @@ +../workflow/agents/wolf.md \ No newline at end of file diff --git a/.claude/commands/workflow.md b/.claude/commands/workflow.md new file mode 120000 index 0000000..e10be31 --- /dev/null +++ b/.claude/commands/workflow.md @@ -0,0 +1 @@ +../workflow/commands/workflow.md \ No newline at end of file diff --git a/.claude/skills/brainstorming b/.claude/skills/brainstorming new file mode 120000 index 0000000..f1466e1 --- /dev/null +++ b/.claude/skills/brainstorming @@ -0,0 +1 @@ +../workflow/skills/brainstorming \ No newline at end of file diff --git a/.claude/skills/dispatching-parallel-agents b/.claude/skills/dispatching-parallel-agents new file mode 120000 index 0000000..55b309d --- /dev/null +++ b/.claude/skills/dispatching-parallel-agents @@ -0,0 +1 @@ +../workflow/skills/dispatching-parallel-agents \ No newline at end of file diff --git a/.claude/skills/executing-plans b/.claude/skills/executing-plans new file mode 120000 index 0000000..a1d8bd0 --- /dev/null +++ b/.claude/skills/executing-plans @@ -0,0 +1 @@ +../workflow/skills/executing-plans \ No newline at end of file diff --git a/.claude/skills/frontend-design b/.claude/skills/frontend-design new file mode 120000 index 0000000..7b7696f --- /dev/null +++ b/.claude/skills/frontend-design @@ -0,0 +1 @@ +../workflow/skills/frontend-design \ No newline at end of file diff --git a/.claude/skills/humanizer b/.claude/skills/humanizer new file mode 120000 index 0000000..b5be2dc --- /dev/null +++ b/.claude/skills/humanizer @@ -0,0 +1 @@ +../workflow/skills/humanizer \ No newline at end of file diff --git a/.claude/skills/mcp-builder b/.claude/skills/mcp-builder new file mode 120000 index 0000000..4e0a8a7 --- /dev/null +++ b/.claude/skills/mcp-builder @@ -0,0 +1 @@ +../workflow/skills/mcp-builder \ No newline at end of file diff --git a/.claude/skills/productivity b/.claude/skills/productivity new file mode 120000 index 0000000..94d80f3 --- /dev/null +++ b/.claude/skills/productivity @@ -0,0 +1 @@ +../workflow/skills/productivity \ No newline at end of file diff --git a/.claude/skills/receiving-code-review b/.claude/skills/receiving-code-review new file mode 120000 index 0000000..eaa7079 --- /dev/null +++ b/.claude/skills/receiving-code-review @@ -0,0 +1 @@ +../workflow/skills/receiving-code-review \ No newline at end of file diff --git a/.claude/skills/requesting-code-review b/.claude/skills/requesting-code-review new file mode 120000 index 0000000..f3ae8c0 --- /dev/null +++ b/.claude/skills/requesting-code-review @@ -0,0 +1 @@ +../workflow/skills/requesting-code-review \ No newline at end of file diff --git a/.claude/skills/skill-creator b/.claude/skills/skill-creator new file mode 120000 index 0000000..3569088 --- /dev/null +++ b/.claude/skills/skill-creator @@ -0,0 +1 @@ +../workflow/skills/skill-creator \ No newline at end of file diff --git a/.claude/skills/subagent-driven-development b/.claude/skills/subagent-driven-development new file mode 120000 index 0000000..7f7cbd3 --- /dev/null +++ b/.claude/skills/subagent-driven-development @@ -0,0 +1 @@ +../workflow/skills/subagent-driven-development \ No newline at end of file diff --git a/.claude/skills/systematic-debugging b/.claude/skills/systematic-debugging new file mode 120000 index 0000000..9630c12 --- /dev/null +++ b/.claude/skills/systematic-debugging @@ -0,0 +1 @@ +../workflow/skills/systematic-debugging \ No newline at end of file diff --git a/.claude/skills/test-driven-development b/.claude/skills/test-driven-development new file mode 120000 index 0000000..850f06d --- /dev/null +++ b/.claude/skills/test-driven-development @@ -0,0 +1 @@ +../workflow/skills/test-driven-development \ No newline at end of file diff --git a/.claude/skills/verification-before-completion b/.claude/skills/verification-before-completion new file mode 120000 index 0000000..b021de5 --- /dev/null +++ b/.claude/skills/verification-before-completion @@ -0,0 +1 @@ +../workflow/skills/verification-before-completion \ No newline at end of file diff --git a/.claude/skills/wordpress-docker-project b/.claude/skills/wordpress-docker-project new file mode 120000 index 0000000..f869128 --- /dev/null +++ b/.claude/skills/wordpress-docker-project @@ -0,0 +1 @@ +../workflow/skills/wordpress-docker-project \ No newline at end of file diff --git a/.claude/skills/workflow b/.claude/skills/workflow new file mode 120000 index 0000000..50a593c --- /dev/null +++ b/.claude/skills/workflow @@ -0,0 +1 @@ +../workflow/skills/workflow \ No newline at end of file diff --git a/.claude/skills/writing-plans b/.claude/skills/writing-plans new file mode 120000 index 0000000..c2885dd --- /dev/null +++ b/.claude/skills/writing-plans @@ -0,0 +1 @@ +../workflow/skills/writing-plans \ No newline at end of file diff --git a/.claude/skills/writing-skills b/.claude/skills/writing-skills new file mode 120000 index 0000000..c65987c --- /dev/null +++ b/.claude/skills/writing-skills @@ -0,0 +1 @@ +../workflow/skills/writing-skills \ No newline at end of file diff --git a/.claude/work/.gitignore b/.claude/work/.gitignore new file mode 100644 index 0000000..b30d03c --- /dev/null +++ b/.claude/work/.gitignore @@ -0,0 +1,5 @@ +/todo.md +/scan.md +/know.md +/sdd/ +/brainstorm/ diff --git a/.claude/workflow b/.claude/workflow new file mode 160000 index 0000000..502b046 --- /dev/null +++ b/.claude/workflow @@ -0,0 +1 @@ +Subproject commit 502b046397daa970e0a81f501888839d917d1243 diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE new file mode 120000 index 0000000..7f5d392 --- /dev/null +++ b/.github/ISSUE_TEMPLATE @@ -0,0 +1 @@ +../.claude/workflow/.github/ISSUE_TEMPLATE \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 120000 index 0000000..3519ec3 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1 @@ +../.claude/workflow/.github/PULL_REQUEST_TEMPLATE.md \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..26b1155 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,26 @@ +name: CI + +on: [push, pull_request] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 18 + cache: 'npm' + - run: npm ci + - run: make lint + + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 18 + cache: 'npm' + - run: npm ci + - run: make test diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..7a532a2 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule ".claude/workflow"] + path = .claude/workflow + url = git@github.com:nofutur3/claude-workflow.git diff --git a/.opencode/agent/keyser.md b/.opencode/agent/keyser.md new file mode 120000 index 0000000..d2a2f1b --- /dev/null +++ b/.opencode/agent/keyser.md @@ -0,0 +1 @@ +../../.claude/workflow/agents/keyser.md \ No newline at end of file diff --git a/.opencode/agent/landa.md b/.opencode/agent/landa.md new file mode 120000 index 0000000..eadcb9d --- /dev/null +++ b/.opencode/agent/landa.md @@ -0,0 +1 @@ +../../.claude/workflow/agents/landa.md \ No newline at end of file diff --git a/.opencode/agent/morpheus.md b/.opencode/agent/morpheus.md new file mode 120000 index 0000000..fe73e4f --- /dev/null +++ b/.opencode/agent/morpheus.md @@ -0,0 +1 @@ +../../.claude/workflow/agents/morpheus.md \ No newline at end of file diff --git a/.opencode/agent/oracle.md b/.opencode/agent/oracle.md new file mode 120000 index 0000000..8b805d7 --- /dev/null +++ b/.opencode/agent/oracle.md @@ -0,0 +1 @@ +../../.claude/workflow/agents/oracle.md \ No newline at end of file diff --git a/.opencode/agent/saul.md b/.opencode/agent/saul.md new file mode 120000 index 0000000..b89e01a --- /dev/null +++ b/.opencode/agent/saul.md @@ -0,0 +1 @@ +../../.claude/workflow/agents/saul.md \ No newline at end of file diff --git a/.opencode/agent/vincent.md b/.opencode/agent/vincent.md new file mode 120000 index 0000000..bb83111 --- /dev/null +++ b/.opencode/agent/vincent.md @@ -0,0 +1 @@ +../../.claude/workflow/agents/vincent.md \ No newline at end of file diff --git a/.opencode/agent/wolf.md b/.opencode/agent/wolf.md new file mode 120000 index 0000000..08615b0 --- /dev/null +++ b/.opencode/agent/wolf.md @@ -0,0 +1 @@ +../../.claude/workflow/agents/wolf.md \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index 58d06c3..cf8e737 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,3 +2,10 @@ package.json package-lock.json public +.claude/workflow +.claude/skills +.claude/agents +.claude/commands +.opencode +.github/ISSUE_TEMPLATE +.github/PULL_REQUEST_TEMPLATE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..b8e8a4b --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,36 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Overview + +happyphpdev.com is a Gatsby v3 (React 17) blog, based on the official `gatsby-starter-blog`, deployed statically to Firebase Hosting. + +## Commands + +- `npm ci` — install dependencies from `package-lock.json` (note: it's `npm ci`, the built-in npm command, not `npm run ci` — no `ci` script exists in `package.json` despite readme.md/AGENTS.md saying otherwise) +- `npm run develop` (alias: `npm start`) — start the dev server at http://localhost:8000 +- `npm run docker-develop` — dev server bound to `0.0.0.0` (used inside Docker) +- `npm run build` — production build into `public/` +- `npm run serve` — serve the built `public/` locally +- `npm run clean` — clear Gatsby's `.cache/` and `public/` (fixes most stale-data/GraphQL-schema build issues) +- `npm run format` — Prettier write across `**/*.{js,jsx,ts,tsx,json,md}` (see `.prettierrc`/`.prettierignore`) +- `npm run deploy` — `gatsby build --prefix-links && firebase deploy` +- `npm test` — currently a stub that always exits 1 (no test suite exists yet) + +Docker: `docker compose up -d` builds from `docker/node/Dockerfile` and runs `npm run docker-develop`, publishing on `${PORT:-8000}` with UID/GID/PORT from `.env` (see `.env.example`). + +There is a `.github/workflows/deploy-to-firebase.yml` CI job that also runs `npm run lint` and `npm run typecheck` and pushes to Firebase on `main` — those two scripts don't exist in `package.json` yet, so the workflow (currently modified/uncommitted) will fail until they're added. + +## Architecture + +- **Content-driven routing**: `gatsby-node.js` queries all `MarkdownRemark` nodes under `content/blog/**` (sourced via `gatsby-source-filesystem`, configured in `gatsby-config.js`) and calls `createPage` for each post using the `src/templates/blog-post.js` template, passing `previousPostId`/`nextPostId` context for prev/next navigation. `onCreateNode` derives each post's URL slug from its file path via `createFilePath`. Categories and tags get their own generated pages via `gatsby-plugin-categories` / `gatsby-plugin-tags`, using `src/templates/category.js` and `src/templates/tag.js` respectively — driven by the `category`/`tags` frontmatter fields. +- **Posts** live at `content/blog////index.md`, each with frontmatter (`title`, `date`, `description`, `category`, `tags`) plus co-located images referenced by relative path (processed by `gatsby-remark-images` / `gatsby-plugin-sharp`). +- **Schema customization**: `gatsby-node.js`'s `createSchemaCustomization` explicitly types `SiteSiteMetadata`, `MarkdownRemark.frontmatter`, and `.fields` so GraphQL queries don't error out when `content/blog` is empty or frontmatter fields are missing. +- **Layout composition**: every page/template wraps content in `src/layouts/base.js`, which renders a sidebar (`Bio`) + main content column (Bootstrap-based `.container`/`.row`/`.col-*` grid) and a shared `Footer`. `src/components/seo.js` handles per-page `` metadata via `react-helmet`. +- **Styling**: Bootstrap 5 + custom Sass (`src/styles/global.scss`, `src/styles/variables.scss`) via `gatsby-plugin-sass`, plus `src/normalize.css`/`src/style.css`. +- **Mixed JS/TS**: most of the codebase is plain `.js`, but a couple of files (`src/pages/using-typescript.tsx`, `src/components/support.tsx`) are `.tsx`. There is no `tsconfig.json` or TypeScript type-checking configured yet — Gatsby transpiles TS/TSX out of the box but nothing enforces types. +- **Feed/manifest**: `gatsby-plugin-feed` generates `/rss.xml` from all `MarkdownRemark` nodes; `gatsby-plugin-manifest` configures the PWA manifest (site name, icon, theme colors). +- **Deployment target**: `firebase.json`/`.firebaserc` point at Firebase project `happyphpdev-com`, serving the `public/` build output. + +@.claude/workflow/CLAUDE.md diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1472e0c --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +.PHONY: lint test + +lint: + npx prettier --check "src/**/*.{js,jsx,ts,tsx}" "gatsby-*.js" + +test: + @echo "No test suite configured yet (see 'npm test' stub in package.json)." diff --git a/opencode.json b/opencode.json new file mode 100644 index 0000000..e639ec3 --- /dev/null +++ b/opencode.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://opencode.ai/config.json", + "instructions": [ + ".claude/workflow/CLAUDE.md", + ".claude/workflow/AGENTS.md", + ".claude/workflow/rules/*.md" + ], + "skills": { + "paths": [".claude/workflow/skills"] + }, + "provider": { + "local": { + "npm": "@ai-sdk/openai-compatible", + "name": "Local Ollama (via LiteLLM)", + "options": { + "baseURL": "http://litellm.dev.local:8888/v1" + }, + "models": { + "local-opus": { "name": "local-opus (deepseek-r1:14b)" }, + "local-sonnet": { "name": "local-sonnet (qwen2.5-coder:14b)" }, + "local-haiku": { "name": "local-haiku (qwen2.5-coder:7b)" } + } + } + } +} diff --git a/src/components/bio.js b/src/components/bio.js index 8c8f454..43424d0 100644 --- a/src/components/bio.js +++ b/src/components/bio.js @@ -34,21 +34,21 @@ const Bio = () => {
{author?.name && ( -

- Written by {author.name} {author?.summary || null} -

+

+ Written by {author.name} {author?.summary || null} +

)}
diff --git a/src/components/build-date.js b/src/components/build-date.js index b9d3cf4..c971657 100644 --- a/src/components/build-date.js +++ b/src/components/build-date.js @@ -1,16 +1,16 @@ import * as React from "react" function getDate() { - const today = new Date(); - const month = today.getMonth() + 1; - const year = today.getFullYear(); - const date = today.getDate(); - return `${date}/${month}/${year}`; + const today = new Date() + const month = today.getMonth() + 1 + const year = today.getFullYear() + const date = today.getDate() + return `${date}/${month}/${year}` } const BuildDate = () => { - const currentDate = getDate(); + const currentDate = getDate() - return ({currentDate}) + return {currentDate} } -export default BuildDate; +export default BuildDate diff --git a/src/components/footer.js b/src/components/footer.js index a7359d3..4ca5bc7 100644 --- a/src/components/footer.js +++ b/src/components/footer.js @@ -1,18 +1,16 @@ import React from "react" -import BuildDate from "./build-date"; +import BuildDate from "./build-date" const Footer = () => ( ) - export default Footer diff --git a/src/components/support.tsx b/src/components/support.tsx index 3db2536..dea4347 100644 --- a/src/components/support.tsx +++ b/src/components/support.tsx @@ -1,9 +1,5 @@ import * as React from "react" -const Support: any = ({ +const Support: any = ({}) =>
Implement
-}) => ( -
Implement
-) - -export default Support; +export default Support diff --git a/src/layouts/base.js b/src/layouts/base.js index fcc0195..13030b6 100644 --- a/src/layouts/base.js +++ b/src/layouts/base.js @@ -1,7 +1,7 @@ import * as React from "react" import { Link } from "gatsby" import Footer from "./../components/footer" -import Bio from "../components/bio"; +import Bio from "../components/bio" const Base = ({ location, title, children }) => { const rootPath = `${__PATH_PREFIX__}/` @@ -25,15 +25,15 @@ const Base = ({ location, title, children }) => { return (
- -
- {children} -
+ +
+ {children} +
-
+
) }