{"owner":"umputun","repo":"remark42","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["CLAUDE.md"],"skills":{"CLAUDE.md":"# Remark42 Development Guidelines\n\n## Build/Test/Lint Commands\n- **Backend**:\n  - Run server: `make rundev`\n  - Build: `make backend`\n  - Race test: `make race_test`\n- **Backend Testing**:\n  - Run all tests: `cd backend/app && go test -timeout=60s -count 1 ./...`\n  - Run single test: `cd backend/app && go test -run TestName ./path/to/package`\n  - **IMPORTANT**: Run example tests: `cd backend/_example/memory_store && go test -race ./... && go build -race ./...`\n- **Frontend**:\n  - Development: `cd frontend && pnpm dev:app`\n  - Tests: `cd frontend && pnpm test`\n- **Lint**:\n  - Backend: `cd backend && golangci-lint run`\n  - **IMPORTANT**: Example lint: `cd backend/_example/memory_store && golangci-lint run --config ../../.golangci.yml`\n  - Frontend: `cd frontend && pnpm lint`\n  - **Before committing**: Always run tests and linter on both main backend AND examples\n- **Dependency Updates**:\n  - When updating Go modules in `backend/`, also run `go mod tidy` (and `go mod vendor`) in `backend/_example/memory_store` to keep indirect deps in sync. The example module replaces `github.com/umputun/remark42/backend` with `../../` so stale indirect deps there will break the example build.\n\n## Release Procedure\n\nRemark42 uses two tags for each release:\n- `vX.Y.Z` - product release tag used by GitHub releases, GoReleaser binary artifacts, and Docker image publishing.\n- `backend/vX.Y.Z` - nested Go module tag for `github.com/umputun/remark42/backend`.\n\nRelease flow:\n1. Create the GitHub release for `vX.Y.Z` with title `Version X.Y.Z`. The GitHub release must exist before the `vX.Y.Z` tag reaches the remote; `gh release create vX.Y.Z` satisfies this because it creates and pushes the tag.\n2. The `vX.Y.Z` tag triggers GoReleaser, which builds and uploads binary artifacts to the existing release.\n3. Create and push the matching backend module tag pointing at the same commit:\n\n```bash\ngit fetch origin --tags\ngit tag backend/vX.Y.Z vX.Y.Z\ngit push origin backend/vX.Y.Z\n```\n\nGoReleaser must ignore `backend/*` tags in `.goreleaser.yml` so release notes and current-tag detection use only product tags. Docker image publishing stays separate and is handled by the existing Docker workflow.\n\nFor local artifact runs, install GoReleaser, Go 1.25, Node 16+, PNPM 8, and Perl, then use `make release`. The target runs a snapshot/no-publish GoReleaser build, leaves local artifacts and metadata in `dist/`, and cleans generated frontend embed files after GoReleaser exits. Do not run raw `goreleaser release` for local artifacts unless you also run `./scripts/cleanup-release-assets.sh` afterward.\n\n## Milestones and Issue Labels\n\n**Milestones** — one `vX.Y.Z` milestone per release. Assign every merged PR, and every issue closed by a code change, to the milestone of the release it shipped in.\n- Decide which release a PR belongs to by whether its merge commit is **contained in a release tag** — not by comparing dates (a tag can be cut from an earlier commit, or moved). `git fetch --tags`, then `git tag --contains <merge_sha> | grep '^v' | sort -V | head -1` is its release. If no release tag contains it yet, it belongs to the next (unreleased) version's milestone — create it if missing (`gh api repos/umputun/remark42/milestones -f title=\"vX.Y.Z\"`).\n- An **issue gets a milestone only when it was closed by a code change** (a linked closing PR/commit); take the milestone from that PR/commit (via the commit-in-tag rule). Issues closed as `duplicate`/`invalid`/`wontfix`/answered get no milestone.\n- Find unassigned: `gh pr list --state merged --search \"no:milestone\"`, `gh issue list --state closed --search \"no:milestone\"`. Assign with `gh pr edit N --milestone \"vX.Y.Z\"` / `gh issue edit N --milestone \"vX.Y.Z\"`.\n\n**Issue labels** — classify each issue with a type and an area (add priority when relevant):\n- Type: `bug`, `enhancement`, `question`, `documentation`, `discussion`\n- Area: `backend`, `frontend`, `site`, `CI`, `design`, `localization`\n- Priority: `important`, `minor`, `some day`\n- Contribution: `help wanted`, `good-first-issue`\n- Resolution (on close, when applicable): `duplicate`, `invalid`, `wontfix`, `no-action-needed`\n- PR auto-labels (applied by Dependabot/Actions, not manual PRs): `dependencies`, `go`, `javascript`, `github_actions`\n\n## Code Style\n- **Backend**: Formatting with golangci-lint, strict error handling\n- **Frontend**: TypeScript with ESLint, Stylelint and Prettier\n- **Imports**: Group stdlib, external packages, then internal packages\n- **CSS**: All components use CSS Modules (`component.module.css`). Class naming: BEM block = `.root`, elements = camelCase, modifiers = camelCase. Use `clsx` for conditional class composition. `raw-content.css` is the only global CSS file (syntax highlighting utility). Root wrapper keeps bare `.dark`/`.light` theme class — 8+ module CSS files depend on `:global(.dark)` ancestor. `comment_highlighting` uses `:global()` for imperative `classList` usage in root.tsx\n\n## Key Backend Packages\n- **Web/API**: `github.com/go-pkgz/routegroup`, `github.com/go-pkgz/rest`\n- **Auth**: `github.com/go-pkgz/auth/v2`\n- **Logging**: `github.com/go-pkgz/lgr`\n- **Testing**: `github.com/stretchr/testify`\n- **Notifications**: `github.com/go-pkgz/notify`\n\n## Repository Structure\n- Backend: Go server using BoltDB for storage\n- Frontend: Preact/Redux-based UI with iframe embedding\n"},"files":{"CLAUDE.md":"# Remark42 Development Guidelines\n\n## Build/Test/Lint Commands\n- **Backend**:\n  - Run server: `make rundev`\n  - Build: `make backend`\n  - Race test: `make race_test`\n- **Backend Testing**:\n  - Run all tests: `cd backend/app && go test -timeout=60s -count 1 ./...`\n  - Run single test: `cd backend/app && go test -run TestName ./path/to/package`\n  - **IMPORTANT**: Run example tests: `cd backend/_example/memory_store && go test -race ./... && go build -race ./...`\n- **Frontend**:\n  - Development: `cd frontend && pnpm dev:app`\n  - Tests: `cd frontend && pnpm test`\n- **Lint**:\n  - Backend: `cd backend && golangci-lint run`\n  - **IMPORTANT**: Example lint: `cd backend/_example/memory_store && golangci-lint run --config ../../.golangci.yml`\n  - Frontend: `cd frontend && pnpm lint`\n  - **Before committing**: Always run tests and linter on both main backend AND examples\n- **Dependency Updates**:\n  - When updating Go modules in `backend/`, also run `go mod tidy` (and `go mod vendor`) in `backend/_example/memory_store` to keep indirect deps in sync. The example module replaces `github.com/umputun/remark42/backend` with `../../` so stale indirect deps there will break the example build.\n\n## Release Procedure\n\nRemark42 uses two tags for each release:\n- `vX.Y.Z` - product release tag used by GitHub releases, GoReleaser binary artifacts, and Docker image publishing.\n- `backend/vX.Y.Z` - nested Go module tag for `github.com/umputun/remark42/backend`.\n\nRelease flow:\n1. Create the GitHub release for `vX.Y.Z` with title `Version X.Y.Z`. The GitHub release must exist before the `vX.Y.Z` tag reaches the remote; `gh release create vX.Y.Z` satisfies this because it creates and pushes the tag.\n2. The `vX.Y.Z` tag triggers GoReleaser, which builds and uploads binary artifacts to the existing release.\n3. Create and push the matching backend module tag pointing at the same commit:\n\n```bash\ngit fetch origin --tags\ngit tag backend/vX.Y.Z vX.Y.Z\ngit push origin backend/vX.Y.Z\n```\n\nGoReleaser must ignore `backend/*` tags in `.goreleaser.yml` so release notes and current-tag detection use only product tags. Docker image publishing stays separate and is handled by the existing Docker workflow.\n\nFor local artifact runs, install GoReleaser, Go 1.25, Node 16+, PNPM 8, and Perl, then use `make release`. The target runs a snapshot/no-publish GoReleaser build, leaves local artifacts and metadata in `dist/`, and cleans generated frontend embed files after GoReleaser exits. Do not run raw `goreleaser release` for local artifacts unless you also run `./scripts/cleanup-release-assets.sh` afterward.\n\n## Milestones and Issue Labels\n\n**Milestones** — one `vX.Y.Z` milestone per release. Assign every merged PR, and every issue closed by a code change, to the milestone of the release it shipped in.\n- Decide which release a PR belongs to by whether its merge commit is **contained in a release tag** — not by comparing dates (a tag can be cut from an earlier commit, or moved). `git fetch --tags`, then `git tag --contains <merge_sha> | grep '^v' | sort -V | head -1` is its release. If no release tag contains it yet, it belongs to the next (unreleased) version's milestone — create it if missing (`gh api repos/umputun/remark42/milestones -f title=\"vX.Y.Z\"`).\n- An **issue gets a milestone only when it was closed by a code change** (a linked closing PR/commit); take the milestone from that PR/commit (via the commit-in-tag rule). Issues closed as `duplicate`/`invalid`/`wontfix`/answered get no milestone.\n- Find unassigned: `gh pr list --state merged --search \"no:milestone\"`, `gh issue list --state closed --search \"no:milestone\"`. Assign with `gh pr edit N --milestone \"vX.Y.Z\"` / `gh issue edit N --milestone \"vX.Y.Z\"`.\n\n**Issue labels** — classify each issue with a type and an area (add priority when relevant):\n- Type: `bug`, `enhancement`, `question`, `documentation`, `discussion`\n- Area: `backend`, `frontend`, `site`, `CI`, `design`, `localization`\n- Priority: `important`, `minor`, `some day`\n- Contribution: `help wanted`, `good-first-issue`\n- Resolution (on close, when applicable): `duplicate`, `invalid`, `wontfix`, `no-action-needed`\n- PR auto-labels (applied by Dependabot/Actions, not manual PRs): `dependencies`, `go`, `javascript`, `github_actions`\n\n## Code Style\n- **Backend**: Formatting with golangci-lint, strict error handling\n- **Frontend**: TypeScript with ESLint, Stylelint and Prettier\n- **Imports**: Group stdlib, external packages, then internal packages\n- **CSS**: All components use CSS Modules (`component.module.css`). Class naming: BEM block = `.root`, elements = camelCase, modifiers = camelCase. Use `clsx` for conditional class composition. `raw-content.css` is the only global CSS file (syntax highlighting utility). Root wrapper keeps bare `.dark`/`.light` theme class — 8+ module CSS files depend on `:global(.dark)` ancestor. `comment_highlighting` uses `:global()` for imperative `classList` usage in root.tsx\n\n## Key Backend Packages\n- **Web/API**: `github.com/go-pkgz/routegroup`, `github.com/go-pkgz/rest`\n- **Auth**: `github.com/go-pkgz/auth/v2`\n- **Logging**: `github.com/go-pkgz/lgr`\n- **Testing**: `github.com/stretchr/testify`\n- **Notifications**: `github.com/go-pkgz/notify`\n\n## Repository Structure\n- Backend: Go server using BoltDB for storage\n- Frontend: Preact/Redux-based UI with iframe embedding\n"},"items":[{"name":"CLAUDE.md","path":"CLAUDE.md","title":"CLAUDE.md","content":"# Remark42 Development Guidelines\n\n## Build/Test/Lint Commands\n- **Backend**:\n  - Run server: `make rundev`\n  - Build: `make backend`\n  - Race test: `make race_test`\n- **Backend Testing**:\n  - Run all tests: `cd backend/app && go test -timeout=60s -count 1 ./...`\n  - Run single test: `cd backend/app && go test -run TestName ./path/to/package`\n  - **IMPORTANT**: Run example tests: `cd backend/_example/memory_store && go test -race ./... && go build -race ./...`\n- **Frontend**:\n  - Development: `cd frontend && pnpm dev:app`\n  - Tests: `cd frontend && pnpm test`\n- **Lint**:\n  - Backend: `cd backend && golangci-lint run`\n  - **IMPORTANT**: Example lint: `cd backend/_example/memory_store && golangci-lint run --config ../../.golangci.yml`\n  - Frontend: `cd frontend && pnpm lint`\n  - **Before committing**: Always run tests and linter on both main backend AND examples\n- **Dependency Updates**:\n  - When updating Go modules in `backend/`, also run `go mod tidy` (and `go mod vendor`) in `backend/_example/memory_store` to keep indirect deps in sync. The example module replaces `github.com/umputun/remark42/backend` with `../../` so stale indirect deps there will break the example build.\n\n## Release Procedure\n\nRemark42 uses two tags for each release:\n- `vX.Y.Z` - product release tag used by GitHub releases, GoReleaser binary artifacts, and Docker image publishing.\n- `backend/vX.Y.Z` - nested Go module tag for `github.com/umputun/remark42/backend`.\n\nRelease flow:\n1. Create the GitHub release for `vX.Y.Z` with title `Version X.Y.Z`. The GitHub release must exist before the `vX.Y.Z` tag reaches the remote; `gh release create vX.Y.Z` satisfies this because it creates and pushes the tag.\n2. The `vX.Y.Z` tag triggers GoReleaser, which builds and uploads binary artifacts to the existing release.\n3. Create and push the matching backend module tag pointing at the same commit:\n\n```bash\ngit fetch origin --tags\ngit tag backend/vX.Y.Z vX.Y.Z\ngit push origin backend/vX.Y.Z\n```\n\nGoReleaser must ignore `backend/*` tags in `.goreleaser.yml` so release notes and current-tag detection use only product tags. Docker image publishing stays separate and is handled by the existing Docker workflow.\n\nFor local artifact runs, install GoReleaser, Go 1.25, Node 16+, PNPM 8, and Perl, then use `make release`. The target runs a snapshot/no-publish GoReleaser build, leaves local artifacts and metadata in `dist/`, and cleans generated frontend embed files after GoReleaser exits. Do not run raw `goreleaser release` for local artifacts unless you also run `./scripts/cleanup-release-assets.sh` afterward.\n\n## Milestones and Issue Labels\n\n**Milestones** — one `vX.Y.Z` milestone per release. Assign every merged PR, and every issue closed by a code change, to the milestone of the release it shipped in.\n- Decide which release a PR belongs to by whether its merge commit is **contained in a release tag** — not by comparing dates (a tag can be cut from an earlier commit, or moved). `git fetch --tags`, then `git tag --contains <merge_sha> | grep '^v' | sort -V | head -1` is its release. If no release tag contains it yet, it belongs to the next (unreleased) version's milestone — create it if missing (`gh api repos/umputun/remark42/milestones -f title=\"vX.Y.Z\"`).\n- An **issue gets a milestone only when it was closed by a code change** (a linked closing PR/commit); take the milestone from that PR/commit (via the commit-in-tag rule). Issues closed as `duplicate`/`invalid`/`wontfix`/answered get no milestone.\n- Find unassigned: `gh pr list --state merged --search \"no:milestone\"`, `gh issue list --state closed --search \"no:milestone\"`. Assign with `gh pr edit N --milestone \"vX.Y.Z\"` / `gh issue edit N --milestone \"vX.Y.Z\"`.\n\n**Issue labels** — classify each issue with a type and an area (add priority when relevant):\n- Type: `bug`, `enhancement`, `question`, `documentation`, `discussion`\n- Area: `backend`, `frontend`, `site`, `CI`, `design`, `localization`\n- Priority: `important`, `minor`, `some day`\n- Contribution: `help wanted`, `good-first-issue`\n- Resolution (on close, when applicable): `duplicate`, `invalid`, `wontfix`, `no-action-needed`\n- PR auto-labels (applied by Dependabot/Actions, not manual PRs): `dependencies`, `go`, `javascript`, `github_actions`\n\n## Code Style\n- **Backend**: Formatting with golangci-lint, strict error handling\n- **Frontend**: TypeScript with ESLint, Stylelint and Prettier\n- **Imports**: Group stdlib, external packages, then internal packages\n- **CSS**: All components use CSS Modules (`component.module.css`). Class naming: BEM block = `.root`, elements = camelCase, modifiers = camelCase. Use `clsx` for conditional class composition. `raw-content.css` is the only global CSS file (syntax highlighting utility). Root wrapper keeps bare `.dark`/`.light` theme class — 8+ module CSS files depend on `:global(.dark)` ancestor. `comment_highlighting` uses `:global()` for imperative `classList` usage in root.tsx\n\n## Key Backend Packages\n- **Web/API**: `github.com/go-pkgz/routegroup`, `github.com/go-pkgz/rest`\n- **Auth**: `github.com/go-pkgz/auth/v2`\n- **Logging**: `github.com/go-pkgz/lgr`\n- **Testing**: `github.com/stretchr/testify`\n- **Notifications**: `github.com/go-pkgz/notify`\n\n## Repository Structure\n- Backend: Go server using BoltDB for storage\n- Frontend: Preact/Redux-based UI with iframe embedding\n","category":"root","tokens":1341}]}