From 294584a553211c5956084cb9b5f4bcc07c9fb577 Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Thu, 2 Jul 2026 14:37:52 +0200 Subject: [PATCH 1/4] Review automation and add custom spelling rules to Vale --- .github/vale/PowerSync/Capitalization.yml | 13 +++++ .github/vale/PowerSync/Terminology.yml | 18 +++++++ .github/workflows/docs-review.yaml | 61 +++++++++++++++++++++++ .vale.ini | 2 +- maintenance-ops/self-hosting/coolify.mdx | 2 +- 5 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 .github/vale/PowerSync/Capitalization.yml create mode 100644 .github/vale/PowerSync/Terminology.yml create mode 100644 .github/workflows/docs-review.yaml diff --git a/.github/vale/PowerSync/Capitalization.yml b/.github/vale/PowerSync/Capitalization.yml new file mode 100644 index 00000000..62faa214 --- /dev/null +++ b/.github/vale/PowerSync/Capitalization.yml @@ -0,0 +1,13 @@ +# Enforces product-term capitalization from the terminology table in .claude/CLAUDE.md. +# Each pattern lists the incorrect casings; the correct form does not match. +extends: substitution +message: "Use '%s' instead of '%s'." +level: error +ignorecase: false +# The 'PowerSync' vocabulary entry would otherwise suppress matches like +# 'PowerSync service' (vocabulary terms are substitution exceptions by default). +vocab: false +swap: + 'Sync rules|sync [Rr]ules': Sync Rules + 'Sync streams|sync [Ss]treams': Sync Streams + '[Pp]owersync [Ss]ervice|PowerSync service': PowerSync Service diff --git a/.github/vale/PowerSync/Terminology.yml b/.github/vale/PowerSync/Terminology.yml new file mode 100644 index 00000000..1c30497d --- /dev/null +++ b/.github/vale/PowerSync/Terminology.yml @@ -0,0 +1,18 @@ +# Enforces the terminology table in .claude/CLAUDE.md. +# vocab: false is required. The spelling vocabularies accept 'PostgreSQL' and +# 'replication', and vocabulary terms are exceptions to substitution rules by +# default, which would silently disable these swaps. +extends: substitution +message: "Use '%s' instead of '%s'." +level: error +ignorecase: true +vocab: false +swap: + # Swapping the Microsoft product name to itself suppresses it: longer keys + # match first, and matches identical to their replacement are not flagged. + 'Azure Database for PostgreSQL': Azure Database for PostgreSQL + 'synchroni[sz]ation': sync + # The lookbehind skips URLs (postgresql.org, docs/postgresql) that Vale's + # scope ignores miss inside indented MDX components. + '(? + !github.event.pull_request.draft && + github.event.pull_request.head.repo.full_name == github.repository + permissions: + contents: read + pull-requests: write + issues: read + id-token: write + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Review documentation changes + uses: anthropics/claude-code-action@v1 + with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + prompt: | + You are reviewing pull request #${{ github.event.pull_request.number }} in ${{ github.repository }}. + + Read .claude/agents/document-reviewer.md and apply its review checklist to the + documentation changes in this PR. Use `gh pr diff ${{ github.event.pull_request.number }}` + to see the changes. + + Scope: + - Review only content that this PR adds or modifies. Do not flag pre-existing + issues in unchanged parts of a file. + - Read the full file for any changed .mdx file when you need surrounding context + (frontmatter, heading hierarchy, tab order). + + Reporting: + - Post each specific issue as an inline comment on the relevant line using + mcp__github_inline_comment__create_inline_comment. Include the rule violated + and a suggested fix. + - Post one summary comment with `gh pr comment` giving the overall assessment + (Approve / Approve with minor fixes / Needs revision) and anything that does + not map to a single line. + - If there are no issues, post only the summary comment saying the changes pass + the writing standards review. + claude_args: | + --model claude-sonnet-5 + --allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr comment:*)" diff --git a/.vale.ini b/.vale.ini index 1c69c9e5..b8d8ff14 100644 --- a/.vale.ini +++ b/.vale.ini @@ -13,7 +13,7 @@ mdx = md # MDX support [*.mdx] -BasedOnStyles = Vale +BasedOnStyles = Vale, PowerSync Vale.Terms = NO # Enforces really harsh capitalization rules, keep off TokenIgnores = (?sm)((?:import|export) .+?$), \ diff --git a/maintenance-ops/self-hosting/coolify.mdx b/maintenance-ops/self-hosting/coolify.mdx index 3d9609c4..591ac6df 100644 --- a/maintenance-ops/self-hosting/coolify.mdx +++ b/maintenance-ops/self-hosting/coolify.mdx @@ -78,7 +78,7 @@ The following configuration options should be updated: PS_DATABASE_TYPE - postgresql + `postgresql` PS_DATABASE_URI From 121e7bdfdc659d15ad166e225f8a64c027a6dd1f Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Thu, 2 Jul 2026 15:13:53 +0200 Subject: [PATCH 2/4] More review automation, including checking external links --- .claude/agents/document-reviewer.md | 94 +++------- .claude/skills/doc-reader/SKILL.md | 239 +++++++++++++++++++++++++ .github/vale/PowerSync/FirstPerson.yml | 19 ++ .github/workflows/check.yaml | 23 +++ .github/workflows/docs-review.yaml | 2 + .gitignore | 1 + lychee.toml | 24 +++ 7 files changed, 333 insertions(+), 69 deletions(-) create mode 100644 .claude/skills/doc-reader/SKILL.md create mode 100644 .github/vale/PowerSync/FirstPerson.yml create mode 100644 lychee.toml diff --git a/.claude/agents/document-reviewer.md b/.claude/agents/document-reviewer.md index c960746d..b5ea44f6 100644 --- a/.claude/agents/document-reviewer.md +++ b/.claude/agents/document-reviewer.md @@ -6,87 +6,43 @@ model: sonnet # PowerSync Documentation Reviewer -You are an experienced, pragmatic technical writer reviewing PowerSync documentation. Your job is to help maintain accuracy, clarity, and consistency — not to approve content unconditionally. +You are an experienced, pragmatic technical writer reviewing PowerSync documentation. The standards you enforce are defined in this repository's CLAUDE.md; that file is the single source of truth. Your job is to apply those standards with judgment, not to approve content unconditionally. -**Rule #1**: If you want an exception to any rule, stop and get explicit permission. Breaking the letter or spirit of the rules is failure. - -## Working Relationship - -- Push back on content that violates standards — cite specific rules when you do - Never rubber-stamp content. Give honest technical judgment -- Ask for clarification rather than assuming intent -- Never lie, guess, or make up information about the product -- If you're unsure whether something is technically accurate, say so - -## Review Checklist - -For each piece of content, check the following areas: - -### 1. Frontmatter - -- `title` is present and uses Title Case -- `description` is present, concise, and does not duplicate the opening paragraph -- No other required fields are missing - -### 2. Writing Standards - -- Second person ("you") throughout -- Active voice, present tense -- No promotional or marketing language ("breathtaking," "robust," "stands as a testament," etc.) -- No editorializing ("it's important to note," "in conclusion") -- No filler words in titles or descriptions ("Comprehensive," "Complete," "Significant") -- No "local-first" or "offline-first" — replace with outcome language: "responds instantly," "stays fully functional in poor network conditions," "responsive" -- No excessive use of "moreover," "furthermore," "additionally" -- Bold used sparingly — only for terms being defined or critical distinctions -- No em-dash connectors between clauses — two sentences instead -- Concepts written out in full sentences, not comma-separated shorthand +- Cite the specific standard when you flag an issue +- If you're unsure whether something is technically accurate, say so rather than guessing +- Only flag issues in content the change adds or modifies, unless asked for a full-page audit -### 3. Headings +## Skip What the Linters Cover -- Title Case throughout -- Hierarchy starts at H2 (H1 is the page title) -- No verb-first headings unless a procedural step +Deterministic checks run in CI. Don't re-report what they catch: -### 4. Terminology +- Spelling and American English: Vale (`Vale.Spelling`) +- Terminology and product-name capitalization (Postgres, sync, partial sync, Sync Rules, Sync Streams, PowerSync Service): Vale (`PowerSync.Terminology`, `PowerSync.Capitalization`) +- First-person singular in body text: Vale (`PowerSync.FirstPerson`) +- Broken internal links and redirects: `mint broken-links` +- Broken external links: lychee -| Use | Avoid | -|-----|-------| -| sync | synchronization | -| Postgres | PostgreSQL | -| partial sync | dynamic partial replication | -| PowerSync Service | powersync service | -| Sync Rules | sync rules | -| Sync Streams | sync streams | - -### 5. Code Examples - -- Language tag present on every code block -- No aliases in SQL unless required (self-joins, ambiguous columns) -- Realistic data — not `foo`, `bar`, `example.com` -- No real API keys or secrets -- No filename shown on Cloud/dashboard examples (only on self-hosted) - -### 6. Mintlify Components - -- `` for sequential procedures -- `` for platform-specific content -- SDK tab order: JS → Dart → Kotlin → Swift → .NET → Rust -- `` wrapping all images -- Callouts used appropriately (``, ``, ``, ``, ``) - -### 7. Links - -- Internal links use relative paths (`/sync/streams/overview`, not absolute URLs) -- No unverified external links +## Review Checklist -### 8. Sync Streams and Sync Rules +These require judgment. Each item maps to a section of CLAUDE.md; apply the full rule as written there. -- Sync Streams are the default — flag any new content that teaches or adds Sync Rules examples -- If existing content shows both side by side, verify the examples return the same data with no mismatched filters +1. **Frontmatter**: `title` and `description` present; description and opening paragraph don't duplicate each other. +2. **Structure**: most important information first; prerequisites at the start of procedures; heading hierarchy starts at H2; headings in Title Case; no verb-first headings except procedural steps. +3. **Voice and tone**: second person, active voice, present tense; no promotional language ("gamechanging," "plays a vital role," or similar); no editorializing ("it's important to note," "in conclusion") or difficulty-minimizing words ("simply," "just," "easily," "obviously"); no filler words in titles or descriptions ("Comprehensive," "Complete"); direct statements over "moreover"/"furthermore"/"additionally"; jargon defined on first use; no generic introductions or concluding summaries that repeat the page. +4. **Insider terms**: "local-first" and "offline-first" only with context. Prefer describing the outcome: the app responds instantly and stays functional in poor network conditions. +5. **Dashes**: no dashes joining clauses in running prose; write two sentences. Genuinely parenthetical asides, headings, and code are fine. +6. **Bold**: reserved for terms being defined and critical distinctions a skimming reader would miss. +7. **Components**: the right Mintlify component for the job (`` for procedures, `` for platforms, `` for multi-language examples, appropriate callouts); SDK tab order JS, Dart, Kotlin, Swift, .NET, Rust; images wrapped in `` with descriptive alt text. +8. **Code examples**: language tag on every block; realistic data; no real secrets; filenames only on self-hosted examples; no SQL table aliases unless required. +9. **Links and navigation**: internal links use relative paths, never absolute URLs; new pages appear in `docs.json` navigation; moved or removed pages have redirects. +10. **Sync Streams policy**: no new content that teaches or promotes Sync Rules; where both appear side by side, the examples must return the same data with matching filters. +11. **Technical accuracy**: flag claims, APIs, or examples you cannot verify. ## Output Format For each issue found, state: + 1. The specific rule violated 2. The problematic text (quoted) 3. A suggested fix diff --git a/.claude/skills/doc-reader/SKILL.md b/.claude/skills/doc-reader/SKILL.md new file mode 100644 index 00000000..6a5e9a01 --- /dev/null +++ b/.claude/skills/doc-reader/SKILL.md @@ -0,0 +1,239 @@ +--- +name: doc-reader +description: Read and navigate external documentation efficiently. Invoke when the task requires checking how a specific function, endpoint, or configuration option works; when the user references an API, SDK, library, or third-party tool by name; when any docs URL or documentation site is mentioned; or when implementing something that depends on an external service or package. +license: MIT +compatibility: Requires internet access. Works best with Mintlify-powered documentation sites which provide MCP servers and llms.txt files. +metadata: + author: Mintlify + url: https://mintlify.com + version: "0.3" +--- + +# Read documentation effectively + +This skill helps you efficiently consume documentation without overwhelming your context window or missing important information. + +## Quick reference: choose your approach + +| Situation | Approach | +|-----------|----------| +| First visit to a doc site | Check for llms.txt, then MCP | +| Know exactly what you're looking for | MCP search or grep llms-full.txt | +| Need to read a specific page | Try `.md` URL variant first, then HTML | +| Exploring/browsing | View HTML page in browser | +| Need comprehensive understanding | Load llms-full.txt (check length first) | +| Multiple doc sites in one task | Set up MCPs for each | + +## Step 1: Discover what's available + +When you encounter a documentation site, check for AI-friendly resources. + +### Check for llms.txt + +Every well-structured doc site should have an llms.txt file at the root. For example `https://docs.example.com/llms.txt` or `https://example.com/docs/llms.txt` + +This file contains: +- A description of what the documentation covers +- Links to each page in the docs + +Sites may also have llms-full.txt files at the root which contain all the content on the documentation site as a single .md file. + +### Try markdown URL variants + +Many doc sites serve clean markdown versions of pages at `.md` URL variants. Prefer the `.md` URL extensions for easier to parse content. + +For any specific page you need to read, try the `.md` variant first: + +``` +https://docs.example.com/page → try https://docs.example.com/page.md +``` + +If it returns valid markdown (not a 404 or HTML error page), use that instead of fetching the HTML. + +### Check for skill.md + +Some documentation sites provide a skill.md file that teaches you how to work with the product that is documented. Check for it at the root like `https://docs.example.com/skill.md` or `https://example.com/docs/skill.md`. + +Read the skill to understand the product and features. Add the skill if it will be helpful with your current task: + +```bash +npx skills add docs.example.com/skill.md +``` + +### Check for MCP server + +Some documentation sites provide MCP servers for semantic search. The MCP endpoint often follows this pattern: + +``` +https://docs.example.com/mcp +``` + +## Step 2: Set up MCP if available + +MCP (Model Context Protocol) servers let you search documentation semantically rather than relying on keyword matching or loading entire files. + +### Connecting to the MCP + +The setup process varies by platform. For Claude Code: + +```json +{ + "mcpServers": { + "example-docs": { + "type": "http", + "url": "https://docs.example.com/mcp" + } + } +} +``` + +Once connected, you'll have access to the search tool for semantic search across the documentation. The tool follows the naming pattern `Search{DocsTitle}` (for example, `SearchMintlify`). + +### Managing multiple MCPs + +When working with multiple documentation sources: + +1. Give each MCP a descriptive name based on the product/library +2. Use the appropriate MCP for each query rather than searching all of them + +## Step 3: Choose your consumption strategy + +### Strategy A: MCP search (preferred for targeted questions) + +Use when: +- You have a specific question or topic +- You're looking for a particular API, function, or concept +- You want semantically relevant results, not just keyword matches + +``` +Use the MCP search tool with a natural language query describing what you need. +``` + +### Strategy B: Fetch markdown variant (for reading specific pages) + +Use when: +- You need to read a specific documentation page +- MCP search returned a result but you need the full page content +- HTML rendering is adding noise or causing truncation + +Try the `.md` variant of the page URL: + +```bash +curl -s "https://docs.example.com/page.md" +``` + +If it returns valid markdown, use it. If it 404s, fall back to HTML (Strategy E). + +### Strategy C: Grep llms-full.txt (for keyword-specific searches) + +Use when: +- You need to find exact matches (function names, error codes, specific terms) +- MCP isn't available +- You want to see all occurrences of a term + +Grep for your terms: +```bash +curl -s "https://docs.example.com/llms-full.txt" | grep -C 3 "your-search-term" +``` + +### Strategy D: Load full content (for comprehensive understanding) + +Use when: +- You need complete context about a library/API +- The llms-full.txt is small enough (< 15k tokens recommended) +- You're doing extensive work that will reference many parts of the docs + +**Always check length first.** Before loading a full file: +```bash +curl -sI "https://docs.example.com/llms-full.txt" | grep -i content-length +``` + +If the file is too large, consider: +- Loading specific files identified from llms.txt instead +- Using MCP search for specific topics +- Loading in chunks as needed + +### Strategy E: View HTML page (for exploration and navigation) + +Use when: +- You need to understand the documentation structure +- The user needs to navigate or click through the docs +- You want to see diagrams, interactive examples, or formatted content +- You're helping the user find something and they need to continue browsing + +Fetch and render the HTML page, or direct the user to open it in their browser. HTML pages provide: +- Navigation menus showing doc structure +- Interactive code examples +- Visual diagrams and illustrations +- Links to related topics + +**Watch for truncation.** Pages over ~150,000 characters may get cut off, which means you may miss critical information without knowing it. If a page seems incomplete, try the `.md` URL variant (Strategy B) or look for section-specific files in llms.txt. + +## Common patterns + +### Pattern: Research before implementation + +1. Fetch llms.txt to understand documentation scope +2. Set up MCP if available +3. Use MCP search for your specific implementation questions +4. Load relevant sections as needed +5. Keep MCP connected for follow-up questions during implementation + +### Pattern: Debugging with docs + +1. Search for the exact error message or code using grep +2. If no results, use MCP search with a description of the problem +3. Load the relevant section for full context on the solution + +### Pattern: Learning a new library + +1. View the HTML landing page to understand structure +2. Load llms-full.txt if small enough, or use section-specific files +3. Set up MCP for ongoing reference during development + +### Pattern: Quick reference lookup + +1. MCP search with the function/method name +2. Or grep llms-full.txt for exact matches + +## Tips for efficiency + +1. **Prefer MCP for Mintlify sites**: Semantic search is more efficient than loading and parsing raw text. + +2. **Cache strategically**: If you'll reference the same docs repeatedly, loading llms-full.txt once may be more efficient than multiple MCP searches. + +3. **Use section files**: If llms.txt links to section-specific files (like `api/llms.txt`), load only what you need. + +4. **Parallel MCP searches**: When working with multiple doc sources, search them in parallel rather than sequentially. + +## Handling edge cases + +### No llms.txt available + +Fall back to: +1. Check if there's an MCP endpoint anyway +2. Try `.md` URL variants of specific pages you need to read +3. Use WebFetch to read specific documentation pages +4. Search the web for the documentation + +### Very large documentation sets + +For docs over 15k tokens: +1. Use MCP search instead of loading the full file +2. Load section-specific files as needed +3. Ask the user which areas are most relevant + +### Page not found (404) + +If a page 404s: +1. Check the 404 page for links to relevant content +2. Check llms.txt for the current URL — it reflects the live site structure +3. Search the MCP with the page topic to find where the content moved +4. Note to the user that the content may have moved and provide the updated URL + +### Outdated or conflicting information + +If you find documentation that seems outdated: +1. Check for version indicators in the docs +2. Note the discrepancy to the user +3. Suggest checking the changelog or release notes diff --git a/.github/vale/PowerSync/FirstPerson.yml b/.github/vale/PowerSync/FirstPerson.yml new file mode 100644 index 00000000..7e1bcae3 --- /dev/null +++ b/.github/vale/PowerSync/FirstPerson.yml @@ -0,0 +1,19 @@ +# Instructional content is written in second person ("you"). "We" is allowed +# for statements from the PowerSync team ("we recommend"), and headings are +# excluded because FAQ-style headings speak in the reader's voice +# ("Where Can I Find..."). +extends: existence +scope: + - paragraph + - list +message: "Avoid first-person singular ('%s'). Write instructions in second person." +level: warning +nonword: true +vocab: false +tokens: + - (?:^|\s)I\s + - (?:^|\s)I,\s + - \bI'm\b + - \bme\b + - \bmy\b + - \bmine\b diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 8ef6f3fe..c2c26410 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -29,3 +29,26 @@ jobs: # This checks internal links, but does not validate external links - name: Check for broken links run: pnpm check:links + + external-links: + name: Check External Links + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Restore lychee cache + uses: actions/cache@v4 + with: + path: .lycheecache + key: lychee-${{ github.sha }} + restore-keys: lychee- + + # Configuration lives in lychee.toml + - name: Check external links + uses: lycheeverse/lychee-action@v2 + with: + args: --no-progress --root-dir "$PWD" '**/*.mdx' + env: + # Raises the rate limit for the many github.com links + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/docs-review.yaml b/.github/workflows/docs-review.yaml index be7c52f4..05aece02 100644 --- a/.github/workflows/docs-review.yaml +++ b/.github/workflows/docs-review.yaml @@ -44,6 +44,8 @@ jobs: Scope: - Review only content that this PR adds or modifies. Do not flag pre-existing issues in unchanged parts of a file. + - CI already runs Vale and the link checkers. Follow the reviewer instructions + on which checks to skip; focus on the judgment calls. - Read the full file for any changed .mdx file when you need surrounding context (frontmatter, heading hierarchy, tab order). diff --git a/.gitignore b/.gitignore index 1c968de2..f2e286fe 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ .idea node_modules +.lycheecache diff --git a/lychee.toml b/lychee.toml new file mode 100644 index 00000000..016cbea6 --- /dev/null +++ b/lychee.toml @@ -0,0 +1,24 @@ +# External link checker configuration (https://lychee.cli.rs). +# Run locally with: lychee --root-dir "$PWD" '**/*.mdx' +# Internal links are resolved against the checkout via --root-dir and then +# skipped by the scheme filter below; `mint broken-links` checks those +# (redirect-aware). This config only validates external http(s) links. + +cache = true +max_cache_age = "1d" +scheme = ["http", "https"] + +# Skip localhost and private IP ranges (used in self-hosting examples). +exclude_all_private = true + +# Resolve internal links against local .mdx files so they parse cleanly. +fallback_extensions = ["mdx"] + +# 403: npmjs.com, dev.mysql.com, and others block CI requests. +# 429: rate limiting is not a broken link. +accept = ["100..=103", "200..=299", "403", "429"] + +# Placeholder hostnames used in configuration examples. +exclude = ["://your-"] + +timeout = 30 From 6a49f6cdf0eb1f8ce0eaf3f03cc9e0f6faa28a06 Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Thu, 2 Jul 2026 15:32:42 +0200 Subject: [PATCH 3/4] Polish after testing --- .claude/agents/document-reviewer.md | 1 + .github/vale/PowerSync/Terminology.yml | 4 +++- maintenance-ops/self-hosting/coolify.mdx | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.claude/agents/document-reviewer.md b/.claude/agents/document-reviewer.md index b5ea44f6..c26e3139 100644 --- a/.claude/agents/document-reviewer.md +++ b/.claude/agents/document-reviewer.md @@ -38,6 +38,7 @@ These require judgment. Each item maps to a section of CLAUDE.md; apply the full 9. **Links and navigation**: internal links use relative paths, never absolute URLs; new pages appear in `docs.json` navigation; moved or removed pages have redirects. 10. **Sync Streams policy**: no new content that teaches or promotes Sync Rules; where both appear side by side, the examples must return the same data with matching filters. 11. **Technical accuracy**: flag claims, APIs, or examples you cannot verify. +12. **Legal and compliance content**: contractual or commercial terms may deviate from standard terminology (for example, "Synchronization Service" in the HIPAA shared-responsibility table). Don't "fix" these; outside legal contexts, the standard terms apply. ## Output Format diff --git a/.github/vale/PowerSync/Terminology.yml b/.github/vale/PowerSync/Terminology.yml index 1c30497d..93479dd3 100644 --- a/.github/vale/PowerSync/Terminology.yml +++ b/.github/vale/PowerSync/Terminology.yml @@ -11,7 +11,9 @@ swap: # Swapping the Microsoft product name to itself suppresses it: longer keys # match first, and matches identical to their replacement are not flagged. 'Azure Database for PostgreSQL': Azure Database for PostgreSQL - 'synchroni[sz]ation': sync + # The lookahead exempts "Synchronization Service", a specific commercial + # term in legal content (HIPAA shared-responsibility table). + 'synchroni[sz]ation(?! Service)': sync # The lookbehind skips URLs (postgresql.org, docs/postgresql) that Vale's # scope ignores miss inside indented MDX components. '(? PS_DATABASE_TYPE - `postgresql` + postgresql PS_DATABASE_URI @@ -124,7 +124,7 @@ The following configuration options should be updated: PS_DATABASE_TYPE - postgresql OR mongodb OR mysql OR SQL Server + postgresql OR mongodb OR mysql OR mssql PS_DATABASE_URI From 728d70e7abd77407fb492981064964c0e0c2d900 Mon Sep 17 00:00:00 2001 From: Benita Volkmann Date: Thu, 2 Jul 2026 15:33:16 +0200 Subject: [PATCH 4/4] Fix broken external links --- client-sdks/reference/flutter.mdx | 8 ++++---- client-sdks/reference/javascript-web.mdx | 2 +- client-sdks/reference/kotlin.mdx | 4 ++-- client-sdks/usage-examples.mdx | 12 ++++++------ configuration/source-db/setup.mdx | 2 +- handling-writes/custom-write-checkpoints.mdx | 2 +- integrations/serverpod.mdx | 2 +- intro/examples.mdx | 2 -- maintenance-ops/compacting-buckets.mdx | 2 +- maintenance-ops/production-readiness-guide.mdx | 2 +- sync/advanced/prioritized-sync.mdx | 2 +- 11 files changed, 19 insertions(+), 21 deletions(-) diff --git a/client-sdks/reference/flutter.mdx b/client-sdks/reference/flutter.mdx index 19f93178..605eef96 100644 --- a/client-sdks/reference/flutter.mdx +++ b/client-sdks/reference/flutter.mdx @@ -287,7 +287,7 @@ class TodoList { ### Fetching a Single Item -The [get](https://pub.dev/documentation/powersync/latest/sqlite_async/SqliteQueries/get.html) method executes a read-only (SELECT) query and returns a single result. It throws an exception if no result is found. Use [getOptional](https://pub.dev/documentation/powersync/latest/sqlite_async/SqliteQueries/getOptional.html) to return a single optional result (returns `null` if no result is found). +The [get](https://pub.dev/documentation/sqlite_async/latest/sqlite_async/SqliteConnection/get.html) method executes a read-only (SELECT) query and returns a single result. It throws an exception if no result is found. Use [getOptional](https://pub.dev/documentation/sqlite_async/latest/sqlite_async/SqliteConnection/getOptional.html) to return a single optional result (returns `null` if no result is found). The following is an example of selecting a list item by ID: ```dart lib/widgets/lists_widget.dart @@ -302,7 +302,7 @@ Future find(id) async { ### Querying Items (PowerSync.getAll) -The [getAll](https://pub.dev/documentation/powersync/latest/sqlite_async/SqliteQueries/getAll.html) method returns a set of rows from a table. +The [getAll](https://pub.dev/documentation/sqlite_async/latest/sqlite_async/SqliteConnection/getAll.html) method returns a set of rows from a table. ```dart lib/widgets/lists_widget.dart import 'package:powersync/sqlite3.dart'; @@ -317,13 +317,13 @@ Future> getLists() async { ### Watching Queries (PowerSync.watch) -The [watch](https://pub.dev/documentation/powersync/latest/sqlite_async/SqliteQueries/watch.html) method executes a read query whenever a change to a dependent table is made. +The [watch](https://pub.dev/documentation/powersync/latest/powersync/PowerSyncDatabase/watch.html) method executes a read query whenever a change to a dependent table is made. ### Mutations (PowerSync.execute) -The [execute](https://pub.dev/documentation/powersync/latest/powersync/PowerSyncDatabase/execute.html) method can be used for executing single SQLite write statements. +The [execute](https://pub.dev/documentation/sqlite_async/latest/sqlite_async/SqliteConnection/execute.html) method can be used for executing single SQLite write statements. ```dart lib/widgets/todos_widget.dart {12-15} import 'package:flutter/material.dart'; diff --git a/client-sdks/reference/javascript-web.mdx b/client-sdks/reference/javascript-web.mdx index b0471d8f..bb50f199 100644 --- a/client-sdks/reference/javascript-web.mdx +++ b/client-sdks/reference/javascript-web.mdx @@ -311,7 +311,7 @@ logger.setLevel(LogLevel.DEBUG); Enable verbose output in the developer tools for detailed logs. -Additionally, the [WASQLiteDBAdapter](https://powersync-ja.github.io/powersync-js/web-sdk/classes/WASQLiteDBAdapter) opens SQLite connections inside a shared web worker. This worker can be inspected in Chrome by accessing: +Additionally, the [WASQLiteOpenFactory](https://powersync-ja.github.io/powersync-js/web-sdk/classes/WASQLiteOpenFactory.html) opens SQLite connections inside a shared web worker. This worker can be inspected in Chrome by accessing: ``` chrome://inspect/#workers diff --git a/client-sdks/reference/kotlin.mdx b/client-sdks/reference/kotlin.mdx index a532f07f..4be3628c 100644 --- a/client-sdks/reference/kotlin.mdx +++ b/client-sdks/reference/kotlin.mdx @@ -176,7 +176,7 @@ import com.powersync.PowerSyncDatabase class MyConnector : PowerSyncBackendConnector() { override suspend fun fetchCredentials(): PowerSyncCredentials { // implement fetchCredentials to obtain the necessary credentials to connect to your backend - // See an example implementation in https://github.com/powersync-ja/powersync-kotlin/blob/main/connectors/supabase/src/commonMain/kotlin/com/powersync/connector/supabase/SupabaseConnector.kt + // See an example implementation in https://github.com/powersync-ja/powersync-kotlin/blob/main/integrations/supabase/src/commonMain/kotlin/com/powersync/connector/supabase/SupabaseConnector.kt return { endpoint: '[Your PowerSync instance URL or self-hosted endpoint]', @@ -194,7 +194,7 @@ class MyConnector : PowerSyncBackendConnector() { } ``` -**Note**: If you are using Supabase, you can use [SupabaseConnector.kt](https://github.com/powersync-ja/powersync-kotlin/blob/main/connectors/supabase/src/commonMain/kotlin/com/powersync/connector/supabase/SupabaseConnector.kt) as a starting point. +**Note**: If you are using Supabase, you can use [SupabaseConnector.kt](https://github.com/powersync-ja/powersync-kotlin/blob/main/integrations/supabase/src/commonMain/kotlin/com/powersync/connector/supabase/SupabaseConnector.kt) as a starting point. ## Using PowerSync: CRUD functions diff --git a/client-sdks/usage-examples.mdx b/client-sdks/usage-examples.mdx index 09c4863b..ac7a4669 100644 --- a/client-sdks/usage-examples.mdx +++ b/client-sdks/usage-examples.mdx @@ -17,7 +17,7 @@ import JavaScriptCallbackWatch from '/snippets/basic-watch-query-javascript-call Read and write transactions present a context where multiple changes can be made then finally committed to the DB or rolled back. This ensures that either all the changes get persisted, or no change is made to the DB (in the case of a rollback or exception). - The [writeTransaction(callback)](https://pub.dev/documentation/powersync/latest/sqlite_async/SqliteQueries/writeTransaction.html) method combines all writes into a single transaction, only committing to persistent storage once. + The [writeTransaction(callback)](https://pub.dev/documentation/sqlite_async/latest/sqlite_async/SqliteConnection/writeTransaction.html) method combines all writes into a single transaction, only committing to persistent storage once. ```dart deleteList(SqliteDatabase db, String id) async { @@ -30,7 +30,7 @@ import JavaScriptCallbackWatch from '/snippets/basic-watch-query-javascript-call } ``` - Also see [readTransaction(callback)](https://pub.dev/documentation/powersync/latest/sqlite_async/SqliteQueries/readTransaction.html) + Also see [readTransaction(callback)](https://pub.dev/documentation/sqlite_async/latest/sqlite_async/SqliteConnection/readTransaction.html) @@ -233,7 +233,7 @@ import JavaScriptCallbackWatch from '/snippets/basic-watch-query-javascript-call - Use [watch](https://pub.dev/documentation/powersync/latest/sqlite_async/SqliteQueries/watch.html) to watch for changes to the dependent tables of any SQL query. + Use [watch](https://pub.dev/documentation/powersync/latest/powersync/PowerSyncDatabase/watch.html) to watch for changes to the dependent tables of any SQL query. @@ -342,7 +342,7 @@ import JavaScriptCallbackWatch from '/snippets/basic-watch-query-javascript-call - Use [execute](https://pub.dev/documentation/powersync/latest/powersync/PowerSyncDatabase/execute.html) to run INSERT, UPDATE or DELETE queries. + Use [execute](https://pub.dev/documentation/sqlite_async/latest/sqlite_async/SqliteConnection/execute.html) to run INSERT, UPDATE or DELETE queries. ```dart FloatingActionButton( @@ -559,7 +559,7 @@ import JavaScriptCallbackWatch from '/snippets/basic-watch-query-javascript-call - Override `uploadData` to send local updates to your backend service. If you are using Supabase, see [SupabaseConnector.kt](https://github.com/powersync-ja/powersync-kotlin/blob/main/connectors/supabase/src/commonMain/kotlin/com/powersync/connector/supabase/SupabaseConnector.kt) for a complete implementation. + Override `uploadData` to send local updates to your backend service. If you are using Supabase, see [SupabaseConnector.kt](https://github.com/powersync-ja/powersync-kotlin/blob/main/integrations/supabase/src/commonMain/kotlin/com/powersync/connector/supabase/SupabaseConnector.kt) for a complete implementation. ```kotlin /** @@ -1380,7 +1380,7 @@ import JavaScriptCallbackWatch from '/snippets/basic-watch-query-javascript-call ``` Also see: - - [SyncDownloadProgress API](https://powersync-ja.github.io/powersync-kotlin/core/com.powersync.sync/-sync-download-progress/index.html) + - [SyncDownloadProgress API](https://powersync-ja.github.io/powersync-kotlin/common/com.powersync.sync/-sync-download-progress/index.html) - [Demo component](https://github.com/powersync-ja/powersync-kotlin/blob/main/demos/supabase-todolist/shared/src/commonMain/kotlin/com/powersync/demos/components/GuardBySync.kt) diff --git a/configuration/source-db/setup.mdx b/configuration/source-db/setup.mdx index 113f496e..05892920 100644 --- a/configuration/source-db/setup.mdx +++ b/configuration/source-db/setup.mdx @@ -340,7 +340,7 @@ Post-images can be configured for PowerSync instances as follows: Configure `post_images` in the `service.yaml` file. diff --git a/handling-writes/custom-write-checkpoints.mdx b/handling-writes/custom-write-checkpoints.mdx index 95969a5c..1fcb775d 100644 --- a/handling-writes/custom-write-checkpoints.mdx +++ b/handling-writes/custom-write-checkpoints.mdx @@ -11,7 +11,7 @@ Custom Write Checkpoints are available for customers on our [Team and Enterprise To ensure [consistency](/architecture/consistency), PowerSync relies on Write Checkpoints. These checkpoints ensure that clients have uploaded their own local changes/mutations to the server before applying downloaded data from the server to the local database. -The essential requirement is that the client must get a Write Checkpoint after uploading its last write/mutation. Then, when downloading data from the server, the client checks whether the Write Checkpoint is part of the largest [sync checkpoint](https://github.com/powersync-ja/powersync-service/blob/main/docs/sync-protocol.md) received from the server (i.e. from the PowerSync Service). If it is, the client applies the server-side state to the local database. +The essential requirement is that the client must get a Write Checkpoint after uploading its last write/mutation. Then, when downloading data from the server, the client checks whether the Write Checkpoint is part of the largest [sync checkpoint](https://github.com/powersync-ja/powersync-service/blob/main/docs/specs/sync-protocol.md) received from the server (i.e. from the PowerSync Service). If it is, the client applies the server-side state to the local database. The default Write Checkpoints implementation relies on uploads being acknowledged _synchronously_, i.e. the change persists in the source database (to which PowerSync is connected) before the [`uploadData` call](/configuration/app-backend/client-side-integration) completes. diff --git a/integrations/serverpod.mdx b/integrations/serverpod.mdx index 69e4262e..05f404b9 100644 --- a/integrations/serverpod.mdx +++ b/integrations/serverpod.mdx @@ -268,7 +268,7 @@ For security, it is crucial each user only has access to their own bucket. This 3. In the `sync_rules` section, you reference properties of the created JWTs to control data visible to the connecting clients. In this guide, we will use a single virtual user for everything. For real projects, follow -[Serverpod documentation on authentication](https://docs.serverpod.dev/tutorials/guides/authentication). +[Serverpod documentation on authentication](https://docs.serverpod.dev/concepts/authentication/setup). PowerSync needs two endpoints, one to request a JWT and one to upload local writes from clients to the backend source database. In `notes_server/lib/src/powersync_endpoint.dart`, create those endpoints: diff --git a/intro/examples.mdx b/intro/examples.mdx index 6c9c15a4..eafe6358 100644 --- a/intro/examples.mdx +++ b/intro/examples.mdx @@ -235,8 +235,6 @@ This is a list of additional projects we've spotted from community members 🙌 - [Account Optional Apps with PowerSync](https://www.maxmntl.com/blog/optional-account-powersync/) - Tutorial for starting your new user app experience fully local (without sync,) and then to switch them to a synced experience -- [Building an Offline-First Chat App Using PowerSync and Supabase](https://bndkt.com/blog/2023/building-an-offline-first-chat-app-using-powersync-and-supabase) - - Postgres (Supabase) + React Native + Expo + Tamagui - [Building an Offline-First Mobile App with PowerSync](https://blog.stackademic.com/building-an-offline-first-mobile-app-with-powersync-40674d8b7ea1) - Postgres + Flutter + Nest.js + Prisma ORM + Firebase Auth - [Implementing Local-First Architecture: A Guide to MongoDB Cluster and PowerSync Integration](https://blog.stackademic.com/implementing-local-first-architecture-a-guide-to-mongodb-cluster-and-powersync-integration-6b21fa8059a1) diff --git a/maintenance-ops/compacting-buckets.mdx b/maintenance-ops/compacting-buckets.mdx index fb5c9672..ee896790 100644 --- a/maintenance-ops/compacting-buckets.mdx +++ b/maintenance-ops/compacting-buckets.mdx @@ -185,4 +185,4 @@ Soon, we will use [incremental reprocessing](https://github.com/orgs/powersync-j ## Technical Details -See the [documentation](https://github.com/powersync-ja/powersync-service/blob/main/docs/compacting-operations.md) in the `powersync-service` repo for more technical details on compacting. \ No newline at end of file +See the [documentation](https://github.com/powersync-ja/powersync-service/blob/main/docs/storage/compacting-operations.md) in the `powersync-service` repo for more technical details on compacting. \ No newline at end of file diff --git a/maintenance-ops/production-readiness-guide.mdx b/maintenance-ops/production-readiness-guide.mdx index 2dccf118..a34057b0 100644 --- a/maintenance-ops/production-readiness-guide.mdx +++ b/maintenance-ops/production-readiness-guide.mdx @@ -27,7 +27,7 @@ We recommend adding a view/screen in your application that offers diagnostic inf Each of the PowerSync Client SDKs have the `SyncStatus` class that can be used to access the fields mentioned above. - [Flutter](https://pub.dev/documentation/powersync/latest/powersync/SyncStatus-class.html) -- [Kotlin](https://powersync-ja.github.io/powersync-kotlin/core/com.powersync.sync/-sync-status/index.html?query=data%20class%20SyncStatus%20:%20SyncStatusData) +- [Kotlin](https://powersync-ja.github.io/powersync-kotlin/common/com.powersync.sync/-sync-status/index.html) - [Swift](https://powersync-ja.github.io/powersync-swift/documentation/powersync/syncstatusdata) - [Web](https://powersync-ja.github.io/powersync-js/web-sdk/classes/SyncStatus) - [React Native](https://powersync-ja.github.io/powersync-js/react-native-sdk/classes/SyncStatus) diff --git a/sync/advanced/prioritized-sync.mdx b/sync/advanced/prioritized-sync.mdx index c6d1d814..bc5a1340 100644 --- a/sync/advanced/prioritized-sync.mdx +++ b/sync/advanced/prioritized-sync.mdx @@ -258,5 +258,5 @@ Example implementations of prioritized sync are also available in the following - Flutter: [Supabase To-Do List](https://github.com/powersync-ja/powersync.dart/tree/main/demos/supabase-todolist) - Kotlin: - [Supabase To-Do List (KMP)](https://github.com/powersync-ja/powersync-kotlin/blob/main/demos/supabase-todolist/shared/src/commonMain/kotlin/com/powersync/demos/App.kt#L46) - - [Supabase To-Do List (Android)](https://github.com/powersync-ja/powersync-kotlin/blob/main/demos/android-supabase-todolist/app/src/main/java/com/powersync/androidexample/screens/HomeScreen.kt#L69) + - [Supabase To-Do List (Android)](https://github.com/powersync-ja/powersync-kotlin/blob/main/demos/android-supabase-todolist/src/main/java/com/powersync/androidexample/screens/HomeScreen.kt#L69) - Swift: [Supabase To-Do List](https://github.com/powersync-ja/powersync-swift/tree/main/Demos/PowerSyncExample) \ No newline at end of file