From 3151281403a4f0fa8a477339e5c062978519b8bd Mon Sep 17 00:00:00 2001 From: simonweigold Date: Mon, 20 Apr 2026 17:43:19 +0200 Subject: [PATCH 01/22] Init plan for pypi release --- docs_for_dev/PYPI_RELEASE.md | 229 +++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 docs_for_dev/PYPI_RELEASE.md diff --git a/docs_for_dev/PYPI_RELEASE.md b/docs_for_dev/PYPI_RELEASE.md new file mode 100644 index 0000000..e90b2d3 --- /dev/null +++ b/docs_for_dev/PYPI_RELEASE.md @@ -0,0 +1,229 @@ +# PyPI Release Plan for `openclerk` + +## Pre-Release Todo List + +Use this checklist to track progress toward the first PyPI release. + +- [ ] **P0**: Verify URLs in pyproject.toml (`packages/clerk/pyproject.toml`) +- [ ] **P0**: Create release workflow (`.github/workflows/release.yml`) +- [ ] **P0**: Ensure LICENSE is packaged (verify or add to package) +- [ ] **P1**: Add release commands to Justfile (`Justfile`) +- [ ] **P1**: Test build locally (run `uv build`) +- [ ] **P2**: Set up TestPyPI upload (test workflow) +- [ ] **P2**: Configure trusted publishing (PyPI + GitHub settings) + +--- + +## Current State Summary + +| Component | Status | +|-----------|--------| +| Package name | `openclerk` | +| Version | `0.1.0` | +| Location | `packages/clerk/` | +| Build system | Hatchling (via UV) | +| Source layout | `src/openclerk/` | +| Python support | 3.13+ | +| CI/CD | Basic (lint, test) | +| Entry points | `clerk`, `openclerk` | + +--- + +## Pre-Release Checklist + +### 1. Package Metadata Verification +- [ ] **Verify classifiers** are accurate (currently "Development Status :: 3 - Alpha") +- [ ] **Update project URLs** in `pyproject.toml` (currently placeholder GitHub URLs) +- [ ] **Confirm license file** is included in package distribution +- [ ] **Review keywords** for PyPI searchability +- [ ] **Add CHANGELOG.md** reference to pyproject.toml if desired + +### 2. Build Verification +```bash +# Test the build locally +cd packages/clerk +uv build +# Verify wheel and sdist are created in dist/ +``` + +### 3. TestPyCI Testing +- [ ] Create TestPyPI account (if not exists) +- [ ] Upload to TestPyPI: `uv publish --index testpypi` +- [ ] Verify installation: `pip install --index-url https://test.pypi.org/simple/ openclerk` +- [ ] Test CLI: `clerk --version` + +### 4. Long Description Verification +- [ ] Ensure `README.md` renders correctly on PyPI +- [ ] Check relative links work (or use absolute URLs) + +--- + +## Required Additions + +### 1. Release GitHub Workflow + +Create `.github/workflows/release.yml`: + +```yaml +name: Release + +on: + push: + tags: + - "v*.*.*" + +jobs: + release: + runs-on: ubuntu-latest + environment: release + permissions: + id-token: write # For trusted publishing + + steps: + - uses: actions/checkout@v4 + + - uses: astral-sh/setup-uv@v3 + with: + version: "0.4.x" + + - name: Build package + run: | + cd packages/clerk + uv build + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: packages/clerk/dist/ +``` + +### 2. Justfile Release Commands + +Add to `Justfile`: + +```just +# Build package for distribution +build: + cd packages/clerk && uv build + +# Publish to TestPyPI +publish-test: build + cd packages/clerk && uv publish --index testpypi + +# Publish to PyPI (requires credentials) +publish: build + cd packages/clerk && uv publish + +# Create a new version tag +version NEW_VERSION: + cd packages/clerk && uvx bump-my-version bump {{NEW_VERSION}} +``` + +### 3. Version Management + +Options: +- **Option A**: Manual version bumping in `pyproject.toml` and `__init__.py` +- **Option B**: Use `bump-my-version` or `hatch-vcs` for automated versioning +- **Option C**: Use git tags with `hatch-vcs` (recommended) + +--- + +## Release Process + +### Phase 1: Preparation (Pre-Release) + +1. **Update version** in both: + - `packages/clerk/pyproject.toml` + - `packages/clerk/src/openclerk/__init__.py` + +2. **Update CHANGELOG.md** with release notes + +3. **Run full test suite**: + ```bash + just test + just lint + ``` + +4. **Build and verify**: + ```bash + just build + ``` + +5. **TestPyPI upload**: + ```bash + just publish-test + ``` + +### Phase 2: Release + +1. **Create git tag**: + ```bash + git tag v0.1.0 + git push origin v0.1.0 + ``` + +2. **GitHub Release** (auto-triggers workflow): + - Navigate to Releases → Create release + - Select tag `v0.1.0` + - Add release notes from CHANGELOG + - Publish + +3. **Verify PyPI**: + - Check package appears at https://pypi.org/project/openclerk/ + - Test: `pip install openclerk` + +### Phase 3: Post-Release + +1. **Update documentation** with installation instructions +2. **Announce** on relevant channels +3. **Bump to dev version** (e.g., `0.2.0-dev`) for next cycle + +--- + +## Open Questions + +Before proceeding, clarify the following: + +1. **PyPI Account**: Do you have a PyPI account set up for `openclerk`? Is the package name reserved? + +2. **Versioning Strategy**: + - Option A: Manual version bumps (simple, explicit) + - Option B: Automated via git tags with `hatch-vcs` (recommended for CI/CD) + +3. **Trusted Publishing**: Would you like to set up PyPI trusted publishing (OIDC) for the GitHub workflow, or use API tokens? + +4. **TestPyPI**: Should we automate TestPyPI uploads on every merge to main, or only on demand? + +5. **Homepage URL**: The README shows `openclerk.dev` - is this the correct domain for `project.urls.Homepage`? + +6. **License**: The LICENSE file is at root level. Should it be copied to `packages/clerk/` or is hatchling configured to find it at workspace root? + +--- + +## Reference Commands + +### Local Build & Test +```bash +# Build package +cd packages/clerk +uv build + +# Check what's in the wheel +unzip -l dist/openclerk-*.whl + +# Check what's in the sdist +tar -tzf dist/openclerk-*.tar.gz +``` + +### Manual PyPI Upload (if not using GitHub Actions) +```bash +# Configure PyPI credentials +uv publish --username __token__ --password $PYPI_TOKEN + +# Or use the Justfile command +just publish +``` + +--- + +*Last updated: 2026-04-20* From 0cba1d6c36eb7e04328dd15221f79c0fa84bf4dd Mon Sep 17 00:00:00 2001 From: simonweigold Date: Mon, 20 Apr 2026 21:35:34 +0200 Subject: [PATCH 02/22] Hotfix: astral version --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2828c98..763e380 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: astral-sh/setup-uv@v3 + - uses: astral-sh/setup-uv@v4 with: version: "0.4.x" - uses: extractions/setup-just@v2 @@ -26,7 +26,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - - uses: astral-sh/setup-uv@v3 + - uses: astral-sh/setup-uv@v4 with: version: "0.4.x" - uses: extractions/setup-just@v2 From ec633d3b5bf111c3093ce24a009e7cce3464bb51 Mon Sep 17 00:00:00 2001 From: simonweigold Date: Mon, 20 Apr 2026 21:35:48 +0200 Subject: [PATCH 03/22] Add documentation and web UI features - Created overview and running kits documentation in the web UI. - Added a comprehensive user guide covering installation, workflows, and common commands. - Introduced core concepts documentation detailing reasoning kits, resources, instructions, and workflows. - Developed an FAQ section addressing common installation and usage questions. - Implemented a new DocsPage component for rendering documentation with navigation. - Integrated documentation syncing script to keep website docs updated. - Updated App and Layout components to include documentation links in the navigation. - Adjusted project metadata to reflect the correct repository links. --- Justfile | 8 + apps/frontend/src/pages/DocsPage.tsx | 181 +- apps/website/README.md | 39 +- apps/website/package-lock.json | 1592 ++++++++++++++++- apps/website/package.json | 4 +- apps/website/public/docs/README.md | 34 + apps/website/public/docs/cli/db.md | 33 + apps/website/public/docs/cli/info.md | 26 + apps/website/public/docs/cli/kit.md | 66 + apps/website/public/docs/cli/list.md | 22 + apps/website/public/docs/cli/run.md | 28 + apps/website/public/docs/cli/sync.md | 29 + apps/website/public/docs/cli/web.md | 22 + .../public/docs/contributing/README.md | 131 ++ .../public/docs/contributing/architecture.md | 309 ++++ .../website/public/docs/contributing/setup.md | 108 ++ apps/website/public/docs/deployment/docker.md | 415 +++++ .../public/docs/deployment/environment.md | 520 ++++++ .../public/docs/deployment/production.md | 739 ++++++++ apps/website/public/docs/integration.md | 129 ++ .../website/public/docs/integration/README.md | 222 +++ .../public/docs/integration/api-reference.md | 176 ++ .../public/docs/integration/examples.md | 128 ++ apps/website/public/docs/manifest.json | 33 + apps/website/public/docs/mcp.md | 20 + apps/website/public/docs/reasoning_kits.md | 51 + apps/website/public/docs/timestamp.json | 4 + apps/website/public/docs/ui/editing_kits.md | 16 + apps/website/public/docs/ui/overview.md | 21 + apps/website/public/docs/ui/running_kits.md | 18 + apps/website/public/docs/user-guide/README.md | 102 ++ .../public/docs/user-guide/concepts.md | 124 ++ apps/website/public/docs/user-guide/faq.md | 174 ++ apps/website/src/App.tsx | 5 + apps/website/src/components/Layout.tsx | 6 +- apps/website/src/hooks/useDocs.ts | 249 +++ apps/website/src/pages/DocsPage.tsx | 335 ++++ docs/README.md | 22 +- packages/clerk/pyproject.toml | 4 +- scripts/sync-docs.sh | 103 ++ 40 files changed, 6114 insertions(+), 134 deletions(-) create mode 100644 apps/website/public/docs/README.md create mode 100644 apps/website/public/docs/cli/db.md create mode 100644 apps/website/public/docs/cli/info.md create mode 100644 apps/website/public/docs/cli/kit.md create mode 100644 apps/website/public/docs/cli/list.md create mode 100644 apps/website/public/docs/cli/run.md create mode 100644 apps/website/public/docs/cli/sync.md create mode 100644 apps/website/public/docs/cli/web.md create mode 100644 apps/website/public/docs/contributing/README.md create mode 100644 apps/website/public/docs/contributing/architecture.md create mode 100644 apps/website/public/docs/contributing/setup.md create mode 100644 apps/website/public/docs/deployment/docker.md create mode 100644 apps/website/public/docs/deployment/environment.md create mode 100644 apps/website/public/docs/deployment/production.md create mode 100644 apps/website/public/docs/integration.md create mode 100644 apps/website/public/docs/integration/README.md create mode 100644 apps/website/public/docs/integration/api-reference.md create mode 100644 apps/website/public/docs/integration/examples.md create mode 100644 apps/website/public/docs/manifest.json create mode 100644 apps/website/public/docs/mcp.md create mode 100644 apps/website/public/docs/reasoning_kits.md create mode 100644 apps/website/public/docs/timestamp.json create mode 100644 apps/website/public/docs/ui/editing_kits.md create mode 100644 apps/website/public/docs/ui/overview.md create mode 100644 apps/website/public/docs/ui/running_kits.md create mode 100644 apps/website/public/docs/user-guide/README.md create mode 100644 apps/website/public/docs/user-guide/concepts.md create mode 100644 apps/website/public/docs/user-guide/faq.md create mode 100644 apps/website/src/hooks/useDocs.ts create mode 100644 apps/website/src/pages/DocsPage.tsx create mode 100755 scripts/sync-docs.sh diff --git a/Justfile b/Justfile index 6ef78d9..dfb7029 100644 --- a/Justfile +++ b/Justfile @@ -43,6 +43,14 @@ dev-backend: dev-frontend: cd apps/website && npm run dev +# Sync documentation to website +sync-docs: + ./scripts/sync-docs.sh + +# Build website for production (includes docs sync) +build-website: sync-docs + cd apps/website && npm run build + # Clean build artifacts clean: find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true diff --git a/apps/frontend/src/pages/DocsPage.tsx b/apps/frontend/src/pages/DocsPage.tsx index 8c7a885..a12643c 100644 --- a/apps/frontend/src/pages/DocsPage.tsx +++ b/apps/frontend/src/pages/DocsPage.tsx @@ -7,22 +7,22 @@ import { getDocsList, getDocContent, type DocItem } from '../lib/api'; export default function DocsPage() { return (
-
- Documentation Menu - -
- -
+
+ Documentation Menu + +
+ +
} /> } /> @@ -33,17 +33,12 @@ export default function DocsPage() { } function DocViewerWrapper() { - // We use a splat route so this works for nested stuff like ui/overview const [slug, setSlug] = useState(''); const location = useLocation(); useEffect(() => { - // Remove leading "/docs/" from the pathname let path = location.pathname.replace(/^\/docs\/?/, '') || 'README'; - // Strip trailing .md if present to fix 404s - if (path.endsWith('.md')) { - path = path.slice(0, -3); - } + if (path.endsWith('.md')) path = path.slice(0, -3); setSlug(path); }, [location.pathname]); @@ -78,8 +73,6 @@ function CopyButton({ text }: { text: string }) { ); } - - function DocsSidebar() { const [docs, setDocs] = useState([]); const [loading, setLoading] = useState(true); @@ -134,8 +127,7 @@ function DocsSidebar() { groupedDocs[dir].push(doc); }); - // Custom order - User-centric docs first - const order = ['User Guide', 'Integration', 'Deployment', 'Contributing', 'General', 'CLI Commands', 'UI Features']; + const order = ['General', 'User Guide', 'Integration', 'Deployment', 'Contributing', 'CLI Commands', 'UI Features']; const groups = Object.keys(groupedDocs).sort((a, b) => { const indexA = order.indexOf(a); const indexB = order.indexOf(b); @@ -151,37 +143,84 @@ function DocsSidebar() { Documentation
); } +/** Convert React children to a plain text string for generating heading IDs */ +function nodeToText(node: any): string { + if (typeof node === 'string') return node; + if (typeof node === 'number') return String(node); + if (Array.isArray(node)) return node.map(nodeToText).join(''); + if (node?.props?.children) return nodeToText(node.props.children); + return ''; +} + +/** Generate a GitHub-style anchor ID from heading text */ +function toHeadingId(children: any): string { + return nodeToText(children) + .toLowerCase() + .replace(/[^\w\s-]/g, '') + .replace(/\s+/g, '-') + .replace(/-+/g, '-') + .trim(); +} + function DocViewer({ slug }: { slug: string }) { const [content, setContent] = useState(''); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const navigate = useNavigate(); + const location = useLocation(); + // Fetch document content useEffect(() => { setLoading(true); setError(''); @@ -197,6 +236,20 @@ function DocViewer({ slug }: { slug: string }) { }); }, [slug]); + // Scroll to top on doc change, or to the anchor if there's a hash + useEffect(() => { + if (loading) return; + const hash = location.hash; + if (hash) { + setTimeout(() => { + const el = document.getElementById(hash.slice(1)); + if (el) el.scrollIntoView({ behavior: 'smooth' }); + }, 50); + } else { + window.scrollTo(0, 0); + } + }, [slug, loading, location.hash]); + if (loading) { return (
@@ -224,9 +277,18 @@ function DocViewer({ slug }: { slug: string }) {

, - h2: ({node, ...props}) =>

, - h3: ({node, ...props}) =>

, + h1: ({ node, children, ...props }) => { + const id = toHeadingId(children); + return

{children}

; + }, + h2: ({ node, children, ...props }) => { + const id = toHeadingId(children); + return

{children}

; + }, + h3: ({ node, children, ...props }) => { + const id = toHeadingId(children); + return

{children}

; + }, p: ({node, ...props}) =>

, ul: ({node, ...props}) =>