diff --git a/.github/AGENTS.md b/.github/AGENTS.md index 285a5089..eb6c269c 100644 --- a/.github/AGENTS.md +++ b/.github/AGENTS.md @@ -6,10 +6,10 @@ GitHub's config for this repo: CI, releases, Pages, dependabot, issue forms, PR | Path | Purpose | | --- | --- | -| `workflows/ci.yml` | push-main + PR gate. A `changes` job diffs the base against the head and gates the other jobs by area (`docs checks` always runs); `ci pass` aggregates them | +| `workflows/ci.yml` | push-main + PR gate. A `changes` job diffs the base against the head and gates the other jobs by area (`docs checks` always runs; `site build` runs `scripts/assemble-site.sh` and `tsc` on the docs when the site files change); `ci pass` aggregates them | | `workflows/release.yml` | on `v*` tag: check the tag against `MARKETING_VERSION` and `CHANGELOG.md`, then (environment `release`) sign, notarize, write the Sparkle appcast, attest, publish. `workflow_dispatch` is a rehearsal that publishes nothing | | `workflows/go-weekly.yml` | Monday run of the Go checks, so new govulncheck findings surface without a code change, plus `go test -fuzz` for 30 s per `Fuzz*` target (a failing input is uploaded as the `fuzz-failures` artifact); files or updates one `security` issue on failure | -| `workflows/github-pages.yml` | builds `_site` on PR, also deploys on push to main | +| `workflows/github-pages.yml` | on push to main (site paths only): builds `_site` and deploys it. The pre-merge check of the same build is the `site build` job in `ci.yml`; keep its `site` regex and this `paths:` list in step | | `workflows/reusable-*.yml` | `workflow_call` only. Edit the check here, never in a caller | | `workflows/scorecard.yml` | OpenSSF Scorecard: Wednesday cron, `branch_protection_rule`, dispatch | | `dependabot.yml` | github-actions, gomod `/crocmobile`, swift `/app` (reads the Xcode project's `Package.resolved`) weekly; npm `/web/docs` monthly. Minor and patch grouped, majors one PR each | @@ -38,5 +38,4 @@ gh api repos/OWNER/REPO/git/ref/tags/TAG --jq '.object.type + " " + .object.sha' - **A label named in config must already exist** in the repo. Dependabot silently drops missing ones, and a `labels:` filter on `listForRepo` silently matches nothing, which breaks issue dedup. - **Dependabot bumps only direct Go requirements.** The `tool` block's modules (`x/mobile`, `x/vuln`) are `// indirect`, so bump them by hand: `go get tool` in `crocmobile/`. - **Go jobs cross-target `darwin/arm64`** because the module only ships through gomobile. Tools have to be built for the runner (`env -u GOOS -u GOARCH go build -o ...`) and then run under the job's env. -- **YAML anchors work** in workflows here (`paths: &site-paths` / `*site-paths` in `github-pages.yml`), despite the common claim that Actions rejects them. - **`release.yml` parses `CHANGELOG.md`.** It requires a [Keep a Changelog](https://keepachangelog.com/) heading, dated: `## [1.2.3] - YYYY-MM-DD`. Change the heading style and the tag stops releasing. The notes end at the next `## [` heading or at the first line starting `[label]: `, so a reference-style link definition inside a version section cuts its release notes short; use inline links there. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b7a5e46d..79bb413a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,6 +29,7 @@ jobs: design: ${{ steps.filter.outputs.design }} interop: ${{ steps.filter.outputs.interop }} scripts: ${{ steps.filter.outputs.scripts }} + site: ${{ steps.filter.outputs.site }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -65,9 +66,10 @@ jobs: out swift '^(app|CrocKit)/|^scripts/screenshots/|^\.swift-format$|^\.xcode-version$|^scripts/format-swift\.sh$|^\.github/workflows/(ci|reusable-swift-format)\.yml$' out go '^crocmobile/|^\.github/workflows/(ci|reusable-go)\.yml$' out build '^(app|CrocKit|crocmobile)/|^scripts/build-xcframework\.sh$|^\.xcode-version$|^\.github/workflows/ci\.yml$' - out design '^design/|^app/.*\.swift$|^app/CrocApp/Assets\.xcassets/|^web/landing/.*\.(css|html)$|^web/docs/src/css/|^scripts/(lib|verify-design)\.sh$|^\.github/workflows/ci\.yml$' + out design '^design/|^app/.*\.swift$|^app/CrocApp/Assets\.xcassets/|^web/landing/.*\.(css|html|js)$|^web/landing/assets/img/favicon/site\.webmanifest$|^web/docs/src/(css/|prismTheme\.ts$)|^scripts/(lib|verify-design)\.sh$|^\.github/workflows/ci\.yml$' out interop '^(crocmobile|CrocKit)/|^scripts/(lib|verify-interop)\.sh$|^scripts/croc-v10\.version$|^\.github/workflows/ci\.yml$' out scripts '^scripts/.*\.sh$|^\.github/workflows/ci\.yml$' + out site '^web/(landing|docs)/|^design/tokens\.css$|^scripts/assemble-site\.sh$|^\.github/workflows/(ci|github-pages)\.yml$' } | tee -a "$GITHUB_OUTPUT" swift-format: @@ -135,6 +137,40 @@ jobs: - run: scripts/verify-docs.sh + # The deploy workflow's build, run before merge so a broken docs link or type + # error fails the PR instead of the push to main. + site: + name: site build + + needs: changes + + if: needs.changes.outputs.site == 'true' + + runs-on: ubuntu-26.04 + + timeout-minutes: 15 + + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 0 # needed because Docusaurus's showLastUpdateTime reads each doc page's git history + persist-credentials: false + + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 + with: + node-version-file: web/docs/.nvmrc + + # Version from `packageManager`. Not corepack: Node 25+ no longer ships it. + - uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0 + with: + package_json_file: web/docs/package.json + cache: true + cache_dependency_path: web/docs/pnpm-lock.yaml + + - run: scripts/assemble-site.sh + + - run: pnpm --dir web/docs run typecheck + # The interop harness against a relay on localhost, never the public relays: # those rate-limit a shared runner address and make the run flaky. The # public-pool scenario stays a local run (docs/BUILDING.md). @@ -297,7 +333,7 @@ jobs: pass: name: ci pass - needs: [changes, swift-format, go, contrast, shellcheck, docs, interop, build] + needs: [changes, swift-format, go, contrast, shellcheck, docs, site, interop, build] if: ${{ always() }} diff --git a/.github/workflows/github-pages.yml b/.github/workflows/github-pages.yml index 8412b297..4a1d19ac 100644 --- a/.github/workflows/github-pages.yml +++ b/.github/workflows/github-pages.yml @@ -3,21 +3,19 @@ name: GitHub Pages on: push: branches: [main] - paths: &site-paths + paths: - "web/landing/**" - "web/docs/**" - "design/tokens.css" - "scripts/assemble-site.sh" - ".github/workflows/github-pages.yml" - pull_request: - paths: *site-paths permissions: contents: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} + cancel-in-progress: false jobs: build: @@ -63,8 +61,6 @@ jobs: needs: build - if: github.event_name == 'push' - runs-on: ubuntu-26.04 timeout-minutes: 10 diff --git a/CHANGELOG.md b/CHANGELOG.md index 50053269..6ab31804 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,9 @@ extra sections where a release needs them, and the project follows ### Changed -- Buttons are easier to read in light mode: text labels now use the darker green, and destructive labels are no longer drawn in red text. +- Buttons are easier to read in light mode: text labels and filled buttons now use the darker green, so white labels pass the 4.5:1 contrast mark, and destructive labels are no longer drawn in red text. +- The website and docs are refreshed. The docs are reorganized around what you are doing (one Settings page in the app's own order, Verify a release under Getting started, Send as link and a keyboard shortcut reference), with a new Uninstall and data page, many accuracy fixes, and redirects from the old addresses. The home page leads with "Send files with a code phrase" and shows the iPhone app beside the Mac one. +- The website and docs use the app icon as their favicon and home-screen icon, and a new social preview card. - The screen that asks you to accept a transfer shows a Receiving header, the encryption badge and the file list as rows. Its Cancel button is gone: Decline answers the other device, leaving the screen gives no answer, and Home shows a banner to return to a request that is still waiting. - Send as Link now says Sending and Receiving like every other transfer, and copying the code shows "Copied". - On iPhone, a light haptic marks a finished, failed or incoming transfer and a copied or scanned code. Cancelling or declining yourself stays silent. diff --git a/README.md b/README.md index 9b90143d..dcea617a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

CrocApp

- Send a file to any device, anywhere, with a code phrase. + Send files with a code phrase
A free, open-source native SwiftUI app for Mac, with iPhone and iPad arriving in the App Store release.

@@ -32,7 +32,7 @@ It is a graphical front end for [croc](https://github.com/schollz/croc), the com | Mac (Apple silicon only) | `CrocApp--arm64.dmg` from [GitHub Releases](https://github.com/bakirgdev/CrocApp/releases/latest) | | Mac (Homebrew cask) | Not available yet. Homebrew accepts a cask once the repo shows [enough public interest](https://docs.brew.sh/Package-Acceptance-Policy#notability): 225 stars, 90 watchers, or 90 forks. Starring the repo helps | -The disk image is Developer ID signed, notarized, and updates itself through Sparkle (**Check for Updates…** in the app menu). Verify it with `gh attestation verify --repo bakirgdev/CrocApp` ([`SECURITY.md`](SECURITY.md)). Install guide: [crocapp.dev/docs/getting-started/install](https://crocapp.dev/docs/getting-started/install/). Or [build from source](docs/BUILDING.md). +The disk image is Developer ID signed, notarized, and updates itself through Sparkle (**Check for Updates…** in the app menu). Verify it with `gh attestation verify --repo bakirgdev/CrocApp` ([`SECURITY.md`](SECURITY.md)). Install guide: [crocapp.dev/docs/getting-started/install](https://crocapp.dev/docs/getting-started/install/). To check a download, see [Verify a release](https://crocapp.dev/docs/getting-started/verify-downloads/). Or [build from source](docs/BUILDING.md). ## How it works diff --git a/SECURITY.md b/SECURITY.md index 265bccee..7885692c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -48,7 +48,7 @@ Also out of scope: reports generated by a scanner with no demonstrated impact, m ## Verifying downloads -Steps to check a release (notarization, build attestation, checksums, update signing) are in the [verify downloads guide](https://crocapp.dev/docs/verify-downloads/). An asset that fails any check, or one that appears anywhere other than this repository's releases page, is worth reporting. +Steps to check a release (notarization, build attestation, checksums, update signing) are in the [verify downloads guide](https://crocapp.dev/docs/getting-started/verify-downloads/). An asset that fails any check, or one that appears anywhere other than this repository's releases page, is worth reporting. ## What CrocApp claims @@ -57,4 +57,4 @@ Transfers are end-to-end encrypted, the code phrase authenticates both devices ( > [!WARNING] > There has been **no formal third-party security audit** of croc, and CrocApp does not claim one. Do not describe CrocApp as audited, certified, or zero-knowledge-verified. -Supporting facts (no accounts, analytics, ads or tracking, history that stays on the device, your own relay, dependency scanning) are on the [security and privacy page](https://crocapp.dev/docs/security-and-privacy/). +Supporting facts (no accounts, analytics, ads or tracking, history that stays on the device, your own relay) are on the [security and privacy page](https://crocapp.dev/docs/security-and-privacy/). diff --git a/app/CrocApp/Assets.xcassets/ColorAccentPressed.colorset/Contents.json b/app/CrocApp/Assets.xcassets/ColorAccentPressed.colorset/Contents.json index fcb15e6d..258fb2b6 100644 --- a/app/CrocApp/Assets.xcassets/ColorAccentPressed.colorset/Contents.json +++ b/app/CrocApp/Assets.xcassets/ColorAccentPressed.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.333", - "green" : "0.502", - "red" : "0.090" + "blue" : "0.263", + "green" : "0.384", + "red" : "0.067" } }, "idiom" : "universal" diff --git a/app/CrocApp/Assets.xcassets/ColorAccentSolid.colorset/Contents.json b/app/CrocApp/Assets.xcassets/ColorAccentSolid.colorset/Contents.json new file mode 100644 index 00000000..2750f917 --- /dev/null +++ b/app/CrocApp/Assets.xcassets/ColorAccentSolid.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.333", + "green" : "0.502", + "red" : "0.090" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.522", + "green" : "0.773", + "red" : "0.176" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/app/CrocApp/Support/AutoVerify.swift b/app/CrocApp/Support/AutoVerify.swift index ed5aa325..4ec4ab8f 100644 --- a/app/CrocApp/Support/AutoVerify.swift +++ b/app/CrocApp/Support/AutoVerify.swift @@ -31,7 +31,7 @@ import ServiceManagement /// --relay-password PW the custom relay's password (croc's default applies without it) /// --shown-relay default make the trust UI name the public relay whatever --relay says /// --shown-link-origin ORIGIN make a stored link show and encode ORIGIN (scheme and host, e.g. -/// https://crocapp.dev) instead of the --store-server's; the upload +/// https://getcroc.com) instead of the --store-server's; the upload /// still goes to --store-server /// --throttle RATE cap the upload rate for a send, e.g. 4m (croc's --throttleUpload) /// --transport auto|relay the Connection setting for this run (croc's --transport) @@ -183,7 +183,7 @@ enum AutoVerify { } controller.startStoreSend( urls: [URL(fileURLWithPath: args[i + 1])], downloads: downloads, - lifetimeSeconds: 3600) + lifetimeSeconds: 86_400) await watchStoreSend(controller, docs: docs, resultURL: resultURL) } else if let i = args.firstIndex(of: "--auto-store-receive"), i + 1 < args.count { guard let link = URL(string: args[i + 1]) else { @@ -367,40 +367,45 @@ enum AutoVerify { )] = [ ( false, .completed, false, 177_000, - ["Quarterly-Report.pdf", "Ridge-Sunrise.jpg", "Meeting-Notes.md"], 3, "4821", + ["Quarterly-Report.pdf", "Ridge-Sunrise.jpg", "Meeting-Notes.md"], 3, "cape-…", 12 * 60, false ), - (true, .completed, true, 148, [], 1, "7305", 2 * hour, false), + (true, .completed, true, 148, [], 1, "wiry-…", 2 * hour, false), ( true, .completed, false, 55_000, ["Design-Assets.zip"], 1, - "crocapp.dev", 5 * hour, true + "getcroc.com", 5 * hour, true ), ( - false, .completed, false, 24_100_000, ["Soundtrack.wav"], 1, "6142", 1.2 * day, + false, .completed, false, 24_100_000, ["Soundtrack.wav"], 1, "junky-…", + 1.2 * day, false ), ( - true, .declined, false, 184_000, ["Contract-Draft.pdf"], 1, "3057", 2 * day, + true, .declined, false, 184_000, ["Contract-Draft.pdf"], 1, "lint-…", 2 * day, false ), ( - false, .failed, false, 96_000_000, ["Field-Recordings.zip"], 1, "9134", 4 * day, + false, .failed, false, 96_000_000, ["Field-Recordings.zip"], 1, "mild-…", + 4 * day, false ), ( true, .completed, false, 18_600_000, - ["Slides.pdf", "Cover-Art.png", "Speaker-Notes.md", "Demo-Reel.mov"], 4, "2290", + ["Slides.pdf", "Cover-Art.png", "Speaker-Notes.md", "Demo-Reel.mov"], 4, "op…", 6 * day, false ), ( false, .cancelled, false, 412_000_000, - ["Raw-Scans.zip"], 1, "8816", 9 * day, false + ["Raw-Scans.zip"], 1, "tamer-…", 9 * day, false ), ( - true, .completed, false, 7_800_000, ["Project-Archive.zip"], 1, "5503", + true, .completed, false, 7_800_000, ["Project-Archive.zip"], 1, "fuzzy-…", 21 * day, false ), - (false, .completed, false, 1_200_000, ["Receipts.pdf"], 1, "1948", 35 * day, false), + ( + false, .completed, false, 1_200_000, ["Receipts.pdf"], 1, "rope-…", 35 * day, + false + ), ] for sample in samples { let record = TransferRecord( diff --git a/app/CrocApp/Support/DesignTokens.swift b/app/CrocApp/Support/DesignTokens.swift index 1411e7e8..269078e5 100644 --- a/app/CrocApp/Support/DesignTokens.swift +++ b/app/CrocApp/Support/DesignTokens.swift @@ -156,7 +156,12 @@ extension Color { /// never use this for a word, see `accentText`. static var accentFill: Color { .accentColor } - /// Pressed state for custom button styles built on the accent fill. + /// `--color-accent-solid`: the background of a filled prominent button. + /// Darker than `accentFill` in light so `onAccent` reads at 4.94:1 + /// (colors.md rule 3); the same green in dark. + static let accentSolid = Color("ColorAccentSolid") + + /// Pressed state for custom button styles built on the accent solid. static let accentPressed = Color("ColorAccentPressed") /// `--color-accent-tint`: the drag-over and secondary-button fill. Alpha diff --git a/app/CrocApp/Views/ButtonVariants.swift b/app/CrocApp/Views/ButtonVariants.swift index 45fddc38..9473408e 100644 --- a/app/CrocApp/Views/ButtonVariants.swift +++ b/app/CrocApp/Views/ButtonVariants.swift @@ -29,7 +29,7 @@ private struct ButtonVariantStyle: PrimitiveButtonStyle { switch variant { case .prominent: - button.buttonStyle(.borderedProminent).tint(Color.accentFill) + button.buttonStyle(.borderedProminent).tint(Color.accentSolid) case .secondary: button.buttonStyle(.bordered).tint(Color.accentFill) case .destructive: diff --git a/app/CrocApp/Views/HomeView.swift b/app/CrocApp/Views/HomeView.swift index 84c9ca1d..56acb19d 100644 --- a/app/CrocApp/Views/HomeView.swift +++ b/app/CrocApp/Views/HomeView.swift @@ -56,7 +56,7 @@ struct HomeView: View { .foregroundStyle(Color.onAccent) .padding(.horizontal, Spacing.space3) .padding(.vertical, Spacing.space1) - .background(Color.accentFill, in: Capsule()) + .background(Color.accentSolid, in: Capsule()) .offset(x: Spacing.space3, y: -Spacing.space3) .accessibilityLabel( "^[\(router.pendingSendURLs.count) file](inflect: true) waiting to send" diff --git a/assets/AGENTS.md b/assets/AGENTS.md index aa17ad46..505802a1 100644 --- a/assets/AGENTS.md +++ b/assets/AGENTS.md @@ -6,10 +6,11 @@ Source-of-truth design and marketing files. Mostly binary and committed as-is; n | Path | What it is | Used by | | --- | --- | --- | -| `mascot.png` | 1024×1024 mascot, the root image every other mascot asset derives from | Icon layer, `web/landing/assets/img/mascot-web.webp`, favicons, social cards | +| `mascot.png` | 1024×1024 mascot, the root image every other mascot asset derives from | Icon layer, `web/landing/assets/img/mascot-web.webp`, social cards | | `CrocAppIcon.icon/` | Icon Composer package: `icon.json` (mint gradient background, dark variant, two glass groups) plus three layers cut from `mascot.png` at full size: `0_body.png` (whole silhouette), `1_belly.png`, `2_outline.png` (ink, white when tinted) | Mirrored to `app/CrocApp/AppIcon.icon`, which is the copy Xcode builds | +| `favicons/` | Favicon set generated from the app icon on realfavicongenerator.net: `favicon.ico`, `favicon-96x96.png`, `apple-touch-icon.png`, `web-app-manifest-{192x192,512x512}.png`, `site.webmanifest` | Source of truth. The served copy is `web/landing/assets/img/favicon/`; the docs site references that copy. Recipe: `design/brand.md` → Favicon recipe | | `dmg-background.tiff` | DMG Finder window background, dark, 660×400 at 1x and 2x | `scripts/build-dmg.sh`. Spec: `design/components.md` → DiskImage | -| `github-social-preview.png` | 1280×640, dark | Only the repository's GitHub Settings → Social preview, uploaded by hand. No file references it | +| `github-social-preview.png` | 1280×640, dark; same layout as `web/landing/assets/img/og.jpg` | Only the repository's GitHub Settings → Social preview, uploaded by hand. No file references it | | `screenshots/{mac,iphone,ipad}/-{light,dark}.png` | Full-resolution app screenshots, one pair per screen | README, docs site, landing hero (through the web copies) | | `screenshots/app-store//NN--{light,dark}.png` | App Store Connect upload set, one folder per size class (`iphone-6.9`, `iphone-6.3`, `iphone-duo-outer`, `ipad-13`, `mac`): ten per class, odd `NN` light and even dark, no alpha, Apple's exact sizes, `NN` is the upload order | Uploaded by hand in App Store Connect. `iphone-duo-outer` is not upload-ready yet (see `docs/knowledge/screenshots.md` → iPhone Duo) | @@ -17,8 +18,9 @@ Source-of-truth design and marketing files. Mostly binary and committed as-is; n - `mascot.png` is never edited. Re-cut derivatives from it instead (recipes in `design/brand.md`). - Change the icon in `CrocAppIcon.icon`, with Icon Composer, then copy it over the app's copy so the two stay identical: `rsync -a --delete assets/CrocAppIcon.icon/ app/CrocApp/AppIcon.icon/`. Check a render without opening Xcode: `"/Applications/Xcode.app/Contents/Applications/Icon Composer.app/Contents/Executables/ictool" assets/CrocAppIcon.icon --export-image --output-file icon.png --platform iOS --rendition Default --width 1024 --height 1024 --scale 1` (renditions include `Dark` and `TintedDark`). +- After changing the icon, regenerate `favicons/` (recipe in `design/brand.md`), then copy the set to `web/landing/assets/img/favicon/`. - `dmg-background.tiff` is a multi-representation TIFF, built with `tiffutil -cathidpicheck bg.png bg@2x.png -out dmg-background.tiff`. Change `design/components.md` → DiskImage and `scripts/build-dmg.sh` together with it. - After replacing `github-social-preview.png`, upload it again in the repository settings. GitHub keeps its own copy. - Screenshots come only from `scripts/capture-screenshots.sh`, driving real Debug builds with the mock data described in `docs/knowledge/screenshots.md`. Never hand-edit, crop or retouch one; re-run the script, for a single screen if that is all that changed. -- Pages use copies, not these files: `web/docs/static/img/screenshots/` and `web/landing/assets/img/screenshots/`. After a capture, refresh them with `scripts/capture-screenshots.sh --copy-web`. +- Pages use WebP copies, not these files: `web/docs/screenshots/` and `web/landing/assets/img/screenshots/`. After a capture, rebuild them with `scripts/capture-screenshots.sh --copy-web` (needs `cwebp`). - When app UI changes, recapture the affected screens, and all of them after a broad visual change. diff --git a/assets/favicons/apple-touch-icon.png b/assets/favicons/apple-touch-icon.png new file mode 100644 index 00000000..af5574e5 Binary files /dev/null and b/assets/favicons/apple-touch-icon.png differ diff --git a/assets/favicons/favicon-96x96.png b/assets/favicons/favicon-96x96.png new file mode 100644 index 00000000..cfe3fa61 Binary files /dev/null and b/assets/favicons/favicon-96x96.png differ diff --git a/assets/favicons/favicon.ico b/assets/favicons/favicon.ico new file mode 100644 index 00000000..9d5e4fd4 Binary files /dev/null and b/assets/favicons/favicon.ico differ diff --git a/assets/favicons/site.webmanifest b/assets/favicons/site.webmanifest new file mode 100644 index 00000000..91542374 --- /dev/null +++ b/assets/favicons/site.webmanifest @@ -0,0 +1,25 @@ +{ + "id": "/", + "name": "CrocApp", + "short_name": "CrocApp", + "description": "Send files, folders and text to another device with a short code phrase. Free, open source and end-to-end encrypted.", + "start_url": "/", + "scope": "/", + "icons": [ + { + "src": "web-app-manifest-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "any" + }, + { + "src": "web-app-manifest-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "any" + } + ], + "theme_color": "#FFFFFF", + "background_color": "#FFFFFF", + "display": "standalone" +} diff --git a/assets/favicons/web-app-manifest-192x192.png b/assets/favicons/web-app-manifest-192x192.png new file mode 100644 index 00000000..bb187675 Binary files /dev/null and b/assets/favicons/web-app-manifest-192x192.png differ diff --git a/assets/favicons/web-app-manifest-512x512.png b/assets/favicons/web-app-manifest-512x512.png new file mode 100644 index 00000000..015f89d3 Binary files /dev/null and b/assets/favicons/web-app-manifest-512x512.png differ diff --git a/assets/github-social-preview.png b/assets/github-social-preview.png index 38ed2912..52651f5e 100644 Binary files a/assets/github-social-preview.png and b/assets/github-social-preview.png differ diff --git a/assets/screenshots/app-store/ipad-13/01-send-files-light.png b/assets/screenshots/app-store/ipad-13/01-send-files-light.png index 2ae9a2a9..4abf1bf4 100644 Binary files a/assets/screenshots/app-store/ipad-13/01-send-files-light.png and b/assets/screenshots/app-store/ipad-13/01-send-files-light.png differ diff --git a/assets/screenshots/app-store/ipad-13/02-send-code-dark.png b/assets/screenshots/app-store/ipad-13/02-send-code-dark.png index 58197184..b3e24446 100644 Binary files a/assets/screenshots/app-store/ipad-13/02-send-code-dark.png and b/assets/screenshots/app-store/ipad-13/02-send-code-dark.png differ diff --git a/assets/screenshots/app-store/ipad-13/03-sending-light.png b/assets/screenshots/app-store/ipad-13/03-sending-light.png index f7f6cbd5..e4b6fda0 100644 Binary files a/assets/screenshots/app-store/ipad-13/03-sending-light.png and b/assets/screenshots/app-store/ipad-13/03-sending-light.png differ diff --git a/assets/screenshots/app-store/ipad-13/04-receive-incoming-dark.png b/assets/screenshots/app-store/ipad-13/04-receive-incoming-dark.png index 181cc20e..95c8385a 100644 Binary files a/assets/screenshots/app-store/ipad-13/04-receive-incoming-dark.png and b/assets/screenshots/app-store/ipad-13/04-receive-incoming-dark.png differ diff --git a/assets/screenshots/app-store/ipad-13/05-receiving-light.png b/assets/screenshots/app-store/ipad-13/05-receiving-light.png index 8bc14880..fcec14b2 100644 Binary files a/assets/screenshots/app-store/ipad-13/05-receiving-light.png and b/assets/screenshots/app-store/ipad-13/05-receiving-light.png differ diff --git a/assets/screenshots/app-store/ipad-13/06-receive-done-dark.png b/assets/screenshots/app-store/ipad-13/06-receive-done-dark.png index f7d5f798..9bcf866a 100644 Binary files a/assets/screenshots/app-store/ipad-13/06-receive-done-dark.png and b/assets/screenshots/app-store/ipad-13/06-receive-done-dark.png differ diff --git a/assets/screenshots/app-store/ipad-13/07-stored-link-light.png b/assets/screenshots/app-store/ipad-13/07-stored-link-light.png index a3e818ff..bce66cac 100644 Binary files a/assets/screenshots/app-store/ipad-13/07-stored-link-light.png and b/assets/screenshots/app-store/ipad-13/07-stored-link-light.png differ diff --git a/assets/screenshots/app-store/ipad-13/08-history-dark.png b/assets/screenshots/app-store/ipad-13/08-history-dark.png index 370b05aa..408ee9c3 100644 Binary files a/assets/screenshots/app-store/ipad-13/08-history-dark.png and b/assets/screenshots/app-store/ipad-13/08-history-dark.png differ diff --git a/assets/screenshots/app-store/ipad-13/09-settings-light.png b/assets/screenshots/app-store/ipad-13/09-settings-light.png index c932e255..5bdfa8f5 100644 Binary files a/assets/screenshots/app-store/ipad-13/09-settings-light.png and b/assets/screenshots/app-store/ipad-13/09-settings-light.png differ diff --git a/assets/screenshots/app-store/ipad-13/10-how-it-works-dark.png b/assets/screenshots/app-store/ipad-13/10-how-it-works-dark.png index 540a8bb6..94a0a8da 100644 Binary files a/assets/screenshots/app-store/ipad-13/10-how-it-works-dark.png and b/assets/screenshots/app-store/ipad-13/10-how-it-works-dark.png differ diff --git a/assets/screenshots/app-store/iphone-6.3/01-send-files-light.png b/assets/screenshots/app-store/iphone-6.3/01-send-files-light.png index 398b7e72..b49e6124 100644 Binary files a/assets/screenshots/app-store/iphone-6.3/01-send-files-light.png and b/assets/screenshots/app-store/iphone-6.3/01-send-files-light.png differ diff --git a/assets/screenshots/app-store/iphone-6.3/02-send-code-dark.png b/assets/screenshots/app-store/iphone-6.3/02-send-code-dark.png index fb578e5e..5b4f313c 100644 Binary files a/assets/screenshots/app-store/iphone-6.3/02-send-code-dark.png and b/assets/screenshots/app-store/iphone-6.3/02-send-code-dark.png differ diff --git a/assets/screenshots/app-store/iphone-6.3/03-sending-light.png b/assets/screenshots/app-store/iphone-6.3/03-sending-light.png index a2fdd56e..d4d4142e 100644 Binary files a/assets/screenshots/app-store/iphone-6.3/03-sending-light.png and b/assets/screenshots/app-store/iphone-6.3/03-sending-light.png differ diff --git a/assets/screenshots/app-store/iphone-6.3/05-receiving-light.png b/assets/screenshots/app-store/iphone-6.3/05-receiving-light.png index c5ceaebd..c2cadf58 100644 Binary files a/assets/screenshots/app-store/iphone-6.3/05-receiving-light.png and b/assets/screenshots/app-store/iphone-6.3/05-receiving-light.png differ diff --git a/assets/screenshots/app-store/iphone-6.3/07-stored-link-light.png b/assets/screenshots/app-store/iphone-6.3/07-stored-link-light.png index 5f9e676d..7279cbe6 100644 Binary files a/assets/screenshots/app-store/iphone-6.3/07-stored-link-light.png and b/assets/screenshots/app-store/iphone-6.3/07-stored-link-light.png differ diff --git a/assets/screenshots/app-store/iphone-6.3/08-history-dark.png b/assets/screenshots/app-store/iphone-6.3/08-history-dark.png index 1fa96c36..a1be7f61 100644 Binary files a/assets/screenshots/app-store/iphone-6.3/08-history-dark.png and b/assets/screenshots/app-store/iphone-6.3/08-history-dark.png differ diff --git a/assets/screenshots/app-store/iphone-6.9/01-send-files-light.png b/assets/screenshots/app-store/iphone-6.9/01-send-files-light.png index 8b60c6de..825fe3ed 100644 Binary files a/assets/screenshots/app-store/iphone-6.9/01-send-files-light.png and b/assets/screenshots/app-store/iphone-6.9/01-send-files-light.png differ diff --git a/assets/screenshots/app-store/iphone-6.9/02-send-code-dark.png b/assets/screenshots/app-store/iphone-6.9/02-send-code-dark.png index 86aa131e..776e706a 100644 Binary files a/assets/screenshots/app-store/iphone-6.9/02-send-code-dark.png and b/assets/screenshots/app-store/iphone-6.9/02-send-code-dark.png differ diff --git a/assets/screenshots/app-store/iphone-6.9/03-sending-light.png b/assets/screenshots/app-store/iphone-6.9/03-sending-light.png index b7ff6e0e..880881cc 100644 Binary files a/assets/screenshots/app-store/iphone-6.9/03-sending-light.png and b/assets/screenshots/app-store/iphone-6.9/03-sending-light.png differ diff --git a/assets/screenshots/app-store/iphone-6.9/05-receiving-light.png b/assets/screenshots/app-store/iphone-6.9/05-receiving-light.png index 8e8b5577..b1af0c32 100644 Binary files a/assets/screenshots/app-store/iphone-6.9/05-receiving-light.png and b/assets/screenshots/app-store/iphone-6.9/05-receiving-light.png differ diff --git a/assets/screenshots/app-store/iphone-6.9/07-stored-link-light.png b/assets/screenshots/app-store/iphone-6.9/07-stored-link-light.png index aa41bf04..dbf81c0c 100644 Binary files a/assets/screenshots/app-store/iphone-6.9/07-stored-link-light.png and b/assets/screenshots/app-store/iphone-6.9/07-stored-link-light.png differ diff --git a/assets/screenshots/app-store/iphone-6.9/08-history-dark.png b/assets/screenshots/app-store/iphone-6.9/08-history-dark.png index 271fc365..c5f0d23d 100644 Binary files a/assets/screenshots/app-store/iphone-6.9/08-history-dark.png and b/assets/screenshots/app-store/iphone-6.9/08-history-dark.png differ diff --git a/assets/screenshots/app-store/iphone-duo-outer/01-send-files-light.png b/assets/screenshots/app-store/iphone-duo-outer/01-send-files-light.png index 6321c0ef..3a9847b7 100644 Binary files a/assets/screenshots/app-store/iphone-duo-outer/01-send-files-light.png and b/assets/screenshots/app-store/iphone-duo-outer/01-send-files-light.png differ diff --git a/assets/screenshots/app-store/iphone-duo-outer/02-send-code-dark.png b/assets/screenshots/app-store/iphone-duo-outer/02-send-code-dark.png index 593ee5ca..53b17eaf 100644 Binary files a/assets/screenshots/app-store/iphone-duo-outer/02-send-code-dark.png and b/assets/screenshots/app-store/iphone-duo-outer/02-send-code-dark.png differ diff --git a/assets/screenshots/app-store/iphone-duo-outer/03-sending-light.png b/assets/screenshots/app-store/iphone-duo-outer/03-sending-light.png index 599a6605..24bf031a 100644 Binary files a/assets/screenshots/app-store/iphone-duo-outer/03-sending-light.png and b/assets/screenshots/app-store/iphone-duo-outer/03-sending-light.png differ diff --git a/assets/screenshots/app-store/iphone-duo-outer/05-receiving-light.png b/assets/screenshots/app-store/iphone-duo-outer/05-receiving-light.png index 1e618daa..5c17d888 100644 Binary files a/assets/screenshots/app-store/iphone-duo-outer/05-receiving-light.png and b/assets/screenshots/app-store/iphone-duo-outer/05-receiving-light.png differ diff --git a/assets/screenshots/app-store/iphone-duo-outer/07-stored-link-light.png b/assets/screenshots/app-store/iphone-duo-outer/07-stored-link-light.png index 2614b68f..64c491ff 100644 Binary files a/assets/screenshots/app-store/iphone-duo-outer/07-stored-link-light.png and b/assets/screenshots/app-store/iphone-duo-outer/07-stored-link-light.png differ diff --git a/assets/screenshots/app-store/iphone-duo-outer/08-history-dark.png b/assets/screenshots/app-store/iphone-duo-outer/08-history-dark.png index a42a270e..66fa2276 100644 Binary files a/assets/screenshots/app-store/iphone-duo-outer/08-history-dark.png and b/assets/screenshots/app-store/iphone-duo-outer/08-history-dark.png differ diff --git a/assets/screenshots/app-store/mac/01-send-files-light.png b/assets/screenshots/app-store/mac/01-send-files-light.png index ca0437a9..40ea7f5b 100644 Binary files a/assets/screenshots/app-store/mac/01-send-files-light.png and b/assets/screenshots/app-store/mac/01-send-files-light.png differ diff --git a/assets/screenshots/app-store/mac/02-send-code-dark.png b/assets/screenshots/app-store/mac/02-send-code-dark.png index 976d43dc..5060583c 100644 Binary files a/assets/screenshots/app-store/mac/02-send-code-dark.png and b/assets/screenshots/app-store/mac/02-send-code-dark.png differ diff --git a/assets/screenshots/app-store/mac/03-sending-light.png b/assets/screenshots/app-store/mac/03-sending-light.png index 38f729cb..ac62ec1c 100644 Binary files a/assets/screenshots/app-store/mac/03-sending-light.png and b/assets/screenshots/app-store/mac/03-sending-light.png differ diff --git a/assets/screenshots/app-store/mac/04-receive-incoming-dark.png b/assets/screenshots/app-store/mac/04-receive-incoming-dark.png index ba13c23a..fe4e62e9 100644 Binary files a/assets/screenshots/app-store/mac/04-receive-incoming-dark.png and b/assets/screenshots/app-store/mac/04-receive-incoming-dark.png differ diff --git a/assets/screenshots/app-store/mac/05-receiving-light.png b/assets/screenshots/app-store/mac/05-receiving-light.png index c50dbaf6..716a22b8 100644 Binary files a/assets/screenshots/app-store/mac/05-receiving-light.png and b/assets/screenshots/app-store/mac/05-receiving-light.png differ diff --git a/assets/screenshots/app-store/mac/06-receive-done-dark.png b/assets/screenshots/app-store/mac/06-receive-done-dark.png index d1f6f6b3..e7b85685 100644 Binary files a/assets/screenshots/app-store/mac/06-receive-done-dark.png and b/assets/screenshots/app-store/mac/06-receive-done-dark.png differ diff --git a/assets/screenshots/app-store/mac/07-stored-link-light.png b/assets/screenshots/app-store/mac/07-stored-link-light.png index 216d6f90..5b987502 100644 Binary files a/assets/screenshots/app-store/mac/07-stored-link-light.png and b/assets/screenshots/app-store/mac/07-stored-link-light.png differ diff --git a/assets/screenshots/app-store/mac/08-history-dark.png b/assets/screenshots/app-store/mac/08-history-dark.png index fe6941eb..f5bd290b 100644 Binary files a/assets/screenshots/app-store/mac/08-history-dark.png and b/assets/screenshots/app-store/mac/08-history-dark.png differ diff --git a/assets/screenshots/app-store/mac/09-settings-light.png b/assets/screenshots/app-store/mac/09-settings-light.png index b6f31b82..36abf565 100644 Binary files a/assets/screenshots/app-store/mac/09-settings-light.png and b/assets/screenshots/app-store/mac/09-settings-light.png differ diff --git a/assets/screenshots/app-store/mac/10-how-it-works-dark.png b/assets/screenshots/app-store/mac/10-how-it-works-dark.png index 32986621..e36bc1f0 100644 Binary files a/assets/screenshots/app-store/mac/10-how-it-works-dark.png and b/assets/screenshots/app-store/mac/10-how-it-works-dark.png differ diff --git a/assets/screenshots/ipad/history-dark.png b/assets/screenshots/ipad/history-dark.png index ea3d96fd..c3c5e884 100644 Binary files a/assets/screenshots/ipad/history-dark.png and b/assets/screenshots/ipad/history-dark.png differ diff --git a/assets/screenshots/ipad/history-light.png b/assets/screenshots/ipad/history-light.png index ed5a5a2e..c87036e0 100644 Binary files a/assets/screenshots/ipad/history-light.png and b/assets/screenshots/ipad/history-light.png differ diff --git a/assets/screenshots/ipad/home-dark.png b/assets/screenshots/ipad/home-dark.png index 01db5338..4f05fdb2 100644 Binary files a/assets/screenshots/ipad/home-dark.png and b/assets/screenshots/ipad/home-dark.png differ diff --git a/assets/screenshots/ipad/home-light.png b/assets/screenshots/ipad/home-light.png index b7268581..256bcf3c 100644 Binary files a/assets/screenshots/ipad/home-light.png and b/assets/screenshots/ipad/home-light.png differ diff --git a/assets/screenshots/ipad/how-it-works-dark.png b/assets/screenshots/ipad/how-it-works-dark.png index ebc7f069..d1444f3d 100644 Binary files a/assets/screenshots/ipad/how-it-works-dark.png and b/assets/screenshots/ipad/how-it-works-dark.png differ diff --git a/assets/screenshots/ipad/how-it-works-light.png b/assets/screenshots/ipad/how-it-works-light.png index 985206ba..c225563f 100644 Binary files a/assets/screenshots/ipad/how-it-works-light.png and b/assets/screenshots/ipad/how-it-works-light.png differ diff --git a/assets/screenshots/ipad/onboarding-dark.png b/assets/screenshots/ipad/onboarding-dark.png index b879a273..19aafa36 100644 Binary files a/assets/screenshots/ipad/onboarding-dark.png and b/assets/screenshots/ipad/onboarding-dark.png differ diff --git a/assets/screenshots/ipad/onboarding-light.png b/assets/screenshots/ipad/onboarding-light.png index 884708ed..a02bbc26 100644 Binary files a/assets/screenshots/ipad/onboarding-light.png and b/assets/screenshots/ipad/onboarding-light.png differ diff --git a/assets/screenshots/ipad/receive-code-dark.png b/assets/screenshots/ipad/receive-code-dark.png index b065dffc..9b2da4e4 100644 Binary files a/assets/screenshots/ipad/receive-code-dark.png and b/assets/screenshots/ipad/receive-code-dark.png differ diff --git a/assets/screenshots/ipad/receive-code-light.png b/assets/screenshots/ipad/receive-code-light.png index 0a4b7bde..0c64bd0d 100644 Binary files a/assets/screenshots/ipad/receive-code-light.png and b/assets/screenshots/ipad/receive-code-light.png differ diff --git a/assets/screenshots/ipad/receive-conflict-dark.png b/assets/screenshots/ipad/receive-conflict-dark.png index 116ddf8b..2af70ddc 100644 Binary files a/assets/screenshots/ipad/receive-conflict-dark.png and b/assets/screenshots/ipad/receive-conflict-dark.png differ diff --git a/assets/screenshots/ipad/receive-conflict-light.png b/assets/screenshots/ipad/receive-conflict-light.png index 11bf45af..d62bfc69 100644 Binary files a/assets/screenshots/ipad/receive-conflict-light.png and b/assets/screenshots/ipad/receive-conflict-light.png differ diff --git a/assets/screenshots/ipad/receive-done-dark.png b/assets/screenshots/ipad/receive-done-dark.png index 1bdac7c4..f326da9f 100644 Binary files a/assets/screenshots/ipad/receive-done-dark.png and b/assets/screenshots/ipad/receive-done-dark.png differ diff --git a/assets/screenshots/ipad/receive-done-light.png b/assets/screenshots/ipad/receive-done-light.png index 025effc3..3627c7eb 100644 Binary files a/assets/screenshots/ipad/receive-done-light.png and b/assets/screenshots/ipad/receive-done-light.png differ diff --git a/assets/screenshots/ipad/receive-incoming-dark.png b/assets/screenshots/ipad/receive-incoming-dark.png index 7482ad36..c18d2300 100644 Binary files a/assets/screenshots/ipad/receive-incoming-dark.png and b/assets/screenshots/ipad/receive-incoming-dark.png differ diff --git a/assets/screenshots/ipad/receive-incoming-light.png b/assets/screenshots/ipad/receive-incoming-light.png index 26939e8d..7b4f42cf 100644 Binary files a/assets/screenshots/ipad/receive-incoming-light.png and b/assets/screenshots/ipad/receive-incoming-light.png differ diff --git a/assets/screenshots/ipad/receiving-dark.png b/assets/screenshots/ipad/receiving-dark.png index 36f46e6f..e0c16c72 100644 Binary files a/assets/screenshots/ipad/receiving-dark.png and b/assets/screenshots/ipad/receiving-dark.png differ diff --git a/assets/screenshots/ipad/receiving-light.png b/assets/screenshots/ipad/receiving-light.png index 8a643f19..68056fc8 100644 Binary files a/assets/screenshots/ipad/receiving-light.png and b/assets/screenshots/ipad/receiving-light.png differ diff --git a/assets/screenshots/ipad/send-code-dark.png b/assets/screenshots/ipad/send-code-dark.png index efc662de..b6a73095 100644 Binary files a/assets/screenshots/ipad/send-code-dark.png and b/assets/screenshots/ipad/send-code-dark.png differ diff --git a/assets/screenshots/ipad/send-code-light.png b/assets/screenshots/ipad/send-code-light.png index 85815b23..be31a922 100644 Binary files a/assets/screenshots/ipad/send-code-light.png and b/assets/screenshots/ipad/send-code-light.png differ diff --git a/assets/screenshots/ipad/send-files-dark.png b/assets/screenshots/ipad/send-files-dark.png index fcf7d4b4..9db74b02 100644 Binary files a/assets/screenshots/ipad/send-files-dark.png and b/assets/screenshots/ipad/send-files-dark.png differ diff --git a/assets/screenshots/ipad/send-files-light.png b/assets/screenshots/ipad/send-files-light.png index f4ffbf0b..954dc690 100644 Binary files a/assets/screenshots/ipad/send-files-light.png and b/assets/screenshots/ipad/send-files-light.png differ diff --git a/assets/screenshots/ipad/sending-dark.png b/assets/screenshots/ipad/sending-dark.png index 2d71b80b..c60ba246 100644 Binary files a/assets/screenshots/ipad/sending-dark.png and b/assets/screenshots/ipad/sending-dark.png differ diff --git a/assets/screenshots/ipad/sending-light.png b/assets/screenshots/ipad/sending-light.png index 44330f59..fb0e213a 100644 Binary files a/assets/screenshots/ipad/sending-light.png and b/assets/screenshots/ipad/sending-light.png differ diff --git a/assets/screenshots/ipad/settings-advanced-dark.png b/assets/screenshots/ipad/settings-advanced-dark.png index a8c83102..e43b909c 100644 Binary files a/assets/screenshots/ipad/settings-advanced-dark.png and b/assets/screenshots/ipad/settings-advanced-dark.png differ diff --git a/assets/screenshots/ipad/settings-advanced-light.png b/assets/screenshots/ipad/settings-advanced-light.png index f61739fd..4d1632c1 100644 Binary files a/assets/screenshots/ipad/settings-advanced-light.png and b/assets/screenshots/ipad/settings-advanced-light.png differ diff --git a/assets/screenshots/ipad/settings-dark.png b/assets/screenshots/ipad/settings-dark.png index b40e397b..157cd09b 100644 Binary files a/assets/screenshots/ipad/settings-dark.png and b/assets/screenshots/ipad/settings-dark.png differ diff --git a/assets/screenshots/ipad/settings-light.png b/assets/screenshots/ipad/settings-light.png index 96bb777d..c4db6571 100644 Binary files a/assets/screenshots/ipad/settings-light.png and b/assets/screenshots/ipad/settings-light.png differ diff --git a/assets/screenshots/ipad/stored-link-dark.png b/assets/screenshots/ipad/stored-link-dark.png index a03e26c4..fb59787c 100644 Binary files a/assets/screenshots/ipad/stored-link-dark.png and b/assets/screenshots/ipad/stored-link-dark.png differ diff --git a/assets/screenshots/ipad/stored-link-light.png b/assets/screenshots/ipad/stored-link-light.png index 509f20c3..db9b6399 100644 Binary files a/assets/screenshots/ipad/stored-link-light.png and b/assets/screenshots/ipad/stored-link-light.png differ diff --git a/assets/screenshots/iphone/history-dark.png b/assets/screenshots/iphone/history-dark.png index 713de1f7..64744fa1 100644 Binary files a/assets/screenshots/iphone/history-dark.png and b/assets/screenshots/iphone/history-dark.png differ diff --git a/assets/screenshots/iphone/history-light.png b/assets/screenshots/iphone/history-light.png index 7cd513b2..9c935fb1 100644 Binary files a/assets/screenshots/iphone/history-light.png and b/assets/screenshots/iphone/history-light.png differ diff --git a/assets/screenshots/iphone/home-light.png b/assets/screenshots/iphone/home-light.png index 58cb77fe..a385dfc3 100644 Binary files a/assets/screenshots/iphone/home-light.png and b/assets/screenshots/iphone/home-light.png differ diff --git a/assets/screenshots/iphone/onboarding-light.png b/assets/screenshots/iphone/onboarding-light.png index 04267b1b..544f88c7 100644 Binary files a/assets/screenshots/iphone/onboarding-light.png and b/assets/screenshots/iphone/onboarding-light.png differ diff --git a/assets/screenshots/iphone/receive-conflict-dark.png b/assets/screenshots/iphone/receive-conflict-dark.png index 95d1ab5d..d1442a32 100644 Binary files a/assets/screenshots/iphone/receive-conflict-dark.png and b/assets/screenshots/iphone/receive-conflict-dark.png differ diff --git a/assets/screenshots/iphone/receive-conflict-light.png b/assets/screenshots/iphone/receive-conflict-light.png index 3a68a399..ec925249 100644 Binary files a/assets/screenshots/iphone/receive-conflict-light.png and b/assets/screenshots/iphone/receive-conflict-light.png differ diff --git a/assets/screenshots/iphone/receive-done-light.png b/assets/screenshots/iphone/receive-done-light.png index 89e6aa77..7ca00b72 100644 Binary files a/assets/screenshots/iphone/receive-done-light.png and b/assets/screenshots/iphone/receive-done-light.png differ diff --git a/assets/screenshots/iphone/receive-incoming-light.png b/assets/screenshots/iphone/receive-incoming-light.png index fd0249ea..61e23a05 100644 Binary files a/assets/screenshots/iphone/receive-incoming-light.png and b/assets/screenshots/iphone/receive-incoming-light.png differ diff --git a/assets/screenshots/iphone/receiving-dark.png b/assets/screenshots/iphone/receiving-dark.png index 10f40b05..da8a796c 100644 Binary files a/assets/screenshots/iphone/receiving-dark.png and b/assets/screenshots/iphone/receiving-dark.png differ diff --git a/assets/screenshots/iphone/receiving-light.png b/assets/screenshots/iphone/receiving-light.png index 81ad143e..b1bef9c3 100644 Binary files a/assets/screenshots/iphone/receiving-light.png and b/assets/screenshots/iphone/receiving-light.png differ diff --git a/assets/screenshots/iphone/send-code-dark.png b/assets/screenshots/iphone/send-code-dark.png index 1d323f63..f1b77f94 100644 Binary files a/assets/screenshots/iphone/send-code-dark.png and b/assets/screenshots/iphone/send-code-dark.png differ diff --git a/assets/screenshots/iphone/send-code-light.png b/assets/screenshots/iphone/send-code-light.png index 49ce2b04..feafdc44 100644 Binary files a/assets/screenshots/iphone/send-code-light.png and b/assets/screenshots/iphone/send-code-light.png differ diff --git a/assets/screenshots/iphone/send-files-light.png b/assets/screenshots/iphone/send-files-light.png index 9af9d678..1505f7b6 100644 Binary files a/assets/screenshots/iphone/send-files-light.png and b/assets/screenshots/iphone/send-files-light.png differ diff --git a/assets/screenshots/iphone/sending-dark.png b/assets/screenshots/iphone/sending-dark.png index 4369db88..f63ccc39 100644 Binary files a/assets/screenshots/iphone/sending-dark.png and b/assets/screenshots/iphone/sending-dark.png differ diff --git a/assets/screenshots/iphone/sending-light.png b/assets/screenshots/iphone/sending-light.png index 90afc7c4..a70e5729 100644 Binary files a/assets/screenshots/iphone/sending-light.png and b/assets/screenshots/iphone/sending-light.png differ diff --git a/assets/screenshots/iphone/stored-link-dark.png b/assets/screenshots/iphone/stored-link-dark.png index 22b17f37..10650697 100644 Binary files a/assets/screenshots/iphone/stored-link-dark.png and b/assets/screenshots/iphone/stored-link-dark.png differ diff --git a/assets/screenshots/iphone/stored-link-light.png b/assets/screenshots/iphone/stored-link-light.png index 337426ac..efe321d1 100644 Binary files a/assets/screenshots/iphone/stored-link-light.png and b/assets/screenshots/iphone/stored-link-light.png differ diff --git a/assets/screenshots/mac/history-dark.png b/assets/screenshots/mac/history-dark.png index 71a22fd2..78e328c3 100644 Binary files a/assets/screenshots/mac/history-dark.png and b/assets/screenshots/mac/history-dark.png differ diff --git a/assets/screenshots/mac/history-light.png b/assets/screenshots/mac/history-light.png index 561efeed..0d7bf1f8 100644 Binary files a/assets/screenshots/mac/history-light.png and b/assets/screenshots/mac/history-light.png differ diff --git a/assets/screenshots/mac/home-dark.png b/assets/screenshots/mac/home-dark.png index 525452e5..7a9624db 100644 Binary files a/assets/screenshots/mac/home-dark.png and b/assets/screenshots/mac/home-dark.png differ diff --git a/assets/screenshots/mac/home-light.png b/assets/screenshots/mac/home-light.png index e9746f23..65cce75b 100644 Binary files a/assets/screenshots/mac/home-light.png and b/assets/screenshots/mac/home-light.png differ diff --git a/assets/screenshots/mac/how-it-works-dark.png b/assets/screenshots/mac/how-it-works-dark.png index dd2d4d20..debbe64c 100644 Binary files a/assets/screenshots/mac/how-it-works-dark.png and b/assets/screenshots/mac/how-it-works-dark.png differ diff --git a/assets/screenshots/mac/receive-code-dark.png b/assets/screenshots/mac/receive-code-dark.png index 1f3778a3..e0bf4d08 100644 Binary files a/assets/screenshots/mac/receive-code-dark.png and b/assets/screenshots/mac/receive-code-dark.png differ diff --git a/assets/screenshots/mac/receive-code-light.png b/assets/screenshots/mac/receive-code-light.png index 3813fa9c..a227fa93 100644 Binary files a/assets/screenshots/mac/receive-code-light.png and b/assets/screenshots/mac/receive-code-light.png differ diff --git a/assets/screenshots/mac/receive-conflict-dark.png b/assets/screenshots/mac/receive-conflict-dark.png index 1dda1bbf..14987a4f 100644 Binary files a/assets/screenshots/mac/receive-conflict-dark.png and b/assets/screenshots/mac/receive-conflict-dark.png differ diff --git a/assets/screenshots/mac/receive-conflict-light.png b/assets/screenshots/mac/receive-conflict-light.png index 34295f4e..de75dd62 100644 Binary files a/assets/screenshots/mac/receive-conflict-light.png and b/assets/screenshots/mac/receive-conflict-light.png differ diff --git a/assets/screenshots/mac/receive-done-dark.png b/assets/screenshots/mac/receive-done-dark.png index b63d4db5..aabbf25b 100644 Binary files a/assets/screenshots/mac/receive-done-dark.png and b/assets/screenshots/mac/receive-done-dark.png differ diff --git a/assets/screenshots/mac/receive-done-light.png b/assets/screenshots/mac/receive-done-light.png index 50153c89..b1639a00 100644 Binary files a/assets/screenshots/mac/receive-done-light.png and b/assets/screenshots/mac/receive-done-light.png differ diff --git a/assets/screenshots/mac/receive-incoming-dark.png b/assets/screenshots/mac/receive-incoming-dark.png index 59ef431d..2f00b05d 100644 Binary files a/assets/screenshots/mac/receive-incoming-dark.png and b/assets/screenshots/mac/receive-incoming-dark.png differ diff --git a/assets/screenshots/mac/receive-incoming-light.png b/assets/screenshots/mac/receive-incoming-light.png index 628679f9..430252c8 100644 Binary files a/assets/screenshots/mac/receive-incoming-light.png and b/assets/screenshots/mac/receive-incoming-light.png differ diff --git a/assets/screenshots/mac/receiving-dark.png b/assets/screenshots/mac/receiving-dark.png index b7d5156c..89034574 100644 Binary files a/assets/screenshots/mac/receiving-dark.png and b/assets/screenshots/mac/receiving-dark.png differ diff --git a/assets/screenshots/mac/receiving-light.png b/assets/screenshots/mac/receiving-light.png index 64995116..5b7e07ef 100644 Binary files a/assets/screenshots/mac/receiving-light.png and b/assets/screenshots/mac/receiving-light.png differ diff --git a/assets/screenshots/mac/send-code-dark.png b/assets/screenshots/mac/send-code-dark.png index 3bd380bc..1b557c82 100644 Binary files a/assets/screenshots/mac/send-code-dark.png and b/assets/screenshots/mac/send-code-dark.png differ diff --git a/assets/screenshots/mac/send-code-light.png b/assets/screenshots/mac/send-code-light.png index 35840573..57fb5a40 100644 Binary files a/assets/screenshots/mac/send-code-light.png and b/assets/screenshots/mac/send-code-light.png differ diff --git a/assets/screenshots/mac/send-files-dark.png b/assets/screenshots/mac/send-files-dark.png index 3739ae75..0ceb4325 100644 Binary files a/assets/screenshots/mac/send-files-dark.png and b/assets/screenshots/mac/send-files-dark.png differ diff --git a/assets/screenshots/mac/send-files-light.png b/assets/screenshots/mac/send-files-light.png index 7ded2bea..d70aa77f 100644 Binary files a/assets/screenshots/mac/send-files-light.png and b/assets/screenshots/mac/send-files-light.png differ diff --git a/assets/screenshots/mac/sending-dark.png b/assets/screenshots/mac/sending-dark.png index 5957e316..b24abcb8 100644 Binary files a/assets/screenshots/mac/sending-dark.png and b/assets/screenshots/mac/sending-dark.png differ diff --git a/assets/screenshots/mac/sending-light.png b/assets/screenshots/mac/sending-light.png index ca7b03d2..303695a6 100644 Binary files a/assets/screenshots/mac/sending-light.png and b/assets/screenshots/mac/sending-light.png differ diff --git a/assets/screenshots/mac/settings-advanced-dark.png b/assets/screenshots/mac/settings-advanced-dark.png index bdaa03f1..b5cba1ad 100644 Binary files a/assets/screenshots/mac/settings-advanced-dark.png and b/assets/screenshots/mac/settings-advanced-dark.png differ diff --git a/assets/screenshots/mac/settings-dark.png b/assets/screenshots/mac/settings-dark.png index f8b111ae..915bf56c 100644 Binary files a/assets/screenshots/mac/settings-dark.png and b/assets/screenshots/mac/settings-dark.png differ diff --git a/assets/screenshots/mac/settings-light.png b/assets/screenshots/mac/settings-light.png index 1f380cdf..aa44c93b 100644 Binary files a/assets/screenshots/mac/settings-light.png and b/assets/screenshots/mac/settings-light.png differ diff --git a/assets/screenshots/mac/stored-link-dark.png b/assets/screenshots/mac/stored-link-dark.png index 12a3c0e6..58c9218a 100644 Binary files a/assets/screenshots/mac/stored-link-dark.png and b/assets/screenshots/mac/stored-link-dark.png differ diff --git a/assets/screenshots/mac/stored-link-light.png b/assets/screenshots/mac/stored-link-light.png index ba956ce7..5017062f 100644 Binary files a/assets/screenshots/mac/stored-link-light.png and b/assets/screenshots/mac/stored-link-light.png differ diff --git a/design/AGENTS.md b/design/AGENTS.md index 4b8d0b66..80529ecb 100644 --- a/design/AGENTS.md +++ b/design/AGENTS.md @@ -38,7 +38,7 @@ The markdown is canonical. Two hand-written mirrors carry it into code: Change a value in a markdown file and in both mirrors in the same commit. `design/tokens.css` is the only committed CSS copy: `scripts/assemble-site.sh` copies it for the landing page and `web/docs`'s `tokens` npm script for the docs site. Never edit a copy. -One script enforces this directory, and CI runs it on any change to `design/`, `app/` Swift or color sets, or web CSS: +One script enforces this directory, and CI runs it on any change to `design/`, `app/` Swift or color sets, or the web CSS, scripts and manifest it lints: ```bash scripts/verify-design.sh # mirror parity (tokens.css = DesignTokens.swift = color sets), contrast (every ratio colors.md claims plus the seven rules) and the no-literals lint diff --git a/design/accessibility.md b/design/accessibility.md index 4b458ac9..a7204c23 100644 --- a/design/accessibility.md +++ b/design/accessibility.md @@ -9,7 +9,7 @@ WCAG 2.2 AA: body text 4.5:1, large text and UI boundaries 3:1. **Light is the c - **Accent is a fill, not a label.** Accent text is `--color-accent-text`, or `--color-accent-text-on-tint` on grouped and tinted surfaces. In the app that includes every bordered and plain button label. - **A status color is a fill, never a foreground.** Status text is `--color-text-primary`. -The one accepted deviation is the filled button (`colors.md` rule 3). +The one accepted deviation is the filled destructive button (`colors.md` rule 3); the filled prominent button clears AA on `--color-accent-solid`. ## Focus diff --git a/design/brand.md b/design/brand.md index 99c5ab7f..9458db6b 100644 --- a/design/brand.md +++ b/design/brand.md @@ -70,13 +70,24 @@ SF Pro and SF Mono through the system font, never a shipped font file, never a s | App icon | `assets/CrocAppIcon.icon` | the logo; the app builds `app/CrocApp/AppIcon.icon` | | Mascot | `assets/mascot.png` | source for every mascot derivative | | Mascot, web | `web/landing/assets/img/mascot-web.webp` | landing, docs navbar, web empty states | +| Favicons | `assets/favicons/` (source set), `web/landing/assets/img/favicon/` (served copy) | the app icon at web sizes: `favicon.ico` (16, 32, 48), `favicon-96x96.png`, `apple-touch-icon.png` (180), `web-app-manifest-{192x192,512x512}.png`, `site.webmanifest`. The docs site references the landing copy. Recipe below | | Screenshots | `assets/screenshots/{mac,iphone,ipad}/-{light,dark}.png` | README, docs, landing hero | | App Store screenshots | `assets/screenshots/app-store//NN--{light,dark}.png` | App Store Connect | -| Social card | `web/landing/assets/img/og.jpg` | 1200×630, light: wordmark, accent `lock`, headline, the site URL, mascot on the trailing side | +| Social card | `web/landing/assets/img/og.jpg` | 1200×630, light: wordmark, accent `lock`, headline "Send files with a code phrase", the line "Encrypted end-to-end", the site URL, mascot on the trailing side | | GitHub social preview | `assets/github-social-preview.png` | 1280×640, the same layout in dark values (`--bg-secondary`, `--label-1`, `--label-2-web`, `--green-400`) with the repo URL; uploaded by hand in the repo settings | | Disk image background | `assets/dmg-background.tiff` | `components.md` → DiskImage | | App Store badges | `web/landing/assets/img/app-store.svg`, `mac-app-store.svg` | Apple's artwork, below | +### Favicon recipe + +Favicons are the app icon, not the bare mascot. Regenerate them whenever the icon changes: + +1. Render the icon: `ictool assets/CrocAppIcon.icon --export-image --output-file icon.png --platform iOS --rendition Default --width 1024 --height 1024 --scale 1` (`ictool` path in `assets/AGENTS.md`). The render is the masked squircle with transparent corners; the macOS platform renders the same pixels. +2. Make an opaque touch master from it, because iOS and Android fill transparent corners with black: scale the render to 1198px (`sips -z 1198 1198`), center-crop to 1024 (`sips -c 1024 1024`), then fill the few remaining transparent corner pixels with the icon's own corner colors. The mascot stays inside the crop. +3. On [realfavicongenerator.net](https://realfavicongenerator.net), upload the step 1 render as the main icon and set: regular icon "Use the icon as is", no dark icon; Apple touch icon "Use a dedicated icon" with the step 2 master, "Use the icon as is", app name `CrocApp`; web app manifest "Use a dedicated icon" with the step 2 master, "Use the icon as is", name and short name `CrocApp`, background and theme color `#FFFFFF`; Windows tile left at its default; favicon path `/`, no version, metadata injection skipped. Download the zip. +4. Keep `favicon.ico`, `favicon-96x96.png`, `apple-touch-icon.png` and the two `web-app-manifest-*` PNGs. Drop `favicon.svg` (it only wraps a PNG) and the generated `site.webmanifest`: ours keeps `id`, `description`, `scope`, relative icon paths and `purpose: "any"`, with `theme_color` and `background_color` equal to `--bg-base` light (`#FFFFFF`). The mascot overflows the 80% maskable safe zone, so the icons are not `maskable`. +5. Put the set in `assets/favicons/`, copy the same files to `web/landing/assets/img/favicon/`. + ## Naming "CrocApp": one word, capital C and A. Never "Croc App", "Crocapp" or "CrocAPP". "croc", the CLI, is always lowercase. Bundle ID `com.bakirgdev.CrocApp`; share extension `com.bakirgdev.CrocApp.CrocShare`. diff --git a/design/colors.md b/design/colors.md index c6a5475c..8af7c035 100644 --- a/design/colors.md +++ b/design/colors.md @@ -13,8 +13,8 @@ Theme-independent literals. The accent alias swaps which step it points at. The | `--green-400` | `#2DC585` | **dark-mode accent** | | `--green-500` | `#22B074` | dark-mode pressed | | `--green-600` | `#1E9E6A` | **light-mode accent (brand color)** | -| `--green-700` | `#178055` | light-mode pressed; small accent text | -| `--green-800` | `#116243` | | +| `--green-700` | `#178055` | light-mode filled-button background; small accent text | +| `--green-800` | `#116243` | light-mode pressed; accent text on tints | | `--green-900` | `#0C4A33` | | `#05271A` is the dark-theme on-accent ink (label drawn on top of `--green-400`). @@ -75,7 +75,8 @@ Pair each with the matching `--blur-*` and `--glass-saturate` (see `materials.md | Alias | Light | Dark | |---|---|---| | `--color-accent` | `--green-600` | `--green-400` | -| `--color-accent-pressed` | `--green-700` | `--green-500` | +| `--color-accent-solid` | `--green-700` | `--green-400` | +| `--color-accent-pressed` | `--green-800` | `--green-500` | | `--color-accent-text` | `--green-700` | `--green-400` | | `--color-accent-text-on-tint` | `--green-800` | `--green-400` | | `--color-accent-tint` | `--glass-tint-accent` | `--glass-tint-accent` | @@ -113,27 +114,28 @@ Every row is recomputed from `tokens.css` by `scripts/verify-design.sh` (contras | `--color-accent` on base / grouped / its own tint | 3.41 / 3.06 / 2.99 | UI + large text only; never a letter | | `--color-accent-text` `#178055` on base / card | 4.94 / 4.94 | AA body | | `--color-accent-text` on grouped / accent tint | 4.42 / 4.32 | fails body: use the step below | -| `--color-accent-text-on-tint` `#116243` on base / grouped / accent tint | 7.36 / 6.60 / 6.45 | AA body everywhere | +| `--color-accent-text` on a `--color-fill-tertiary` wash (inline code, striped table row) | 4.28 | fails body: use the step below | +| `--color-accent-text-on-tint` `#116243` on base / grouped / accent tint / fill wash | 7.36 / 6.60 / 6.45 / 6.38 | AA body everywhere | | `--label-2` 0.60 on base | 3.44 | fails body: Apple's own secondaryLabel | | `--label-2-web` 0.75 on base / grouped | 5.16 / 4.85 | AA body | | `--color-text-secondary` (`--label-2-web`) on accent tint | 4.78 | AA body, 0.28 of headroom | | `--label-3` on base | 1.73 | decorative fill only | -| `--color-accent` band of `--shadow-focus-ring` on base / on the accent fill | 3.41 / 3.41 | AA non-text, rule 7 | +| `--color-accent` band of `--shadow-focus-ring` on base, and the base band on `--color-accent-solid` | 3.41 / 4.94 | AA non-text, rule 7 | | `--glass-tint-accent` composited on base | 1.14 | not a focus indicator, rule 7 | -| `--color-on-accent` on `--color-accent` | 3.41 | filled-button deviation, rule 3 | -| `--color-on-status` on `--color-status-error` | 3.55 | filled-button deviation, rule 3 | +| `--color-on-accent` on `--color-accent-solid` `#178055` / `--color-accent-pressed` `#116243` | 4.94 / 7.36 | AA body, rule 3 | +| `--color-on-status` on `--color-status-error` | 3.55 | filled-destructive deviation, rule 3 | | `--color-status-success` / `-warning` / `-error` on its own tint | 1.98 / 1.96 / 2.94 | nothing | | `--color-status-success` / `-warning` / `-error` / `-info` on base | 2.22 / 2.20 / 3.55 / 4.02 | fill and glyph only | -Dark, for the record: accent 9.44 on base, 7.65 on card, 7.72 on its own tint; `--color-on-accent` 7.19 on the accent; `--color-on-status` 3.41 on `--color-status-error`, the same rule-3 deviation as light; `--label-2` 6.36 on base; every status color on its own tint: success 8.05, warning 7.93, error 5.25, info 4.92 (all AA body). Nothing else in dark needs a substitute, which is why all three accent-text aliases collapse to `--green-400` there. +Dark, for the record: accent 9.44 on base, 7.65 on card, 7.72 on its own tint; `--color-on-accent` 7.19 on `--color-accent-solid` (the accent itself) and 5.74 on `--color-accent-pressed`; `--color-on-status` 3.41 on `--color-status-error`, the same rule-3 deviation as light; `--label-2` 6.36 on base; every status color on its own tint: success 8.05, warning 7.93, error 5.25, info 4.92 (all AA body). Nothing else in dark needs a substitute, which is why `--color-accent-solid` and all three accent-text aliases collapse to `--green-400` there. ### Rules -1. **Accent as text is not accent as a fill.** Icons, fills, borders and progress bars keep `--color-accent`: they owe 3:1 and clear it. Anything with a letter in it takes `--color-accent-text` on `--color-surface-base` / `--color-surface-card`, and `--color-accent-text-on-tint` on every other light surface: `--color-accent-tint`, and `--color-surface-grouped`, which is the app's page fill. In the app that means a `.bordered` or plain button's label too, never the inherited tint (`swiftui.md` → Colors). `--green-800` is the only accent step that clears AA everywhere in light. +1. **Accent as text is not accent as a fill.** Icons, fills, borders and progress bars keep `--color-accent`: they owe 3:1 and clear it. Anything with a letter in it takes `--color-accent-text` on `--color-surface-base` / `--color-surface-card`, and `--color-accent-text-on-tint` on every other light surface: `--color-accent-tint`, a `--color-fill-tertiary` wash (inline code, striped table rows: 4.28:1 for the plain step), and `--color-surface-grouped`, which is the app's page fill. In the app that means a `.bordered` or plain button's label too, never the inherited tint (`swiftui.md` → Colors). `--green-800` is the only accent step that clears AA everywhere in light. 2. **A status color is a fill, never a foreground.** In light it fails on its own tint (1.96 - 2.94) and three of four fail on base. Status *text* (banner titles, tinted-destructive labels, trust-badge labels, the app's destructive button labels) is `--color-text-primary`; the tint and border carry the semantic. Status *glyphs* may stay in the kind color: they are `aria-hidden` and always redundant with an adjacent label (`iconography.md`), which makes them decorative, so 1.4.11 does not bind them. They do read faint in light, which is why the label, not the glyph, has to carry the meaning. Never "improve" a banner by tinting its body copy. -3. **Filled prominent and destructive buttons ship at 3.41:1 and 3.55:1.** Both clear 3:1, neither clears 4.5:1. Accepted, because it is what Apple's own filled controls measure, on two conditions: the label stays ≥ 17px semibold and never shrinks, and small sizes use a tinted variant instead of a filled one. Their ink is `--color-on-accent` and `--color-on-status`: the only two places a knocked-out white label is allowed, and neither is a raw literal. +3. **A filled prominent button is `--color-accent-solid`, not `--color-accent`.** White on the brand green is 3.41:1, so light fills with `--green-700` (4.94:1, AA body) and presses to `--green-800` (7.36:1); dark keeps the accent, which already clears 7.19:1. Accent as a background that carries a label is the one use `--color-accent` does not serve. The filled destructive button has no such step and ships at 3.55:1 light, 3.41:1 dark: the system has one error red (`--sys-red`, Apple's own value, and the app's destructive controls read as the system's), darkening it for one control would fork the status color from every glyph, tint and border that share it, and a darker red is a new base color rather than an existing ramp step. It clears 3:1 on three conditions: the label stays ≥ 17px semibold and never shrinks, small sizes use `destructive-tinted`, and filled destructive stays limited to Decline and confirming Clear History (`components.md` → Button). Their ink is `--color-on-accent` and `--color-on-status`: the only two places a knocked-out label is allowed, and neither is a raw literal. 4. **`--color-text-secondary` is not `--label-2` in light.** Apple's secondaryLabel (0.60) is 3.44:1 on white, below AA for anything under large text, which is most of a web page. `--label-2` keeps the true system value so the app stays visually native; the alias resolves to `--label-2-web` (0.75). An app view consuming these tokens directly wants `--label-2`. @@ -141,4 +143,4 @@ Dark, for the record: accent 9.44 on base, 7.65 on card, 7.72 on its own tint; ` 6. **`--color-text-link` is `--color-accent-text`, not the accent**, and follows rule 1: a link on `--color-surface-grouped` or a tint takes `--color-accent-text-on-tint`, or sits on a card. -7. **The focus ring owes 3:1 and is not decoration.** It is two 2px bands, `--color-surface-base` inside and `--color-accent` outside, precisely so one of them always has a 3.41:1 edge against whatever it surrounds, including the accent-filled button. A tint cannot do this job: `--glass-tint-accent` at 12% composites to 1.14:1 on base, which leaves the ring invisible. Non-text contrast (1.4.11) binds focus indicators; a calm-looking ring that nobody can see is a failure, not a style. +7. **The focus ring owes 3:1 and is not decoration.** It is two 2px bands, `--color-surface-base` inside and `--color-accent` outside, precisely so one of them always has a 3.41:1 edge against whatever it surrounds, including the filled button, whose `--color-accent-solid` fill reads against the base band at 4.94:1. A tint cannot do this job: `--glass-tint-accent` at 12% composites to 1.14:1 on base, which leaves the ring invisible. Non-text contrast (1.4.11) binds focus indicators; a calm-looking ring that nobody can see is a failure, not a style. diff --git a/design/components.md b/design/components.md index 0b820093..cbbceaa7 100644 --- a/design/components.md +++ b/design/components.md @@ -46,7 +46,7 @@ Always `--weight-semibold`, `--tracking-headline`, `line-height: 1`, `--radius-c | Variant | Background | Label | Border | Pressed | |---|---|---|---|---| -| `prominent` | `--color-accent` | `--color-on-accent` | none | `--color-accent-pressed` | +| `prominent` | `--color-accent-solid` | `--color-on-accent` | none | `--color-accent-pressed` | | `secondary` | `--color-accent-tint` | `--color-accent-text-on-tint` | none | `color-mix(in srgb, var(--color-accent) 12%, var(--color-accent-tint))` | | `destructive` | `--color-status-error` | `--color-on-status` | none | `color-mix(in srgb, var(--color-status-error) 82%, black)` | | `destructive-tinted` | `--color-status-error-tint` | `--color-text-primary` | 22% error | `color-mix(in srgb, var(--color-status-error) 12%, var(--color-status-error-tint))` | @@ -54,7 +54,7 @@ Always `--weight-semibold`, `--tracking-headline`, `line-height: 1`, `--radius-c `prominent` and `destructive` carry `--shadow-sm` on web. -- `prominent` (3.41:1) and `destructive` (3.55:1) are the filled-button deviation (`colors.md` rule 3). **There is no small filled button**: a small accent or destructive action is `secondary` or `destructive-tinted`. +- `prominent` is 4.94:1 (AA) because its fill is `--color-accent-solid`, not the brand green; `destructive` is 3.55:1, the one accepted deviation (`colors.md` rule 3). **There is no small filled button**: a small accent or destructive action is `secondary` or `destructive-tinted`. - `destructive-tinted` never draws its label in the error color (2.94:1). The tint and border say "destructive"; the leading glyph may stay `--color-status-error`. - Usage: at most one `prominent` per screen. Filled `destructive` only for Decline (the accept gate) and confirming Clear History. Cancel transfer and Discard are `destructive-tinted`: they sit on screens the user watches for a while, and a calm screen does not shout. Everything else that is secondary is `secondary` or `plain`. diff --git a/design/materials.md b/design/materials.md index 0507fc36..958d2f73 100644 --- a/design/materials.md +++ b/design/materials.md @@ -53,6 +53,6 @@ Depth ladder: page, then card (`sm` or `glass`), then sheet (`lg`). Three levels ## Focus -On web, `:focus-visible` replaces the native outline with `--shadow-focus-ring`: two 2px bands, `--color-surface-base` inside and `--color-accent` outside, so one band always has a 3.41:1 edge against whatever it surrounds (`colors.md` rule 7). A focused element swaps its own shadow for the ring. A transparent `outline` stays underneath so forced-colors mode, which drops box shadows, still draws an indicator. +On web, `:focus-visible` replaces the native outline with `--shadow-focus-ring`: two 2px bands, `--color-surface-base` inside and `--color-accent` outside, so one band always has a 3.41:1 or better edge against whatever it surrounds (`colors.md` rule 7). A focused element swaps its own shadow for the ring. A transparent `outline` stays underneath so forced-colors mode, which drops box shadows, still draws an indicator. In the app the system draws focus (`swiftui.md` → Focus). Never remove a focus indicator without replacing it. diff --git a/design/swiftui.md b/design/swiftui.md index 7f273dad..ddedde06 100644 --- a/design/swiftui.md +++ b/design/swiftui.md @@ -11,6 +11,7 @@ One color set per semantic alias that has no exact system equivalent; a system s | Token | App | |---|---| | `--color-accent` | `AccentColor` set; `Color.accentFill` (also the global tint) | +| `--color-accent-solid` | `ColorAccentSolid` set; `Color.accentSolid` (the `prominent` button tint and any solid accent fill that carries a label) | | `--color-accent-pressed` | `ColorAccentPressed` set; `Color.accentPressed` | | `--color-accent-tint` | `ColorAccentTint` set; `Color.accentTint` | | `--color-accent-text`, `--color-text-link` | `ColorAccentText` set; `Color.accentText` | @@ -92,7 +93,7 @@ Haptics: `.sensoryFeedback(_:trigger:)`, iPhone only (`UIDevice.current.userInte | Design | SwiftUI | |---|---| -| Button `prominent` | `.buttonStyle(.borderedProminent)`, `.buttonBorderShape(.capsule)`, label `Color.onAccent` | +| Button `prominent` | `.buttonStyle(.borderedProminent)`, `.buttonBorderShape(.capsule)`, tint `Color.accentSolid`, label `Color.onAccent` | | Button `secondary` | `.buttonStyle(.bordered)`, tint `Color.accentFill`, label `Color.accentTextOnTint` | | Button `destructive` | `.buttonStyle(.borderedProminent)`, tint `Color.statusError`, label `Color.onStatus` | | Button `destructive-tinted` | `.buttonStyle(.bordered)`, tint `Color.statusError`, label `Color.textPrimary` | diff --git a/design/tokens.css b/design/tokens.css index 99d30556..02c0967a 100644 --- a/design/tokens.css +++ b/design/tokens.css @@ -57,7 +57,10 @@ /* Semantic aliases: consume these */ --color-accent: light-dark(var(--green-600), var(--green-400)); - --color-accent-pressed: light-dark(var(--green-700), var(--green-500)); + /* Accent as a filled-button background: white (--color-on-accent) must read + on it, so light takes a darker step than --color-accent. colors.md rule 3. */ + --color-accent-solid: light-dark(var(--green-700), var(--green-400)); + --color-accent-pressed: light-dark(var(--green-800), var(--green-500)); --color-accent-tint: var(--glass-tint-accent); --color-on-accent: light-dark(#FFFFFF, #05271A); --color-on-status: #FFFFFF; diff --git a/design/web.md b/design/web.md index 96f0bc3e..57b6f1e8 100644 --- a/design/web.md +++ b/design/web.md @@ -25,7 +25,17 @@ One narrow exception: an element that depicts the app (a hero screenshot) takes Every themed token is a `light-dark()` pair resolved by `color-scheme`. `:root` declares `light dark`, so an untouched page follows the OS; `[data-theme="light"]` and `[data-theme="dark"]` pin it. -The landing page sets `data-theme` from `localStorage` in an inline script before first paint, accepting only `light` or `dark`; the docs site gets the same from Docusaurus. The theme toggle also rewrites ``, whose two literals are `--bg-base` light and dark (`#FFFFFF`, `#000000`). +The landing page sets `data-theme` from `localStorage` in the external, synchronous `theme-init.js` in `` before first paint, accepting only `light` or `dark`; the docs site gets the same from Docusaurus. The theme toggle also rewrites ``, whose two literals are `--bg-base` light and dark (`#FFFFFF`, `#000000`). + +## Head, images and policy + +| Rule | Why | +|---|---| +| Every landing page carries the same `` (`default-src 'self'`, `connect-src 'self'`, `object-src 'none'`, `base-uri 'none'`, `form-action 'none'`, `'self'` for script, style and image). No inline script, inline style or `data:` image | No hashes to maintain; a page cannot call a third party. The docs site has none (`docs/knowledge/landing-page.md`, "Content-Security-Policy") | +| Screenshots are WebP, one file per theme. Every `` has `width` and `height`; the above-the-fold image takes `fetchpriority="high"`, the rest `loading="lazy"`. A themed hero image is a `` whose dark `` carries `media="(prefers-color-scheme: dark)"` | No layout shift; only the variant that matches the theme downloads | +| Every landing page links `site.webmanifest`, the 96px PNG, `favicon.ico` and the apple-touch icon, and sets description, Open Graph and Twitter tags with `og.jpg`; the indexable pages (home, privacy, support) add a canonical link, `404.html` and `r/` add `noindex` | The favicon set is the app icon (`brand.md` → Favicon recipe); the docs site reuses it | +| The landing keeps `llms.txt`, `robots.txt` and `sitemap.xml` at the root | Crawler and assistant entry points (`docs/knowledge/landing-page.md`, "Crawler files") | +| The docs site's tagline, `` and social image repeat the landing headline | One headline everywhere (`brand.md` → Positioning) | ## Type @@ -45,7 +55,7 @@ Lucide, inlined as one `<symbol>` sprite referenced with `<use>`, `aria-hidden=" ## Docs site (Docusaurus) -`web/docs/src/css/custom.css` maps Infima's variables onto tokens, so the theme renders in our colors: the primary ladder onto the accent aliases, grays onto fills and separators, admonitions onto the status tints (text stays primary), headings onto the web scale, and the code theme onto tokens. Nothing in it is a literal. The mascot is the navbar mark (`brand.md` → Mascot). +`web/docs/src/css/custom.css` maps Infima's variables onto tokens, so the theme renders in our colors: the primary ladder onto the accent aliases (a `.button--primary` takes `--color-accent-solid` so its label clears AA), links on a fill wash (table cells, inline code) onto `--color-accent-text-on-tint`, grays onto fills and separators, admonitions onto the status tints (text stays primary), headings onto the web scale, and the code theme onto tokens. Nothing in it is a literal; `web/docs/src/prismTheme.ts` writes `var(--token)` strings, weight included. The mascot is the navbar mark (`brand.md` → Mascot). ## Writing direction @@ -56,9 +66,9 @@ Logical properties everywhere: `padding-inline`, `margin-block`, `inset-inline-s | Literal | Why | |---|---| | breakpoint widths in a media condition | `var()` does not resolve there (`spacing-layout.md` → Breakpoints) | -| the two `theme-color` meta values | browser chrome cannot take a custom property | +| the two `theme-color` meta values, and `theme_color` / `background_color` in `site.webmanifest` | browser chrome cannot take a custom property; the manifest values must equal `--bg-base` in light, which `scripts/verify-design.sh` checks | | `0` (any unit), `100%`, `100svh`, `1px` inside a visually-hidden utility, `90deg` rotation of a chevron | geometry, not design values | | `50%` inside a visually-hidden utility (`clip-path: inset(50%)`) | geometry of the clip; any other `50%` (centering, `translate`) is a token or a logical-property layout | | `12%`, `22%`, `82%` and `black` inside `color-mix()` | the Button state specs in `components.md` → Button (and the 22% status border); outside `color-mix()` every other percentage and every named color (`white`, `red`, …) is a finding | -Everything else, including component metrics, is a token (`--btn-*-web`, `--pill-*-web`, …). `scripts/verify-design.sh` enforces this. +Everything else, including component metrics, is a token (`--btn-*-web`, `--pill-*-web`, …). `scripts/verify-design.sh` enforces this over the CSS, the landing HTML and `app.js`, and `prismTheme.ts` (JS and TS files also take no numeric font weight). diff --git a/docs/BUILDING.md b/docs/BUILDING.md index d9a44858..5d4d9940 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -14,6 +14,8 @@ The exact toolchain and the steps from a fresh clone to a running app, plus how | golangci-lint | `2.x`; CI pins `v2.15.0` | `.github/workflows/reusable-go.yml`; rules in `crocmobile/.golangci.yml` (`version: "2"` schema) | `brew install golangci-lint` | | govulncheck | the `golang.org/x/vuln` version in the `tool` block of `crocmobile/go.mod` | `.github/workflows/reusable-go.yml` | `cd crocmobile && go tool govulncheck ./...` | | create-dmg | unpinned | `.github/workflows/release.yml` installs it with `brew` | `brew install create-dmg`; only `scripts/build-dmg.sh` needs it | +| Node, pnpm | Node `26.12.0`, pnpm `12.14.0`; only the docs site (`web/docs/`) needs them | `web/docs/.nvmrc`, `packageManager` in `web/docs/package.json` | `brew install fnm pnpm`, then `fnm use` in `web/docs/`; `pnpm --dir web/docs install` (`knowledge/docs-site.md`) | +| cwebp | unpinned; only `scripts/capture-screenshots.sh --copy-web` needs it, to write the web WebP files | none | `brew install webp` | | croc CLI | `v11.5.4`, the version the embedded engine uses | `crocmobile/go.mod` (`github.com/schollz/croc/v11`) | `brew install croc` (lands at `$HOMEBREW_PREFIX/bin/croc`, the harnesses' default). `croc --version` must match the pin; if the bottle lags, use `go install github.com/schollz/croc/v11@<pin>` and point `CROC` at it; only `scripts/verify-*.sh` and `crockit-verify` need it | ## First build @@ -112,6 +114,13 @@ scripts/verify-design.sh # token mirrors, contrast, no literals (design/AGENTS scripts/verify-docs.sh # links, repo paths and stale markers in the markdown (docs/AGENTS.md) ``` +The website (landing page and docs site) builds into one artifact. Broken links and anchors fail it, and CI runs the same script in the `site build` job: + +```bash +pnpm --dir web/docs install +scripts/assemble-site.sh _site # landing at /, docs at /docs/ +``` + CI runs the Go checks with `GOOS=darwin GOARCH=arm64` set for the whole job, so `go build` and `go vet` analyze the platform the code ships on while running on a cheap Linux runner. Only `go test` unsets them. See "Troubleshooting" for the `go install` trap this causes. ## Tests diff --git a/docs/RELEASING.md b/docs/RELEASING.md index 2ebf5204..b1293569 100644 --- a/docs/RELEASING.md +++ b/docs/RELEASING.md @@ -199,13 +199,14 @@ These steps are done by a person, not by a script. Follow them on a new machine, 1. **Bump the version.** In `app/Config/Version.xcconfig`, set `MARKETING_VERSION` for a new version, and raise `CURRENT_PROJECT_VERSION` for every upload or tag. Do this in its own pull request or commit. A tag run fails when the build number is not above every build in the published `appcast.xml`. App Store Connect refuses a build number it has already seen for that version. 2. **Write the CHANGELOG heading.** Rename `## [Unreleased]` and date it as `## [X.Y.Z] - YYYY-MM-DD` (Keep a Changelog). `release.yml` requires exactly that heading for the tagged version, requires the section to be non-empty, and publishes the section as the release notes and the Sparkle notes. `X.Y.Z` must be a plain dotted version. -3. **Rehearse.** With the change on `main`, start the workflow from GitHub Actions with `workflow_dispatch`. Approve the `release` environment deployment as the required reviewer (in the run's page, or with `gh api -X POST repos/<owner>/<repo>/actions/runs/<id>/pending_deployments -F 'environment_ids[]=<env id>' -f state=approved -f comment=...`). The rehearsal builds, signs, notarizes and writes the appcast, and publishes nothing. -4. **Tag.** Tag the squashed commit on `main` as `vX.Y.Z` and push the tag. The tag must equal `MARKETING_VERSION`. Approve the `release` environment again. -5. **Verify the published DMG.** Download it from the release and run `xcrun stapler validate <dmg>` and `spctl -a -vv -t open --context context:primary-signature <dmg>`. Expect "Notarized Developer ID". Compare it against `SHA256SUMS.txt`, and run `gh attestation verify <file> --repo bakirgdev/CrocApp`. -6. **Check Sparkle.** Confirm the new item in `appcast.xml` carries `sparkle:edSignature`, and that an older installed build offers the update. -7. **Upload App Store builds** when the release includes the App Store: run `scripts/build-appstore.sh --upload`, then follow "Checking the result of an upload". It prints `APPSTORE-UPLOAD-OK ios` and `APPSTORE-UPLOAD-OK macos`. -8. **Run the device checklist** in `docs/knowledge/device-test-checklist.md` on a physical iPhone whenever a change calls for it. -9. **Before Submit for Review** (the first App Store release, 1.1.0), finish the open owner items: +3. **Update the website.** In `web/landing/index.html`, bump `softwareVersion` in the JSON-LD block and update the "available now" and "coming soon" copy and the store cards. In `web/landing/llms.txt`, update the current release and its status. In `web/landing/sitemap.xml`, bump `lastmod` for each page you changed. `datePublished` stays the first public release (`knowledge/landing-page.md`, "Hand-maintained"). +4. **Rehearse.** With the change on `main`, start the workflow from GitHub Actions with `workflow_dispatch`. Approve the `release` environment deployment as the required reviewer (in the run's page, or with `gh api -X POST repos/<owner>/<repo>/actions/runs/<id>/pending_deployments -F 'environment_ids[]=<env id>' -f state=approved -f comment=...`). The rehearsal builds, signs, notarizes and writes the appcast, and publishes nothing. +5. **Tag.** Tag the squashed commit on `main` as `vX.Y.Z` and push the tag. The tag must equal `MARKETING_VERSION`. Approve the `release` environment again. +6. **Verify the published DMG.** Download it from the release and run `xcrun stapler validate <dmg>` and `spctl -a -vv -t open --context context:primary-signature <dmg>`. Expect "Notarized Developer ID". Compare it against `SHA256SUMS.txt`, and run `gh attestation verify <file> --repo bakirgdev/CrocApp`. +7. **Check Sparkle.** Confirm the new item in `appcast.xml` carries `sparkle:edSignature`, and that an older installed build offers the update. +8. **Upload App Store builds** when the release includes the App Store: run `scripts/build-appstore.sh --upload`, then follow "Checking the result of an upload". It prints `APPSTORE-UPLOAD-OK ios` and `APPSTORE-UPLOAD-OK macos`. +9. **Run the device checklist** in `docs/knowledge/device-test-checklist.md` on a physical iPhone whenever a change calls for it. +10. **Before Submit for Review** (the first App Store release, 1.1.0), finish the open owner items: - The App Store Connect listing: pricing, availability without France, privacy answers, age rating, export compliance answers and screenshots. The field text is in `docs/knowledge/app-store-listing.md`. - An Accessibility Inspector and VoiceOver audit. - Apple's answer on the multicast entitlement request. If it is granted, Apple adds "Multicast Networking" as a capability on `com.bakirgdev.CrocApp`, and the `com.apple.developer.networking.multicast` entitlement can be added to the iOS target. If it is not granted by submission, ship without it, hide the iOS multicast setting, and file a `future` issue. diff --git a/docs/THREAT-MODEL.md b/docs/THREAT-MODEL.md index 7778800d..223c793c 100644 --- a/docs/THREAT-MODEL.md +++ b/docs/THREAT-MODEL.md @@ -131,14 +131,14 @@ Local Network Only (`OnlyLocal`) keeps the connection on the local network. With ### Build, update and release -- **Signing:** the DMG app is signed with a Developer ID certificate, hardened runtime and timestamp; the app and the DMG are notarized and stapled (`.github/workflows/release.yml`, `web/docs/content/verify-downloads.md`). App Store builds go through Apple's signing and review. +- **Signing:** the DMG app is signed with a Developer ID certificate, hardened runtime and timestamp; the app and the DMG are notarized and stapled (`.github/workflows/release.yml`, `web/docs/content/getting-started/verify-downloads.md`). App Store builds go through Apple's signing and review. - **Updates (Direct build only):** Sparkle 2 over HTTPS (`SPARKLE_FEED_URL` build setting in `app/CrocApp.xcodeproj/project.pbxproj`, read by `SUFeedURL`). The app carries the EdDSA public key (`SUPublicEDKey`) and installs an update only if the signature matches. `release.yml` fails the run if the appcast entry lacks `sparkle:edSignature` (around line 228). `SUEnableSystemProfiling` is `false` (`app/Config/CrocApp-Direct-Info.plist`). App Store builds contain no updater. -- **Provenance:** a GitHub build provenance attestation covers the DMG, the engine archive and `appcast.xml`, made after stapling (`actions/attest-build-provenance` in `release.yml`). Verification commands are in `web/docs/content/verify-downloads.md`. +- **Provenance:** a GitHub build provenance attestation covers the DMG, the engine archive and `appcast.xml`, made after stapling (`actions/attest-build-provenance` in `release.yml`). Verification commands are in `web/docs/content/getting-started/verify-downloads.md`. - **Pipeline hygiene:** third-party actions are pinned to commit SHAs; checkouts set `persist-credentials: false`; the release job runs in the `release` environment, which needs maintainer approval and allows only `main` and `v*` tags; the signing material is removed from the runner at the end of the job. Dependabot covers GitHub Actions, Go modules and Swift packages (`.github/dependabot.yml`). ## Privacy -CrocApp has no account system and no analytics or advertising code. History is a local SwiftData store (`TransferRecord`, `app/CrocApp/Models/TransferHistory.swift`) holding up to 20 file names per record, counts, sizes, a code hint and status, never the full code phrase or file contents (`web/docs/content/guide/history.md`). The servers the app can contact are listed in the [privacy policy](https://crocapp.dev/privacy/). The link page at `crocapp.dev/r/` makes no network request and sets a `no-referrer` policy. +CrocApp has no account system and no analytics or advertising code. History is a local SwiftData store (`TransferRecord`, `app/CrocApp/Models/TransferHistory.swift`) holding up to 20 file names per record, counts, sizes, a code hint and status, never the full code phrase or file contents (`web/docs/content/guide/history.md`). The servers the app can contact are listed in the [privacy policy](https://crocapp.dev/privacy/). The link page at `crocapp.dev/r/` makes no network request and sets a `no-referrer` policy. Every landing page (`web/landing/`) ships a `<meta http-equiv>` Content-Security-Policy with `default-src 'self'` and `connect-src 'self'`, so a page cannot call a third party even if script were injected (`knowledge/landing-page.md`, "Content-Security-Policy"). The pages load only their own files and keep only the theme choice in local storage. ## Design principles applied @@ -185,7 +185,7 @@ The path traversal, injection, overflow and time-of-check rows cover glob `*` in | croc prints the code phrase, and a non-default relay password, to stderr on every send | Accepted. Nothing in the app captures stderr; a Finder, Dock or Home Screen launch connects it to `/dev/null` (strong inference, not measured on a device). A harness or Xcode debug session does capture it. `known-issues.md`. | | `release.yml` passes the signing `.p12` and keychain passwords on `security` argv | Accepted for a single-tenant runner. Do not run on a shared runner. | | `create-dmg` is installed unpinned during the release build | Accepted. `known-issues.md`. | -| One maintainer approves releases, so there is no second reviewer on the `release` environment | Accepted. Disclosed in `web/docs/content/verify-downloads.md`. | +| One maintainer approves releases, so there is no second reviewer on the `release` environment | Accepted. Disclosed in `SECURITY.md`, and `RELEASING.md` describes the approval gate. | | Compromise of the Sparkle EdDSA private key or the `release` secrets | Would allow signed malicious updates or releases. Mitigation is limited to approval gating and attestation, which a compromised pipeline could also satisfy. | | `manifest.batch` in the share extension's manifest is joined to the App Group path without a name check (`ShareInbox.refresh`) | Only a process with the same App Group can write it, so the writer is already inside the same-developer trust domain. Not countered by code; noted, not exploited. | | A sender can offer a very large total size; CrocApp adds no disk quota | The accept sheet shows the file list; the user decides. | @@ -205,4 +205,4 @@ Follow `AGENTS.md`. Update this file in the same pull request when any of these - the release workflow: signing, notarization, attestation, Sparkle keys or feed; - a new weakness class gets a fix: add a row to Common weaknesses countered with its test. -Docs rules are in [`AGENTS.md`](AGENTS.md). Related: [`SECURITY.md`](../SECURITY.md), [`ARCHITECTURE.md`](ARCHITECTURE.md), [`known-issues.md`](known-issues.md), `web/docs/content/security-and-privacy.md`, `web/docs/content/verify-downloads.md`. +Docs rules are in [`AGENTS.md`](AGENTS.md). Related: [`SECURITY.md`](../SECURITY.md), [`ARCHITECTURE.md`](ARCHITECTURE.md), [`known-issues.md`](known-issues.md), `web/docs/content/security-and-privacy.md`, `web/docs/content/getting-started/verify-downloads.md`. diff --git a/docs/knowledge/app-ui-architecture.md b/docs/knowledge/app-ui-architecture.md index 90fe41e9..e25fa4ec 100644 --- a/docs/knowledge/app-ui-architecture.md +++ b/docs/knowledge/app-ui-architecture.md @@ -162,7 +162,7 @@ Neither surface owns transfer state. Both drive the one `TransferController`, so The shared views route onto `design/`. A screen picks one of these instead of styling ad hoc. -- `Views/ButtonVariants.swift`: `.buttonVariant(_:)` with `prominent`, `secondary`, `destructive`, `destructiveTinted`, `plain` (`design/components.md`, "Button"; `design/swiftui.md`, "Components"). It is a `PrimitiveButtonStyle`, so the label color sits on the label itself. Disabled buttons get only the system dimming, never an extra opacity on the label. +- `Views/ButtonVariants.swift`: `.buttonVariant(_:)` with `prominent`, `secondary`, `destructive`, `destructiveTinted`, `plain` (`design/components.md`, "Button"; `design/swiftui.md`, "Components"). It is a `PrimitiveButtonStyle`, so the label color sits on the label itself. `prominent` fills with `Color.accentSolid`, not `Color.accent`, so the white label clears 4.5:1 in light mode (`design/colors.md`, rule 3). The pending-count badge on Home uses it too. Disabled buttons get only the system dimming, never an extra opacity on the label. - Filled `.destructive` is for Decline on the accept gate and the Clear History confirmation only. Cancel (waiting, transferring, confirm-send, menu bar) and Discard (`StagedFilesSheet`) are `.destructiveTinted`. - `DropZone`, `CodePhraseDisplay` (eyebrow, code, **Copy Code**; `compact` for the 300-wide menu bar column), `DirectionHeader` (arrow plus Sending or Receiving). - `ForwardProgressBar` never moves backwards, and `resetKey` snaps it when the measured thing changes (`design/motion.md`, "Choreography"). diff --git a/docs/knowledge/docs-site.md b/docs/knowledge/docs-site.md index bc68f197..a7bc1289 100644 --- a/docs/knowledge/docs-site.md +++ b/docs/knowledge/docs-site.md @@ -4,7 +4,10 @@ Operational knowledge for `web/docs/` (Docusaurus 3.10.2, pnpm 12, TypeScript 7) ## Local development +Node 26 (`web/docs/.nvmrc`) and pnpm 12 are required (`tooling.md`). + ```bash +pnpm --dir web/docs install pnpm --dir web/docs start ``` @@ -12,6 +15,8 @@ pnpm --dir web/docs start The same `tokens` script copies `web/landing/assets/img/mascot-web.webp` to `static/img/mascot.webp` (gitignored), the navbar logo. It is the one web derivative of the mascot (`design/brand.md` → Mascot); never commit a second copy. +The docs site keeps no icon or social-card file of its own. `docusaurus.config.ts` points the favicon, the apple-touch icon, the web manifest and the social image (`og.jpg`) at the landing copies under `web/landing/assets/img/` through absolute `https://crocapp.dev/assets/img/...` URLs (a site-relative URL would get the `/docs/` base prefixed). Replace those files on the landing side only. The mascot is the exception: it stays a local copy so `docusaurus start` does not depend on the live site. + To build the full Pages artifact (both surfaces, what CI publishes) locally: ```bash @@ -22,25 +27,27 @@ scripts/assemble-site.sh # writes ./_site/, landing at /, docs at /docs - Page copy is bound by `design/content.md` (terminology, capitalization, the approved security claims) and `design/brand.md`. Headings and sidebar titles are sentence case; app controls are quoted in bold, Title Case, exactly as the app spells them. - Theme styling lives in `web/docs/src/css/custom.css`, mapped onto `design/tokens.css` with no literals (`design/web.md` → Docs site). The code theme is `src/prismTheme.ts`, the same token mapping. The navbar collapses at Docusaurus's own 996px breakpoint, not ours, so do not set `display` on a `.navbar__item` outside a `min-width: 997px` media query. -- Screenshots come from `scripts/capture-screenshots.sh --copy-web` and go in as a light and dark pair on one line, each with a `#gh-light-mode-only` or `#gh-dark-mode-only` fragment (`custom.css` shows the one that matches the theme toggle). Docusaurus rewrites the paths to hashed ones, so the phone-width cap in `custom.css` keys off the alt text: an iPhone shot's alt must say "on iOS". +- Screenshots come from `scripts/capture-screenshots.sh --copy-web` into `web/docs/screenshots/{mac,iphone}/` as WebP (not under `static/`, so Docusaurus hashes them). A page references them by relative path as a light and dark pair on one line, each with a `#gh-light-mode-only` or `#gh-dark-mode-only` fragment: `![Send screen on macOS](../../screenshots/mac/send-files-light.webp#gh-light-mode-only)`. `custom.css` shows the one that matches the theme toggle. Every image carries `width` and `height`, so the page does not shift while it loads. The alt text must not contain an apostrophe. The phone-width cap in `custom.css` keys off the alt text, so an iPhone shot's alt must say "on iOS". ## Adding a page -New file under `web/docs/content/` (not `docs/`, that name is taken by the repository's own contributor docs). Frontmatter needs `title`, `description`, and `sidebar_position`. The sidebar is autogenerated from the directory tree, so nothing is ever added to `sidebars.ts`: order comes from `sidebar_position`, and a new directory needs a `_category_.json`. `routeBasePath: '/'`, so `content/guide/foo.md` serves at `/docs/guide/foo/`. +New file under `web/docs/content/` (not `docs/`, that name is taken by the repository's own contributor docs). Frontmatter needs `title`, `description`, and `sidebar_position`. The sidebar is hand-written in `web/docs/sidebars.ts`, grouped by task rather than by directory, so a new page is added there by doc id (its path under `content/` without `.md`). A page missing from `sidebars.ts` has no sidebar. The groups have no landing page of their own, so no thin `/category/` pages exist. `routeBasePath: '/'`, so `content/guide/foo.md` serves at `/docs/guide/foo/`. + +The docs site is English only: `docusaurus.config.ts` configures the single locale `en`. It has 18 pages (the `content/` files, the home page included). -The docs site is English only: `docusaurus.config.ts` configures the single locale `en`. +Moving or deleting a page also needs a redirect, or the old URL, which search engines and the GitHub issue forms still hold, answers 404. The `redirects` array of the `@docusaurus/plugin-client-redirects` entry in `docusaurus.config.ts` maps each old path to its new one (the plugin writes a small HTML stub at the old path). Add the entry in the same change. -## Cutting a version +## Versions -No second version exists. `current` is labelled `1.0` in `docusaurus.config.ts` (`versions.current.label`) and no `versioned_docs/` exists. When a later release changes behavior that the old version's readers still need described, run `pnpm --dir web/docs run docusaurus docs:version 1.0` first, then relabel `current` for the new release. `web/docs/package.json` carries the release version (`1.0.0`). Until a second version exists, the navbar's `docsVersionDropdown` renders nothing. Docusaurus hides it below two versions, so this is not a misconfiguration. +The site has one version and `docusaurus.config.ts` configures none, so there is no version dropdown and no `versioned_docs/`. `web/docs/package.json` carries the release version (`1.0.0`). When a later release changes behavior that an older version's readers still need described, run `pnpm --dir web/docs run docusaurus docs:version 1.0` and add the dropdown to the navbar then. Release notes are not a docs page: the navbar and footer link to GitHub Releases. ## Broken links fail the build -`onBrokenLinks`, `onBrokenAnchors`, `markdown.hooks.onBrokenMarkdownLinks`, and `markdown.hooks.onBrokenMarkdownImages` are all `throw`. A bad internal link or anchor fails `pnpm run build`, which fails `scripts/assemble-site.sh`, which fails `github-pages.yml`. `github-pages.yml` runs the same assembly on `pull_request` (build only, no deploy), so a broken link is caught before merge. +`onBrokenLinks`, `onBrokenAnchors`, `markdown.hooks.onBrokenMarkdownLinks`, and `markdown.hooks.onBrokenMarkdownImages` are all `throw`. A bad internal link or anchor fails `pnpm run build`, which fails `scripts/assemble-site.sh`, which fails the `site build` job and `github-pages.yml`. The `site build` job in `ci.yml` runs the same assembly (and `tsc`) on every pull request that touches the site files, so a broken link is caught before merge. ## One workflow publishes both surfaces -`github-pages.yml` calls `scripts/assemble-site.sh` and uploads the whole `_site/`. Editing only `web/docs/**` still rebuilds the Docusaurus site and re-copies `web/landing/` verbatim, and editing only `web/landing/**` does the reverse. GitHub Pages replaces the entire artifact on every deploy, so a single workflow always ships both. The workflow triggers on `web/landing/**`, `web/docs/**`, `design/tokens.css`, `scripts/assemble-site.sh` and its own file. +`github-pages.yml` runs on a push to `main` only: it deploys. The pre-merge build is the `site build` job in `ci.yml`. It calls `scripts/assemble-site.sh` and uploads the whole `_site/`. Editing only `web/docs/**` still rebuilds the Docusaurus site and re-copies `web/landing/` verbatim, and editing only `web/landing/**` does the reverse. GitHub Pages replaces the entire artifact on every deploy, so a single workflow always ships both. The workflow triggers on `web/landing/**`, `web/docs/**`, `design/tokens.css`, `scripts/assemble-site.sh` and its own file. ## What `assemble-site.sh` asserts @@ -49,4 +56,4 @@ The script fails the build unless the landing files and the receive-link page ar ## Traps - **Frontmatter values containing a colon must be quoted.** `description: Fixes for X: stalled transfers` breaks the build with "bad indentation of a mapping entry". Quote the whole value: `description: "Fixes for X: stalled transfers"`. Several pages under `content/` already need this, check before adding a colon to any frontmatter field. -- **`showLastUpdateTime` renders nothing for a file that is not yet committed.** It reads git history per file (`fetch-depth: 0` in `github-pages.yml` makes this work in CI); a new page with only uncommitted local edits shows no "last updated" line until it lands in a commit. This is not a bug, only confusing while drafting. +- **`showLastUpdateTime` renders nothing for a file that is not yet committed.** It reads git history per file (`fetch-depth: 0` in `github-pages.yml` and the `site build` job makes this work in CI); a new page with only uncommitted local edits shows no "last updated" line until it lands in a commit. This is not a bug, only confusing while drafting. diff --git a/docs/knowledge/landing-page.md b/docs/knowledge/landing-page.md index 0a405df0..1e702b73 100644 --- a/docs/knowledge/landing-page.md +++ b/docs/knowledge/landing-page.md @@ -6,18 +6,19 @@ Operational knowledge for `web/landing/`, the plain HTML site at `https://crocap | Path | Purpose | |---|---| -| `index.html`, `styles.css`, `app.js` | The landing page. `app.js` only enhances (theme toggle, FAQ, nav); the page reads with JavaScript off | -| `r/index.html` | The receive-link page behind `https://crocapp.dev/r/#<code>`. It offers to open the app, get the app or receive in a browser | +| `index.html`, `styles.css`, `app.js` | The landing page. `app.js` only enhances (the theme toggle, and keeping the hero `<picture>` sources in step with a pinned theme); the page reads with JavaScript off. The FAQ is native `<details>` | +| `theme-init.js` | Loaded synchronously in the `<head>` of every page: sets `data-theme` from `localStorage` before first paint. External so the CSP needs no hash | +| `r/index.html`, `r/receive.js` | The receive-link page behind `https://crocapp.dev/r/#<code>`. It offers to open the app, get the app or receive in a browser. `receive.js` parses the fragment and fills the links | | `privacy/`, `support/` | Static pages | | `.well-known/apple-app-site-association` | Universal links for `/r/*`, for both app IDs (`com.bakirgdev.CrocApp` and `.direct`, each with the team prefix) | | `.well-known/security.txt` | The address `SECURITY.md` hands out | | `llms.txt`, `robots.txt`, `sitemap.xml` | Crawler and assistant files. `robots.txt` lists this sitemap and the docs one | | `CNAME`, `404.html` | Custom domain and not-found page | -| `web/landing/assets/img/` | Store badges, favicons and the web manifest | +| `web/landing/assets/img/` | `mascot-web.webp`, the store badges (SVG), `og.jpg` (the social card, also used by the docs site), `favicon/` (the app-icon based favicon set and `site.webmanifest`, also used by the docs site) and `screenshots/{mac,iphone}/` (the hero shots, WebP, a light and dark file each) | ## How it ships -`scripts/assemble-site.sh` copies `web/landing/` to the site root, copies `design/tokens.css` beside it (the only copy that ships; `index.html` links `tokens.css`, which is never committed under `web/landing/`) and puts the built Docusaurus site under `/docs`. `.github/workflows/github-pages.yml` runs it on a pull request (build only) and on a push to `main` (build and deploy). One deploy always ships both surfaces: `docs-site.md`, "One workflow publishes both surfaces". +`scripts/assemble-site.sh` copies `web/landing/` to the site root, copies `design/tokens.css` beside it (the only copy that ships; `index.html` links `tokens.css`, which is never committed under `web/landing/`) and puts the built Docusaurus site under `/docs`. `.github/workflows/github-pages.yml` runs it on a push to `main` and deploys. The pre-merge build is the `site build` job in `ci.yml`. One deploy always ships both surfaces: `docs-site.md`, "One workflow publishes both surfaces". The script fails the build unless these hold: @@ -26,6 +27,22 @@ The script fails the build unless these hold: - `.well-known/apple-app-site-association` exists and lists both app IDs. - `r/index.html` sets `<meta name="referrer" content="no-referrer">` and loads no remote `script`, `link`, `img` or `iframe`. The code lives in the URL fragment, so the page must not leak it. Its one network hop is a link the user clicks, to getcroc.com. +## Content-Security-Policy + +Every landing page (`index.html`, `privacy/`, `support/`, `r/`, `404.html`) carries the same `<meta http-equiv="Content-Security-Policy">`: `default-src 'self'` plus `script-src`, `style-src`, `img-src` and `connect-src` of `'self'`, and `object-src`, `base-uri` and `form-action` at `'none'`. `connect-src` is `'self'` rather than `'none'` only so Lighthouse's robots.txt audit can fetch the file; the pages make no requests of their own. GitHub Pages cannot send headers, so a meta tag is all there is (`frame-ancestors` is ignored there). The docs site has no CSP. + +The policy forbids inline script and style, `data:` images and any remote host, and nothing on the pages needs them (JSON-LD is data, not script). To add a resource, load it from a file in the same origin. If a page truly needs another origin, widen the one directive for it in every page that loads it, and record why in `THREAT-MODEL.md`, "Privacy". A violation shows only in the browser console, so load each changed page once with the console open: `scripts/assemble-site.sh` does not check the policy. + +## Images + +Screenshots are WebP, one file per theme, and the hero uses `<picture>` with a `<source media="(prefers-color-scheme: dark)" data-theme-source>` so only the variant that matches the OS downloads. A manual theme pin cannot reach a `<source>` before parse, so `app.js` rewrites that `media` to `all` or `not all` on load and on toggle. Trade-off: a pin that disagrees with the OS fetches the OS variant first, then the pinned one (`known-issues.md`, "Landing page"). Every image has `width` and `height`; the Mac hero image has `fetchpriority="high"` and the rest are `loading="lazy"`. `scripts/capture-screenshots.sh --copy-web` writes the WebP files and needs `cwebp` (`brew install webp`). + +## Crawler files + +- `llms.txt` is hand-written to the llmstxt.org shape: an H1, a blockquote, then H2 sections of `- [Title](url): note` lines. It links every docs page, so a docs page added, renamed or removed is edited here too. +- `sitemap.xml` lists the landing, support and privacy pages with a `lastmod`. Update the date when a page's content changes. The docs sitemap is generated. +- `robots.txt` lists both sitemaps. + ## Rules - Visual and copy rules are `design/web.md` and `design/content.md`. Colors, spacing and type come from the tokens, with no literals in the page or its stylesheet (`scripts/verify-design.sh` checks). @@ -35,7 +52,7 @@ The script fails the build unless these hold: Nothing checks these. They are listed in `docs/known-issues.md`, "Landing page": -- `llms.txt` release status and the store cards (version, channels, "coming soon" wording) change on every release. +- Per release: `softwareVersion` in the JSON-LD block of `index.html`, the release status in `llms.txt`, and the "available now" and "coming soon" copy and store cards in `index.html` (`RELEASING.md`, "Each release"). `datePublished` stays the first public release. - The store badges stay unlinked until the apps are on the App Store. - `security.txt` has an `Expires` field to renew. - The AASA `/r/*` component is wider than the one page that exists. diff --git a/docs/knowledge/screenshots.md b/docs/knowledge/screenshots.md index d11f790b..a2598934 100644 --- a/docs/knowledge/screenshots.md +++ b/docs/knowledge/screenshots.md @@ -26,7 +26,12 @@ scripts/capture-screenshots.sh --copy-web # refresh the web copies, no disp - It creates simulators named "CrocApp Shots <device>" (iPhone and iPad for the main set, then iPhone 17 Pro and iPhone Duo one at a time for the store-only classes, each deleted as soon as its pass ends), starts a croc relay and, for `stored-link`, a store server, and removes all of them on exit. - Needs Go (the store server comes from `crocmobile/cmd/croctest`) and a v11 `croc` (default `/opt/homebrew/bin/croc`, override with `CROC`; crocmobile embeds v11.5.4). -After a run, refresh the web copies with `--copy-web`. It overwrites only the files already present under `web/docs/static/img/screenshots/` and `web/landing/assets/img/screenshots/` (same `mac/`, `iphone/`, `ipad/` subfolders); to publish a new shot, copy its file there once. +After a run, refresh the web copies with `--copy-web`. The pages use WebP, not PNG, so it rebuilds with `cwebp` (`brew install webp`; the script fails if it is missing) every `.webp` already present under `web/docs/screenshots/` and `web/landing/assets/img/screenshots/`: + +- Each file's source is `assets/screenshots/` plus the same relative path with `.png`. A `.webp` with no matching source fails the run. +- Each file keeps its current pixel size (read with `sips`), so the landing hero stays 840x1050 (Mac) and 660x1434 (iPhone), matching the `width` and `height` attributes in `index.html`. A source whose aspect ratio no longer matches the file fails the run: resize the file once by hand with the same `cwebp` flags and the new size, update the page's attributes, then re-run. +- Flags are `-q 85 -m 6`, with `-resize W H` only when the size differs from the source. +- To publish a new shot, run `cwebp` on its source into the web folder once, at the size the page needs; later runs keep it fresh. ## The screens @@ -116,7 +121,7 @@ The one fixed wait left is `settle` (one second): a view needs a frame or two to - The relay runs with `--debug` because its "room has first peer" line is the signal that a sender is registered; the receiver must join after that, or the PAKE handshake is corrupted. - This leans on croc v11's log wording, so the script refuses another major version. -**Codes are random.** `new_code` builds `NNNN-word-word-word` from `/dev/urandom` with three distinct words. The relay derives the room from the first four characters of this legacy shape (`what-is-croc.md`, "Rendezvous"), so the four digits are unique within a run. +**Codes are random.** `new_code` builds the app's current shape, `word-word-word`, from `/dev/urandom` with three distinct words. The relay derives the room from the first word of a three-word code (`what-is-croc.md`, "Rendezvous"), so the first word is unique within a run. **Mid-transfer shots.** Localhost moves 150 MB in under a second, so nothing is photographable unthrottled. The sender is throttled (`--throttle 6m` on the app, `--throttleUpload 6m` on the CLI), and at 40% the script sends `SIGSTOP` to the peer. Both ends then stand still, so the bar and the rate stay as they are. `sending` has the app as sender and a CLI receiver; `receiving` is the mirror. @@ -150,15 +155,19 @@ The script is host-independent this way. For any future screenshot work: - **Real files, generated at run time, never committed.** `scripts/screenshots/payload.swift` renders a three-page PDF (`Quarterly-Report.pdf`) and a JPEG (`Ridge-Sunrise.jpg`); the Markdown note is a heredoc; `Design-Assets.zip` comes from `ditto`. File rows show a symbol by file type, so real extensions matter more than real content. Large transfer payloads (`Project-Archive.zip`, `Field-Recordings.zip`, 150 MB) are random bytes under a believable name, because only the name is ever shown. -- **Neutral, pleasant names.** No personal names, no real people or companies, no real hosts beyond the project's own (`crocapp.dev` for the stored-link record). Names read like work files. +- **Neutral, pleasant names.** No personal names, no real people or companies, no real hosts beyond the project's own (`getcroc.com`, the default link server, for the stored-link record). Names read like work files. - **History is a showcase list** (`seedHistory` in `AutoVerify.swift`): sends and receives, completed, declined, failed and cancelled, a text snippet, a stored link with its expiry, file counts of one to four, ages from twelve minutes to five weeks. Names match the payload names where a payload exists, and sizes match the real payloads, so the incoming preview and the history agree. - **The code on screen is random per run** and never a real one. -- **What is on screen must be true of a default setup.** The relay is local, but the trust UI is pinned to the default relay (`--shown-relay default`) so the browser-receive note and the pill read as a normal install. The `stored-link` shot uploads to a local store server but passes `--shown-link-origin https://crocapp.dev`, so the link and its QR code read `https://crocapp.dev/s/...#v1...`. +- **What is on screen must be true of a default setup.** The relay is local, but the trust UI is pinned to the default relay (`--shown-relay default`) so the browser-receive note and the pill read as a normal install. The `stored-link` shot uploads to a local store server but passes `--shown-link-origin https://getcroc.com` with the app's default one-day lifetime, so the link and its QR code read `https://getcroc.com/s/...#v1...`, as a default install produces (`StoredSendOptions().server`). - **Same states on every device**, so a screen name means one thing everywhere. Add a screen by adding its name to `SCREENS`, a case to `capture_screen`, and, for macOS, its window title to `mac_titles`. - **Keep shots free of transient UI**: no "Starting...", no spinners that mean "slow", no permission alerts, no focus carets. Wait on a harness signal, not a delay. ## Known soft spots +- **Mac Settings (General) is scrolled to its end.** The form is taller than the window and the window cannot be stretched, so `mac_settings` scrolls it (`window scroll`) and the shot shows Transfer through About, with the top sliding under the toolbar. The earlier sections (Receive, Menu bar, Relay, Send as link, Connection) are not in this shot. +- **Mac light shots have no window edge.** Window captures are made without the system shadow (`screencapture -o`), in both themes. A light window on a white page looks unframed; a page that needs an edge adds it in CSS. +- **`iphone/onboarding` is a real sheet.** On iOS the onboarding is a `.sheet`, so the light shot shows the dimmed home screen above and around it. Dark shows the same over black. + - **`ipad/` is the phone layout stretched.** See `../known-issues.md`, "Design system". - **No `iphone-duo-inner`, and `iphone-duo-outer` is not upload-ready.** See "iPhone Duo" above. The outer shots lay out sideways and clip the bottom of taller screens (`02-send-code-dark` loses "Waiting for the receiver…"). Recapture before an upload that needs them, once a runtime or Simulator.app can drive the Duo properly. - **No menu-bar shot.** The menu-bar popover cannot be captured reliably: macOS hides the status item when the menu bar is full, so no script can click it. @@ -166,22 +175,24 @@ For any future screenshot work: ## Where they are used -Seven pairs are referenced; the rest and the whole `app-store/` set are captured and unused by the web (`../known-issues.md`, "Docs site"). +Ten pairs are referenced by the web or the README; the rest and the whole `app-store/` set are captured and unused by the web (`../known-issues.md`, "Docs site"). - Root `README.md`: `mac/send-code`, `iphone/receive-incoming`, `mac/settings`, via `<picture>` elements that swap on the viewer's GitHub theme. -- Docs site: copies under `web/docs/static/img/screenshots/`, one pair per page: +- Docs site: WebP copies under `web/docs/screenshots/` (outside `static/`, so Docusaurus ships only the hashed copy), referenced by relative path, one pair per page: | Pair | Page | |---|---| + | `iphone/onboarding` | index | | `mac/send-code` | first-transfer | | `mac/send-files` | sending | | `iphone/receive-incoming` | receiving | - | `mac/settings` | settings-and-trust | - | `iphone/settings` | power-options | + | `mac/receive-conflict` | receiving | + | `mac/stored-link` | send-as-link | + | `mac/settings` | settings | + | `mac/settings-advanced` | settings | | `mac/history` | history | - | `iphone/onboarding` | index | `.md` there is CommonMark (`docusaurus.config.ts` sets `markdown.format: 'detect'`), so `<ThemedImage>` is unavailable. The pages use GitHub's `#gh-light-mode-only` and `#gh-dark-mode-only` fragments, and `src/css/custom.css` supplies the rule that makes them mean anything. That rule follows Docusaurus's theme toggle, not the OS setting. -- Landing hero: `web/landing/assets/img/screenshots/mac/send-code-*`, two `<img>` elements swapped by CSS. Not a `<picture>` with `prefers-color-scheme`, because the header's toggle pins `[data-theme]` and a media query would ignore it. +- Landing hero: WebP copies of `mac/send-code-*` and `iphone/send-code-*` under `web/landing/assets/img/screenshots/`, two `<img>` elements per device swapped by CSS. Not a `<picture>` with `prefers-color-scheme`, because the header's toggle pins `[data-theme]` and a media query would ignore it. A copy is a copy: changing a shot means re-running the script and `scripts/capture-screenshots.sh --copy-web`. diff --git a/docs/knowledge/tooling.md b/docs/knowledge/tooling.md index e2940682..6392bcd0 100644 --- a/docs/knowledge/tooling.md +++ b/docs/knowledge/tooling.md @@ -15,17 +15,18 @@ What is wired up, what was deliberately skipped, and the traps in each. | xcbeautify | none | CI only (`ci.yml`; `release.yml` does not use it) | | create-dmg 1.3.0 (Homebrew; CI installs it unpinned with `brew install create-dmg`) | none; called by `scripts/build-dmg.sh` | local + `release.yml` | | croc v10 CLI (the v10 peer of `verify-interop.sh` scenario 10) | `scripts/croc-v10.version` (read by the script and the `interop` job) | local + CI | -| Node 24 | `web/docs/.nvmrc` (pinned exact), `engines` in `web/docs/package.json` | docs site, local + CI | -| pnpm 12 | `packageManager` in `web/docs/package.json` (CI: `pnpm/action-setup` reads it) | docs site, local + CI | -| Docusaurus 3.10, React 19.3, TypeScript 7 | `web/docs/package.json`, `pnpm-lock.yaml`; `pnpm-workspace.yaml` holds `overrides` for transitive advisories | docs site, local + CI (`pnpm run typecheck` in `github-pages.yml`) | +| Node 26.12.0 | `web/docs/.nvmrc` (pinned exact), `engines` in `web/docs/package.json` | docs site, local + CI | +| pnpm 12.14.0 | `packageManager` in `web/docs/package.json` (CI: `pnpm/action-setup` reads it) | docs site, local + CI | +| Docusaurus 3.10, React 19.3, TypeScript 7 | `web/docs/package.json`, `pnpm-lock.yaml`; `pnpm-workspace.yaml` holds `overrides` for transitive advisories | docs site, local + CI (`pnpm run typecheck` in the `site build` job and `github-pages.yml`). `@docusaurus/plugin-client-redirects` writes the old-URL redirects (`docs-site.md`) | | Sparkle 2.10.0 (SwiftPM, `CrocApp Direct` only; auto-update for the direct-download build) | `Package.resolved` under `app/CrocApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/`, minimum in the `XCRemoteSwiftPackageReference` in `project.pbxproj`; Dependabot (`swift`, `/app`) reads the Xcode project's `Package.resolved` and opens the bump | `CrocApp Direct` build, local + CI (unsigned build step) | | MCP servers `xcode` (`xcrun mcpbridge`) and `gopls` (`gopls mcp`) for AI sessions | `.mcp.json` (Claude Code asks each user to approve them); `gopls` starts in `crocmobile/` because the Go module lives there, not at the repo root | local AI sessions. Use `xcode` to build, run tests, render previews and read diagnostics; it needs the project open in Xcode with MCP enabled, and never replaces the harnesses (`BUILDING.md`, "Verification harnesses"). Use `gopls` for symbol search and references in `crocmobile/` | -| `scripts/verify-design.sh` (pure bash and awk, no toolchain) | none; holds the token parity, contrast (the ratios `design/colors.md` claims, which must also appear in its Contrast section) and no-literals tables | local + CI (`contrast` job, shown as `design checks`) | +| `scripts/verify-design.sh` (pure bash and awk, no toolchain) | none; also lints the landing and docs CSS, `app.js`, `theme-init.js`, `prismTheme.ts` and `site.webmanifest` (the `design` filter in `ci.yml` covers those paths). Holds the token parity, contrast (the ratios `design/colors.md` claims, which must also appear in its Contrast section) and no-literals tables | local + CI (`contrast` job, shown as `design checks`) | +| `cwebp` (Homebrew `webp`) | none; called by `scripts/capture-screenshots.sh --copy-web` to write the web WebP files | local only | | `scripts/verify-docs.sh` (pure bash and awk) | none; the rules it enforces are in `docs/AGENTS.md` | local + CI (`docs checks`, on every push and pull request, because renaming any file can break a path a doc names) | | ShellCheck 0.11 (Homebrew locally; preinstalled on `ubuntu-26.04`) | none (`shellcheck -x scripts/*.sh`, default checks) | local + CI (`shellcheck` job) | | GitHub Actions | `.github/workflows/ci.yml` | push to main, every PR; a `changes` job skips the jobs whose area is untouched (see "CI gotchas"); `interop (local relay)` runs `scripts/verify-interop.sh` on `macos-26` against a local `croc relay` | | GitHub Actions | `.github/workflows/go-weekly.yml` | Mondays 06:17 UTC + manual | -| GitHub Actions | `.github/workflows/github-pages.yml` | Triggers on changes to `web/landing/**`, `web/docs/**`, `design/tokens.css`, `scripts/assemble-site.sh` and the workflow file. PRs build only; a push to main also deploys | +| GitHub Actions | `.github/workflows/github-pages.yml` | Push to `main` only, on changes to `web/landing/**`, `web/docs/**`, `design/tokens.css`, `scripts/assemble-site.sh` and the workflow file: builds `_site` and deploys. The pre-merge build is the `site build` job in `ci.yml` | | GitHub Actions | `.github/workflows/release.yml` | `v*` tag publishes; `workflow_dispatch` is a rehearsal that publishes nothing | - Xcode baseline lives in `.xcode-version` (plain text, one line). @@ -41,7 +42,7 @@ The build settings that must not change casually (Swift 6 mode, deployment targe - **`ci.yml` has no workflow-level `paths:`.** A filtered-out workflow never reports, so a required check would stay pending. Jobs skip through `if:` instead (see the next bullet). - **The `changes` job decides which jobs run.** - - It diffs the PR base (or the push's `before`) against the head with `git diff --name-only` and sets one output per area: `swift`, `go`, `build`, `design`, `interop` and `scripts`. Each job gates on its output with `if:`. + - It diffs the PR base (or the push's `before`) against the head with `git diff --name-only` and sets one output per area: `swift`, `go`, `build`, `design`, `interop`, `scripts` and `site`. Each job gates on its output with `if:`. - The regexes in the `changes` job of `ci.yml` are the source of truth for what each area covers; the rule for new files is in `.github/AGENTS.md`. - An unknown base (a new branch, a force push) runs everything. - **Branch protection requires only `ci pass`** (`.github/AGENTS.md`). The reason: a skipped matrix job reports under its unexpanded name and stays pending, while `ci pass` treats `success` and `skipped` as passing. diff --git a/docs/known-issues.md b/docs/known-issues.md index 6cb83ce3..244a95fc 100644 --- a/docs/known-issues.md +++ b/docs/known-issues.md @@ -72,20 +72,21 @@ These items gate Submit for Review of the first App Store release (`knowledge/pr - **The two store badges are not links.** - The hero **Download** button scrolls to three channels. The direct-download card links to the latest GitHub release. - - The App Store and Mac App Store cards say "at launch" and show unlinked badges, because those apps are not released. + - The App Store and Mac App Store cards say "Coming soon" and show unlinked badges, because those apps are not released. - They become links when the apps ship, with real alt text (the markup carries a comment saying so). - **The hero mockup uses `--content-max-width`.** - `design/web.md` allows this for an element that depicts the app. - The exception is narrow and easy to over-apply. -- **`llms.txt` release status is hand-maintained and nothing checks it.** - - It has to be edited on every release. +- **The release status in `llms.txt` and `index.html` is hand-maintained and nothing checks it.** + - `llms.txt`, the JSON-LD `softwareVersion` and the "available now" copy have to be edited on every release (`RELEASING.md`, "Each release"). - The JSON-LD carries only `datePublished`, which stays true. A `dateModified` would go stale on every commit, and templating it from `git log` would put a moving part inside a structured-data block, where a broken template corrupts silently. - `og.jpg` is a second hand-made asset, but it does not change. -- **The landing and docs pages set no Content-Security-Policy.** - - GitHub Pages cannot send headers, so only a `<meta http-equiv>` CSP is possible. It would need a hash for each inline script (the theme script on every page, the code parser in `r/index.html`, Docusaurus's own inline scripts), regenerated on every edit. - - A wrong hash breaks the page silently in the browser, and `scripts/assemble-site.sh` does not check it. - - No injection sink exists today: `r/index.html` and `app.js` write with `textContent`, links are built with `encodeURIComponent`, and nothing loads third-party script. - - Clickjacking of the `/r/` buttons stays open either way, because `frame-ancestors` is ignored in a meta tag. +- **The landing CSP is a meta tag, so it cannot stop framing, and the docs site has none.** + - GitHub Pages cannot send headers. `frame-ancestors` is ignored in a meta tag, so clickjacking of the `/r/` buttons stays open. + - The docs pages carry no policy, because Docusaurus injects inline scripts that would need a hash for each. + - `scripts/assemble-site.sh` does not check the landing policy; a violation shows only in the browser console (`knowledge/landing-page.md`, "Content-Security-Policy"). +- **A manual theme pin that disagrees with the OS downloads both hero image variants.** The `<picture>` source follows the OS until `app.js` runs, so the OS variant loads first and the pinned one after it. Accepted: only a visitor who overrode the OS theme pays it. +- **GitHub Pages serves `.well-known/apple-app-site-association` as `application/octet-stream`.** It has no extension and Pages cannot set a header. Apple fetches it that way today. Not verified on a device after each deploy; re-test universal links if Apple tightens the check. - **`/r/` accepts any fragment of six or more characters without whitespace as a code.** - So `/r/#download` offers to open "download" in CrocApp. - It is display only: the text is escaped and the app validates the code. @@ -99,12 +100,11 @@ These items gate Submit for Review of the first App Store release (`knowledge/pr - **No site search, on purpose.** - A local search plugin is a new dependency. Algolia DocSearch is an external account plus a third-party request from a page that makes a privacy claim. - - Twenty-one pages with a full sidebar and browser find-in-page are enough at this size. Revisit if the page count grows. -- **The version dropdown is invisible.** Docusaurus hides `docsVersionDropdown` while only one version exists. It stays hidden until the first `docusaurus docs:version` cut. + - Eighteen pages with a full sidebar and browser find-in-page are enough at this size. Revisit if the page count grows. +- **The docs 404 page keeps Docusaurus's default meta description.** The theme's NotFound page sets only a title. Changing it needs a swizzle, which is not worth the upkeep. - **A landing-only change rebuilds the docs site too, and the reverse.** `github-pages.yml` calls `scripts/assemble-site.sh`, which builds both surfaces regardless of which one changed. -- **Thirty-seven of the 44 screenshot pairs are unused.** - - `scripts/capture-screenshots.sh` writes 44 light/dark pairs under `assets/screenshots/{mac,iphone,ipad}/`. - - Seven are referenced, by the README, seven docs pages and the landing hero: `mac/send-code`, `mac/send-files`, `mac/settings`, `mac/history`, `iphone/receive-incoming`, `iphone/settings`, `iphone/onboarding`. +- **Most screenshot pairs are unused.** + - `scripts/capture-screenshots.sh` writes light/dark pairs under `assets/screenshots/{mac,iphone,ipad}/`. The README, the docs pages and the landing hero reference ten of them: `mac/send-code`, `mac/send-files`, `mac/settings`, `mac/settings-advanced`, `mac/history`, `mac/receive-conflict`, `mac/stored-link`, `iphone/send-code`, `iphone/receive-incoming`, `iphone/onboarding`. The web copies are WebP, under `web/docs/screenshots/` and `web/landing/assets/img/screenshots/`. - The `app-store/` set is for App Store Connect only. - The rest are headroom on purpose: adding a usage is cheap, and re-capturing a deleted one is not. - **The two sitemaps stay separate.** diff --git a/scripts/capture-screenshots.sh b/scripts/capture-screenshots.sh index b60ac33f..feb709fb 100755 --- a/scripts/capture-screenshots.sh +++ b/scripts/capture-screenshots.sh @@ -33,7 +33,7 @@ # DEVICE mac, iphone, ipad, iphone63 or duo: only those devices # SCREEN only those screens, both appearances, plus the store file # --list print the manifest and exit -# --copy-web refresh the web copies from assets/screenshots/ and exit +# --copy-web rebuild the web WebP copies from assets/screenshots/ and exit (needs cwebp) # Environment: CROC (default: the Homebrew croc, v11 like crocmobile), # PHONE_TYPE, PHONE63_TYPE, PAD_TYPE and DUO_TYPE (simulator device type ids), # DUO_OUTER_DISPLAY (simctl display id of the Duo's outer screen), RUNTIME (simulator @@ -125,15 +125,33 @@ case "${1:-}" in exit 0 ;; --copy-web) - # Refreshes the files a web surface already uses, keeping their device - # subfolder; a new shot goes in by adding its file to the folder first. - for dir in web/docs/static/img/screenshots web/landing/assets/img/screenshots; do + # Rebuilds the WebP files a web surface already uses from their PNG sources + # (same relative path under assets/screenshots/), at each file's current + # pixel size. A new shot goes in by running cwebp on it once, into the web + # folder, at the size its page needs. + command -v cwebp > /dev/null || fail "cwebp is missing (brew install webp)" + for dir in web/docs/screenshots web/landing/assets/img/screenshots; do n=0 while IFS= read -r f; do - cp "$OUT/${f#"$dir"/}" "$f" + rel=${f#"$dir"/} + src="$OUT/${rel%.webp}.png" + [ -f "$src" ] || fail "$f has no source $src" + w=$(sips -g pixelWidth "$f" | awk '/pixelWidth/ {print $2}') + h=$(sips -g pixelHeight "$f" | awk '/pixelHeight/ {print $2}') + sw=$(sips -g pixelWidth "$src" | awk '/pixelWidth/ {print $2}') + sh=$(sips -g pixelHeight "$src" | awk '/pixelHeight/ {print $2}') + # Cross-multiplied, so a one-pixel rounding difference still passes. + d=$((w * sh - h * sw)) + [ "${d#-}" -le $((sw + sh)) ] \ + || fail "$f is ${w}x${h} but $src is ${sw}x${sh}: the aspect ratio changed, resize the page's image by hand (see docs/knowledge/screenshots.md)" + if [ "$w" = "$sw" ] && [ "$h" = "$sh" ]; then + cwebp -quiet -q 85 -m 6 "$src" -o "$f" 2> /dev/null || fail "cwebp failed on $src" + else + cwebp -quiet -q 85 -m 6 -resize "$w" "$h" "$src" -o "$f" 2> /dev/null || fail "cwebp failed on $src" + fi n=$((n + 1)) - done < <(find "$dir" -name '*.png') - echo "refreshed $n files in $dir" + done < <(find "$dir" -name '*.webp' | sort) + echo "rebuilt $n files in $dir" done exit 0 ;; @@ -256,26 +274,33 @@ rand_int() { od -An -N4 -tu4 /dev/urandom | tr -d ' '; } rand_hex() { od -An -N12 -tx1 /dev/urandom | tr -d ' \n'; } WORDS=(amber willow signal copper lantern summit quiet meadow anchor violet harbor drift - golden cedar morrow silver thicket crimson pillar indigo marsh russet canyon) - -# Sets the variable named by $1 to a fresh code, NNNN-word-word-word. The relay -# hashes a code's first 4 characters into a room name, so those must not repeat -# within a run; a fresh relay per run covers the runs before this one. + golden cedar morrow silver thicket crimson pillar indigo marsh russet canyon bridge falcon + garden hollow island jasper kernel lagoon mosaic nectar orchard pebble quartz ribbon sparrow + timber umber velvet walnut yonder zephyr acorn basil clover dune ember fjord glacier heron + ivory juniper kettle lilac maple nutmeg olive prairie quill river saffron tundra uplands + vista wren xenon yarrow zenith) + +# Sets the variable named by $1 to a fresh code, word-word-word, the shape the +# app generates. The relay hashes a three-word code's first word into a room +# name, so that word must not repeat among recent codes (CODE_PREFIXES, cleared +# once most of WORDS is used); a fresh relay per run covers the runs before this one. new_code() { # new_code VAR - local prefix words="" i w + local first words="" i w + [ "$(wc -w <<< "$CODE_PREFIXES")" -lt $((${#WORDS[@]} - 8)) ] || CODE_PREFIXES="" while :; do - prefix=$((1000 + $(rand_int) % 9000)) - in_list "$CODE_PREFIXES" "$prefix" || break + first=${WORDS[$(($(rand_int) % ${#WORDS[@]}))]} + in_list "$CODE_PREFIXES" "$first" || break done - CODE_PREFIXES="$CODE_PREFIXES$prefix " - for i in 1 2 3; do + CODE_PREFIXES="$CODE_PREFIXES$first " + words=$first + for i in 1 2; do while :; do w=${WORDS[$(($(rand_int) % ${#WORDS[@]}))]} - case "$words-" in *"-$w-"*) ;; *) break ;; esac + case "-$words-" in *"-$w-"*) ;; *) break ;; esac done words="$words-$w" done - printf -v "$1" '%s' "$prefix$words" + printf -v "$1" '%s' "$words" } port_up() { nc -z 127.0.0.1 "$1" > /dev/null 2>&1; } @@ -604,6 +629,10 @@ mac_settings() { # mac_settings TAB done osascript -e "tell application \"System Events\" to tell (first process whose unix id is $APP_PID) to click button \"$1\" of toolbar 1 of window 1" >/dev/null poll 5 mac_window_shown "$(mac_titles)" || die "the Settings window never showed the $1 tab" + # The General form is taller than the window and cannot be stretched, so + # scroll it to its end: the bottom then closes on a whole caption, and the + # top slides under the toolbar like any scrolled form. + [ "$1" != General ] || "$TMP/bin/window" scroll CrocApp settle snap quit_app @@ -681,7 +710,7 @@ capture_screen() { stored-link) start_store_server launch --auto-store-send "$DOCS/shots/Quarterly-Report.pdf" --store-server "$STORE_URL" \ - --shown-link-origin https://crocapp.dev --store-downloads 3 --screen send + --shown-link-origin https://getcroc.com --store-downloads 3 --screen send await_docs_file verify-store-link.txt 60 settle snap @@ -690,7 +719,7 @@ capture_screen() { } # A local croc store server, as in verify-app-mac.sh, so "Send as link" never -# uploads to a real server. The link on screen is rewritten to crocapp.dev. +# uploads to a real server. The link on screen is rewritten to the default link server, getcroc.com. start_store_server() { [ -z "$STORE_URL" ] || return 0 ( cd crocmobile && go build -o "$TMP/bin/croctest" ./cmd/croctest ) diff --git a/scripts/screenshots/window.swift b/scripts/screenshots/window.swift index 67caa7b7..da111b30 100644 --- a/scripts/screenshots/window.swift +++ b/scripts/screenshots/window.swift @@ -1,6 +1,8 @@ // Window and permission queries the shell has no tool for. // window list OWNER one line per on-screen window of the app named OWNER: // id, layer, title, width, height (tab separated) +// window scroll OWNER scrolls the content of OWNER's front window to its end +// (moves the pointer over it, then posts wheel events) // window preflight exit 1 and name what is missing unless Screen Recording // and Accessibility are granted to the calling terminal // @@ -32,6 +34,27 @@ case "list" where args.count > 2: let height = (bounds?["Height"] as? NSNumber)?.intValue ?? 0 print("\(number)\t\(layer)\t\(name)\t\(width)\t\(height)") } +case "scroll" where args.count > 2: + guard + let list = CGWindowListCopyWindowInfo( + [.optionOnScreenOnly, .excludeDesktopElements], kCGNullWindowID) as? [[String: Any]], + let window = list.first(where: { + $0[kCGWindowOwnerName as String] as? String == args[2] + && $0[kCGWindowLayer as String] as? Int == 0 + }), + let bounds = window[kCGWindowBounds as String] as? [String: Any], + let x = (bounds["X"] as? NSNumber)?.doubleValue, + let y = (bounds["Y"] as? NSNumber)?.doubleValue, + let w = (bounds["Width"] as? NSNumber)?.doubleValue, + let h = (bounds["Height"] as? NSNumber)?.doubleValue + else { fail("no window of \(args[2]) to scroll") } + CGWarpMouseCursorPosition(CGPoint(x: x + w / 2, y: y + h / 2)) + for _ in 0..<10 { + CGEvent( + scrollWheelEvent2Source: nil, units: .pixel, wheelCount: 1, wheel1: -400, wheel2: 0, + wheel3: 0)?.post(tap: .cghidEventTap) + usleep(50_000) + } case "preflight": var missing: [String] = [] if !CGPreflightScreenCaptureAccess() { missing.append("Screen Recording") } @@ -40,5 +63,5 @@ case "preflight": fail("missing: \(missing.joined(separator: ", "))") } default: - fail("usage: window list OWNER | window preflight") + fail("usage: window list OWNER | window scroll OWNER | window preflight") } diff --git a/scripts/verify-design.sh b/scripts/verify-design.sh index 951c0d68..317c3d70 100755 --- a/scripts/verify-design.sh +++ b/scripts/verify-design.sh @@ -10,7 +10,7 @@ # tokens.css (WCAG 2.x relative luminance, alpha composited onto the # surface underneath), and the seven rules under the table hold as # invariants. Edit a green step and this names the rule you just broke. -# 3. No literals. Web CSS and the app write tokens, not hex, px, ms, raw +# 3. No literals. Web CSS and scripts and the app write tokens, not hex, px, ms, raw # system colors or spring presets (design/web.md -> The only literals web # may write, design/swiftui.md -> Allowed literals). # @@ -36,9 +36,11 @@ TOKENS=design/tokens.css SWIFT_TOKENS=app/CrocApp/Support/DesignTokens.swift COLORSETS=app/CrocApp/Assets.xcassets COLORS_MD=design/colors.md +MANIFEST=web/landing/assets/img/favicon/site.webmanifest [ -r "$TOKENS" ] || { echo "FAIL: $TOKENS not readable" >&2; exit 2; } [ -r "$SWIFT_TOKENS" ] || { echo "FAIL: $SWIFT_TOKENS not readable" >&2; exit 2; } [ -r "$COLORS_MD" ] || { echo "FAIL: $COLORS_MD not readable" >&2; exit 2; } +[ -r "$MANIFEST" ] || { echo "FAIL: $MANIFEST not readable" >&2; exit 2; } [ -d "$COLORSETS" ] || { echo "FAIL: $COLORSETS not a directory" >&2; exit 2; } # --------------------------------------------------------------------------- @@ -96,6 +98,7 @@ NUMERIC_TABLE=' # --------------------------------------------------------------------------- COLOR_TABLE=' AccentColor|--color-accent +ColorAccentSolid|--color-accent-solid ColorAccentPressed|--color-accent-pressed ColorAccentTint|--color-accent-tint ColorAccentText|--color-accent-text @@ -160,6 +163,8 @@ light|--color-accent-text|--color-surface-base|4.94 light|--color-accent-text|--color-surface-grouped|4.42 light|--color-accent-text|--color-accent-tint>--color-surface-base|4.32 light|--color-accent-text|--color-surface-card|4.94 +light|--color-accent-text|--color-fill-tertiary>--color-surface-base|4.28 +light|--color-accent-text-on-tint|--color-fill-tertiary>--color-surface-base|6.38 light|--color-accent-text-on-tint|--color-surface-base|7.36 light|--color-accent-text-on-tint|--color-surface-grouped|6.60 light|--color-accent-text-on-tint|--color-accent-tint>--color-surface-base|6.45 @@ -168,7 +173,8 @@ light|--label-2-web|--color-surface-base|5.16 light|--label-2-web|--color-surface-grouped|4.85 light|--color-text-secondary|--color-accent-tint>--color-surface-base|4.78 light|--label-3|--color-surface-base|1.73 -light|--color-on-accent|--color-accent|3.41 +light|--color-on-accent|--color-accent-solid|4.94 +light|--color-on-accent|--color-accent-pressed|7.36 light|--color-on-status|--color-status-error|3.55 light|--color-status-success|--color-status-success-tint>--color-surface-base|1.98 light|--color-status-warning|--color-status-warning-tint>--color-surface-base|1.96 @@ -181,7 +187,8 @@ light|--glass-tint-accent|--color-surface-base|1.14 dark|--color-accent|--color-surface-base|9.44 dark|--color-accent|--color-surface-card|7.65 dark|--color-accent|--color-accent-tint>--color-surface-base|7.72 -dark|--color-on-accent|--color-accent|7.19 +dark|--color-on-accent|--color-accent-solid|7.19 +dark|--color-on-accent|--color-accent-pressed|5.74 dark|--color-on-status|--color-status-error|3.41 dark|--label-2|--color-surface-base|6.36 dark|--color-status-success|--color-status-success-tint>--color-surface-base|8.05 @@ -194,11 +201,15 @@ accent-text clears AA on base|light|--color-accent-text|--color-surface-base|min accent-text-on-tint clears AA on grouped|light|--color-accent-text-on-tint|--color-surface-grouped|min|4.5 accent-text-on-tint clears AA on tint|light|--color-accent-text-on-tint|--color-accent-tint>--color-surface-base|min|4.5 web secondary clears AA on grouped|light|--label-2-web|--color-surface-grouped|min|4.5 -filled prominent clears 3:1|light|--color-on-accent|--color-accent|min|3.0 +filled prominent clears AA, light|light|--color-on-accent|--color-accent-solid|min|4.5 +filled prominent clears AA, dark|dark|--color-on-accent|--color-accent-solid|min|4.5 +filled prominent pressed clears AA, light|light|--color-on-accent|--color-accent-pressed|min|4.5 +filled prominent pressed clears AA, dark|dark|--color-on-accent|--color-accent-pressed|min|4.5 +accent-text-on-tint clears AA on a fill-tertiary wash (link in code or table)|light|--color-accent-text-on-tint|--color-fill-tertiary>--color-surface-base|min|4.5 filled destructive clears 3:1, light|light|--color-on-status|--color-status-error|min|3.0 filled destructive clears 3:1, dark|dark|--color-on-status|--color-status-error|min|3.0 focus ring outer band clears 3:1 on base|light|--color-accent|--color-surface-base|min|3.0 -focus ring inner band clears 3:1 on the accent fill|light|--color-surface-base|--color-accent|min|3.0 +focus ring inner band clears 3:1 on the accent solid fill|light|--color-surface-base|--color-accent-solid|min|3.0 tertiary is NOT a usable text color|light|--label-3|--color-surface-base|max|3.0 secondary text clears AA on the accent tint (rule 4)|light|--color-text-secondary|--color-accent-tint>--color-surface-base|min|4.5 accent-text clears AA on a card|light|--color-accent-text|--color-surface-card|min|4.5 @@ -213,6 +224,8 @@ rule 4: secondary text is label-2-web, dark|dark|--color-text-secondary|--label- rule 6: link is accent-text, light|light|--color-text-link|--color-accent-text rule 6: link is accent-text, dark|dark|--color-text-link|--color-accent-text dark accent collapses to green-400|dark|--color-accent|--green-400 +dark accent-solid collapses to green-400|dark|--color-accent-solid|--green-400 +light accent-solid is green-700, the step white clears AA on|light|--color-accent-solid|--green-700 dark accent-text collapses to green-400|dark|--color-accent-text|--green-400 dark accent-text-on-tint collapses to green-400|dark|--color-accent-text-on-tint|--green-400 ' @@ -237,7 +250,7 @@ SWIFT_FILES=$(find app -name '*.swift' ! -path "$SWIFT_TOKENS" ! -path 'app/Croc [ -n "$SWIFT_FILES" ] || { echo "FAIL: no Swift files under app/" >&2; exit 2; } WEB_FILES=$( - for f in web/landing/styles.css web/docs/src/css/custom.css; do + for f in web/landing/styles.css web/docs/src/css/custom.css web/landing/app.js web/landing/theme-init.js web/landing/r/receive.js web/docs/src/prismTheme.ts; do [ -r "$f" ] || { echo "FAIL: $f not readable" >&2; exit 2; } echo "$f" done @@ -651,6 +664,20 @@ function check_ring( ring, n, bands, k, parts, np, spread, color, want_spread, } } +# The web manifest paints the installed app before any CSS loads. It has one +# value per key, so both are --bg-base in light (web.md -> The only literals). +function check_manifest(path, text, key, k, rest, hex, want) { + text = read_file(path) + if (text ~ /^\001unreadable/) die(path " not readable") + want = resolve("--bg-base", "light", 0) + split("theme_color background_color", key, " ") + for (k = 1; k <= 2; k++) { + if (!match(text, "\"" key[k] "\"[ \t\n]*:[ \t\n]*\"#[0-9A-Fa-f]+\"")) { fail(path ": no " key[k] " hex color"); continue } + rest = substr(text, RSTART, RLENGTH); sub(/^.*"#/, "#", rest); hex = substr(rest, 1, length(rest) - 1) + if (parse_color(hex, "light", 0) != want) fail(path ": " key[k] " is " hex ", web.md needs --bg-base in light") + } +} + # The Contrast section of colors.md: from its heading to the next `## ` line. function contrast_section(path, lines, n, i, in_sec, out) { n = split(read_file(path), lines, "\n") @@ -733,6 +760,7 @@ BEGIN { } check_ring() + check_manifest(ENVIRON["MANIFEST"]) if (nfail) { for (i = 1; i <= nfail; i++) print failures[i] @@ -741,7 +769,7 @@ BEGIN { exit 1 } if (!quiet) - printf "contrast: OK (%d documented ratios, %d invariants, %d alias rules, 2 focus-ring bands)\n", ncase, ninvariant, nalias + printf "contrast: OK (%d documented ratios, %d invariants, %d alias rules, 2 focus-ring bands, manifest colors)\n", ncase, ninvariant, nalias } ' @@ -836,8 +864,8 @@ function lint_text(path, text, line0, use_ex, n, T, ln, t, rest, tok, prev, ne off += RSTART + RLENGTH - 1 rest = substr(rest, RSTART + RLENGTH) hexlen = length(tok) - 1 - if (before ~ /url\($/) continue - if (index(" \t:,(", prev) > 0 && nextc !~ /[A-Za-z0-9_-]/ && (hexlen == 3 || hexlen == 4 || hexlen == 6 || hexlen == 8)) + if (before ~ /url\([\047"]?$/) continue + if (index(" \t:,(\047\"", prev) > 0 && nextc !~ /[A-Za-z0-9_-]/ && (hexlen == 3 || hexlen == 4 || hexlen == 6 || hexlen == 8)) finding(path, line0 + ln - 1, "hex color literal " tok ": use a color token", t) } rest = t @@ -892,6 +920,22 @@ function lint_css(path, text, line0, s) { lint_text(path, blank_preludes(s), line0, 1) } +# JS and TS: comments gone (a // only at line start or after whitespace, so +# URLs in strings survive), then the same literal rules as CSS, plus a numeric +# font weight, which CSS-shaped rules cannot see. +function lint_script(path, text, s, n, T, ln, t) { + s = strip_css_comments(text) + n = split(s, T, "\n"); s = "" + for (ln = 1; ln <= n; ln++) { + t = T[ln] + if (match(t, /(^|[ \t])\/\/.*$/)) t = substr(t, 1, RSTART - 1) blank(substr(t, RSTART)) + s = s t (ln < n ? "\n" : "") + if (t ~ /[Ww]eight[\047"]?:[ \t]*[\047"]?[0-9]+/) + finding(path, ln, "font weight literal: use a --weight-* token", t) + } + lint_text(path, s, 1, 0) +} + # Every style="..." (q is the quote character) in an HTML file. function lint_style_attrs(path, text, re, q, rest, base, pre, m, qi, body, prevc) { rest = text; base = 0 @@ -940,7 +984,9 @@ BEGIN { if (f == "") continue text = read_file(f) if (text ~ /^\001unreadable/) die(f " not readable") - if (f ~ /\.html$/) lint_html(f, text); else lint_css(f, text, 1) + if (f ~ /\.html$/) lint_html(f, text) + else if (f ~ /\.(js|ts)$/) lint_script(f, text) + else lint_css(f, text, 1) nfile++ } if (nfind) { @@ -1104,7 +1150,7 @@ BEGIN { } ' -export TOKENS SWIFT_TOKENS COLORSETS COLORS_MD NUMERIC_TABLE COLOR_TABLE CONTRAST_TABLE NOT_MIRRORED \ +export TOKENS SWIFT_TOKENS COLORSETS COLORS_MD MANIFEST NUMERIC_TABLE COLOR_TABLE CONTRAST_TABLE NOT_MIRRORED \ ALLOW_WEB ALLOW_SWIFT SWIFT_FILES WEB_FILES export QUIET diff --git a/web/docs/.nvmrc b/web/docs/.nvmrc index df6ae337..2b42e392 100644 --- a/web/docs/.nvmrc +++ b/web/docs/.nvmrc @@ -1 +1 @@ -24.21.0 +26.12.0 diff --git a/web/docs/content/contribute.md b/web/docs/content/contribute.md index 8ee37ceb..d18cb393 100644 --- a/web/docs/content/contribute.md +++ b/web/docs/content/contribute.md @@ -1,20 +1,50 @@ --- -sidebar_position: 8 +sidebar_position: 5 title: Contribute -description: Where to find CrocApp's contributor and internals documentation on GitHub. +description: How to build and contribute to CrocApp, how it was made, and the projects that inspired it. --- # Contribute -Contributor and internals documentation lives in the repository, not on this site, because it has to track the code exactly as it changes. This site covers using the app; the repository covers building and changing it. +Contributor and internals documentation lives in the repository, not on this site, because it has to track the code as it changes. This site covers using the app. The repository covers building and changing it. -- [`CONTRIBUTING.md`](https://github.com/bakirgdev/CrocApp/blob/main/CONTRIBUTING.md): setup, branches, commits, style, verification, PR flow +Pull requests are welcome: bugs, features, docs, design and the landing page. Start with `CONTRIBUTING.md`. + +## Build from source + +```bash +git clone https://github.com/bakirgdev/CrocApp.git +cd CrocApp +scripts/build-xcframework.sh # Go engine -> CrocKit/Croc.xcframework +open app/CrocApp.xcodeproj +``` + +:::warning +A fresh clone builds nothing until the xcframework exists. The `CrocKit` binary target points at a file that is not committed, so `scripts/build-xcframework.sh` is required. [`docs/BUILDING.md`](https://github.com/bakirgdev/CrocApp/blob/main/docs/BUILDING.md) lists the exact toolchain versions. +::: + +## Where things are + +- [`CONTRIBUTING.md`](https://github.com/bakirgdev/CrocApp/blob/main/CONTRIBUTING.md): setup, branches, commits, style, verification, pull request flow - [`CODE_OF_CONDUCT.md`](https://github.com/bakirgdev/CrocApp/blob/main/CODE_OF_CONDUCT.md): Contributor Covenant 3.0 - [`SECURITY.md`](https://github.com/bakirgdev/CrocApp/blob/main/SECURITY.md): scope and private reporting for vulnerabilities - [`docs/README.md`](https://github.com/bakirgdev/CrocApp/blob/main/docs/README.md): index of every contributor and internals doc - [`docs/ARCHITECTURE.md`](https://github.com/bakirgdev/CrocApp/blob/main/docs/ARCHITECTURE.md): system map, layers, event flow -- [`docs/BUILDING.md`](https://github.com/bakirgdev/CrocApp/blob/main/docs/BUILDING.md): exact toolchain, fresh-clone steps, verification harnesses -- [`docs/GLOSSARY.md`](https://github.com/bakirgdev/CrocApp/blob/main/docs/GLOSSARY.md): full contributor and internals vocabulary -- [Issue templates](https://github.com/bakirgdev/CrocApp/tree/main/.github/ISSUE_TEMPLATE): where to file bugs, features, and other reports +- [`docs/BUILDING.md`](https://github.com/bakirgdev/CrocApp/blob/main/docs/BUILDING.md): toolchain, fresh-clone steps, verification harnesses +- [`docs/GLOSSARY.md`](https://github.com/bakirgdev/CrocApp/blob/main/docs/GLOSSARY.md): the contributor and internals vocabulary +- [Issue templates](https://github.com/bakirgdev/CrocApp/tree/main/.github/ISSUE_TEMPLATE): where to file bugs, features and other reports + +## How it was made + +croc's Go library is compiled to an XCFramework with `gomobile` and driven from a Swift actor. It is not a subprocess, because iOS does not allow those. The interface is SwiftUI throughout, targeting iOS 26 and macOS 26. [`docs/ARCHITECTURE.md`](https://github.com/bakirgdev/CrocApp/blob/main/docs/ARCHITECTURE.md) has the full picture. + +## Inspirations + +CrocApp exists because of these. Some are the foundation, and some showed what good looks like on other platforms. -Pull requests are welcome: bugs, features, docs, design, landing page. Start with `CONTRIBUTING.md` above. +- [croc](https://github.com/schollz/croc): the engine and the protocol. Everything CrocApp does, croc does underneath. +- [magic-wormhole](https://github.com/magic-wormhole/magic-wormhole): the original code-phrase transfer, and croc's own inspiration. +- [LocalSend](https://github.com/localsend/localsend): proof that a cross-platform transfer app can be genuinely pleasant to use. +- [croc-app](https://github.com/Dking08/croc-app): the Android client, and the best mobile reference for what a croc GUI should feel like. +- [crock](https://github.com/KD-MM2/crock): a desktop croc GUI, and where the QR deeplink idea comes from. +- [crocgui](https://github.com/howeyc/crocgui): the long-running cross-platform croc GUI. diff --git a/web/docs/content/faq.md b/web/docs/content/faq.md index c6c5b33b..27089d68 100644 --- a/web/docs/content/faq.md +++ b/web/docs/content/faq.md @@ -1,63 +1,62 @@ --- -sidebar_position: 7 +sidebar_position: 2 title: FAQ -description: Frequently asked questions about CrocApp, cost, security, accounts, and platform support. +description: Short answers about CrocApp's cost, accounts, relays, browsers, platforms and the croc command line, plus a glossary. --- # FAQ -## Where do I get it, and how does it update? - -CrocApp is available as a notarized disk image for Mac, and is coming to the App Store and the Mac App Store. The store listings will be linked from [crocapp.dev](https://crocapp.dev) once they are live. App Store builds update through the App Store. The disk image updates itself: choose **Check for Updates…** in the CrocApp menu. See [Install](getting-started/install.md). - ## What does it cost? -Nothing. No purchase, no subscription, no advertising and no analytics. CrocApp is free, MIT-licensed, and stays that way. Monetization is limited to optional sponsorship. - -## What does CrocApp guarantee? - -Transfers are end-to-end encrypted, the code phrase authenticates both devices, and the relay only ever sees ciphertext. CrocApp has not had a formal third-party security audit. The code is open if you want to look. +Nothing. CrocApp is free and MIT-licensed, with no purchase, subscription, ads or analytics. Optional [sponsorship](https://github.com/sponsors/bakirgdev) is the only way to support it with money. ## Do I need an account? No. CrocApp has no accounts, analytics, ads or tracking. -## Does my file go through the relay? +## Where do I get it, and how does it update? -Usually, when the two devices cannot reach each other directly. The relay forwards the encrypted transfer and only ever sees ciphertext. You can point CrocApp at your own relay instead. +See [Requirements and install](getting-started/install.md). -## What if both devices are on the same Wi-Fi? +## Does my file go through a relay? -Then the two devices connect over the local network and the data stays on that network. CrocApp tries the local network and the relay at once and uses whichever connects first. +CrocApp tries the local network and the relay at once and uses whichever connects first. When the two devices connect over the local network, the data stays on that network. Otherwise the relay forwards the encrypted transfer and only ever sees ciphertext. You can point CrocApp at your own relay. See [Security and privacy](security-and-privacy.md) and [Settings](guide/settings.md#relay). ## Can large files go directly between devices? -Yes, with the default **Automatic** connection setting. A send of 128 MiB or more also tries a direct connection, set up through `tailcat.dev`, and whichever path connects first carries the transfer. It is end-to-end encrypted either way. Choose **Relay Only** under [power options](guide/power-options.md) to keep your sends on croc's relays and away from those servers. A receive follows the sender's choice. +Yes. With **Connection** set to **Automatic**, a send of 128 MiB or more also tries a direct connection. See [Settings](guide/settings.md#connection) for how it works and how to turn it off. -## Can the other device use a browser instead of the app? +## Can the other person use a browser instead of the app? -Yes. The QR code on the sender's screen and the **Share Link** button open a page at `crocapp.dev/r/` that offers CrocApp and **Receive in Your Browser**. The browser option is croc's own web app at getcroc.com, not CrocApp, and it only works when the sender uses the default relays. It also depends on getcroc.com to serve the code that decrypts the file; see [Security and privacy](security-and-privacy.md#receiving-in-a-browser). +Yes, through the QR code or **Share Link**, which open a page at `crocapp.dev/r/` with a **Receive in Your Browser** option. That option is croc's own web app at getcroc.com, which sees your code and serves the script that decrypts the file. See [Receiving in a browser](security-and-privacy.md#receiving-in-a-browser). ## How is this different from AirDrop? AirDrop needs two Apple devices close to each other. CrocApp works between any two devices running croc or CrocApp, on any network, including from a Mac to a Linux machine on the other side of the world. -## Does it work with the croc command line tool? - -Yes, in both directions. CrocApp embeds croc v11.5.4 as a library, so it speaks the same protocol. Run `croc send` on a laptop and receive in the app on a phone, or the reverse. The other device needs croc 11 or newer; croc 10 cannot complete a transfer with it. - -## Can I run my own relay? +## Does it work with the croc command line? -Yes. Point CrocApp at any croc relay, with a relay password and an IPv6 address if you want them. Running `croc relay` on a machine you control is enough. +Yes, in both directions. Send with `croc send` on a laptop and receive in the app, or the reverse. The other device needs croc 11 or newer. See [croc CLI interoperability](reference/croc-cli-interop.md). ## Why iOS 26 and macOS 26 only? -CrocApp is a greenfield app with no existing users. Supporting older releases would mean availability checks everywhere and giving up current SwiftUI APIs and the Liquid Glass design language. The minimum is `26.0`, and every later version works. The floor is pinned at `26.0` rather than at a later minor so nobody running 26.0 through 26.4 is locked out. - -## Is it free? Will it ever have a paid tier? - -Free, MIT-licensed, and it stays that way. Monetization is limited to optional [sponsorship](https://github.com/sponsors/bakirgdev). +CrocApp uses the current SwiftUI and the Liquid Glass design, which need the 26 releases. The minimum is `26.0`, so every later version works. ## Will there be a Windows, Linux or Android version? -No. CrocApp is Apple-platform only by design. Use the [croc CLI](https://github.com/schollz/croc) elsewhere: it works with this app. +No. CrocApp is for Apple platforms only. Use the [croc command line](https://github.com/schollz/croc) elsewhere: it works with this app. The [other croc apps](contribute.md#inspirations) include an Android client. + +## Glossary + +| Term | Means | +|---|---| +| Code phrase | The `word-word-word` text both devices use to find each other and to prove they hold the same secret. See [Code phrases and links](guide/code-phrases.md). | +| Relay | A server both devices connect to when they cannot connect directly. It only ever sees ciphertext. | +| Direct connection | A transfer between the two devices with no relay in between: over the local network, or for a large send under **Automatic**. | +| Local network | The Wi-Fi or Ethernet network both devices share. CrocApp finds devices there without the relay, though some networks block it. | +| Link | A `https://crocapp.dev/r/#<code>` address that carries a code phrase after the `#`. Opening one fills in **Receive** and never connects by itself. | +| Send as link | Sending encrypted files to a link server so the other device can receive later. See [Send as link](guide/send-as-link.md). | +| Link server | The server that holds the files of a Send as link transfer until the link ends. The default is `https://getcroc.com`. | +| Trust badge | The label that says a transfer is end-to-end encrypted and names the route you configured. See [Settings](guide/settings.md#the-trust-badge). | +| History | CrocApp's list of past transfers, kept only on your device. See [History](guide/history.md). | +| Connection | The setting that decides whether a large send may use a direct connection: **Automatic** or **Relay Only**. | diff --git a/web/docs/content/getting-started/_category_.json b/web/docs/content/getting-started/_category_.json deleted file mode 100644 index fef57771..00000000 --- a/web/docs/content/getting-started/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "Getting started", - "position": 2, - "link": { - "type": "generated-index", - "description": "Where to get CrocApp and a walkthrough of your first send and receive." - } -} diff --git a/web/docs/content/getting-started/first-transfer.md b/web/docs/content/getting-started/first-transfer.md index 25347d26..8e62bc36 100644 --- a/web/docs/content/getting-started/first-transfer.md +++ b/web/docs/content/getting-started/first-transfer.md @@ -1,39 +1,29 @@ --- sidebar_position: 2 title: Your first transfer -description: A walkthrough of one send and one receive in CrocApp, using the app's on-screen labels. +description: One send and one receive in CrocApp, using the app's on-screen labels. --- # Your first transfer -![CrocApp on macOS showing Ready to send with the code phrase, a Copy Code button, and a QR code](/img/screenshots/mac/send-code-light.png#gh-light-mode-only)![CrocApp on macOS showing Ready to send with the code phrase, a Copy Code button, and a QR code](/img/screenshots/mac/send-code-dark.png#gh-dark-mode-only) +![CrocApp on macOS showing Ready to send with the code phrase, a Copy Code button, and a QR code](../../screenshots/mac/send-code-light.webp#gh-light-mode-only)![CrocApp on macOS showing Ready to send with the code phrase, a Copy Code button, and a QR code](../../screenshots/mac/send-code-dark.webp#gh-dark-mode-only) -CrocApp's home screen has two buttons: **Send** and **Receive**. Everything else follows from a three-step flow: +The home screen has two buttons, **Send** and **Receive**. On the first launch, CrocApp shows a short welcome screen first. Tap **Get Started** to continue. CrocApp may then ask for camera access (to scan QR codes) and local network access (for faster nearby transfers). -1. The sender picks files, a folder, or a snippet of text. -2. CrocApp generates a code phrase. Speak it, message it, or show it as a QR code. -3. The other device enters the phrase, sees the file list and accepts. +## Send -The code phrase authenticates both devices (PAKE), and the transfer is end-to-end encrypted. The relay only ever sees ciphertext. On the same Wi-Fi or on different continents, CrocApp tries the local network and the relay at once and uses whichever connects first. +1. Tap or click **Send**. +2. Pick **Files** or **Text** under **What to Send**. For files, use **Add Files** or **Add Folder**. On a Mac you can also drop files anywhere on the window. +3. Tap **Send**. +4. Give the other person the code phrase on screen. They can type it, scan the QR code, or open the link from **Share Link**. +5. When the other device accepts, the transfer runs. **Transfer complete** appears when it ends. -## Sending +## Receive -1. From the home screen, tap or click **Send**. -2. Under **What to Send**, pick **Files** or **Text**. - - For files: use **Add Files** or **Add Folder**, or drag files onto the drop area (macOS). - - For text: type or paste into the text box. -3. Optionally set a **Custom Code** (at least 6 characters) instead of a generated one. -4. Tap **Send**. -5. CrocApp shows **Ready to send** with the code phrase, a **Copy Code** button, a QR code, and a **Share Link** button. Share the code or the link with the other device over a channel you trust. -6. Once the other device connects and accepts, the transfer starts. When it finishes, CrocApp shows **Transfer complete**. +1. Tap or click **Receive**. +2. Enter the code phrase, paste it (a link works too), or on iOS tap **Scan QR Code**. +3. Check the destination folder under the code field. Change it with **Change…** if needed. +4. Tap **Receive**, then review the file list and tap **Accept** or **Decline**. +5. When it ends, open the folder with **Open in Files** (iOS) or **Show in Finder** (Mac). -## Receiving - -1. From the home screen, tap or click **Receive**. -2. Enter the **Code Phrase** the sender gave you, paste it (a link works too), or (on iOS) tap **Scan QR Code**. -3. Check the destination folder shown below the code field; change it with **Change** if needed. -4. Tap **Receive**. -5. CrocApp shows the file list and total size. Review it, then tap **Accept** or **Decline**. -6. When the transfer finishes, CrocApp shows **Transfer complete** with a button to open the destination folder (**Open in Files** on iOS, **Show in Finder** on macOS). - -For the full detail on each step, see [Sending files](../guide/sending.md) and [Receiving files](../guide/receiving.md). +For more on each step, see [Send](../guide/sending.md) and [Receive](../guide/receiving.md). To see why the code phrase is safe to share and what the relay sees, see [Security and privacy](../security-and-privacy.md). diff --git a/web/docs/content/getting-started/install.md b/web/docs/content/getting-started/install.md index fb1ccb42..dbcd6ccf 100644 --- a/web/docs/content/getting-started/install.md +++ b/web/docs/content/getting-started/install.md @@ -1,63 +1,40 @@ --- sidebar_position: 1 -title: Install -description: "How to get CrocApp: a notarized disk image for Mac today, the App Store and the Mac App Store soon, plus how updates work and how to build from source." +title: Requirements and install +description: "Which devices CrocApp supports, where to get it, how updates work and how to avoid mixing the App Store and disk image builds on one Mac." --- -# Install +# Requirements and install -CrocApp has three channels. The disk image is available now; the two App Store channels are coming. Pick the one that matches your device. All of them need **iOS 26**, **iPadOS 26** or **macOS 26** (`26.0` or any later version). +CrocApp needs **iOS 26**, **iPadOS 26** or **macOS 26** (`26.0` or any later version). The Mac app runs on Apple silicon only. There is no Intel build, no Windows, Linux or Android client, and no package-manager channel such as Homebrew. -| Channel | For | Where | -|---|---|---| -| App Store | iPhone and iPad | The listing is linked from [crocapp.dev](https://crocapp.dev) when it is live | -| Mac App Store | Mac | The listing is linked from [crocapp.dev](https://crocapp.dev) when it is live | -| Disk image | Mac with Apple silicon | `CrocApp-<version>-arm64.dmg` on [GitHub Releases](https://github.com/bakirgdev/CrocApp/releases/latest), from version 1.0.0 | - -The store listings arrive at launch, so this page does not link them yet. There is no Intel build and no package-manager channel (Homebrew and the like). - -## Disk image - -Open the disk image from GitHub Releases and drag **CrocApp** onto **Applications**. Use version 1.0.0 or later: the 0.9.x disk images are not notarized and use croc 10. From 1.0.0 on, the app is signed with a Developer ID certificate, notarized by Apple and stapled, so macOS opens it with the standard first-launch confirmation and nothing else. - -To check that a disk image came from this project's release workflow, run: - -```bash -gh attestation verify CrocApp-<version>-arm64.dmg --repo bakirgdev/CrocApp \ - --signer-workflow bakirgdev/CrocApp/.github/workflows/release.yml -``` - -See [Verify a release](../verify-downloads.md) for what the attestation covers and the other checks. +The other device needs **croc 11 or newer**, whether it runs CrocApp or the croc command line. croc 10 cannot complete a transfer with CrocApp. See [croc CLI interoperability](../reference/croc-cli-interop.md). -## Updates +## Where to get it -- **App Store builds** update through the App Store, like any other app. -- **The disk image build** updates itself with Sparkle. Choose **Check for Updates…** in the CrocApp menu. From the second launch on, Sparkle asks whether it may check automatically. Each update is signed, and the app installs it only when the signature matches the key built into the app. The check reads a feed on github.com and sends no system profile. -- Building from source does not update itself. +The disk image for Mac is available now. The App Store and Mac App Store versions are coming, and [crocapp.dev](https://crocapp.dev) links them once they are live. -The App Store builds contain no updater, so they never contact github.com to look for updates. +| Channel | For | Where | +|---|---|---| +| Disk image | Mac | `CrocApp-<version>-arm64.dmg` on [GitHub Releases](https://github.com/bakirgdev/CrocApp/releases/latest), version 1.0.0 or later | +| App Store | iPhone and iPad | Coming | +| Mac App Store | Mac | Coming | -## The other device +### Disk image -The device you transfer with needs **croc 11 or newer**, whether it runs CrocApp or the croc CLI. croc 10 cannot complete a transfer with CrocApp; see [croc CLI interoperability](../reference/croc-cli-interop.md). +Open the disk image and drag **CrocApp** onto **Applications**. Use version 1.0.0 or later. The 0.9.x disk images are not notarized and use croc 10. From 1.0.0 on, Apple has notarized the app, so macOS shows only its standard first-launch confirmation. -## Build from source +To check a download before you run it, see [Verify a release](verify-downloads.md). -Requires: +:::warning +Use one channel per Mac. The App Store and disk image builds are both named `CrocApp.app`, so dragging the disk image copy into **Applications** replaces the App Store copy. Their data is kept apart, but one app takes the other's place. +::: -- **macOS 26** -- **Xcode 27.1** -- **Go 1.27.2** or newer (`gomobile` and `gobind` are rebuilt from the `go.mod` `tool` block on every run) +## Updates -```bash -git clone https://github.com/bakirgdev/CrocApp.git -cd CrocApp -scripts/build-xcframework.sh # Go engine -> CrocKit/Croc.xcframework -open app/CrocApp.xcodeproj -``` +- **App Store builds** update through the App Store. +- **The disk image build** updates itself. Choose **Check for Updates…** in the CrocApp menu. From the second launch on, it asks whether it may check automatically. It installs an update only when the update's signature matches the key built into the app. The check reads a feed on github.com and sends no system profile. -:::warning -A fresh clone builds nothing until the xcframework exists. `CrocKit`'s binary target points at a gitignored artifact, so `scripts/build-xcframework.sh` is not optional. -::: +The App Store builds contain no updater, so they never contact github.com to look for updates. What changed in each release is on [GitHub Releases](https://github.com/bakirgdev/CrocApp/releases). -Full toolchain reference, build settings, and troubleshooting: [`docs/BUILDING.md`](https://github.com/bakirgdev/CrocApp/blob/main/docs/BUILDING.md) on GitHub. +To build from source, see the [contributor docs](../contribute.md). diff --git a/web/docs/content/getting-started/verify-downloads.md b/web/docs/content/getting-started/verify-downloads.md new file mode 100644 index 00000000..27c36b6c --- /dev/null +++ b/web/docs/content/getting-started/verify-downloads.md @@ -0,0 +1,58 @@ +--- +sidebar_position: 3 +title: Verify a release +description: What each CrocApp release asset is, and how to check a download is notarized, built by the release workflow and unmodified. +--- + +# Verify a release + +Each release on the [releases page](https://github.com/bakirgdev/CrocApp/releases) has four assets: + +| Asset | What it is | +|---|---| +| `CrocApp-<version>-arm64.dmg` | The Mac app, as a disk image | +| `appcast.xml` | The update feed the app reads | +| `Croc.xcframework-<version>.zip` | The prebuilt Go engine, for building from source | +| `SHA256SUMS.txt` | Checksums for the disk image and the engine archive | + +The disk image is the only file of the app. No separate app zip is published. + +## Notarized and stapled + +The app inside the disk image is signed with a Developer ID certificate. Apple has notarized both the app and the disk image, and each carries its notarization ticket, so macOS verifies them offline. To check the disk image: + +```bash +xcrun stapler validate CrocApp-<version>-arm64.dmg +spctl -a -vv -t open --context context:primary-signature CrocApp-<version>-arm64.dmg +``` + +## Build attestation + +The release workflow records a [build provenance attestation](https://github.com/bakirgdev/CrocApp/attestations) for the disk image, the engine archive and `appcast.xml`. Verify one before you run it: + +```bash +gh attestation verify <file> --repo bakirgdev/CrocApp \ + --signer-workflow bakirgdev/CrocApp/.github/workflows/release.yml +``` + +`--signer-workflow` proves the file came from the release workflow, not just any workflow in the repository. Without it, the check covers only the repository. + +## Checksums + +`SHA256SUMS.txt` lists a SHA-256 checksum for the disk image and for the engine archive. Download it next to the disk image, then run this in the folder that holds both: + +```bash +grep 'arm64.dmg' SHA256SUMS.txt | shasum -a 256 -c +``` + +It prints `CrocApp-<version>-arm64.dmg: OK` when the file matches. + +`SHA256SUMS.txt` itself has no attestation. It catches a damaged or incomplete download, but it does not prove who built the file. For that, use the attestation above. + +## Updates + +Only the disk image build updates itself. Every update in `appcast.xml` is signed, and the app installs an update only when the signature matches the key built into it. The feed is served over HTTPS from this repository's releases, and update checks send no system profile. The App Store builds contain no updater. + +## If a check fails + +A file that fails any check, or that appears anywhere other than this repository's releases page, is worth reporting. See the [security policy](https://github.com/bakirgdev/CrocApp/blob/main/SECURITY.md). diff --git a/web/docs/content/guide/_category_.json b/web/docs/content/guide/_category_.json deleted file mode 100644 index e980579f..00000000 --- a/web/docs/content/guide/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "Guide", - "position": 3, - "link": { - "type": "generated-index", - "description": "How sending, receiving, code phrases, power options, settings, and history work in CrocApp." - } -} diff --git a/web/docs/content/guide/advanced-settings.md b/web/docs/content/guide/advanced-settings.md deleted file mode 100644 index 6b71f116..00000000 --- a/web/docs/content/guide/advanced-settings.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -sidebar_position: 5.5 -title: Advanced settings -description: Proxies, ports, encryption curve, send speed limit and more, with each option's default, which device it affects, and whether the other device has to match. ---- - -# Advanced settings - -**Advanced** holds the croc options most people never need: proxies, the encryption curve, a send speed limit, ports and a few more. Every default is croc's own, so you can ignore this page unless you know you need something here. - -On iOS, open **Settings** from the home toolbar and tap **Advanced**. On macOS, open Settings (⌘,) and choose the **Advanced** tab. **Reset to Defaults** at the bottom puts every setting back after a confirmation, and removes the saved proxies. - -Each field checks what you type and shows a message under it. If a saved value is not usable, a transfer fails to start with "An Advanced setting can't be used" instead of falling back to something else. - -## Who has to match - -| Setting | Default | Affects | Other device must match? | -|---|---|---|---| -| Curve | P-256 | Receiving | No, the sending device uses the receiving device's choice | -| File hash | xxHash | Sending | No, the receiving device uses the sender's choice | -| SOCKS5 proxy | None | This device | No | -| HTTP proxy | None | This device | No | -| Built-in DNS resolver | Off | This device | No | -| Multicast address (macOS only) | `239.255.255.250` | Both devices | Yes, the same address, to find each other on the local network | -| Sender IP | None | Receiving | No, but it must be the sender's address and base port | -| Send speed limit | No limit | Sending | No | -| Base port | 9009 | Sending | Only if the other device connects by sender IP: it must use this port | -| Parallel connections | 4 | Sending | No | -| Multiplexing | On | Sending | No, the receiving device follows | - -"Sending" means the setting applies when this device sends; the receiving device follows what the sender does. - -## Security - -**Curve** picks the key-exchange curve: P-256 (the default), P-384, P-521, SIEC or Ed25519. The receiving device's choice wins: the sender switches to it, so the two devices never have to match, and the setting only matters when this device receives. - -**File Hash** picks how the sender fingerprints files so the other device can check them: xxHash (the default), imohash, MD5 or HighwayHash. Only the sender's choice matters. - -## Network - -**SOCKS5 Proxy** and **HTTP Proxy** send this device's connections through a proxy. Enter `host:port`, or an address such as `socks5://user:password@host:1080` (SOCKS5: `socks5://` or `socks5h://`; HTTP: `http://` or `https://`). If both are set, the SOCKS5 proxy is used. Connections to devices on your local network skip the proxy. The proxies also apply to [Send as link](stored-transfers.md) sends, receives and revokes. - -A proxy address can contain a password, so CrocApp keeps both proxies in the Keychain, never in the settings file, and never shows them in an error message. - -**Built-in DNS Resolver** looks up relay names with croc's own resolver instead of the system's. It is off by default and only affects this device. - -**Multicast Address** is the group croc uses to find other devices on the local network. Both devices must use the same address, or they will not find each other locally (unless **Local Network Only** is on, they can still connect through a relay). It must be an IPv4 multicast address, from `224.0.0.0` to `239.255.255.255`. This setting is available on macOS only for now: iOS needs an Apple entitlement for multicast that CrocApp does not have, so iOS always uses the default address. - -**Sender IP** is for receiving. Enter the sender's address and port, such as `192.168.1.20:9009` or `[fe80::1]:9009`, and CrocApp connects straight to the sender and skips relays and discovery. The port is the sender's **Base Port**, 9009 unless they changed it. The sender must be reachable at that address, for example on the same network. If nothing answers there, the receive fails at once; it does not fall back to a relay. While it is set, the trust badge on a receive reads "Straight to the sender, no relay in between". - -## Performance - -**Send Speed Limit** caps how fast this device sends, in bytes per second: digits with an optional `k`, `m` or `g`, such as `500k`, `2m` or `1g`. Leave it blank for no limit. - -**Base Port** and **Parallel Connections** set the ports the sender's local relay listens on: the base port, then one more per connection. With the defaults that is 9009 to 9013. The last port must stay at or below 65535. They matter when the other device connects by sender IP, or when something else on your device already uses those ports. - -**Multiplexing** is on by default. Turning it off sends over one data connection. The receiving device follows. - -## See also - -- [Power options](power-options.md) for relay, connection, compression and confirmation settings. -- [Receiving files](receiving.md) for connecting by sender IP. -- [Settings and trust](settings-and-trust.md) for where settings are stored. diff --git a/web/docs/content/guide/code-phrases.md b/web/docs/content/guide/code-phrases.md index 1901b4a1..2f77f1b0 100644 --- a/web/docs/content/guide/code-phrases.md +++ b/web/docs/content/guide/code-phrases.md @@ -1,56 +1,43 @@ --- sidebar_position: 3 -title: Code phrases -description: What a CrocApp code phrase is, how the two devices use it, and how to share one. +title: Code phrases and links +description: What a CrocApp code phrase is, how to share one by voice, QR code or link, and what to know about custom codes. --- -# Code phrases +# Code phrases and links -A code phrase looks like `cape-junky-widow`: three random words. It is generated fresh for every transfer, unless you set a custom one on the [Send screen](sending.md). +A code phrase looks like `cape-junky-widow`: three random words, new for every transfer. Entering it on the other device is all that is needed. It finds the other device and proves both sides know the same phrase, so a wrong code fails at once. [Security and privacy](../security-and-privacy.md#how-a-transfer-is-protected) explains why. -## One phrase finds the other device and authenticates it +Each code works for one transfer and expires with it. Anyone who has the code before the transfer completes can join it, so share it only over a channel you trust. -Entering the code on the other device is all that is needed. It is how the two devices find each other, and it authenticates both of them. There is nothing else to configure for a normal transfer. +## Share a code -## How the code phrase is used +CrocApp shows the code as text and as a QR code, with **Copy Code** and **Share Link** beside it. The QR code and the link are the same address, `https://crocapp.dev/r/#<code>`. A phone camera that scans it opens CrocApp, or a page that explains the options if the app is not installed. -Both devices run **PAKE** (password-authenticated key exchange) with the code phrase, so the code phrase authenticates both devices: - -- A wrong code fails immediately, before any file data moves. -- The transfer is end-to-end encrypted. - -## One transfer, then it expires - -Every transfer uses a fresh code phrase. Whoever has the code can join that transfer, and the code expires with it. It is not reusable for a later transfer. - -## Sharing it: QR code and paste - -CrocApp shows the code as text and as a QR code, and a **Share Link** button next to it. The QR code and the shared link are the same web link, `https://crocapp.dev/r/#<code>`. A phone camera that scans it opens CrocApp if it is installed, or a page that explains the options if it is not (see [Receiving a link](#receiving-a-link)). - -To bring a code into the **Receive** field, you have two explicit options: use the **Paste** button, or (iOS) tap **Scan QR Code**. CrocApp does not silently read the clipboard; pasting is always something you trigger yourself. +On the other device, bring the code into **Receive** by typing it, tapping **Paste**, or on iOS tapping **Scan QR Code**. CrocApp never reads the clipboard on its own. ## Accepted forms -Whatever you paste, scan, or open, CrocApp reads the code out of it. These forms are accepted: +Whatever you paste, scan or open, CrocApp reads the code out of it: -- a bare code, as long as it is at least 6 characters with no whitespace -- `https://crocapp.dev/r/#<code>`, the link CrocApp itself shares +- a bare code of at least 6 characters with no spaces +- `https://crocapp.dev/r/#<code>`, the link CrocApp shares - `crocapp://receive?code=<code>` -- `https://getcroc.com/?code=<code>`, the link the croc CLI's `--qrcode` shows -- `croc://<code>`, the form in the QR codes of earlier CrocApp builds, which still scan +- `https://getcroc.com/?code=<code>`, the link the croc command line's `--qrcode` shows +- `croc://<code>`, from QR codes in earlier CrocApp builds ## Receiving a link -Opening a link, or pasting or scanning one, takes you to **Receive** with the code filled in. Nothing connects until you tap **Receive**. If a transfer is already running, the link is kept and CrocApp does not move you away from it. +Opening, pasting or scanning a link takes you to **Receive** with the code filled in. Nothing connects until you tap **Receive**. If a transfer is already running, the link is kept and CrocApp stays on the current transfer. -The page at `crocapp.dev/r/` reads the code from the part of the address after the `#`. Browsers never send that part to a server, and the page makes no network request. From the page you can open CrocApp, get it from the App Store or as a disk image, or receive in your browser. +The page at `crocapp.dev/r/` reads the code from the part of the address after the `#`. Browsers never send that part to a server, and the page makes no network request. It offers to open CrocApp, get it, or receive in a browser. -**Receive in Your Browser** opens `https://getcroc.com/?code=<code>`, which is croc's own web app, not part of CrocApp. The code is in the query string there, so getcroc.com's server receives it. That path depends on getcroc.com fully, because getcroc.com serves the JavaScript that decrypts the file. It also needs the default relays, so the sender's waiting screen shows a note when a custom relay or **Local Network Only** is active. To avoid that dependency, receive in CrocApp or the croc CLI. +**Receive in Your Browser** goes to croc's own web app, not part of CrocApp. See [Receiving in a browser](../security-and-privacy.md#receiving-in-a-browser) for what that means for your code. ## Custom codes -A custom code must be at least 6 characters. Set it in the **Custom Code** field on the Send screen so you can share it through a channel you already trust, such as a phone call, instead of relying on the generated one. - -## Sharing a code safely +Type your own into **Custom code (optional)** on the Send screen to share it by a channel you already trust, such as a phone call. Three things to know: -Share it over a channel you trust: speak it, send it through a chat you already trust, or let the other device scan the QR code directly off your screen. A shared link carries the code too, so send it only over a channel you would trust with the code itself. Anyone who obtains the code before the transfer completes can join the transfer. +- It must be at least 6 characters. A short, guessable code is easier for someone else to join. +- Codes that start with the same word can land in the same relay room. Generated codes rarely collide: two share a first word about once in 1296. +- Start the sender before the receiver. A receiver that joins first can fail with a generic error. See [Troubleshooting](../troubleshooting.md#the-receiver-started-first). diff --git a/web/docs/content/guide/history.md b/web/docs/content/guide/history.md index 79c88b41..1199040b 100644 --- a/web/docs/content/guide/history.md +++ b/web/docs/content/guide/history.md @@ -1,40 +1,38 @@ --- -sidebar_position: 7 +sidebar_position: 6 title: History -description: "CrocApp's local-only transfer history: what it records, what it deliberately never records, and how to clear it." +description: "CrocApp's local-only transfer history: what it records, what it never records, and how to delete entries." --- # History -![CrocApp's History screen on macOS listing past transfers with their direction, file counts, and status](/img/screenshots/mac/history-light.png#gh-light-mode-only)![CrocApp's History screen on macOS listing past transfers with their direction, file counts, and status](/img/screenshots/mac/history-dark.png#gh-dark-mode-only) +![The History screen on macOS listing past transfers with their direction, file counts, and status](../../screenshots/mac/history-light.webp#gh-light-mode-only)![The History screen on macOS listing past transfers with their direction, file counts, and status](../../screenshots/mac/history-dark.webp#gh-dark-mode-only) -CrocApp keeps a local list of past transfers, reachable from the home screen's history icon. It never leaves the device: there is no sync, no export and no server involved. +CrocApp keeps a list of past transfers on your device. Open it from the clock icon on the home screen. It has no sync, no export and no server. -## What's recorded +## What is recorded For each finished or failed transfer: -- Direction (sent or received) and whether it was a text transfer -- Up to 20 file names -- Total file count and total size -- A **code hint**: the first word of a code shaped like a generated one (for example, "wiry-…"), or only the first two characters of any other code, never the full phrase. A Send as Link transfer keeps the link server's host instead (see [Links sent](#links-sent)) -- Date and status (completed, failed, cancelled, or declined) -- For sends, a set of file bookmarks used to support **Send Again**, captured all-or-nothing and only up to 200 items. A record with no bookmarks does not offer Send Again +- the direction (sent or received), and whether it was text +- up to 20 file names, the file count and the total size +- a **code hint**: the first word of a code shaped like a generated one (for example `wiry-…`), or only the first two characters of any other code. The full phrase is never stored +- the date and the status: **Completed**, **Failed**, **Cancelled** or **Declined** +- for sends, bookmarks to the original files (up to 200) that make **Send Again** possible -## What's never recorded +File contents are never recorded. -- File contents -- The full code phrase, only that hint -- Anything beyond the 20-name and 200-bookmark caps +## Send Again -## Links sent +For a past send, the row's context menu (or a swipe on iOS) offers **Send Again**, which stages the same files in a new send. If the originals were moved or deleted, CrocApp says so instead of sending nothing. -A file sent with [Send as link](stored-transfers.md) is recorded with the link server's host name and the time the link expires, then **Link expired** or **Link revoked** later. **Revoke Link**, in the row's context menu (and as a swipe action on iOS), deletes the files from the link server after a confirmation. The link and the token that revokes it are never stored in History; they stay in the Keychain until the link is revoked or expires. +## Links you sent -## Send Again +A [Send as link](send-as-link.md) row shows the link server's host and when the link expires, then **Link expired** or **Link revoked**. Use **Revoke Link** in the row's context menu to end a live link. The link itself is never stored here. -For a past send, the history entry's context menu (or swipe action on iOS) offers **Send Again** if bookmarks were captured for it. This re-stages the same files into a new send. If the original files were moved or deleted since, CrocApp tells you they are no longer available rather than silently sending nothing. +## Delete -## Clearing history +- **Delete** in a row's context menu (or a swipe on iOS) removes that entry. +- **Clear** in the toolbar, then **Clear All**, removes the whole list. -Tap **Clear** in the history screen's toolbar, then confirm. This removes the list only. Files you have already received stay where they were saved. +Both remove the list only. Files you already received stay where they were saved. Revoke a live link before you delete its row, because the row is where you revoke from. diff --git a/web/docs/content/guide/menu-bar.md b/web/docs/content/guide/menu-bar.md index 62359b0f..cb840865 100644 --- a/web/docs/content/guide/menu-bar.md +++ b/web/docs/content/guide/menu-bar.md @@ -1,48 +1,37 @@ --- -sidebar_position: 8 -title: Menu bar -description: Send files and clipboard text from the Mac menu bar, open CrocApp at login, and use the File menu commands on iPad. +sidebar_position: 7 +title: Mac menu bar and keyboard shortcuts +description: Send files and clipboard text from the Mac menu bar, open CrocApp at login, and the keyboard shortcuts on Mac and iPad. --- -# Menu bar +# Mac menu bar and keyboard shortcuts -## macOS: quick send +## Quick send from the menu bar -CrocApp puts an icon in the Mac menu bar. Click it to open a small window where you can send without opening the main window. +CrocApp puts an icon in the Mac menu bar. Click it to open a small window that sends without opening the main window. | Control | What it does | |---|---| -| **Drop Files to Send** | Drop files or folders on this area to send them | -| **Choose Files…** | Opens a file panel; pick files and folders to send | -| **Send Clipboard Text** | Sends the text on the clipboard. If the clipboard has no text, the window says so | +| Drop area | Drop files or folders here to send them | +| **Choose Files…** | Opens a file panel to pick files and folders | +| **Send Clipboard Text** | Sends the text on the clipboard. If there is none, the window says so | +| **Open CrocApp** | Brings the main window forward | -Dropping works only once the window is open. You cannot drop files onto the menu bar icon itself: click the icon first, then drop. +Click the icon first, then drop. You cannot drop files onto the icon itself. -Once a send starts, the window shows the code, a QR code, **Copy Code**, progress and **Cancel**, the same as the Send screen. Quick send always uses a generated code; to choose your own, use the main window ([Sending files](sending.md)). +Once a send starts, the window shows the code, a QR code, **Copy Code**, progress and **Cancel**. Quick send always uses a generated code. To choose your own, use the [main window](sending.md#custom-code). -The window shares the one active transfer with the main window. It shows a transfer you started there, or from [Shortcuts](shortcuts.md), and it refuses to start a new one while another runs. If a receive needs you to accept or decline, the window tells you to open CrocApp, because that prompt lives in the main window. **Open CrocApp** at the bottom brings the main window forward. +The window shares the one active transfer with the main window, and with [Shortcuts](shortcuts.md). It will not start a second one. If a receive needs you to accept or decline, the window says to open CrocApp, because that prompt lives in the main window. -### Settings +Turn the icon off with **Show in Menu Bar**, or start CrocApp at login with **Open at Login**, in [Settings](settings.md#receive-and-menu-bar-mac). -Under **Menu Bar** in Settings (⌘,), on the General tab: +## Keyboard shortcuts -- **Show in Menu Bar** is on by default. Turn it off to remove the icon. -- **Open at Login** is off by default. Turn it on to start CrocApp when you log in. The switch shows what macOS reports, so it follows a change you make in System Settings > General > Login Items. If macOS needs you to approve CrocApp there, the setting says so and an **Open Settings** button takes you to Login Items. - -## iPad: File menu commands - -On iPad, the iPadOS 26 menu bar lists the same File commands as the Mac: +These work on Mac and on iPad with a keyboard. **Send…** and **Receive…** are disabled while a transfer is running. | Command | Shortcut | |---|---| -| **Send…** | ⌘1 | -| **Receive…** | ⌘2 | -| **Show Receive Folder in Files** | ⇧⌘R | - -**Show Receive Folder in Files** opens the Files app at your receive folder. On a Mac the same shortcut reveals the folder in Finder. The Files hand-off has not been checked on an iPad yet. - -## See also - -- [Sending files](sending.md) for the full Send screen. -- [Shortcuts](shortcuts.md) for automating sends and receives. -- [Settings and trust](settings-and-trust.md) for where settings live. +| **Send…** (File menu) | ⌘1 | +| **Receive…** (File menu) | ⌘2 | +| **Show Receive Folder in Finder** (Mac) or **Show Receive Folder in Files** (iPad) | ⇧⌘R | +| Settings (Mac) | ⌘, | diff --git a/web/docs/content/guide/power-options.md b/web/docs/content/guide/power-options.md deleted file mode 100644 index 9f5993ea..00000000 --- a/web/docs/content/guide/power-options.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -sidebar_position: 5 -title: Power options -description: The shipped power-user settings and the croc CLI flag each one maps to. ---- - -# Power options - -![CrocApp Settings on iOS showing the power options under the settings screen](/img/screenshots/iphone/settings-light.png#gh-light-mode-only)![CrocApp Settings on iOS showing the power options under the settings screen](/img/screenshots/iphone/settings-dark.png#gh-dark-mode-only) - -CrocApp exposes a set of power options with sane defaults. On macOS they live in the Settings scene (⌘,); on iOS they're under the settings screen from the home toolbar. All eight below are shipped. The croc options most people never need, such as proxies and ports, are on a separate page: [Advanced settings](advanced-settings.md). - -| Option | Control | croc equivalent | -|---|---|---| -| Custom relay, password, IPv6 | **Address**, **IPv6 Address**, **Password** fields under Relay | `--relay --relay6 --pass` | -| Connection: Automatic or Relay only | **Connection** picker | `--transport auto\|relay` | -| Force local-only transfers | **Local Network Only** toggle | `--local` | -| Disable compression | **Disable Compression** toggle | `--no-compress` | -| Zip a folder before sending | **Zip Folders Before Sending** toggle | `--zip` | -| Exclude patterns, respect `.gitignore` | **Patterns, One per Line** field, **Respect .gitignore** toggle | `--exclude --git` | -| Auto-accept, off by default | **Auto-Accept Transfers** toggle | `--yes` | -| Require confirmation on both sides | **Confirm on Both Sides** toggle | `--ask` | - -## Relay - -The **Address** and **IPv6 Address** fields read "Public relay pool" as placeholder text; leave them blank to use croc's public relay pool, the same one the croc command line uses. Leave **Password** blank to use croc's default relay password. - -## Connection - -The **Connection** picker has its own section after Relay. **Automatic** is the default. **Relay Only** sends every transfer through croc's relays. - -With **Automatic**, a send of 128 MiB or more also tries a direct path between the two devices. This path is called Tailcat. It is set up through `tailcat.dev`, and it uses its own relays (`*.ipn.dev`) when the devices cannot reach each other. CrocApp starts it next to croc's relay, and whichever path connects first carries the transfer. The data is still end-to-end encrypted on either path. Smaller sends never start it. - -With **Relay Only**, a send never contacts `tailcat.dev` or the `*.ipn.dev` servers. A receive can still use them when the sender chose Automatic (or the croc CLI's default, `auto`). - -Only the sender's choice applies. A receive follows whatever the sender uses, so the picker has no effect when you receive. The picker is disabled while **Local Network Only** is on, because local-only transfers always use **Automatic**. The footer under the picker reads: "Automatic can carry files of 128 MiB or more directly between devices. Only the sender's choice applies; a receive follows it." - -## Local network only - -When on, transfers never touch a relay on the internet: CrocApp only uses the local network. If a direct local connection cannot be made, the transfer fails rather than falling back to a relay. - -## Exclude patterns - -Patterns go one per line in the **Patterns, One per Line** field. **Respect .gitignore** additionally excludes anything your `.gitignore` would. - -## Auto-accept - -Auto-accept is off by default. With it on, a picker, **When a File Already Exists**, chooses what happens to received files whose names are already taken: **Keep Both** (the default) saves them under a new name such as `name (1).ext`, **Replace** overwrites the existing file. See [Receiving files](receiving.md) for how each choice behaves. With auto-accept on, CrocApp warns that files from anyone who has your code are saved without preview or confirmation, that Keep Both saves a new copy next to an existing file while Replace overwrites it, that unsafe file names still cancel the transfer, and that **Confirm on Both Sides** overrides auto-accept. With it off, the footer says to leave it off unless you fully trust the sender. - -## Confirm on both sides - -When on, the sender also has to approve the transfer, through a prompt reading **The other device is connected**, before it starts. That comes in addition to the other device's normal accept step. - -## Not in the app - -The app cannot run a relay itself. To use your own relay, run `croc relay` on a machine you control and enter its address under Relay. The other croc options (proxies, send speed limit, curve and hash choice, sender IP, multicast address, ports and the internal DNS resolver) are under [Advanced settings](advanced-settings.md). diff --git a/web/docs/content/guide/receiving.md b/web/docs/content/guide/receiving.md index 0af342cf..7c613186 100644 --- a/web/docs/content/guide/receiving.md +++ b/web/docs/content/guide/receiving.md @@ -1,60 +1,65 @@ --- sidebar_position: 2 -title: Receiving files -description: How to receive a transfer in CrocApp, review the file list, and handle conflicts. +title: Receive +description: How to receive a transfer in CrocApp, review the file list, choose where files land and handle name conflicts. --- -# Receiving files +# Receive -![CrocApp on iOS showing a receive of three files with Decline and Accept buttons](/img/screenshots/iphone/receive-incoming-light.png#gh-light-mode-only)![CrocApp on iOS showing a receive of three files with Decline and Accept buttons](/img/screenshots/iphone/receive-incoming-dark.png#gh-dark-mode-only) +![CrocApp on iOS showing a receive of three files with Decline and Accept buttons](../../screenshots/iphone/receive-incoming-light.webp#gh-light-mode-only)![CrocApp on iOS showing a receive of three files with Decline and Accept buttons](../../screenshots/iphone/receive-incoming-dark.webp#gh-dark-mode-only) -Open **Receive** from the home screen. +Tap or click **Receive** on the home screen. -## Entering a code +## Enter the code -Type the **Code Phrase** into the field, paste it with the **Paste** button, or (iOS only) tap **Scan QR Code** to scan the sender's QR code. The **Receive** button stays disabled until the entered code is at least 6 characters long. +Type the code phrase into the **Code phrase** field, tap **Paste**, or on iOS tap **Scan QR Code**. **Receive** stays disabled until the code is at least 6 characters. -You can also paste a link, or open one from outside the app (for example by scanning the QR code with the camera). CrocApp fills in the code and waits: nothing connects until you tap **Receive**. See [Code phrases](code-phrases.md#accepted-forms) for the link forms it accepts, and for receiving in a browser instead. +You can also paste or open a link. CrocApp fills in the code and waits. Nothing connects until you tap **Receive**. See [Code phrases and links](code-phrases.md#accepted-forms) for the forms it accepts. -A link from [Send as link](stored-transfers.md) works the same way: paste it, or scan its QR code on iOS, and the code field is replaced by a **Receive from Link** row naming the link server. Tapping **Receive** then shows the usual file list below, with **Keep Both** and **Replace**; auto-accept does not apply to it. +A link from [Send as link](send-as-link.md) replaces the code field with a **Receive from Link** row that names the link server. -## Choosing where files land +If the code is right but nothing connects, ask the sender to start first, and see [Troubleshooting](../troubleshooting.md). -Below the code field, CrocApp shows the current destination folder. Tap **Change** to pick a different one, or **Reset** to return to the default. +## Choose where files land -Defaults differ by platform: +The current destination folder shows below the code field. **Change…** picks another folder, and **Reset** returns to the default: -- **macOS**: `Downloads/CrocApp` -- **iOS**: the app's Documents folder, which is visible in the Files app +- **Mac:** `Downloads/CrocApp` +- **iOS:** the app's Documents folder, which shows in the Files app -## Accepting or declining +On a Mac you can also change it in [Settings](settings.md) under **Save Received Files To**. -After you tap **Receive** and connect to the sender, CrocApp shows the full file list with sizes and a total. From here: +## Accept or decline -- **Accept** starts the transfer. It appears alone when nothing at the destination clashes with the files being received, and it then means Keep Both (below). -- **Decline** refuses it. This is the only way to refuse once you have seen the list. There is no cancel button at this stage. +After you tap **Receive** and connect, CrocApp lists the files with sizes and a total. Tap **Accept** to start, or **Decline** to refuse. Decline is the only way out at this point. If the sender turned on **Confirm on Both Sides**, they confirm too. -If the sender has [Confirm on both sides](power-options.md) turned on, the sender must also confirm before the transfer proceeds. +If you know the sender's address, you can connect straight to it with **Sender IP** in [Settings](settings.md#advanced). -If you know the sender's address, you can connect to it directly with **Sender IP** under [Advanced settings](advanced-settings.md#network). +When a transfer is waiting for your answer and you are on another screen, the home screen shows **Files are waiting for your answer** with **Review**. -## Overwrite and conflicts +## Name conflicts -CrocApp never overwrites an existing file unless you say so. If any file being received already exists at the destination, the accept screen shows a banner that says how many items already exist and what each choice does, and replaces **Accept** with two choices, besides **Decline**: +CrocApp never overwrites a file unless you say so. When a name is already taken, a banner reads **Some names are already taken** and **Accept** is replaced by two choices: -- **Keep Both** (the prominent default) saves the new file under a new name next to the old one: `name (1).ext`, then `name (2).ext`, and so on. -- **Replace** overwrites the existing file. A partly received file resumes where it stopped instead of restarting. +- **Keep Both** (the default) saves the new file as `name (1).ext`, then `name (2).ext`, and so on. +- **Replace** overwrites the existing file. A partly received file resumes where it stopped. -A file that already exists with identical content is left as it is under either choice. Files with unsafe names (for example, ones trying to escape the destination folder) block the accept buttons entirely, as a safety measure on top of croc's own name sanitization. +A file that already exists with identical content is left alone under either choice. A file with an unsafe name (one that tries to escape the destination folder) blocks the buttons. -A folder sent as a zip arrives as a single `.zip` name, so the preview cannot see which of its files already exist. The sheet then offers only **Accept**, which is Keep Both: it silently keeps the existing files and skips the matching ones in the archive. Replace and auto-accept keep them too. To get the sender's copies, move the old folder away before receiving. +A folder sent as a zip arrives as one `.zip` name, so CrocApp cannot tell which of its files exist. The sheet then offers only **Accept**, which behaves as **Keep Both**: existing files stay and matching files in the archive are skipped. To get the sender's copies, move your old folder away first. + +![CrocApp on macOS showing three incoming files, a warning that some names are already taken, and the Decline, Replace and Keep Both buttons](../../screenshots/mac/receive-conflict-light.webp#gh-light-mode-only)![CrocApp on macOS showing three incoming files, a warning that some names are already taken, and the Decline, Replace and Keep Both buttons](../../screenshots/mac/receive-conflict-dark.webp#gh-dark-mode-only) ## Auto-accept -Auto-accept is **off by default**. When off, you always see the file-list preview above before anything is saved. Turning it on (in [power options](power-options.md)) skips that preview. That page describes the warning CrocApp shows when it is enabled. Because there is no sheet to ask, a setting under it, **When a File Already Exists**, decides between Keep Both (the default) and Replace. Replace overwrites existing files, except inside a zipped folder, where the existing files are kept (see above). +Auto-accept is off by default, so you always see the file list first. Turning on **Auto-Accept Transfers** in [Settings](settings.md#confirmation) skips that preview. Because there is no sheet to ask, **When a File Already Exists** decides between **Keep Both** and **Replace**. ## After the transfer -When it finishes, CrocApp shows **Transfer complete** (or a message if something went wrong) with a button to open the destination: **Open in Files** on iOS, **Show in Finder** on macOS. The File menu also has **Show Receive Folder in Finder** (macOS) and **Show Receive Folder in Files** (iPad), both ⇧⌘R; see [Menu bar](menu-bar.md#ipad-file-menu-commands). +CrocApp shows **Transfer complete**, or a message if something went wrong. Open the folder with **Show in Finder** (Mac) or **Open in Files** (iOS). On iOS, **Open in Files** appears only when the destination is the default Documents folder. If you picked another folder, open it from the Files app. + +A received text snippet shows as **Received text** with **Copy Text**. + +The Mac **File** menu also has **Show Receive Folder in Finder**, and iPad has **Show Receive Folder in Files**. Both use ⇧⌘R. -A [Shortcuts](shortcuts.md) action can receive for you with a code or link and return the files. +A [Shortcuts](shortcuts.md) action can receive for you and hand back the files. diff --git a/web/docs/content/guide/send-as-link.md b/web/docs/content/guide/send-as-link.md new file mode 100644 index 00000000..15c91f00 --- /dev/null +++ b/web/docs/content/guide/send-as-link.md @@ -0,0 +1,100 @@ +--- +sidebar_position: 4 +title: Send as link +description: "Send encrypted files to a link server and share a link, so the other device can receive later without being online at the same time." +--- + +# Send as link + +![CrocApp on macOS showing Link ready, the expiry and download count, a QR code and the link itself with Copy Link and Share Link buttons](../../screenshots/mac/stored-link-light.webp#gh-light-mode-only)![CrocApp on macOS showing Link ready, the expiry and download count, a QR code and the link itself with Copy Link and Share Link buttons](../../screenshots/mac/stored-link-dark.webp#gh-dark-mode-only) + +**Send as Link** sends your files, encrypted on your device, to a link server and gives you a link. The other device opens the link and receives the files whenever it likes, until the link expires or runs out of downloads. You do not need to stay online, and the two devices never connect to each other. + +croc's command line has the same feature, so the two work together. + +## Link or code + +| Question | Code phrase | Send as link | +|---|---|---| +| Both devices online at the same time? | Yes | No | +| How many devices can receive? | One | As many downloads as you allow | +| Folders and text? | Yes | No, files only | +| Where do the files rest? | Nowhere: they travel through a relay or directly | On the link server until the link ends | +| How do I end it early? | Cancel while it runs | [Revoke](#history-and-revoking) before it expires | + +Use a code when both people are available now, or for folders and text. Use a link when the other device is not around, or when several people need the same files. + +## Send + +1. Open **Send** and add files. +2. Turn on **Send as Link**. +3. Choose **Link Lasts**: **1 hour**, **1 day** (the default) or **7 days**. +4. Set **Downloads allowed**, from 1 (the default) to 100. +5. Tap **Send as Link**. + +A line under the options names the link server. While it runs, the screen reads **Sending** with progress. A link send uses no relay, so it shows no relay badge. + +The **Send as Link** switch is disabled, with a line saying why, when text is selected or a folder is staged. Switch to **Files**, remove the folders, or send them with a code. The custom code field is hidden while the switch is on, since there is no code. + +These [Settings](settings.md) do not apply to a link send: relay, **Connection** and **Local Network Only**. The proxies under **Advanced** do apply. + +## The result screen + +When the send finishes, CrocApp shows **Link ready**, when the link stops working, and the download count, with: + +- a QR code of the link +- the link itself +- **Copy Link** +- **Share Link**, which opens the share sheet + +CrocApp does not show the link again after you tap **Done**, and [History](history.md) never stores it. Copy or share it first. If you lose it, revoke the link from History and send again. + +On iOS, **Copy Link** keeps the link off Universal Clipboard, because the link contains the key. macOS offers no such option. + +Anyone who has the whole link can open the files until it ends. Send it over a channel you would trust with the files. + +## Receive + +In **Receive**, paste the link, or on iOS tap **Scan QR Code** and scan the QR code from the result screen. A **Receive from Link** row shows the link server's host name with a **Clear** button. Nothing is fetched until you tap **Receive**. + +CrocApp then fetches the file list for you to review. Choose **Accept**, or **Keep Both** or **Replace** if a name is taken, as in [Receive](receiving.md#name-conflicts). Auto-accept never applies to a link. + +A link that has expired, been revoked or run out of downloads says so: "This link has expired, was revoked, or has no downloads left." + +The phone's Camera app does not open CrocApp for these links, because they point at the link server. A camera scan opens the link server's page in the browser. Use **Scan QR Code** inside CrocApp, or paste the link. + +### In a browser + +Opening the link in a browser shows the link server's own page. For the default server, that is a getcroc.com page run by croc's author, not by CrocApp. The key is in the part of the link after the `#`, which browsers do not send to a server, so the page decrypts in your browser. This depends on the page the link server serves. See [Receiving in a browser](../security-and-privacy.md#receiving-in-a-browser). + +## History and revoking + +A link send appears in [History](history.md) with the link server's host name and one of **Link expires**, **Link expired** or **Link revoked**, each with a time. + +To end a live link early, choose **Revoke Link**. On a Mac, use the row's context menu. On iOS, touch and hold the row, or swipe it left and tap **Revoke**. A confirmation reads "Revoke this link?" and says the files are deleted from the link server and the link stops working for everyone. + +**Revoke Link** appears only while the link is live and this device still holds the receipt for the send. Deleting a History row, or clearing History, removes the place you revoke from, so revoke first if you want the link ended. + +## The link server + +The **Link Server** field is under **Send as link** in [Settings](settings.md#send-as-link). The default is `https://getcroc.com`, run by croc's author, not by CrocApp. + +The link server decides how long it keeps files and which limits it enforces. For a received link, the server in the link is used, whatever your setting says. + +## Limits + +CrocApp refuses, before sending, more than 100 files, more than 1 GiB in total, or more than 100 downloads. Those are croc's defaults. A link server with lower limits, or one that rate-limits sends, can still refuse. CrocApp then says which limit it hit: size, file count, downloads or too many recent sends. + +## Privacy + +Files are encrypted on your device before they reach the link server, and the key travels in the link's `#` fragment, which browsers never send to a server. A link send contacts only the link server in Settings. + +The link server sees the size of the encrypted data, the lifetime and download count you chose, and the usual details of any web request, such as your IP address and the time. Whether it can read file names has not been verified, so do not rely on names being hidden. + +On your device, [History](history.md) keeps only the server's host and the transfer id, never the link or the revoke token. The receipt, which holds both, lives only in the Keychain. CrocApp removes it when you revoke and at the first launch after the link expires. + +For everything CrocApp can contact, see [Security and privacy](../security-and-privacy.md). + +## If iOS interrupts a send + +A link send keeps going when you leave the app, but iOS may stop it. CrocApp then says iOS stopped it in the background. A link send cannot resume, so trying again starts over and makes a new link. If iOS stops a receive from a link, open the link again. Keep the app in the foreground for a large send if you can. diff --git a/web/docs/content/guide/sending.md b/web/docs/content/guide/sending.md index 0593e694..2fae9858 100644 --- a/web/docs/content/guide/sending.md +++ b/web/docs/content/guide/sending.md @@ -1,54 +1,53 @@ --- sidebar_position: 1 -title: Sending files -description: How to send files, folders, and text in CrocApp, including the share extension and the one-active-transfer rule. +title: Send +description: How to send files, folders and text in CrocApp, from the app, a drop, the share sheet or Finder. --- -# Sending files +# Send -![The CrocApp Send screen on macOS with three files staged and the Send button ready](/img/screenshots/mac/send-files-light.png#gh-light-mode-only)![The CrocApp Send screen on macOS with three files staged and the Send button ready](/img/screenshots/mac/send-files-dark.png#gh-dark-mode-only) +![The CrocApp Send screen on macOS with three files staged and the Send button ready](../../screenshots/mac/send-files-light.webp#gh-light-mode-only)![The CrocApp Send screen on macOS with three files staged and the Send button ready](../../screenshots/mac/send-files-dark.webp#gh-dark-mode-only) -Open **Send** from the home screen. The **What to Send** picker switches between two modes: +Tap or click **Send** on the home screen. The **What to Send** picker switches between **Files** and **Text**. ## Files -- **Add Files** opens a file picker; you can select multiple files at once. -- **Add Folder** picks a whole folder to send. -- On macOS, you can also drag files or folders onto the drop area. -- Picked items appear in a list, each removable with its **x** button. +- **Add Files** opens a picker. Select as many files as you like. +- **Add Folder** picks a whole folder. +- Remove an item from the list with its **x** button. + +On a Mac you can also drag files or folders onto the window at any point: a **Drop to Send** overlay appears. Dropping on the Dock icon, or choosing CrocApp in Finder's **Open With**, starts a send the same way. If a transfer is already running, the files wait, and a count appears on the **Send** button. ## Text -Type or paste into the text box, or use the **Paste** button to pull the current clipboard contents in directly (an explicit action, never a silent background read). +Type or paste into the text box, or tap **Paste** to insert the clipboard. CrocApp never reads the clipboard unless you ask. ## Custom code -The **Custom Code** field is optional. Leave it blank for a generated code, or enter your own (minimum 6 characters) so it can be shared through a channel you already trust, for example by dictating it over a call. - -## Starting the send - -Tap **Send**. CrocApp shows the generated (or custom) code phrase, a **Copy Code** button, a QR code the other device can scan, and a **Share Link** button. The QR code and the link open CrocApp on the other device, or a page at `crocapp.dev/r/` if it does not have the app (see [Code phrases](code-phrases.md#receiving-a-link)). With a custom relay or Local network only, a note on the screen says that receiving in a browser needs the default relays. The screen also shows a trust badge describing which relay path is in use. - -## Send as link - -Instead of a code, **Send as Link** (files only) sends your files, encrypted on your device, to a link server and gives you a link the other device can open later, with no need to be online at the same time. You choose how long the link lasts and how many downloads it allows. See [Send as link](stored-transfers.md). +Leave the code field empty for a generated code phrase. To choose your own, type it into the field marked **Custom code (optional)**. It needs at least 6 characters. See [Code phrases and links](code-phrases.md#custom-codes) before you do. -## Menu bar and Shortcuts +## Start the send -On a Mac, the [menu bar icon](menu-bar.md) sends files or clipboard text without opening the main window. On any device, [Shortcuts](shortcuts.md) can send files and text for you and hand back the code. +Tap **Send**. The screen shows **Ready to send** with: -## One active transfer at a time +- the code phrase and **Copy Code** +- a QR code +- **Share Link**, which shares a `crocapp.dev/r/` link that opens the app on the other device, or a page that explains the options if it is not installed (see [Code phrases and links](code-phrases.md#receiving-a-link)) +- a trust badge naming the route you configured (see [The trust badge](settings.md#the-trust-badge)) -CrocApp allows exactly one active transfer at a time, matching a limit in the underlying engine. You cannot start a second send or receive while one is in progress; finish or cancel the current transfer first. +The screen reads **Waiting for the other device…** until the other device connects. A note appears when a custom relay or **Local Network Only** is on, because receiving in a browser needs the default relays. -## Share extension (iOS only) +If **Confirm on Both Sides** is on, a prompt reading **The other device is connected** appears when it connects, and nothing moves until you tap **Send**. Once the transfer runs, CrocApp shows per-file and overall progress, speed and **Cancel**. -On iOS, you can share files into CrocApp from any other app's share sheet. Shared items are staged, and a **Shared Files** sheet appears with **Discard** and **Send** buttons when you next open CrocApp. Choosing **Send** carries the staged files into the normal Send flow. +Start the sender before the receiver. A receiver that joins first can fail with a generic error. See [Troubleshooting](../troubleshooting.md#the-receiver-started-first). -## Staged files sheet +## One transfer at a time -The staged-files sheet lists every item that was shared in, so you can review what will be sent before committing to it. +You cannot start a second send or receive while one is running. Finish or cancel the current one first. -## What the sender sees during the transfer +## Other ways to send -Once the other device connects, CrocApp shows **Ready to send** and waits. If [**Confirm on Both Sides**](power-options.md) is on, you get a prompt reading **The other device is connected**, with **Send** and **Cancel**, before anything moves. During transfer, CrocApp shows per-file and overall progress with speed, plus a **Cancel** button. +- **Share sheet (iOS).** Share files into CrocApp from any app. A **Shared Files** sheet lists what arrived, with **Discard** and **Send**. +- **Mac menu bar.** Send without opening the main window. See [Mac menu bar and keyboard shortcuts](menu-bar.md). +- **Shortcuts and Siri.** See [Shortcuts and Siri](shortcuts.md). +- **Send as Link.** Send files to a link server so the other device can receive later. See [Send as link](send-as-link.md). diff --git a/web/docs/content/guide/settings-and-trust.md b/web/docs/content/guide/settings-and-trust.md deleted file mode 100644 index 13377583..00000000 --- a/web/docs/content/guide/settings-and-trust.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -sidebar_position: 6 -title: Settings and trust -description: Where CrocApp's settings live, why you might run your own relay, and what the trust badge tells you. ---- - -# Settings and trust - -![CrocApp Settings on macOS showing the receive folder and the relay address fields](/img/screenshots/mac/settings-light.png#gh-light-mode-only)![CrocApp Settings on macOS showing the receive folder and the relay address fields](/img/screenshots/mac/settings-dark.png#gh-dark-mode-only) - -## Where settings live - -On macOS, settings are in the Settings scene (⌘,), with a **Receive** section (destination folder, plus a **Show in Finder** button) above the [power options](power-options.md). On iOS, the settings screen (reached from the home toolbar) holds the power options; the receive destination folder is changed from the **Receive** screen itself instead. - -Settings persist locally on the device. There is no sync and no account to sign into. - -## Custom relay - -By default, CrocApp uses croc's public relay. You can point it at a relay you run yourself instead, under the [Relay power option](power-options.md). Reasons to run your own: - -- You want transfers to route through infrastructure you control rather than the shared public relay. -- You are on a network where you would rather not depend on an external service. - -Running `croc relay` on a machine you control is enough; then enter its address (and password, if you set one) in CrocApp's relay fields. - -## Link server - -The **Send as Link** section holds the **Server** field for [Send as link](stored-transfers.md#the-link-server-setting). It defaults to `https://getcroc.com`, which is run by croc's author, not by CrocApp, and it accepts an `https` address (or `http` on localhost) with nothing after the host. A **Reset** button restores the default. The relay and **Connection** settings do not apply to a link send. - -## Connection - -The **Connection** picker under the [power options](power-options.md) chooses how a send carries large files. **Automatic** (the default) can also use a direct path between the devices for a send of 128 MiB or more, set up through `tailcat.dev`. A send set to **Relay Only** never contacts those servers; a receive follows the sender's choice. The data is end-to-end encrypted either way. - -## Advanced - -Proxies, ports, the encryption curve and similar options are under **Advanced**; see [Advanced settings](advanced-settings.md). The two proxy addresses can contain a password, so they are kept in the Keychain. - -## Menu bar (macOS) - -The **Menu Bar** section of Settings has **Show in Menu Bar** and **Open at Login**; see [Menu bar](menu-bar.md#settings). - -## The trust badge - -While CrocApp is waiting, confirming or transferring, CrocApp shows a trust badge: an **End-to-end encrypted** label plus a line describing the relay path actually in use for that transfer: - -- "Local network only: nothing leaves your network" -- "Via custom relay `<address>`, which sees only encrypted data" -- "Via the public croc relay, which sees only encrypted data" -- "Straight to the sender, no relay in between" (a receive with a [sender IP](advanced-settings.md#network) set) - -The badge is captured when the transfer starts, so changing settings mid-transfer cannot make it describe a different path. - -## What is stored - -Settings (relay address, relay password, connection, link server, local-only, compression, zip, exclude patterns, gitignore, both-sides confirm, auto-accept, and the Advanced options) are stored locally on the device. The relay password and the two proxy addresses are in the Keychain. No settings, transfer content or code phrases are sent anywhere except as part of a transfer you start. diff --git a/web/docs/content/guide/settings.md b/web/docs/content/guide/settings.md new file mode 100644 index 00000000..118c438b --- /dev/null +++ b/web/docs/content/guide/settings.md @@ -0,0 +1,109 @@ +--- +sidebar_position: 5 +title: Settings +description: Every CrocApp setting in the order the app lists them, with defaults, what each one affects and whether the other device has to match. +--- + +# Settings + +![CrocApp Settings on macOS, General tab, showing the Transfer, Exclude from sends, Confirmation and About sections](../../screenshots/mac/settings-light.webp#gh-light-mode-only)![CrocApp Settings on macOS, General tab, showing the Transfer, Exclude from sends, Confirmation and About sections](../../screenshots/mac/settings-dark.webp#gh-dark-mode-only) + +On a Mac, open Settings with ⌘, and use the **General** and **Advanced** tabs. On iOS, tap the gear on the home screen. **Advanced** is a row at the bottom of that screen. + +Settings stay on the device. There is no sync and no account. Defaults suit most people. + +## Receive and Menu bar (Mac) + +The **Receive** section shows **Save Received Files To**, with **Change…**, **Reset** and **Show in Finder**. On iOS, change the destination from the **Receive** screen instead. + +The **Menu bar** section has **Show in Menu Bar** (on by default) and **Open at Login** (off by default). **Open at Login** follows what macOS reports, so a change in System Settings > General > Login Items shows up here. If macOS needs your approval, an **Open Settings** button takes you to Login Items. See [Mac menu bar and keyboard shortcuts](menu-bar.md). + +## Relay + +By default CrocApp uses croc's public relay pool, the same one the croc command line uses. **Address** and **IPv6 Address** show "Public relay pool" when empty, and **Password** shows "Default". + +To use your own relay, run `croc relay` on a machine you control and enter its address, and its password if you set one. The other device must use the same relay. The app cannot run a relay itself. Reasons to run your own: your transfers route through infrastructure you control, or you would rather not depend on an external service. + +## Send as link + +**Link Server** holds the server for [Send as link](send-as-link.md). The default is `https://getcroc.com`, run by croc's author, not by CrocApp. **Reset to https://getcroc.com** appears once you change it. + +The address is checked as you type. It must use `https` (plain `http` is allowed only for `localhost`), and it can have nothing after the host name: no path, query or fragment. The server must speak croc's stored-transfer protocol. + +## Connection + +**Connection** chooses how a send carries large files. + +- **Automatic** (the default): a send of 128 MiB or more also tries a direct connection between the two devices, set up through `tailcat.dev`. That path uses its own relays (`*.ipn.dev`) when the devices cannot reach each other. It starts next to croc's relay, and whichever connects first carries the transfer. Smaller sends never start it. +- **Relay Only**: a send never contacts `tailcat.dev` or the `*.ipn.dev` servers. + +The data is end-to-end encrypted on every path. Only the sender's choice applies. A receive follows whatever the sender uses, so the picker has no effect when you receive, and a receive from a sender on Automatic can use those servers. The picker is disabled while **Local Network Only** is on. + +## Transfer + +- **Local Network Only**: transfers never use a relay on the internet. If a direct local connection cannot be made, the transfer fails instead of falling back. +- **Disable Compression**: sends file data uncompressed. +- **Zip Folders Before Sending**: packs a folder into one archive before sending. + +## Exclude from sends + +Type patterns in **Patterns, one per line** to skip matching files when you send a folder. **Respect .gitignore** also skips whatever your `.gitignore` would. + +## Confirmation + +- **Confirm on Both Sides**: the sender also approves each transfer, through the prompt **The other device is connected**, on top of the other device's accept step. It overrides **Auto-Accept Transfers**. +- **Auto-Accept Transfers**: off by default. When on, files from anyone who has your code are saved without a preview. Turn it on only for senders you fully trust. **When a File Already Exists** then decides between **Keep Both** (the default) and **Replace**. Unsafe file names still cancel the transfer. + +## Advanced + +![CrocApp Settings on macOS showing the Advanced tab with Curve, File Hash and the proxy fields](../../screenshots/mac/settings-advanced-light.webp#gh-light-mode-only)![CrocApp Settings on macOS showing the Advanced tab with Curve, File Hash and the proxy fields](../../screenshots/mac/settings-advanced-dark.webp#gh-dark-mode-only) + +**Advanced** holds croc options most people never need. Every default is croc's own. Each field checks what you type and shows a message under it. If a saved value is not usable, a transfer fails with "An Advanced setting can't be used" instead of falling back to something else. **Reset to Defaults** at the bottom puts every setting back after a confirmation, and removes the saved proxies. + +| Setting | Default | Affects | Does the other device have to match? | +|---|---|---|---| +| Curve | P-256 | Receiving | No: the sender uses the receiver's choice | +| File Hash | xxHash | Sending | No: the receiver uses the sender's choice | +| SOCKS5 Proxy | None | This device | No | +| HTTP Proxy | None | This device | No | +| Built-in DNS Resolver | Off | This device | No | +| Multicast Address (Mac only) | `239.255.255.250` | Both devices | Yes, to find each other on the local network | +| Sender IP | None | Receiving | No, but it must be the sender's address and base port | +| Send Speed Limit | No limit | Sending | No | +| Base Port | 9009 | Sending | Only if the other device connects by sender IP | +| Parallel Connections | 4 | Sending | No | +| Multiplexing | On | Sending | No: the receiver follows | + +**Security.** **Curve** is P-256, P-384, P-521, SIEC or Ed25519. **File Hash** is xxHash, imohash, MD5 or HighwayHash. + +**Network.** + +- **SOCKS5 Proxy** and **HTTP Proxy** send this device's connections through a proxy. Enter `host:port` or an address such as `socks5://user:password@host:1080` (SOCKS5 takes `socks5://` or `socks5h://`, HTTP takes `http://` or `https://`). If both are set, SOCKS5 wins. Connections to your local network skip the proxy. They also apply to [Send as link](send-as-link.md). A proxy address can contain a password, so CrocApp keeps both in the Keychain, never in the settings file or an error message. +- **Built-in DNS Resolver** looks up relay names with croc's own resolver instead of the system's. +- **Multicast Address** is the group croc uses to find devices on the local network. It must be an IPv4 multicast address, `224.0.0.0` to `239.255.255.255`. iOS needs an Apple entitlement for this that CrocApp does not have, so iOS always uses the default. +- **Sender IP** is for receiving. Enter the sender's address and port, such as `192.168.1.20:9009` or `[fe80::1]:9009`, and CrocApp connects straight to it, skipping relays and discovery. If nothing answers, the receive fails at once. It does not fall back to a relay. + +**Performance.** + +- **Send Speed Limit** caps this device's sending speed in bytes per second: digits with an optional `k`, `m` or `g`, such as `500k` or `2m`. +- **Base Port** and **Parallel Connections** set the ports the sender listens on: the base port, then one more per connection. With the defaults that is 9009 to 9013, and the last port must stay at or below 65535. They matter when the other device connects by sender IP, or when something else on your device uses those ports. +- **Multiplexing** off sends over one data connection. + +## The trust badge + +Waiting, confirming and transferring screens, and the home screen, show **End-to-end encrypted** with one line naming the route you configured: + +- "Local network only: nothing leaves your network" +- "Via custom relay `<address>`, which sees only encrypted data" +- "Via the public croc relay, which sees only encrypted data" +- "Straight to the sender, no relay in between" (a receive with **Sender IP** set) + +The badge reads your settings. It does not report which path carried the data. A transfer that croc moved over the local network, or over the direct connection under **Automatic**, can still say "Via the public croc relay". The statement that the server sees only encrypted data holds on every path. + +## About + +**About** shows the app version and links to the privacy policy and support page. + +## What is stored + +Settings are stored on the device. The relay password, the two proxies and Send as link receipts are in the Keychain. Nothing in Settings, no transfer content and no code phrase is sent anywhere except as part of a transfer you start. See [Uninstall and data](../uninstall.md) for where it all lives. diff --git a/web/docs/content/guide/shortcuts.md b/web/docs/content/guide/shortcuts.md index 1a4f4a6f..d54cc103 100644 --- a/web/docs/content/guide/shortcuts.md +++ b/web/docs/content/guide/shortcuts.md @@ -1,10 +1,10 @@ --- -sidebar_position: 9 -title: Shortcuts +sidebar_position: 8 +title: Shortcuts and Siri description: Three CrocApp actions for the Shortcuts app, Siri and Spotlight, to send files, send text and receive, and what each one returns. --- -# Shortcuts +# Shortcuts and Siri CrocApp adds three actions to the Shortcuts app on iPhone, iPad and Mac. Use them in your own shortcuts, or say or type the phrase in Siri and Spotlight. @@ -24,21 +24,17 @@ Both send actions use a generated code. They finish as soon as croc has a code, ## Receiving -**Receive with CrocApp** takes a croc code or any link CrocApp opens: a `crocapp://` link, a `crocapp.dev/r/` link, a `getcroc.com` link, or a [Send as link](stored-transfers.md) link. It waits until the transfer ends, then returns the received files and shows "Received N items." +**Receive with CrocApp** takes a croc code or any link CrocApp opens: a `crocapp://` link, a `crocapp.dev/r/` link, a `getcroc.com` link, or a [Send as link](send-as-link.md) link. It waits until the transfer ends, then returns the received files and shows "Received 3 items." (or "Received 1 item.") Received text comes back as a file named `Received text.txt`. -The action does not accept or decline for you. The prompt appears in CrocApp unless **Auto-Accept Transfers** is on in [Settings](power-options.md). If a received file has the same name as an existing one, the **When a File Already Exists** setting decides (Keep Both or Replace), and the action returns the new copies. +The action does not accept or decline for you. The prompt appears in CrocApp unless **Auto-Accept Transfers** is on in [Settings](settings.md#confirmation). If a received file has the same name as an existing one, the **When a File Already Exists** setting decides (Keep Both or Replace), and the action returns the new copies. ## One transfer at a time CrocApp runs one transfer at a time. If one is already running, the action fails with "CrocApp is already sending or receiving. Wait for it to finish." -## Finder Quick Action - -On a Mac, Shortcuts can offer a shortcut as a Quick Action in Finder. A shortcut that uses **Send Files with CrocApp** should work as one, with no extra setup. This has not been checked on a Mac yet. - ## See also -- [Sending files](sending.md) and [Receiving files](receiving.md) for the same flows in the app. -- [Menu bar](menu-bar.md) for sending from the Mac menu bar. +- [Send](sending.md) and [Receive](receiving.md) for the same flows in the app. +- [Mac menu bar and keyboard shortcuts](menu-bar.md) for sending from the Mac menu bar. diff --git a/web/docs/content/guide/stored-transfers.md b/web/docs/content/guide/stored-transfers.md deleted file mode 100644 index deae4d96..00000000 --- a/web/docs/content/guide/stored-transfers.md +++ /dev/null @@ -1,115 +0,0 @@ ---- -sidebar_position: 4 -title: Send as link -description: "Send encrypted files to a link server and share a link, so the other device can receive later without being online at the same time." ---- - -# Send as link - -**Send as Link** sends your files, encrypted on your device, to a link server and gives you a link. The other device opens the link and receives the files whenever it likes, until the link expires or runs out of downloads. You do not need to stay online, and the two devices never connect to each other. - -This is croc's *stored transfer* feature. The croc command line has the same feature, so the two work together. - -## When to use it instead of a code - -| | Code phrase | Send as link | -|---|---|---| -| Both devices online at the same time | Required | Not required | -| Devices that can receive | One per code | Up to the number of downloads you set | -| Folders and text | Yes | No, files only | -| Where the files rest | Nowhere, they travel through a relay or directly | On the link server until the link ends | -| End it early | Cancel while it runs | [Revoke](#history-and-revoking) at any time before it expires | - -Use a code phrase when both people are available now, or for folders and text. Use a link when the other device is not around, or when several people need the same files. - -## Sending - -1. Open **Send** and add files. -2. Turn on **Send as Link**. -3. Choose **Link Lasts**: **1 Hour**, **1 Day** (the default) or **7 Days**. -4. Set **Downloads allowed**, from 1 (the default) to 100. -5. Tap **Send as Link**. - -A line under the options names the link server the files will go to. While it runs, the screen reads **Sending** with progress and a note that the files are encrypted on this device. It shows no relay badge, because a link send does not use a relay. - -The **Send as Link** switch is disabled, with a line saying why, when text is selected or a folder is staged. Switch to **Files**, remove the folders, or send them with a code instead. The custom code field is hidden while **Send as Link** is on, since there is no code. - -The relay, **Connection** and **Local Network Only** settings do not apply to a link send. The SOCKS5 and HTTP proxies under [Advanced settings](advanced-settings.md#network) do apply, to sends, receives and revokes. If the server address in [Settings](#the-link-server-setting) is invalid, the Send screen shows the problem and **Send as Link** stays disabled. - -## The result screen - -When the send finishes, CrocApp shows **Link ready**, the time the link works until, and the number of downloads. Below that are: - -- a QR code of the link -- the link itself -- **Copy Link**, which puts the link on the clipboard -- **Share Link**, which opens the system share sheet - -CrocApp does not show the link again after you tap **Done**, and [History](history.md) never stores it. Copy or share it first. If you lose it, revoke the link from History and send again. - -On iOS, **Copy Link** keeps the link off Universal Clipboard, so it does not paste on your other Apple devices. The link contains the key, which is why. macOS offers no such option, so on a Mac CrocApp cannot keep the copied link off Universal Clipboard. - -Anyone who has the whole link can open the files until it ends. Send it over a channel you would trust with the files. - -## Receiving - -In **Receive**, paste the link with the **Paste** button, type or paste it into the field, or on iOS tap **Scan QR Code** and scan the QR code from the result screen. The code field is replaced by a **Receive from Link** row with the link server's host name and a **Clear** button. Nothing is fetched until you tap **Receive**. - -CrocApp then fetches the file list and shows it for review. Choose **Accept**, or **Keep Both** or **Replace** if a file with the same name already exists, exactly as in [Receiving files](receiving.md#overwrite-and-conflicts). Auto-accept never applies to a link: you always see the file list first. The progress screen reads **Receiving**. - -The phone's Camera app does not open CrocApp for these links. They point at the link server, and CrocApp's universal links cover only `crocapp.dev/r/`. A camera scan opens the link server's own page in the browser. In CrocApp use **Scan QR Code** or paste the link. - -### Receiving in a browser - -Opening the link in any browser shows the link server's own page. For the default server that is a getcroc.com page run by croc's author, not by CrocApp. The key is in the part of the link after the `#`, which browsers do not send to a server, so the page decrypts in your browser. That means a browser receive depends on the page the link server serves, in the same way as [receiving a code in a browser](code-phrases.md#receiving-a-link). To avoid that dependency, receive in CrocApp or the croc CLI. - -A link that has expired, been revoked or run out of downloads says so in CrocApp: "This link has expired, was revoked, or has no downloads left." - -## History and revoking - -A link send appears in [History](history.md) with the link server's host name and one of: - -- **Link expires** and the time, while it is live -- **Link expired** and the time -- **Link revoked** and the time - -Choose **Revoke Link** to end it early. On macOS use the row's context menu. On iOS use the context menu (touch and hold) or swipe the row left and tap **Revoke**. A confirmation asks "Revoke this link?" and says the files are deleted from the link server and the link stops working for everyone. If the link server no longer has the files, CrocApp treats the revoke as done. - -**Revoke Link** appears only while the link is live and this device still holds the receipt for the send. A transfer you received, or a link that has already expired, has nothing to revoke. Deleting a History row, or clearing History, removes the place you revoke from, so revoke first if you want the link ended. - -## The link server setting - -Under the **Send as Link** section of Settings (the Settings scene on macOS, the settings screen on iOS), the **Server** field holds the link server. The default is `https://getcroc.com`, run by croc's author, not by CrocApp. A **Reset** button appears once you change it. - -The address is checked as you type: - -- It must use `https`. Plain `http` is allowed only for `localhost` (including `127.0.0.1` and `::1`). -- It must be the address only: nothing after the host name, no path, query or fragment. - -The link server must speak croc's stored-transfer protocol. The link server you send to decides how long it keeps files and which limits it enforces. The link server in a received link is the one in the link, whatever your setting says. - -## Limits - -CrocApp refuses, before sending, a send of more than 100 files, more than 1 GiB in total, or more than 100 downloads allowed. Those are croc's defaults. A link server with lower limits, or one that rate-limits sends, can still refuse, and CrocApp then says the server refused it for size, file count, download limit, or too many recent sends. - -Only regular files go in a link. Folders and text do not. - -## Privacy - -The files are encrypted on your device before they reach the link server, and the key travels in the link's `#` fragment, which browsers never send to a server. CrocApp makes no network request for a link send except to the link server in Settings. - -The link server sees the size of the encrypted data, the lifetime and download count you chose, and the usual details of any web request, such as your IP address and the time. CrocApp has not verified whether the link server can read file names, so do not rely on names being hidden. - -Anyone who has the whole link can decrypt the files, so treat the link itself with care. - -On your device: - -- [History](history.md) keeps only the link server's host and the transfer id for a link send, never the link or the token that revokes it. -- The receipt, which holds that token and the link, lives only in the iOS or macOS Keychain. CrocApp removes it when you revoke and at the first launch after the link expires. -- See [Security and privacy](../security-and-privacy.md) for the full list of what CrocApp can contact. - -## If iOS interrupts a send - -A link send is wrapped in iOS background processing, so it can continue when you leave the app, but iOS may stop it. If it does, CrocApp says iOS stopped it in the background and asks you to try again. A link send cannot resume, so trying again starts over from the beginning and produces a new link. If iOS stops a receive from a link, open the link again. - -Keep the app in the foreground for a large send if you can. diff --git a/web/docs/content/index.md b/web/docs/content/index.md index 4bbe7213..da816b60 100644 --- a/web/docs/content/index.md +++ b/web/docs/content/index.md @@ -1,43 +1,29 @@ --- slug: / sidebar_position: 1 -title: CrocApp documentation +sidebar_label: Overview +title: Documentation description: Send files, folders and text to another device with a short code phrase. Free, open source and end-to-end encrypted. --- # CrocApp documentation -![CrocApp's first-run welcome screen on iOS, explaining the code phrase in three lines](/img/screenshots/iphone/onboarding-light.png#gh-light-mode-only)![CrocApp's first-run welcome screen on iOS, explaining the code phrase in three lines](/img/screenshots/iphone/onboarding-dark.png#gh-dark-mode-only) +![The first-run welcome screen on iOS, explaining the code phrase in three lines](../screenshots/iphone/onboarding-light.webp#gh-light-mode-only)![The first-run welcome screen on iOS, explaining the code phrase in three lines](../screenshots/iphone/onboarding-dark.webp#gh-dark-mode-only) -CrocApp sends files, folders and text to another device with a short code phrase like `cape-junky-widow`. Transfers are end-to-end encrypted. There is no account, and the two devices do not need to share a network. +CrocApp sends files, folders and text to another device with a short code phrase like `cape-junky-widow`. There is no account, and the two devices do not need to share a network. It runs on iPhone, iPad and Mac. -It is a graphical front end for [croc](https://github.com/schollz/croc), the command-line file-transfer tool by Zack Scholl. CrocApp embeds croc's Go library rather than shelling out to the binary, so a code phrase from the croc CLI works in the app, and a code phrase from the app works in the CLI. +It is a graphical front end for [croc](https://github.com/schollz/croc), the command-line file-transfer tool by Zack Scholl. A code phrase from the croc command line works in the app, and the other way round. -:::note -CrocApp is unofficial and unaffiliated. Nothing here implies endorsement by croc's author. -::: - -## How it works, in short - -The sender picks files, a folder or a snippet of text. CrocApp generates a code phrase, which can be spoken, messaged or shown as a QR code. The other device enters the phrase, sees the file list and accepts. The code phrase authenticates both devices (PAKE, password-authenticated key exchange), and the transfer is end-to-end encrypted. The relay only ever sees ciphertext. When the two devices connect over the local network, the data stays on that network. +## Start here -## Platform requirements +- [Requirements and install](getting-started/install.md): get the app and check your device is supported. +- [Your first transfer](getting-started/first-transfer.md): one send and one receive, step by step. +- [Code phrases and links](guide/code-phrases.md): share a code by voice, QR code or link. +- [Troubleshooting](troubleshooting.md): a transfer that will not connect. +- [Security and privacy](security-and-privacy.md): what is protected, and what each server sees. -CrocApp requires **iOS 26**, **iPadOS 26**, or **macOS 26**, meaning `26.0` or any later version. It is Apple-platform only: there is no Windows, Linux or Android client. +The sidebar lists the rest. The [FAQ](faq.md) has short answers and a glossary. :::note -The other device needs **croc 11 or newer**, whether it runs CrocApp or the croc CLI. croc 10 cannot complete a transfer with CrocApp. +CrocApp is unofficial and unaffiliated with croc. Nothing here implies endorsement by croc's author. ::: - -CrocApp is available as a notarized disk image for Mac. Apps for iPhone and iPad and a Mac App Store version are coming to the App Store. See [Install](getting-started/install.md) for where to get each one. - -## Where to go next - -- [Install](getting-started/install.md): the three channels, updates, and how to build from source -- [Your first transfer](getting-started/first-transfer.md): a walkthrough of one send and one receive -- [Sending files](guide/sending.md), [Receiving files](guide/receiving.md), [Code phrases](guide/code-phrases.md), [Send as link](guide/stored-transfers.md) -- [Power options](guide/power-options.md), [Advanced settings](guide/advanced-settings.md), [Settings and trust](guide/settings-and-trust.md), [History](guide/history.md) -- [Menu bar](guide/menu-bar.md) and [Shortcuts](guide/shortcuts.md) -- [croc CLI interoperability](reference/croc-cli-interop.md) and the [feature matrix](reference/feature-matrix.md) -- [Security and privacy](security-and-privacy.md), [Troubleshooting](troubleshooting.md), [FAQ](faq.md) -- [Contribute](contribute.md) diff --git a/web/docs/content/reference/_category_.json b/web/docs/content/reference/_category_.json deleted file mode 100644 index c6a8dbd9..00000000 --- a/web/docs/content/reference/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "Reference", - "position": 4, - "link": { - "type": "generated-index", - "description": "croc CLI interoperability, the full feature matrix, and a user-facing glossary." - } -} diff --git a/web/docs/content/reference/croc-cli-interop.md b/web/docs/content/reference/croc-cli-interop.md index 4a3bd2e6..ad472c15 100644 --- a/web/docs/content/reference/croc-cli-interop.md +++ b/web/docs/content/reference/croc-cli-interop.md @@ -6,7 +6,7 @@ description: CrocApp embeds croc v11.5.4 as a Go library, so a code phrase gener # croc CLI interoperability -CrocApp embeds **croc v11.5.4** as a Go library (via a `gomobile`-built framework) rather than shelling out to the `croc` binary. That means it speaks the exact same protocol as the CLI, in both directions. +CrocApp embeds **croc v11.5.4** as a Go library rather than shelling out to the `croc` binary. That means it speaks the exact same protocol as the CLI, in both directions. :::note The other device needs croc 11 or newer. A croc 10 device cannot complete a transfer with CrocApp. @@ -41,7 +41,7 @@ Both devices need to agree on the relay. From the CLI: croc --relay myserver:9009 send file.txt ``` -In CrocApp, set the same address under the [relay power option](../guide/power-options.md). +In CrocApp, set the same address under **Relay** in [Settings](../guide/settings.md#relay). ## Connection and `--transport` @@ -51,32 +51,27 @@ The **Connection** setting maps to croc's `--transport` flag: **Automatic** is ` croc send --transport relay file.txt ``` -For a send under 128 MiB, the two settings behave the same. See [power options](../guide/power-options.md) for what **Automatic** does above that size. +For a send under 128 MiB, the two settings behave the same. See [Settings](../guide/settings.md#connection) for what **Automatic** does above that size. -## Feature-to-flag mapping +## Settings and croc flags -| Feature | croc flag / origin | +| In CrocApp | croc flag | |---|---| -| Send files (multi) | positional args | -| Send folders | positional args | -| Send text/clipboard | `--text` | -| Receive via code | positional args | -| Custom code phrase (min 6 chars) | `--code` | -| QR show on send / scan on receive | `--qrcode` | -| Choose output folder | `--out` | -| Keep Both / Replace on receive | `--rename` (Keep Both), `--overwrite` (Replace) | -| File list preview, then accept or decline | interactive prompt | -| Progress, speed, cancel | none | -| Local network and relay race | croc default | -| Transfer history | none | -| Custom relay, password, IPv6 | `--relay --relay6 --pass` | -| Force local-only | `--local` | -| Disable compression | `--no-compress` | -| Zip folder before send | `--zip` | -| Exclude patterns / `.gitignore` | `--exclude --git` | -| Auto-accept toggle | `--yes` | -| Both-sides confirm | `--ask` | -| Connection: Automatic or Relay only | `--transport auto\|relay` | +| Custom code phrase (at least 6 characters) | `--code` | +| Send text or clipboard | `--text` | +| QR code on send and scan on receive | `--qrcode` | +| Receive folder | `--out` | +| **Keep Both** and **Replace** | `--rename` and `--overwrite` | +| Relay **Address**, **IPv6 Address**, **Password** | `--relay`, `--relay6`, `--pass` | +| **Connection**: **Automatic** or **Relay Only** | `--transport auto\|relay` | +| **Local Network Only** | `--local` | +| **Disable Compression** | `--no-compress` | +| **Zip Folders Before Sending** | `--zip` | +| **Patterns, one per line** and **Respect .gitignore** | `--exclude` and `--git` | +| **Auto-Accept Transfers** | `--yes` | +| **Confirm on Both Sides** | `--ask` | + +The file list preview, progress and history are CrocApp's own. The croc command line has no equivalent. ## Version and relay compatibility diff --git a/web/docs/content/reference/feature-matrix.md b/web/docs/content/reference/feature-matrix.md deleted file mode 100644 index 4108a990..00000000 --- a/web/docs/content/reference/feature-matrix.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -sidebar_position: 2 -title: Feature matrix -description: Every CrocApp feature, grouped and marked with its ship status. ---- - -# Feature matrix - -"Shipped" means the feature is in CrocApp 1.0 (see [Install](../getting-started/install.md) for where to get it). - -## Core (shipped) - -| Feature | croc flag / origin | -|---|---| -| Send files (multi) | positional args, drag-drop + file picker | -| Send folders | positional args | -| Send text/clipboard | `--text` | -| Receive via code | positional args | -| Custom code phrase (min 6 chars) | `--code` | -| QR show on send + QR scan on receive | `--qrcode` + GUI-native | -| Choose output folder; iOS default is a Files-visible app folder | `--out` | -| Keep Both / Replace on receive, resume with Replace | `--rename` (Keep Both), `--overwrite` (Replace) + resume | -| File list preview, then accept or decline | interactive prompt equivalent | -| Progress, speed, cancel; Live Activity on iOS | polled from engine | -| Local network and relay race | croc default | -| Transfer history (local only) | GUI-native | - -## Power options (shipped) - -| Feature | croc flag | -|---|---| -| Custom relay + password + IPv6 | `--relay --relay6 --pass` | -| Force local-only | `--local` | -| Disable compression | `--no-compress` | -| Zip folder before send | `--zip` | -| Exclude patterns / respect `.gitignore` | `--exclude --git` | -| Auto-accept toggle (off by default, warning shown) | `--yes` | -| Both-sides confirm | `--ask` | -| Connection: Automatic or Relay only (the sender's choice applies, a receive follows it) | `--transport auto\|relay` | -| SOCKS5 proxy (Settings > Advanced) | `--socks5` | -| HTTP proxy | `--connect` | -| Send speed limit (sender-side) | `--throttleUpload` | -| Curve choice (the receiving device's choice wins; the sender adopts it) | `--curve` | -| Hash algorithm choice (sender-side) | `--hash` | -| Sender IP, direct connect (receive-side) | `--ip` | -| Custom multicast address (macOS only: iOS has no multicast entitlement) | `--multicast` | -| Base port, parallel connections, multiplexing toggle (sender-side) | `--port --transfers --no-multi` | -| Built-in DNS resolver | `--internal-dns` | - -## GUI-native (shipped) - -| Feature | Status | -|---|---| -| Share extension (send from any app) | shipped, iOS only | -| Receive links: `crocapp://` scheme, `crocapp.dev/r/` universal links, and `croc://` QR codes from earlier builds | shipped | -| Trust UI: end-to-end badge, "how it works", active-relay indicator | shipped | -| Share Link, a QR code that is a web link, and a `crocapp.dev/r/` page with an option to receive in a browser | shipped | -| Send as link: files encrypted on your device and sent to a link server, a link with a chosen lifetime and number of downloads, receive from the link, and revoke from History | shipped | -| macOS menu bar quick send: drop or choose files, or send clipboard text, from a menu-bar window; Show in menu bar and Open at login settings (see [Menu bar](../guide/menu-bar.md)) | shipped, macOS only | -| Shortcuts and Siri actions: Send Files, Send Text and Receive with CrocApp (see [Shortcuts](../guide/shortcuts.md)) | shipped | -| iPad File menu: Show Receive Folder in Files | shipped, iPad only | - -## After 1.0, not started - -None of these are built yet. - -| Feature | croc flag / origin | -|---|---| -| Run own relay from Mac app (menu-bar relay) | `croc relay` | -| Saved codes / favorite devices | GUI-native | -| Relay health check + diagnostics screen | GUI-native | - -## Later - -| Feature | Note | -|---|---| -| Wi-Fi Aware direct path | iOS/iPadOS 26 only, absent on macOS 26; app-to-app fast path | - -## Deliberately left out - -| Feature | Reason | -|---|---| -| `--stdout` piping | CLI-only concept | -| `--classic` mode | weaker by design | -| `--remember` | GUI settings persist anyway | diff --git a/web/docs/content/reference/glossary.md b/web/docs/content/reference/glossary.md deleted file mode 100644 index dabe1ff3..00000000 --- a/web/docs/content/reference/glossary.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -sidebar_position: 3 -title: Glossary -description: User-facing terms used throughout the CrocApp documentation. ---- - -# Glossary - -| Term | Means | -|---|---| -| Code phrase | The `word-word-word` string both devices use to find each other and to authenticate. Custom codes are at least 6 characters. | -| PAKE | Password-authenticated key exchange. The protocol that lets the code phrase authenticate both devices. | -| Link | A `https://crocapp.dev/r/#<code>` address that carries a code phrase after the `#`. The QR code on the sender's screen and **Share Link** are this link. Opening one fills in **Receive** and never connects by itself. | -| Relay | The machine both devices connect to when a direct local-network path is not available. It only ever sees ciphertext. | -| Room | The rendezvous channel on the relay, derived from the first word of the code phrase. Two codes sharing that word can collide into the same room. | -| Curve | The elliptic curve PAKE runs over. CrocApp uses croc's default, P-256; the receiving device's choice wins and the sender adopts it, so the devices never have to match (see [Advanced settings](../guide/advanced-settings.md)). | -| Sender IP | The sender's address and port, entered on the receiving device to connect straight to it and skip relays. See [Advanced settings](../guide/advanced-settings.md#network). | -| Hash algorithm | The integrity check used on transferred files. | -| Local network discovery | How two devices on the same network find each other without the relay; not guaranteed to work on every network. | -| Connection | The setting that chooses how a send carries large files: Automatic (default) or Relay only. Only the sender's choice applies; a receive follows it. | -| Tailcat | The direct connection that Automatic can use for a send of 128 MiB or more. It is set up through `tailcat.dev` and falls back to its own relays when the devices cannot reach each other. Still end-to-end encrypted. | -| Local network only | A setting that keeps a transfer on the local network and refuses the relay if a direct path is not available. | -| Link server | The server that holds the encrypted files of a [Send as link](../guide/stored-transfers.md) transfer until the link ends. By default `https://getcroc.com`, run by croc's author. | -| Compression | File data is compressed by default in transit; it can be turned off. | -| Menu bar quick send | The CrocApp icon in the Mac menu bar. Its window sends files or clipboard text and shows the code and progress. See [Menu bar](../guide/menu-bar.md). | -| Shortcuts action | One of three CrocApp actions (Send Files, Send Text, Receive) for the Shortcuts app, Siri and Spotlight. See [Shortcuts](../guide/shortcuts.md). | -| Trust badge | The on-screen indicator showing that a transfer is end-to-end encrypted and which relay path it is using. | -| Transfer history | CrocApp's local, on-device-only log of past transfers. | - -For the full contributor and internals glossary (croc protocol internals, the Go/gomobile bridge, app architecture, and repo conventions), see [`docs/GLOSSARY.md`](https://github.com/bakirgdev/CrocApp/blob/main/docs/GLOSSARY.md) on GitHub. diff --git a/web/docs/content/security-and-privacy.md b/web/docs/content/security-and-privacy.md index 131d9ce8..fb61f1b2 100644 --- a/web/docs/content/security-and-privacy.md +++ b/web/docs/content/security-and-privacy.md @@ -1,49 +1,77 @@ --- -sidebar_position: 5 +sidebar_position: 3 title: Security and privacy -description: What CrocApp guarantees, what it does and does not collect, and how to report a vulnerability. +description: What CrocApp claims about security, how a transfer is protected, what each server can see, and how to report a vulnerability. --- # Security and privacy -## What CrocApp guarantees +## What CrocApp claims -Transfers are end-to-end encrypted, the code phrase authenticates both devices (PAKE), and the relay only ever sees ciphertext. That is the whole claim. +These six statements are the entire claim: + +1. Transfers are end-to-end encrypted. +2. The code phrase authenticates both devices (PAKE). +3. The relay only ever sees ciphertext. +4. Send as link: files are encrypted on your device before they reach the link server, and the key travels in the link's `#` fragment, which browsers never send to a server. +5. When the two devices connect over the local network, the data stays on that network. +6. CrocApp has no accounts, analytics, ads or tracking, and history stays on the device. :::warning CrocApp has **not had a formal third-party security audit**. Do not treat it as audited or certified. ::: -## How it works +## How a transfer is protected + +Both devices run PAKE (password-authenticated key exchange) with the code phrase. That proves both sides know the same phrase, and turns it into a strong encryption key. The phrase itself never crosses the network, and a wrong code fails at once. Files are encrypted on your device and decrypted only on the other one. + +CrocApp tries the local network and the relay at once, and the faster one carries the transfer. When the two devices cannot connect directly, a relay forwards the encrypted stream and sees only ciphertext. By default that is one of croc's public relays. You can [run your own](guide/settings.md#relay). + +Every transfer uses a fresh code. Whoever has it before the transfer completes can join, so share it over a channel you trust. A `crocapp.dev/r/#<code>` link keeps the code after the `#`, which browsers never send to a server. The page makes no network request and sets a `no-referrer` policy. Anyone who sees the link still has the code. + +For a send of 128 MiB or more under **Connection** > **Automatic**, CrocApp also tries a direct connection set up through `tailcat.dev`. It is end-to-end encrypted too. See [Settings](guide/settings.md#connection). + +You stay in control: a receive shows the file list and waits for you to accept or decline, unless you turn on **Auto-Accept Transfers**. -- **One code, one transfer.** Every transfer uses a fresh code phrase. Whoever has the code can join the transfer, so share it over a channel you trust. -- **The code phrase authenticates both devices.** Both devices run PAKE (password-authenticated key exchange) with the code phrase. A wrong code fails immediately. -- **End-to-end encrypted.** Everything is encrypted on your device and decrypted on the other one. -- **The relay only ever sees ciphertext.** When the two devices cannot connect directly, an internet relay forwards the encrypted stream. You can also run your own relay and set it in Settings. -- **A direct connection for large files.** With the default **Automatic** connection setting, a send of 128 MiB or more also tries a direct connection, set up through `tailcat.dev`, with its own relays (`*.ipn.dev`) when the devices cannot reach each other. Whichever path connects first carries the transfer, and it is end-to-end encrypted on either path. Those servers are contacted only for such a send. Choose **Relay Only** under [power options](guide/power-options.md) and your sends never contact them. A receive follows the sender's choice, so receiving a large file from a sender on Automatic (or the croc CLI's default) can use them. -- **The local network.** When the two devices connect over the local network, the data stays on that network. The local connection and the relay race, and the faster one wins. -- **Send as link.** [Send as link](guide/stored-transfers.md) encrypts the files on your device before they reach the link server, and the key travels in the link's `#` fragment, which browsers never send to a server. The link server is the one named in Settings, by default `https://getcroc.com`, run by croc's author and not by CrocApp. A link send contacts that server and nothing else. Anyone with the whole link can decrypt the files, and you can revoke the link from [History](guide/history.md). -- **Links carry the code in the fragment.** A `https://crocapp.dev/r/#<code>` link keeps the code after the `#`, which browsers never send to a server. The page at that address makes no network request and sets a `no-referrer` policy. Anyone who sees the link still has the code, so share it the way you would share the code. -- **You stay in control.** A receive shows the file list and waits for you to accept or decline. Auto-accept is off unless you turn it on. +## What each server sees + +| Server | When | What it can see | +|---|---|---| +| croc public relays (`1.getcroc.com` to `4.getcroc.com`) | Every transfer with a code, unless you use your own relay or **Local Network Only** | Both devices' IP addresses, timing, amount of data, and a room name hashed from the code's first word. The data is ciphertext | +| Link server (`getcroc.com` by default) | **Send as Link**, and opening or revoking a link | The encrypted files and their size, the lifetime and download count you chose, and your IP address | +| `tailcat.dev` and `*.ipn.dev` | A send of 128 MiB or more under **Automatic**, and a receive from such a sender | Both devices' IP addresses, timing and the size of encrypted packets. The data is ciphertext | +| `github.com` | Update checks in the Mac disk image build only | The usual details of a web request. The request carries no system profile | + +An operator decides what its own server logs, so this is what each can see by design. The [privacy policy](https://crocapp.dev/privacy/) has the full list, including servers you choose yourself. + +## Send as link + +Files are encrypted on your device before they reach the link server. The key travels in the link's `#` fragment, which browsers never send to a server. The default link server, `https://getcroc.com`, is run by croc's author, not by CrocApp. Anyone with the whole link can decrypt the files, and you can revoke the link from [History](guide/history.md). See [Send as link](guide/send-as-link.md). ## Receiving in a browser -The link page offers **Receive in Your Browser**, which opens `https://getcroc.com/?code=<code>`. That is croc's own web app, not run by CrocApp. The code travels in the query string there, so it reaches getcroc.com's server. The browser path also depends on getcroc.com fully, because getcroc.com serves the JavaScript that decrypts the file. It reaches only croc's default relays. The CrocApp and croc CLI paths do not have this dependency. If that is more than you want to depend on, receive in CrocApp. +The link page offers **Receive in Your Browser**, which opens `https://getcroc.com/?code=<code>`. That is croc's own web app, not run by CrocApp. + +- The code is in the query string, so it reaches the getcroc.com server, along with your IP address. +- getcroc.com serves the JavaScript that decrypts the file, so this path trusts that site fully. +- That site's own pages also load third-party analytics and advertising scripts (Umami and Google AdSense when last checked), which CrocApp does not control. +- It reaches only croc's default relays. + +The CrocApp and croc command line paths have none of these dependencies. If that is more than you want to trust, receive in CrocApp. ## Privacy - CrocApp has no accounts, analytics, ads or tracking. -- History stays on the device. See [History](guide/history.md) for exactly what it records. -- You can point CrocApp at your own croc relay instead of the default public one. -- The disk image build checks github.com for updates through Sparkle and installs only updates whose signature matches the key built into the app. It sends no system profile. See [Verify a release](verify-downloads.md) for how to check a release. The App Store builds contain no updater. -- Dependencies in the Go engine (`crocmobile/`) are scanned by `govulncheck` in CI when the Go code or the Go CI workflows change, and on a weekly schedule. +- [History](guide/history.md) stays on the device and never stores file contents or the full code phrase. +- The Mac disk image checks github.com for updates and installs only updates signed with the key built into the app. The App Store builds contain no updater. See [Verify a release](getting-started/verify-downloads.md). +- The camera is used only to scan a QR code, and nothing is saved. -The [privacy policy](https://crocapp.dev/privacy/) lists every server CrocApp can contact, what each one can see, and how long a link send is kept. +For where data lives and how to remove it, see [Uninstall and data](uninstall.md). -## Reporting a vulnerability +## Report a vulnerability Report privately through [GitHub Security Advisories](https://github.com/bakirgdev/CrocApp/security/advisories/new). Never open a public issue, discussion or pull request for a suspected vulnerability. -Useful to include: what an attacker gains and what access they would need, reproduction steps (code phrase flow, relay, platform), the CrocApp version or commit plus OS version and device, and whether the same behavior reproduces with the upstream `croc` CLI. +Useful to include: what an attacker gains and what access they need, steps to reproduce (code phrase flow, relay, platform), the CrocApp and OS versions and device, and whether the upstream `croc` command line behaves the same. -Full policy, scope, and what is out of scope (the transfer protocol itself belongs to croc upstream): [`SECURITY.md`](https://github.com/bakirgdev/CrocApp/blob/main/SECURITY.md) on GitHub. +The full policy, scope, and what is out of scope (the transfer protocol itself belongs to croc upstream) is in [`SECURITY.md`](https://github.com/bakirgdev/CrocApp/blob/main/SECURITY.md). diff --git a/web/docs/content/troubleshooting.md b/web/docs/content/troubleshooting.md index 9249768d..029beb36 100644 --- a/web/docs/content/troubleshooting.md +++ b/web/docs/content/troubleshooting.md @@ -1,57 +1,73 @@ --- -sidebar_position: 6 +sidebar_position: 1 title: Troubleshooting -description: "Fixes for common CrocApp problems: stalled transfers, rejected codes, backgrounding limits and permission issues." +description: "Fixes for common CrocApp problems: a transfer that never connects, a rejected code, permission prompts, interrupted transfers and missing files." --- # Troubleshooting -## Transfer stalls or never connects +## The transfer never connects -CrocApp races a direct local-network connection against the relay and uses whichever connects first. Finding devices on the local network uses UDP multicast, and it is not guaranteed to work on every network. Some networks (client-isolation-style Wi-Fi, for example) hide other devices entirely, even though the relay path still works. If a transfer stalls at "Waiting" or "Connecting": +CrocApp tries the local network and the relay at once and uses whichever connects first. Finding devices on the local network uses UDP multicast, which some networks block, such as guest Wi-Fi with client isolation. The relay path still works there, so: -- Check that both devices have working internet access, so the relay path can work even if the local path can't. -- Check the [local network permission](#local-network-permission-prompt) below. -- There is no in-app fix for a network that blocks multicast discovery outright. The transfer should still complete over the relay. +- Check that both devices have internet access. +- Check the [local network permission](#local-network-access-is-off). +- Start the sender first, then the receiver (see below). +- If you see "This is taking longer than usual", double-check the code and make sure the other device is ready. -## Code rejected or the receive button stays disabled +## The receiver started first -- A code phrase must be at least 6 characters. The **Receive** button stays disabled until you've entered enough. -- A wrong code fails immediately rather than hanging. -- If you're using a custom code you also use for testing or scripting, note that codes sharing their first word can collide into the same relay room. Generated codes rarely do: two share a first word about once in 1296. +If the receiver joins before the sender has started, the receive can fail with a generic "Transfer failed. Try again, or check your connection." This hits custom codes, and the croc command line sending with a fixed code. Start the sender, then the receiver. + +## No internet + +With no connection, a send with a generated code fails before a code appears, with "No public relay answered. Check your internet connection, or turn on Local Network Only in Settings if both devices are on the same network." Reconnect, or turn on **Local Network Only** in [Settings](guide/settings.md#transfer) when both devices share a network. + +If only croc's public relay is unreachable from your network, set a [custom relay](guide/settings.md#relay) you control, or use **Local Network Only**. + +## The code is rejected, or Receive stays disabled + +- A code needs at least 6 characters. **Receive** stays disabled until it has them. +- A wrong code fails at once with "The codes don't match." +- "That code is already in use. Try a different code." means another transfer holds that custom code. Pick another. +- Codes that start with the same word can land in the same relay room. Generated codes rarely collide. ## A link or QR code does not open CrocApp -- A link only fills in the code on **Receive**; nothing connects until you tap **Receive**. If a transfer is already running, the link is kept and CrocApp does not move you away from it. -- If the phone camera opens `crocapp.dev/r/` in the browser instead of the app, CrocApp is not installed, or iOS has not opened the link in it. Tap **Open in CrocApp** on that page, or copy the link into the **Receive** field. -- On Mac, a link may open the page in the browser rather than the app; **Open in CrocApp** on the page still works. -- **Receive in Your Browser** fails if the sender uses a custom relay or **Local Network Only**. The browser client knows only the default relays; receive in CrocApp instead. +- A link only fills in the code. Tap **Receive** to connect. If a transfer is already running, CrocApp keeps the link and stays on that transfer. +- If the phone camera opens `crocapp.dev/r/` in the browser, CrocApp is not installed or iOS did not hand the link over. Tap **Open in CrocApp** on that page, or copy the link into the **Receive** field. +- On a Mac the link may open in the browser. **Open in CrocApp** on the page still works. +- **Receive in Your Browser** fails when the sender uses a custom relay or **Local Network Only**. The browser client knows only the default relays. +- A [Send as link](guide/send-as-link.md) QR code does not open CrocApp from the Camera app. Use **Scan QR Code** inside CrocApp. + +## The other device uses an older croc -## The other device uses a different croc version +The other device needs croc 11 or newer. When both sides reach the same relay, CrocApp says "The other device runs an older croc. Both sides need croc 11 or newer." Often it does not: with a generated code, or when the two use different relays, the app keeps waiting. If a transfer with a croc 10 user never connects, ask them to upgrade. -CrocApp embeds croc v11.5.4 as its engine. It's built to interoperate with the `croc` CLI in both directions. The other device needs croc 11 or newer: croc 10 cannot complete a transfer with the app. When both sides reach the same relay, the app says the other device runs an older croc. Often it does not (with a generated code, or when the two use different relays), and the app just keeps waiting for the other device, so if a transfer with a croc 10 user never connects, ask them to upgrade to croc 11. +## Local network access is off -## iOS backgrounding limits +The first time CrocApp needs the local network, the system asks for permission. If you refuse it, or the permission seems stuck (an iOS quirk where a granted permission does not work until you toggle it or restart), CrocApp falls back to the relay and shows **Local network access is off**. Tap **Open Settings** and turn on CrocApp under Privacy & Security > Local Network. This applies on iOS and on Mac. -iOS does not allow raw TCP transfers to keep running arbitrarily in the background. CrocApp uses `BGContinuedProcessingTask` (iOS 26+) to keep a transfer going and show a system Live Activity, but it's best-effort: the system can end it under memory pressure, and a low-progress transfer is more likely to be killed than a nearly-finished one. For a transfer you don't want interrupted, keep CrocApp in the foreground until it finishes. If it does get cut off, croc's own resume behavior means restarting the same transfer picks up from where it left off rather than starting over, as long as you choose **Replace** for the partly received files. **Keep Both** saves the partly received file as a new copy instead of resuming it. +## Scan QR Code does not work -## Local network permission prompt +On iOS, scanning needs camera access. If you refused it, CrocApp shows "Camera access denied". Tap **Open Settings** and allow it. If it says "Camera access restricted", a parental control or device policy blocks it, and Settings cannot change that. Type or paste the code instead. -On first local-network use, iOS shows a system prompt asking to allow CrocApp to find devices on your local network. If you deny it, or the grant ends up "stuck" (a known iOS quirk where a granted permission does not work until you toggle it or reboot), CrocApp falls back to the relay only. If you see the banner **Local network access is off**, use its **Open Settings** button to check Settings > Privacy > Local Network. +## A transfer stopped in the background -## Received files not visible where expected +On iOS, a transfer keeps running when you leave the app and shows a Live Activity, but iOS can stop it, more likely for a transfer with little progress. Keep CrocApp in the foreground for a transfer you do not want interrupted. -- On iOS, received files land in the app's Documents folder, which is visible in the Files app by default. -- If your receive destination was set to a folder picked through a cloud-storage provider (rather than a local location), the **Open in Files** button after a receive may not open it correctly. This is a known limitation. Navigate to the folder manually in the Files app instead. +To resume, start the same transfer again and choose **Replace** for the partly received files. **Keep Both** saves a new copy instead of resuming. -## Relay unreachable +## Received files are not where I expect -CrocApp uses croc's public relay by default. If it's unreachable from your network, you can set a [custom relay](guide/settings-and-trust.md) you control instead, or turn on **Local Network Only** if both devices are on the same network and you don't need the relay at all. +- On iOS, files land in the app's Documents folder, visible in the Files app. +- **Open in Files** appears only when the destination is that default folder. For a folder you picked, such as one in cloud storage, open it from the Files app. +- On a Mac, the default is `Downloads/CrocApp`. **Show in Finder** or ⇧⌘R opens it. -## Auto-accept and `--ask` senders +## Auto-accept and a sender who confirms -If you have auto-accept on and the sender is using croc's `--ask` confirmation flag, the transfer can be auto-declined. CrocApp's message currently says the other device declined, rather than explaining that your own auto-accept setting caused it. This is a known issue with no fix yet; turning off auto-accept avoids it. +With **Auto-Accept Transfers** on and a sender using croc's `--ask` option, the transfer can be declined, and CrocApp says the other device declined. Turn off auto-accept to avoid it. -## No cancel button while reviewing a receive +## Still stuck -Once you are looking at the file list, **Decline** is the only way out. There is no separate cancel button at that stage, and the transfer-ended notification can lag slightly while croc finishes reconnect attempts underneath. This is expected behavior, not a bug. +Ask on [GitHub Discussions](https://github.com/bakirgdev/CrocApp/discussions), or see [Support](https://crocapp.dev/support/). diff --git a/web/docs/content/uninstall.md b/web/docs/content/uninstall.md new file mode 100644 index 00000000..ea6aeca2 --- /dev/null +++ b/web/docs/content/uninstall.md @@ -0,0 +1,50 @@ +--- +sidebar_position: 4 +title: Uninstall and data +description: How to remove CrocApp from iPhone, iPad and Mac, where it keeps data, and what deleting the app does and does not remove. +--- + +# Uninstall and data + +## What CrocApp stores + +| Data | Where | Removed by deleting the app? | +|---|---|---| +| Settings, including the receive folder you chose | The app's preferences | Yes | +| [History](guide/history.md) | A database in the app's own storage | Yes | +| Relay password, the two proxies, and receipts for [Send as link](guide/send-as-link.md) | The Keychain | Not guaranteed: Keychain items can outlast an app | +| Received files, iOS | The app's **Documents** folder | Yes: they are deleted with the app | +| Received files, Mac | `Downloads/CrocApp`, or the folder you chose | No | +| Files staged by the share sheet, iOS | The app's shared storage | Yes | + +CrocApp keeps nothing in the cloud and has no account, so there is nothing to delete on a server, except a [Send as link](guide/send-as-link.md) upload that has not expired. + +## Before you delete + +You can leave this out if you do not care about leftovers. Each step is in the app: + +1. **Revoke live links.** In **History**, choose **Revoke Link** on any link that has not expired. This deletes the files from the link server. Without a receipt on the device, you cannot revoke later. +2. **Clear History.** Tap **Clear**, then **Clear All**. +3. **Remove secrets.** In [Settings](guide/settings.md), empty **Password** under **Relay**, then in **Advanced** choose **Reset to Defaults**, which also removes the saved proxies. +4. **Mac only:** turn off **Open at Login** in Settings, or the login item stays registered until you remove it in System Settings > General > Login Items. +5. **Save any received files you want.** On iOS they live in the app's Documents folder and go with the app. + +Keychain items for a revoked link are removed on revoke, and for an expired link at the next launch. On Mac they live in your login keychain, which deleting the app never touches: remove them in Keychain Access (search for `com.bakirgdev.CrocApp`). On iPhone and iPad, whether they survive deleting the app is not verified, which is why step 3 comes first. + +## iPhone and iPad + +Touch and hold the CrocApp icon, tap **Remove App**, then **Delete App**. The app's preferences, history and Documents folder go with it. + +Shortcuts that use CrocApp's actions stop working. Delete them in the Shortcuts app if you no longer want them. + +## Mac, App Store build + +Move **CrocApp** from **Applications** to the Trash. The menu bar icon goes with it. CrocApp is sandboxed, so its preferences and history sit in `~/Library/Containers/com.bakirgdev.CrocApp`. Delete that folder to remove them. + +## Mac, disk image build + +Move **CrocApp** from **Applications** to the Trash. Its sandbox container is `~/Library/Containers/com.bakirgdev.CrocApp.direct`. Delete that folder to remove the preferences and history, including the updater's own choices. + +The updater (Sparkle) is part of the app, so there is no separate updater to remove. + +If you used both builds, remember that they take each other's place in **Applications** (see [Requirements and install](getting-started/install.md#disk-image)). Each has its own container. diff --git a/web/docs/content/verify-downloads.md b/web/docs/content/verify-downloads.md deleted file mode 100644 index c1b05732..00000000 --- a/web/docs/content/verify-downloads.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -sidebar_position: 5.5 -title: Verify a release -description: What each CrocApp release asset is, and how to check one is notarized, built by the release workflow and unmodified. ---- - -# Verify a release - -Each release on the [releases page](https://github.com/bakirgdev/CrocApp/releases) carries four assets: - -| Asset | What it is | -|---|---| -| `CrocApp-<version>-arm64.dmg` | The Mac app, as a disk image | -| `appcast.xml` | The update feed Sparkle reads | -| `Croc.xcframework-<version>.zip` | The prebuilt Go engine, for building from source | -| `SHA256SUMS.txt` | Checksums for the disk image and the engine archive | - -No app zip is published. The disk image is the only file of the app. - -## Notarized and stapled - -The app inside the disk image is signed with a Developer ID certificate with the hardened runtime and a timestamp. The app and the disk image are each notarized by Apple and stapled, so macOS verifies them without a network connection. Check the disk image yourself: - -```bash -xcrun stapler validate CrocApp-<version>-arm64.dmg -spctl -a -vv -t open --context context:primary-signature CrocApp-<version>-arm64.dmg -``` - -## Build attestation - -The release workflow makes a [build provenance attestation](https://github.com/bakirgdev/CrocApp/attestations) for the disk image, the engine archive and `appcast.xml` after stapling, because stapling rewrites the disk image and the attestation has to cover the bytes that ship. Verify any of them before you run it: - -```bash -gh attestation verify <file> --repo bakirgdev/CrocApp \ - --signer-workflow bakirgdev/CrocApp/.github/workflows/release.yml -``` - -The `--signer-workflow` flag is the recommended form: it proves the file came from the release workflow, not just any workflow in the repository. Without it, `gh attestation verify <file> --repo bakirgdev/CrocApp` checks only the repository. - -## Checksums - -`SHA256SUMS.txt` ships alongside the assets and covers the disk image and the engine archive. - -## Updates - -Only the disk image build updates itself, through Sparkle 2. Every update in `appcast.xml` is signed with an EdDSA (Ed25519) key. The private key is a secret of the repository's `release` environment, which runs only after the maintainer approves the run, plus the maintainer's own copy. CrocApp has one maintainer, so no second person reviews that approval. The app carries the matching public key and installs an update only when the signature matches. - -The feed is served over HTTPS from this repository's releases, and update checks send no system profile. The App Store builds contain no Sparkle and no update feed. - -## If a check fails - -An asset that fails any of these checks, or one that appears anywhere other than this repository's releases page, is worth reporting. See the [security policy](https://github.com/bakirgdev/CrocApp/blob/main/SECURITY.md) and [Security and privacy](security-and-privacy.md). diff --git a/web/docs/docusaurus.config.ts b/web/docs/docusaurus.config.ts index 936e5644..1c172d33 100644 --- a/web/docs/docusaurus.config.ts +++ b/web/docs/docusaurus.config.ts @@ -7,14 +7,17 @@ import prismTheme from './src/prismTheme'; // published together by scripts/assemble-site.sh. const config: Config = { title: 'CrocApp', - tagline: 'End-to-end encrypted file transfer for iPhone, iPad and Mac', - favicon: 'img/favicon.ico', + tagline: 'Send files with a code phrase', + // The favicon set, OG image and manifest live in web/landing/ and are served + // from the site root, so the docs ship no copies. `favicon` and the OG image + // need absolute URLs: a site-relative path there is prefixed with baseUrl + // (/docs/). headTags are emitted verbatim, so root-relative paths work. + favicon: 'https://crocapp.dev/assets/img/favicon/favicon.ico', - // `faster` is what makes @docusaurus/faster a real dependency: Rspack, SWC - // and Lightning CSS instead of webpack, Babel and cssnano. + // `v4` includes `fasterByDefault`, which turns on every `future.faster` flag + // and needs @docusaurus/faster: Rspack, SWC, Lightning CSS, eager git reads. future: { v4: true, - faster: true, }, // The theme-color values are the two literals web may write (design/web.md): @@ -36,11 +39,27 @@ const config: Config = { media: '(prefers-color-scheme: dark)', }, }, + { + tagName: 'link', + attributes: { + rel: 'icon', + type: 'image/png', + sizes: '96x96', + href: '/assets/img/favicon/favicon-96x96.png', + }, + }, { tagName: 'link', attributes: { rel: 'apple-touch-icon', - href: '/docs/img/apple-touch-icon.png', + href: '/assets/img/favicon/apple-touch-icon.png', + }, + }, + { + tagName: 'link', + attributes: { + rel: 'manifest', + href: '/assets/img/favicon/site.webmanifest', }, }, ], @@ -49,9 +68,6 @@ const config: Config = { baseUrl: '/docs/', trailingSlash: true, - organizationName: 'bakirgdev', - projectName: 'CrocApp', - onBrokenLinks: 'throw', onBrokenAnchors: 'throw', @@ -71,10 +87,35 @@ const config: Config = { defaultLocale: 'en', locales: ['en'], localeConfigs: { - en: {label: 'English', htmlLang: 'en-US'}, + en: {label: 'English', htmlLang: 'en'}, }, }, + plugins: [ + [ + '@docusaurus/plugin-client-redirects', + { + redirects: [ + {from: '/guide/stored-transfers', to: '/guide/send-as-link'}, + { + from: ['/guide/power-options', '/guide/settings-and-trust'], + to: '/guide/settings', + }, + {from: '/guide/advanced-settings', to: '/guide/settings#advanced'}, + { + from: '/verify-downloads', + to: '/getting-started/verify-downloads', + }, + {from: '/reference/feature-matrix', to: '/reference/croc-cli-interop'}, + {from: '/reference/glossary', to: '/faq#glossary'}, + {from: '/category/getting-started', to: '/getting-started/install'}, + {from: '/category/guide', to: '/guide/sending'}, + {from: '/category/reference', to: '/reference/croc-cli-interop'}, + ], + }, + ], + ], + presets: [ [ 'classic', @@ -87,16 +128,10 @@ const config: Config = { sidebarPath: './sidebars.ts', editUrl: 'https://github.com/bakirgdev/CrocApp/tree/main/web/docs/', showLastUpdateTime: true, - // Current *is* 1.0 (release 1.0.0, see package.json), rather than an - // unlabeled "Next" sitting on top of a duplicated snapshot, so a - // versioned_docs/ copy would only be a second place to edit. No - // snapshot of the earlier build is cut. Cut the first one when a - // release changes behavior this site must still describe for the - // old version: `pnpm run docusaurus docs:version 1.0`. - lastVersion: 'current', - versions: { - current: {label: '1.0'}, - }, + }, + sitemap: { + lastmod: 'date', + ignorePatterns: ['/docs/category/**'], }, // No blog. Release notes belong in GitHub Releases and CHANGELOG.md. blog: false, @@ -108,15 +143,17 @@ const config: Config = { ], themeConfig: { - image: 'img/og.jpg', + image: 'https://crocapp.dev/assets/img/og.jpg', colorMode: { respectPrefersColorScheme: true, }, navbar: { title: 'CrocApp', logo: { - alt: 'CrocApp', + alt: '', src: 'img/mascot.webp', + width: 32, + height: 32, }, items: [ { @@ -125,10 +162,6 @@ const config: Config = { position: 'left', target: '_self', }, - { - type: 'docsVersionDropdown', - position: 'right', - }, { href: 'https://github.com/bakirgdev/CrocApp', label: 'GitHub', @@ -154,6 +187,10 @@ const config: Config = { items: [ {label: 'crocapp.dev', href: 'https://crocapp.dev/'}, {label: 'GitHub', href: 'https://github.com/bakirgdev/CrocApp'}, + { + label: 'Release notes', + href: 'https://github.com/bakirgdev/CrocApp/releases', + }, { label: 'Issues', href: 'https://github.com/bakirgdev/CrocApp/issues', @@ -167,6 +204,8 @@ const config: Config = { { title: 'More', items: [ + {label: 'Privacy', href: 'https://crocapp.dev/privacy/'}, + {label: 'Support', href: 'https://crocapp.dev/support/'}, { label: 'Contributing', href: 'https://github.com/bakirgdev/CrocApp/blob/main/CONTRIBUTING.md', diff --git a/web/docs/package.json b/web/docs/package.json index 7b7f9c84..1af111cb 100644 --- a/web/docs/package.json +++ b/web/docs/package.json @@ -2,7 +2,7 @@ "name": "crocapp-docs", "version": "1.0.0", "private": true, - "packageManager": "pnpm@12.11.2", + "packageManager": "pnpm@12.14.0", "scripts": { "docusaurus": "docusaurus", "tokens": "cp ../../design/tokens.css src/css/tokens.css && cp ../landing/assets/img/mascot-web.webp static/img/mascot.webp", @@ -18,12 +18,13 @@ "dependencies": { "@docusaurus/core": "^3.10.2", "@docusaurus/faster": "^3.10.2", + "@docusaurus/plugin-client-redirects": "^3.10.2", "@docusaurus/preset-classic": "^3.10.2", "@mdx-js/react": "^3.1.1", "clsx": "^2.1.1", "prism-react-renderer": "^2.4.1", - "react": "^19.3.0", - "react-dom": "^19.3.0" + "react": "^19.3.1", + "react-dom": "^19.3.1" }, "devDependencies": { "@docusaurus/module-type-aliases": "^3.10.2", @@ -45,6 +46,6 @@ ] }, "engines": { - "node": ">=24.21.0" + "node": ">=26.12.0" } } diff --git a/web/docs/pnpm-lock.yaml b/web/docs/pnpm-lock.yaml index 843c9034..0343d084 100644 --- a/web/docs/pnpm-lock.yaml +++ b/web/docs/pnpm-lock.yaml @@ -7,153 +7,153 @@ importers: configDependencies: {} packageManagerDependencies: pnpm: - specifier: 12.11.2 - version: 12.11.2 + specifier: 12.14.0 + version: 12.14.0 packages: - '@pnpm/exe.android-arm64@12.11.2': - resolution: {integrity: sha512-owLw13OfPkEoY+hLBNeeG+dCFhywr7q2d/EHPz4mNL2RhKnv8gNwMARkjkiDQu234aItVwFNDeGnmQXm+ikkAg==} + '@pnpm/exe.android-arm64@12.14.0': + resolution: {integrity: sha512-+iSh7x21C3A2hqc+Z0ZmbKTcn6YNlzrXM142PsnQH/dLj0DYxFzoBvc6XAnL/yfQ5nnH2ebBiRj/zVxr61fZbQ==} cpu: [arm64] os: [android] - '@pnpm/exe.android-x64@12.11.2': - resolution: {integrity: sha512-GYPkVebl4iokOA/4MPSpGoUVfFlsth7uqOCe1XiaiM23LAdvUOMJBObqHJijr89ZqjwHm9pO6vO45GRwJ2U2qA==} + '@pnpm/exe.android-x64@12.14.0': + resolution: {integrity: sha512-qT+0LqEr2wBVaxcG2T8cX/R8SSRz2Rvpp8nRR4fh8tnGUZRch87gFmsHUAoSQh7w6j1h0qTjrA384j4xi8frvw==} cpu: [x64] os: [android] - '@pnpm/exe.darwin-arm64@12.11.2': - resolution: {integrity: sha512-n9M4On66y8FDxUAKgMO1FXt0qihyG4e+56p3/F0uo8Bx9KplW8BwKVnXigzCJ8aNM6sVVPkOE6M9XXbeVIxnZA==} + '@pnpm/exe.darwin-arm64@12.14.0': + resolution: {integrity: sha512-tnrdUB8ecJoehuKKqi1YHCBVl61xtJ9XVGcx5EviC6fWO4DeGI8GtXrjvJxDBM3nuVjJeWistgsUp/N142x4sw==} cpu: [arm64] os: [darwin] - '@pnpm/exe.darwin-x64@12.11.2': - resolution: {integrity: sha512-oSW7n3sBT0c0cyk4kj10T2Y6Mpm+OFEiCAWozgX039tdoI6yqJF1uaFD3sw7ugLdu6VV3+uY0pa1TUZIPdxDWA==} + '@pnpm/exe.darwin-x64@12.14.0': + resolution: {integrity: sha512-vlBfGkruqQRsEHTW43cPwpYd7QlbIJ//cvpAdb3bVXkI8SgTPoXhCnc05m+ZNiPrrEkBsX/t7KHw9aXpkzPm3Q==} cpu: [x64] os: [darwin] - '@pnpm/exe.freebsd-x64@12.11.2': - resolution: {integrity: sha512-qbzc3KoDpa/Lkf8vs3jnDe6dUUbso+6eLIyssYFMiliLpYNxn8dirk11YoNnOQcdHVB50v5RFls1Yid6ttT5pg==} + '@pnpm/exe.freebsd-x64@12.14.0': + resolution: {integrity: sha512-Qg5rxBrGYl6Tfso+EyygPf84fY1Fzy55E/0or+iuYKtnf0vc0MlHJfVIlT7pBukMRntQHRik7hUi0Z4s7AlJsw==} cpu: [x64] os: [freebsd] - '@pnpm/exe.linux-arm64-musl@12.11.2': - resolution: {integrity: sha512-uMEYDwKRktGwANubQ+kYCwmhNwg3Ik6qK89ahsbQ5cP30R/5FVJb/T99vr9XRUBC/A7mZI6eeT92oyVas9ACyg==} + '@pnpm/exe.linux-arm64-musl@12.14.0': + resolution: {integrity: sha512-DRIe4yQkXBGA/PhVJdzlbnllxBdAtnMMvTVLLcGpsK5FvJz9kxD2Hyxtn68ovmNkVX06f6p45cQwfm3wx2jn1A==} cpu: [arm64] os: [linux] libc: [musl] - '@pnpm/exe.linux-arm64@12.11.2': - resolution: {integrity: sha512-6e8ZAQUwFXAWHHHv5FesWqf/kEK04wuitBv5f/gxzkC0DiBfaixr+f+6JQede8SF4Ji5LcMwVFJbzAtffpWxEg==} + '@pnpm/exe.linux-arm64@12.14.0': + resolution: {integrity: sha512-7joGShZ44Nk3WpNU+60JoOPjCXlgxhJAq11S2UiVtwCUDgTer1yTPPfxGW8pxaD6046actYLIYDbZNlubHWs0A==} cpu: [arm64] os: [linux] libc: [glibc] - '@pnpm/exe.linux-ppc64@12.11.2': - resolution: {integrity: sha512-Ui8A4nepkVupx2VpuFfysEluMvWK6gTB5rgVts7Ss/+8dj0RD28x3F/seNeH/zSypgC6yKdV6qsKVQh/uffTuQ==} + '@pnpm/exe.linux-ppc64@12.14.0': + resolution: {integrity: sha512-gSoryn7ySdXd//gjgf3MvvA8ZerJayaSbuMZMtAWq4vb2/wlVEgpl0Kvqt54y58TRj533Qjq2txKgnxd4JyoAQ==} cpu: [ppc64] os: [linux] libc: [glibc] - '@pnpm/exe.linux-riscv64@12.11.2': - resolution: {integrity: sha512-i1yLdQ5bu+wjQ+srtFoJAaY2gN/+oXHFdjul4llCeoDxHE0rTIG3R41NhHfCjyFPW4+CpbBT58933CL9sMOCnA==} + '@pnpm/exe.linux-riscv64@12.14.0': + resolution: {integrity: sha512-EMjew1H9WqQ7pL+tYqCPwiuB+0PeCiJRV7fyWeuFw0wwYUajFBjcaPO3IGAVu9sdmJDU+e+HYv/Zey6aKae0Vw==} cpu: [riscv64] os: [linux] libc: [glibc] - '@pnpm/exe.linux-s390x@12.11.2': - resolution: {integrity: sha512-YS1/lhPjjTsN4QL50VaFZKRa3Uc/bDnhE8eKbJMFvuX06UuFS5YaiDg04APoZdfVSGqTfX27QAg7rfLMSWaqxA==} + '@pnpm/exe.linux-s390x@12.14.0': + resolution: {integrity: sha512-shYOj/SFoXD35fHe0pWr2JofwSXulC0BnEIXLj2QokDi0EF//AfKsui35yKIkTEl+s2VJybc3PO4iJNhKIj5Qw==} cpu: [s390x] os: [linux] libc: [glibc] - '@pnpm/exe.linux-x64-musl@12.11.2': - resolution: {integrity: sha512-7eIxQR05fvJxCujUSKp5KTtehJ7QqrgqP/HD1+BcB/SaV2Be4XI1PEHiOgA1zxsiMIeMvTF6E4G4dYHrFjeXRg==} + '@pnpm/exe.linux-x64-musl@12.14.0': + resolution: {integrity: sha512-btZiZ2Ot0llKK1ndSfA5i3IRX7/S0VrmzseNH/BJ4c+Cady+S81H6vvU1zByggHMyqQhC8OgxO5PiIY7D9bH0Q==} cpu: [x64] os: [linux] libc: [musl] - '@pnpm/exe.linux-x64@12.11.2': - resolution: {integrity: sha512-FK7QKe24AYgppJwO3mpooYptduuvIGqKJPi5ac7MdnWkjUy46JBfYhCW0grnkWKC8YOf0x+vGviuQqJEj3SpQQ==} + '@pnpm/exe.linux-x64@12.14.0': + resolution: {integrity: sha512-F6K8e/jWxiuEYJaQtRRUG9ynBSTEHa+t7Lf86MKuOO5UA7WVVMbi+oB8nY6iKW++ncWS2yG6T9faXZGxqNsfoQ==} cpu: [x64] os: [linux] libc: [glibc] - '@pnpm/exe.win32-arm64@12.11.2': - resolution: {integrity: sha512-PCTjVDdJb6VvraZxrEeFv6EqEA0hhIsAySx28e95J2Tqpi88hLpgOXgNqV0vpxq9A+b8GLQfyk/D+1UlJPv/YQ==} + '@pnpm/exe.win32-arm64@12.14.0': + resolution: {integrity: sha512-DOjlkVB6TtTKeAAe0hNZXn5S7YqESmo1Z6SGbR4BZNQ4isRg31XVHjX2RFTbY8gnZq68IwzyLmPqlEjMmYxofg==} cpu: [arm64] os: [win32] - '@pnpm/exe.win32-x64@12.11.2': - resolution: {integrity: sha512-8sgX86OvRjJ3yZs/TvGR2L31wH9ScPZ+f+geKI3ikuB0RRiK3i4LlTRO8OXN6pdRqj8epMde4312MCjj7JsJdA==} + '@pnpm/exe.win32-x64@12.14.0': + resolution: {integrity: sha512-/LSX6mew/sLf08XqcjemuklNKf1K/Ftpgj4//hK/HKzI2dKbmxDB27a/2OaQ5a0O3/3OFzlssXDziZsi+yVBwQ==} cpu: [x64] os: [win32] - pnpm@12.11.2: - resolution: {integrity: sha512-JaUWUqGWeFr18ovabf6NxYLr76SsHRgCIc4TkCMcX7dmN4IupLbkYzznSs3LCnf3Ja8RutOBd/3t2u6BipVcuQ==} + pnpm@12.14.0: + resolution: {integrity: sha512-wYum2HmT09Fky16JSPMrLAbuhUSH4GzY2GeBNC+z5btGNDZwNHEehoArqpw3vqkGzhkprQjXCITJfYAd8TOJpg==} engines: {node: '>=18.*'} hasBin: true snapshots: - '@pnpm/exe.android-arm64@12.11.2': + '@pnpm/exe.android-arm64@12.14.0': optional: true - '@pnpm/exe.android-x64@12.11.2': + '@pnpm/exe.android-x64@12.14.0': optional: true - '@pnpm/exe.darwin-arm64@12.11.2': + '@pnpm/exe.darwin-arm64@12.14.0': optional: true - '@pnpm/exe.darwin-x64@12.11.2': + '@pnpm/exe.darwin-x64@12.14.0': optional: true - '@pnpm/exe.freebsd-x64@12.11.2': + '@pnpm/exe.freebsd-x64@12.14.0': optional: true - '@pnpm/exe.linux-arm64-musl@12.11.2': + '@pnpm/exe.linux-arm64-musl@12.14.0': optional: true - '@pnpm/exe.linux-arm64@12.11.2': + '@pnpm/exe.linux-arm64@12.14.0': optional: true - '@pnpm/exe.linux-ppc64@12.11.2': + '@pnpm/exe.linux-ppc64@12.14.0': optional: true - '@pnpm/exe.linux-riscv64@12.11.2': + '@pnpm/exe.linux-riscv64@12.14.0': optional: true - '@pnpm/exe.linux-s390x@12.11.2': + '@pnpm/exe.linux-s390x@12.14.0': optional: true - '@pnpm/exe.linux-x64-musl@12.11.2': + '@pnpm/exe.linux-x64-musl@12.14.0': optional: true - '@pnpm/exe.linux-x64@12.11.2': + '@pnpm/exe.linux-x64@12.14.0': optional: true - '@pnpm/exe.win32-arm64@12.11.2': + '@pnpm/exe.win32-arm64@12.14.0': optional: true - '@pnpm/exe.win32-x64@12.11.2': + '@pnpm/exe.win32-x64@12.14.0': optional: true - pnpm@12.11.2: + pnpm@12.14.0: optionalDependencies: - '@pnpm/exe.android-arm64': 12.11.2 - '@pnpm/exe.android-x64': 12.11.2 - '@pnpm/exe.darwin-arm64': 12.11.2 - '@pnpm/exe.darwin-x64': 12.11.2 - '@pnpm/exe.freebsd-x64': 12.11.2 - '@pnpm/exe.linux-arm64': 12.11.2 - '@pnpm/exe.linux-arm64-musl': 12.11.2 - '@pnpm/exe.linux-ppc64': 12.11.2 - '@pnpm/exe.linux-riscv64': 12.11.2 - '@pnpm/exe.linux-s390x': 12.11.2 - '@pnpm/exe.linux-x64': 12.11.2 - '@pnpm/exe.linux-x64-musl': 12.11.2 - '@pnpm/exe.win32-arm64': 12.11.2 - '@pnpm/exe.win32-x64': 12.11.2 + '@pnpm/exe.android-arm64': 12.14.0 + '@pnpm/exe.android-x64': 12.14.0 + '@pnpm/exe.darwin-arm64': 12.14.0 + '@pnpm/exe.darwin-x64': 12.14.0 + '@pnpm/exe.freebsd-x64': 12.14.0 + '@pnpm/exe.linux-arm64': 12.14.0 + '@pnpm/exe.linux-arm64-musl': 12.14.0 + '@pnpm/exe.linux-ppc64': 12.14.0 + '@pnpm/exe.linux-riscv64': 12.14.0 + '@pnpm/exe.linux-s390x': 12.14.0 + '@pnpm/exe.linux-x64': 12.14.0 + '@pnpm/exe.linux-x64-musl': 12.14.0 + '@pnpm/exe.win32-arm64': 12.14.0 + '@pnpm/exe.win32-x64': 12.14.0 --- lockfileVersion: '9.0' @@ -174,38 +174,41 @@ importers: dependencies: '@docusaurus/core': specifier: ^3.10.2 - version: 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + version: 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) '@docusaurus/faster': specifier: ^3.10.2 - version: 3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5) + version: 3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5) + '@docusaurus/plugin-client-redirects': + specifier: ^3.10.2 + version: 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) '@docusaurus/preset-classic': specifier: ^3.10.2 - version: 3.10.2(@algolia/client-search@5.59.0)(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(@types/react@19.3.0)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(search-insights@2.17.3)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + version: 3.10.2(@algolia/client-search@5.59.0)(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(@types/react@19.3.0)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(search-insights@2.17.3)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) '@mdx-js/react': specifier: ^3.1.1 - version: 3.1.1(@types/react@19.3.0)(react@19.3.0) + version: 3.1.1(@types/react@19.3.0)(react@19.3.1) clsx: specifier: ^2.1.1 version: 2.1.1 prism-react-renderer: specifier: ^2.4.1 - version: 2.4.1(react@19.3.0) + version: 2.4.1(react@19.3.1) react: - specifier: ^19.3.0 - version: 19.3.0 + specifier: ^19.3.1 + version: 19.3.1 react-dom: - specifier: ^19.3.0 - version: 19.3.0(react@19.3.0) + specifier: ^19.3.1 + version: 19.3.1(react@19.3.1) devDependencies: '@docusaurus/module-type-aliases': specifier: ^3.10.2 - version: 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + version: 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) '@docusaurus/tsconfig': specifier: ^3.10.2 version: 3.10.2 '@docusaurus/types': specifier: ^3.10.2 - version: 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + version: 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) '@types/react': specifier: ^19.3.0 version: 19.3.0 @@ -1273,6 +1276,13 @@ packages: react: '*' react-dom: '*' + '@docusaurus/plugin-client-redirects@3.10.2': + resolution: {integrity: sha512-z5I5ttCXw+8y2gHVZvqAMmUw4Rb0ZzKA5eCPk87SfM/jCKOTvE24yDpPAwwipvug96ij7mOwEHXWw8G4LlWdGA==} + engines: {node: '>=20.0'} + peerDependencies: + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + '@docusaurus/plugin-content-blog@3.10.2': resolution: {integrity: sha512-0cbEnNKf0InmLkhj/+nVRmqEnWEoOE8Mh+2x1qOXI0qYpCnphq4RXknVJ8BvybKRXqYVvbmdMfiJSup+k4tm5w==} engines: {node: '>=20.0'} @@ -4900,10 +4910,10 @@ packages: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true - react-dom@19.3.0: - resolution: {integrity: sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q==} + react-dom@19.3.1: + resolution: {integrity: sha512-Y0bARz53lhEC1NMCASs0/j+faB/zqt3R8hpvg1e8+61ZVJ4UL0UdC4cBbXfZMcIuhrfgeILTLe+ZeBCavQPtKQ==} peerDependencies: - react: ^19.3.0 + react: ^19.3.1 react-fast-compare@3.2.2: resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} @@ -4940,8 +4950,8 @@ packages: peerDependencies: react: '>=15' - react@19.3.0: - resolution: {integrity: sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==} + react@19.3.1: + resolution: {integrity: sha512-QNhWdt7nrgVWWQG58QuGsAR3jv3Hbe4mb4vz7w2csnHavciZJgda1CPNaldF6eVxv90ud3jUXpKlHL69gO38yw==} engines: {node: '>=0.10.0'} readable-stream@2.3.8: @@ -6954,29 +6964,29 @@ snapshots: '@discoveryjs/json-ext@0.5.7': {} - '@docsearch/core@4.7.1(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + '@docsearch/core@4.7.1(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': optionalDependencies: '@types/react': 19.3.0 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) '@docsearch/css@4.7.1': {} - '@docsearch/react@4.7.1(@algolia/client-search@5.59.0)(@types/react@19.3.0)(algoliasearch@5.59.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(search-insights@2.17.3)': + '@docsearch/react@4.7.1(@algolia/client-search@5.59.0)(@types/react@19.3.0)(algoliasearch@5.59.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(search-insights@2.17.3)': dependencies: '@algolia/autocomplete-core': 1.19.2(@algolia/client-search@5.59.0)(algoliasearch@5.59.0)(search-insights@2.17.3) - '@docsearch/core': 4.7.1(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@docsearch/core': 4.7.1(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) '@docsearch/css': 4.7.1 optionalDependencies: '@types/react': 19.3.0 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) search-insights: 2.17.3 transitivePeerDependencies: - '@algolia/client-search' - algoliasearch - '@docusaurus/babel@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)': + '@docusaurus/babel@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)': dependencies: '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/generator': 7.29.8 @@ -6988,7 +6998,7 @@ snapshots: '@babel/runtime': 7.29.10 '@babel/traverse': 7.29.10(supports-color@8.1.1) '@docusaurus/logger': 3.10.2 - '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) babel-plugin-dynamic-import-node: 2.3.3 fs-extra: 11.4.1 tslib: 2.8.1 @@ -7014,14 +7024,14 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/bundler@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(csso@5.0.5)(lightningcss@1.33.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': + '@docusaurus/bundler@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(csso@5.0.5)(lightningcss@1.33.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': dependencies: '@babel/core': 7.29.7(supports-color@8.1.1) - '@docusaurus/babel': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/babel': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) '@docusaurus/cssnano-preset': 3.10.2 '@docusaurus/logger': 3.10.2 - '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) babel-loader: 9.2.1(@babel/core@7.29.7(supports-color@8.1.1))(webpack@5.111.1(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(svgo@3.3.5)) clean-css: 5.3.3 copy-webpack-plugin: 11.0.0(webpack@5.111.1(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(svgo@3.3.5)) @@ -7041,7 +7051,7 @@ snapshots: webpack: 5.111.1(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(svgo@3.3.5) webpackbar: 7.0.0(@rspack/core@1.7.12)(webpack@5.111.1(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(svgo@3.3.5)) optionalDependencies: - '@docusaurus/faster': 3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5) + '@docusaurus/faster': 3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5) transitivePeerDependencies: - '@minify-html/node' - '@napi-rs/image' @@ -7063,16 +7073,16 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/core@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': + '@docusaurus/core@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': dependencies: - '@docusaurus/babel': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/bundler': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(csso@5.0.5)(lightningcss@1.33.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/babel': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/bundler': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(csso@5.0.5)(lightningcss@1.33.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) '@docusaurus/logger': 3.10.2 - '@docusaurus/mdx-loader': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-common': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@mdx-js/react': 3.1.1(@types/react@19.3.0)(react@19.3.0) + '@docusaurus/mdx-loader': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-common': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@mdx-js/react': 3.1.1(@types/react@19.3.0)(react@19.3.1) boxen: 6.2.1 chalk: 4.1.2 chokidar: 3.6.0 @@ -7093,14 +7103,14 @@ snapshots: open: 8.4.2 p-map: 4.0.0 prompts: 2.4.2 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) - react-helmet-async: '@slorber/react-helmet-async@1.3.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0)' - react-loadable: '@docusaurus/react-loadable@6.0.0(react@19.3.0)' - react-loadable-ssr-addon-v5-slorber: 1.0.3(@docusaurus/react-loadable@6.0.0(react@19.3.0))(webpack@5.111.1(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(svgo@3.3.5)) - react-router: 5.3.4(react@19.3.0) - react-router-config: 5.1.1(react-router@5.3.4(react@19.3.0))(react@19.3.0) - react-router-dom: 5.3.4(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + react-helmet-async: '@slorber/react-helmet-async@1.3.0(react-dom@19.3.1(react@19.3.1))(react@19.3.1)' + react-loadable: '@docusaurus/react-loadable@6.0.0(react@19.3.1)' + react-loadable-ssr-addon-v5-slorber: 1.0.3(@docusaurus/react-loadable@6.0.0(react@19.3.1))(webpack@5.111.1(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(svgo@3.3.5)) + react-router: 5.3.4(react@19.3.1) + react-router-config: 5.1.1(react-router@5.3.4(react@19.3.1))(react@19.3.1) + react-router-dom: 5.3.4(react@19.3.1) semver: 7.8.5 serve-handler: 6.1.7 tinypool: 2.2.0 @@ -7111,7 +7121,7 @@ snapshots: webpack-dev-server: 5.2.6(debug@4.4.3(supports-color@8.1.1))(supports-color@8.1.1)(webpack@5.111.1(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(svgo@3.3.5)) webpack-merge: 6.0.1 optionalDependencies: - '@docusaurus/faster': 3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5) + '@docusaurus/faster': 3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5) transitivePeerDependencies: - '@minify-html/node' - '@napi-rs/image' @@ -7145,9 +7155,9 @@ snapshots: postcss-sort-media-queries: 5.2.0(postcss@8.5.29) tslib: 2.8.1 - '@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5)': + '@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5)': dependencies: - '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) '@rspack/core': 1.7.12 '@swc/core': 1.16.18 '@swc/html': 1.16.18 @@ -7179,11 +7189,11 @@ snapshots: chalk: 4.1.2 tslib: 2.8.1 - '@docusaurus/mdx-loader@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)': + '@docusaurus/mdx-loader@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)': dependencies: '@docusaurus/logger': 3.10.2 - '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) '@mdx-js/mdx': 3.1.1(supports-color@8.1.1) '@slorber/remark-comment': 1.0.0 escape-html: 1.0.3 @@ -7193,8 +7203,8 @@ snapshots: image-size: 2.0.4 mdast-util-mdx: 3.0.0(supports-color@8.1.1) mdast-util-to-string: 4.0.0 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) rehype-raw: 7.0.0 remark-directive: 3.0.1(supports-color@8.1.1) remark-emoji: 4.0.1 @@ -7227,17 +7237,17 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/module-type-aliases@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)': + '@docusaurus/module-type-aliases@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)': dependencies: - '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) '@types/history': 4.7.11 '@types/react': 19.3.0 '@types/react-router-config': 5.0.11 '@types/react-router-dom': 5.3.3 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) - react-helmet-async: '@slorber/react-helmet-async@1.3.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0)' - react-loadable: '@docusaurus/react-loadable@6.0.0(react@19.3.0)' + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + react-helmet-async: '@slorber/react-helmet-async@1.3.0(react-dom@19.3.1(react@19.3.1))(react@19.3.1)' + react-loadable: '@docusaurus/react-loadable@6.0.0(react@19.3.1)' transitivePeerDependencies: - '@minify-html/node' - '@napi-rs/image' @@ -7258,24 +7268,65 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/plugin-content-blog@3.10.2(7809bca50ede2ab82d88fec35f9d2eb0)': + '@docusaurus/plugin-client-redirects@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': + dependencies: + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/logger': 3.10.2 + '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-common': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + eta: 2.2.0 + fs-extra: 11.4.1 + lodash: 4.18.1 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + tslib: 2.8.1 + transitivePeerDependencies: + - '@docusaurus/faster' + - '@mdx-js/react' + - '@minify-html/node' + - '@napi-rs/image' + - '@parcel/css' + - '@rspack/core' + - '@swc/core' + - '@swc/css' + - '@swc/html' + - bufferutil + - clean-css + - cssnano + - csso + - debug + - esbuild + - html-minifier-terser + - imagemin + - lightningcss + - postcss + - sharp + - supports-color + - svgo + - typescript + - uglify-js + - utf-8-validate + - webpack-cli + + '@docusaurus/plugin-content-blog@3.10.2(dda51235fe29e19939db10839f647af7)': dependencies: - '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) '@docusaurus/logger': 3.10.2 - '@docusaurus/mdx-loader': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/plugin-content-docs': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/theme-common': 3.10.2(64b3f8cf059f0b58958eacd82c2941fa) - '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-common': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/mdx-loader': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/plugin-content-docs': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/theme-common': 3.10.2(85a6246b8c50563fee538661c0711376) + '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-common': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) cheerio: 1.0.0-rc.12 combine-promises: 1.2.0 feed: 4.2.2 fs-extra: 11.4.1 lodash: 4.18.1 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) schema-dts: 1.1.5 srcset: 4.0.0 tslib: 2.8.1 @@ -7310,24 +7361,24 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-content-docs@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': + '@docusaurus/plugin-content-docs@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': dependencies: - '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) '@docusaurus/logger': 3.10.2 - '@docusaurus/mdx-loader': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/module-type-aliases': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/theme-common': 3.10.2(64b3f8cf059f0b58958eacd82c2941fa) - '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-common': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/mdx-loader': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/module-type-aliases': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/theme-common': 3.10.2(85a6246b8c50563fee538661c0711376) + '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-common': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) '@types/react-router-config': 5.0.11 combine-promises: 1.2.0 fs-extra: 11.4.1 js-yaml: 4.3.2 lodash: 4.18.1 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) schema-dts: 1.1.5 tslib: 2.8.1 utility-types: 3.11.0 @@ -7360,16 +7411,16 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-content-pages@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': + '@docusaurus/plugin-content-pages@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': dependencies: - '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/mdx-loader': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/mdx-loader': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) fs-extra: 11.4.1 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) tslib: 2.8.1 webpack: 5.111.1(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(svgo@3.3.5) transitivePeerDependencies: @@ -7400,12 +7451,12 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-css-cascade-layers@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': + '@docusaurus/plugin-css-cascade-layers@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': dependencies: - '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) tslib: 2.8.1 transitivePeerDependencies: - '@docusaurus/faster' @@ -7437,15 +7488,15 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-debug@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': + '@docusaurus/plugin-debug@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': dependencies: - '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) fs-extra: 11.4.1 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) - react-json-view-lite: 2.5.0(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + react-json-view-lite: 2.5.0(react@19.3.1) tslib: 2.8.1 transitivePeerDependencies: - '@docusaurus/faster' @@ -7475,13 +7526,13 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-google-analytics@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': + '@docusaurus/plugin-google-analytics@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': dependencies: - '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) tslib: 2.8.1 transitivePeerDependencies: - '@docusaurus/faster' @@ -7511,13 +7562,13 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-google-gtag@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': + '@docusaurus/plugin-google-gtag@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': dependencies: - '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) tslib: 2.8.1 transitivePeerDependencies: - '@docusaurus/faster' @@ -7547,13 +7598,13 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-google-tag-manager@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': + '@docusaurus/plugin-google-tag-manager@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': dependencies: - '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) tslib: 2.8.1 transitivePeerDependencies: - '@docusaurus/faster' @@ -7583,17 +7634,17 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-sitemap@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': + '@docusaurus/plugin-sitemap@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': dependencies: - '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) '@docusaurus/logger': 3.10.2 - '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-common': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-common': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) fs-extra: 11.4.1 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) sitemap: 7.1.3 tslib: 2.8.1 transitivePeerDependencies: @@ -7624,16 +7675,16 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-svgr@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': + '@docusaurus/plugin-svgr@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': dependencies: - '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) '@svgr/core': 8.1.0(supports-color@8.1.1)(typescript@7.0.2) '@svgr/webpack': 8.1.0(supports-color@8.1.1)(typescript@7.0.2) - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) tslib: 2.8.1 webpack: 5.111.1(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(svgo@3.3.5) transitivePeerDependencies: @@ -7664,25 +7715,25 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/preset-classic@3.10.2(@algolia/client-search@5.59.0)(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(@types/react@19.3.0)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(search-insights@2.17.3)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': - dependencies: - '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/plugin-content-blog': 3.10.2(7809bca50ede2ab82d88fec35f9d2eb0) - '@docusaurus/plugin-content-docs': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/plugin-content-pages': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/plugin-css-cascade-layers': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/plugin-debug': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/plugin-google-analytics': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/plugin-google-gtag': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/plugin-google-tag-manager': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/plugin-sitemap': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/plugin-svgr': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/theme-classic': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(@types/react@19.3.0)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/theme-common': 3.10.2(64b3f8cf059f0b58958eacd82c2941fa) - '@docusaurus/theme-search-algolia': 3.10.2(@algolia/client-search@5.59.0)(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(@types/react@19.3.0)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(search-insights@2.17.3)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + '@docusaurus/preset-classic@3.10.2(@algolia/client-search@5.59.0)(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(@types/react@19.3.0)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(search-insights@2.17.3)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': + dependencies: + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/plugin-content-blog': 3.10.2(dda51235fe29e19939db10839f647af7) + '@docusaurus/plugin-content-docs': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/plugin-content-pages': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/plugin-css-cascade-layers': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/plugin-debug': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/plugin-google-analytics': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/plugin-google-gtag': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/plugin-google-tag-manager': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/plugin-sitemap': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/plugin-svgr': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/theme-classic': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(@types/react@19.3.0)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/theme-common': 3.10.2(85a6246b8c50563fee538661c0711376) + '@docusaurus/theme-search-algolia': 3.10.2(@algolia/client-search@5.59.0)(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(@types/react@19.3.0)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(search-insights@2.17.3)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) transitivePeerDependencies: - '@algolia/client-search' - '@docusaurus/faster' @@ -7714,38 +7765,38 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/react-loadable@6.0.0(react@19.3.0)': + '@docusaurus/react-loadable@6.0.0(react@19.3.1)': dependencies: '@types/react': 19.3.0 - react: 19.3.0 + react: 19.3.1 - '@docusaurus/theme-classic@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(@types/react@19.3.0)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': + '@docusaurus/theme-classic@3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(@types/react@19.3.0)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': dependencies: - '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) '@docusaurus/logger': 3.10.2 - '@docusaurus/mdx-loader': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/module-type-aliases': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/plugin-content-blog': 3.10.2(7809bca50ede2ab82d88fec35f9d2eb0) - '@docusaurus/plugin-content-docs': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/plugin-content-pages': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/theme-common': 3.10.2(64b3f8cf059f0b58958eacd82c2941fa) + '@docusaurus/mdx-loader': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/module-type-aliases': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/plugin-content-blog': 3.10.2(dda51235fe29e19939db10839f647af7) + '@docusaurus/plugin-content-docs': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/plugin-content-pages': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/theme-common': 3.10.2(85a6246b8c50563fee538661c0711376) '@docusaurus/theme-translations': 3.10.2 - '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-common': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@mdx-js/react': 3.1.1(@types/react@19.3.0)(react@19.3.0) + '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-common': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@mdx-js/react': 3.1.1(@types/react@19.3.0)(react@19.3.1) clsx: 2.1.1 copy-text-to-clipboard: 3.2.2 infima: 0.2.0-alpha.45 lodash: 4.18.1 nprogress: 0.2.0 postcss: 8.5.29 - prism-react-renderer: 2.4.1(react@19.3.0) + prism-react-renderer: 2.4.1(react@19.3.1) prismjs: 1.30.0 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) - react-router-dom: 5.3.4(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + react-router-dom: 5.3.4(react@19.3.1) rtlcss: 4.3.0 tslib: 2.8.1 utility-types: 3.11.0 @@ -7776,21 +7827,21 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/theme-common@3.10.2(64b3f8cf059f0b58958eacd82c2941fa)': + '@docusaurus/theme-common@3.10.2(85a6246b8c50563fee538661c0711376)': dependencies: - '@docusaurus/mdx-loader': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/module-type-aliases': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/plugin-content-docs': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-common': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/mdx-loader': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/module-type-aliases': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/plugin-content-docs': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-common': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) '@types/history': 4.7.11 '@types/react': 19.3.0 '@types/react-router-config': 5.0.11 clsx: 2.1.1 parse-numeric-range: 1.3.0 - prism-react-renderer: 2.4.1(react@19.3.0) - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + prism-react-renderer: 2.4.1(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) tslib: 2.8.1 utility-types: 3.11.0 transitivePeerDependencies: @@ -7813,25 +7864,25 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/theme-search-algolia@3.10.2(@algolia/client-search@5.59.0)(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(@types/react@19.3.0)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(search-insights@2.17.3)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': + '@docusaurus/theme-search-algolia@3.10.2(@algolia/client-search@5.59.0)(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(@types/react@19.3.0)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(search-insights@2.17.3)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2)': dependencies: '@algolia/autocomplete-core': 1.19.12(@algolia/client-search@5.59.0)(algoliasearch@5.59.0)(search-insights@2.17.3) - '@docsearch/react': 4.7.1(@algolia/client-search@5.59.0)(@types/react@19.3.0)(algoliasearch@5.59.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(search-insights@2.17.3) - '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docsearch/react': 4.7.1(@algolia/client-search@5.59.0)(@types/react@19.3.0)(algoliasearch@5.59.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(search-insights@2.17.3) + '@docusaurus/core': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) '@docusaurus/logger': 3.10.2 - '@docusaurus/plugin-content-docs': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) - '@docusaurus/theme-common': 3.10.2(64b3f8cf059f0b58958eacd82c2941fa) + '@docusaurus/plugin-content-docs': 3.10.2(@docusaurus/faster@3.10.2(@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5))(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(postcss@8.5.29)(svgo@3.3.5))(@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1))(@rspack/core@1.7.12)(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(debug@4.4.3(supports-color@8.1.1))(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)(typescript@7.0.2) + '@docusaurus/theme-common': 3.10.2(85a6246b8c50563fee538661c0711376) '@docusaurus/theme-translations': 3.10.2 - '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-validation': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) algoliasearch: 5.59.0 algoliasearch-helper: 3.30.0(algoliasearch@5.59.0) clsx: 2.1.1 eta: 2.2.0 fs-extra: 11.4.1 lodash: 4.18.1 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) tslib: 2.8.1 utility-types: 3.11.0 transitivePeerDependencies: @@ -7872,7 +7923,7 @@ snapshots: '@docusaurus/tsconfig@3.10.2': {} - '@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)': + '@docusaurus/types@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)': dependencies: '@mdx-js/mdx': 3.1.1(supports-color@8.1.1) '@types/history': 4.7.11 @@ -7880,9 +7931,9 @@ snapshots: '@types/react': 19.3.0 commander: 5.1.0 joi: 17.13.8 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) - react-helmet-async: '@slorber/react-helmet-async@1.3.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0)' + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + react-helmet-async: '@slorber/react-helmet-async@1.3.0(react-dom@19.3.1(react@19.3.1))(react@19.3.1)' utility-types: 3.11.0 webpack: 5.111.1(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(svgo@3.3.5) webpack-merge: 5.10.0 @@ -7906,9 +7957,9 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/utils-common@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)': + '@docusaurus/utils-common@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)': dependencies: - '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) tslib: 2.8.1 transitivePeerDependencies: - '@minify-html/node' @@ -7932,11 +7983,11 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/utils-validation@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)': + '@docusaurus/utils-validation@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)': dependencies: '@docusaurus/logger': 3.10.2 - '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-common': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-common': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) fs-extra: 11.4.1 joi: 17.13.8 js-yaml: 4.3.2 @@ -7964,12 +8015,12 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/utils@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5)': + '@docusaurus/utils@3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5)': dependencies: '@11ty/gray-matter': 1.0.0 '@docusaurus/logger': 3.10.2 - '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) - '@docusaurus/utils-common': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/types': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) + '@docusaurus/utils-common': 3.10.2(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(supports-color@8.1.1)(svgo@3.3.5) escape-string-regexp: 4.0.0 execa: 5.1.1 file-loader: 6.2.0(webpack@5.111.1(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(svgo@3.3.5)) @@ -8228,11 +8279,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.0)': + '@mdx-js/react@3.1.1(@types/react@19.3.0)(react@19.3.1)': dependencies: '@types/mdx': 2.0.14 '@types/react': 19.3.0 - react: 19.3.0 + react: 19.3.1 '@module-federation/error-codes@0.22.0': {} @@ -8455,13 +8506,13 @@ snapshots: '@sindresorhus/is@5.6.0': {} - '@slorber/react-helmet-async@1.3.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + '@slorber/react-helmet-async@1.3.0(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': dependencies: '@babel/runtime': 7.29.10 invariant: 2.2.4 prop-types: 15.8.1 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) react-fast-compare: 3.2.2 shallowequal: 1.1.0 @@ -11869,11 +11920,11 @@ snapshots: pretty-time@1.1.0: {} - prism-react-renderer@2.4.1(react@19.3.0): + prism-react-renderer@2.4.1(react@19.3.1): dependencies: '@types/prismjs': 1.26.6 clsx: 2.1.1 - react: 19.3.0 + react: 19.3.1 prismjs@1.30.0: {} @@ -11940,43 +11991,43 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 - react-dom@19.3.0(react@19.3.0): + react-dom@19.3.1(react@19.3.1): dependencies: - react: 19.3.0 + react: 19.3.1 scheduler: 0.28.0 react-fast-compare@3.2.2: {} react-is@16.13.1: {} - react-json-view-lite@2.5.0(react@19.3.0): + react-json-view-lite@2.5.0(react@19.3.1): dependencies: - react: 19.3.0 + react: 19.3.1 - react-loadable-ssr-addon-v5-slorber@1.0.3(@docusaurus/react-loadable@6.0.0(react@19.3.0))(webpack@5.111.1(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(svgo@3.3.5)): + react-loadable-ssr-addon-v5-slorber@1.0.3(@docusaurus/react-loadable@6.0.0(react@19.3.1))(webpack@5.111.1(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(svgo@3.3.5)): dependencies: '@babel/runtime': 7.29.10 - react-loadable: '@docusaurus/react-loadable@6.0.0(react@19.3.0)' + react-loadable: '@docusaurus/react-loadable@6.0.0(react@19.3.1)' webpack: 5.111.1(@swc/core@1.16.18)(@swc/html@1.16.18)(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.29))(csso@5.0.5)(html-minifier-terser@7.2.0)(lightningcss@1.33.0)(postcss@8.5.29)(svgo@3.3.5) - react-router-config@5.1.1(react-router@5.3.4(react@19.3.0))(react@19.3.0): + react-router-config@5.1.1(react-router@5.3.4(react@19.3.1))(react@19.3.1): dependencies: '@babel/runtime': 7.29.10 - react: 19.3.0 - react-router: 5.3.4(react@19.3.0) + react: 19.3.1 + react-router: 5.3.4(react@19.3.1) - react-router-dom@5.3.4(react@19.3.0): + react-router-dom@5.3.4(react@19.3.1): dependencies: '@babel/runtime': 7.29.10 history: 4.10.1 loose-envify: 1.4.0 prop-types: 15.8.1 - react: 19.3.0 - react-router: 5.3.4(react@19.3.0) + react: 19.3.1 + react-router: 5.3.4(react@19.3.1) tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - react-router@5.3.4(react@19.3.0): + react-router@5.3.4(react@19.3.1): dependencies: '@babel/runtime': 7.29.10 history: 4.10.1 @@ -11984,12 +12035,12 @@ snapshots: loose-envify: 1.4.0 path-to-regexp: 1.9.0 prop-types: 15.8.1 - react: 19.3.0 + react: 19.3.1 react-is: 16.13.1 tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - react@19.3.0: {} + react@19.3.1: {} readable-stream@2.3.8: dependencies: diff --git a/web/docs/screenshots/iphone/onboarding-dark.webp b/web/docs/screenshots/iphone/onboarding-dark.webp new file mode 100644 index 00000000..cad49436 Binary files /dev/null and b/web/docs/screenshots/iphone/onboarding-dark.webp differ diff --git a/web/docs/screenshots/iphone/onboarding-light.webp b/web/docs/screenshots/iphone/onboarding-light.webp new file mode 100644 index 00000000..d9c4c551 Binary files /dev/null and b/web/docs/screenshots/iphone/onboarding-light.webp differ diff --git a/web/docs/screenshots/iphone/receive-incoming-dark.webp b/web/docs/screenshots/iphone/receive-incoming-dark.webp new file mode 100644 index 00000000..afd954a7 Binary files /dev/null and b/web/docs/screenshots/iphone/receive-incoming-dark.webp differ diff --git a/web/docs/screenshots/iphone/receive-incoming-light.webp b/web/docs/screenshots/iphone/receive-incoming-light.webp new file mode 100644 index 00000000..f8890816 Binary files /dev/null and b/web/docs/screenshots/iphone/receive-incoming-light.webp differ diff --git a/web/docs/screenshots/mac/history-dark.webp b/web/docs/screenshots/mac/history-dark.webp new file mode 100644 index 00000000..bba15689 Binary files /dev/null and b/web/docs/screenshots/mac/history-dark.webp differ diff --git a/web/docs/screenshots/mac/history-light.webp b/web/docs/screenshots/mac/history-light.webp new file mode 100644 index 00000000..25a3da2b Binary files /dev/null and b/web/docs/screenshots/mac/history-light.webp differ diff --git a/web/docs/screenshots/mac/receive-conflict-dark.webp b/web/docs/screenshots/mac/receive-conflict-dark.webp new file mode 100644 index 00000000..9512490e Binary files /dev/null and b/web/docs/screenshots/mac/receive-conflict-dark.webp differ diff --git a/web/docs/screenshots/mac/receive-conflict-light.webp b/web/docs/screenshots/mac/receive-conflict-light.webp new file mode 100644 index 00000000..4d701f8c Binary files /dev/null and b/web/docs/screenshots/mac/receive-conflict-light.webp differ diff --git a/web/docs/screenshots/mac/send-code-dark.webp b/web/docs/screenshots/mac/send-code-dark.webp new file mode 100644 index 00000000..c1627043 Binary files /dev/null and b/web/docs/screenshots/mac/send-code-dark.webp differ diff --git a/web/docs/screenshots/mac/send-code-light.webp b/web/docs/screenshots/mac/send-code-light.webp new file mode 100644 index 00000000..6342af67 Binary files /dev/null and b/web/docs/screenshots/mac/send-code-light.webp differ diff --git a/web/docs/screenshots/mac/send-files-dark.webp b/web/docs/screenshots/mac/send-files-dark.webp new file mode 100644 index 00000000..56d8593f Binary files /dev/null and b/web/docs/screenshots/mac/send-files-dark.webp differ diff --git a/web/docs/screenshots/mac/send-files-light.webp b/web/docs/screenshots/mac/send-files-light.webp new file mode 100644 index 00000000..f55dbcd5 Binary files /dev/null and b/web/docs/screenshots/mac/send-files-light.webp differ diff --git a/web/docs/screenshots/mac/settings-advanced-dark.webp b/web/docs/screenshots/mac/settings-advanced-dark.webp new file mode 100644 index 00000000..2b773ed1 Binary files /dev/null and b/web/docs/screenshots/mac/settings-advanced-dark.webp differ diff --git a/web/docs/screenshots/mac/settings-advanced-light.webp b/web/docs/screenshots/mac/settings-advanced-light.webp new file mode 100644 index 00000000..878a5d1d Binary files /dev/null and b/web/docs/screenshots/mac/settings-advanced-light.webp differ diff --git a/web/docs/screenshots/mac/settings-dark.webp b/web/docs/screenshots/mac/settings-dark.webp new file mode 100644 index 00000000..86cea725 Binary files /dev/null and b/web/docs/screenshots/mac/settings-dark.webp differ diff --git a/web/docs/screenshots/mac/settings-light.webp b/web/docs/screenshots/mac/settings-light.webp new file mode 100644 index 00000000..f1c30782 Binary files /dev/null and b/web/docs/screenshots/mac/settings-light.webp differ diff --git a/web/docs/screenshots/mac/stored-link-dark.webp b/web/docs/screenshots/mac/stored-link-dark.webp new file mode 100644 index 00000000..1589fd53 Binary files /dev/null and b/web/docs/screenshots/mac/stored-link-dark.webp differ diff --git a/web/docs/screenshots/mac/stored-link-light.webp b/web/docs/screenshots/mac/stored-link-light.webp new file mode 100644 index 00000000..684ab633 Binary files /dev/null and b/web/docs/screenshots/mac/stored-link-light.webp differ diff --git a/web/docs/sidebars.ts b/web/docs/sidebars.ts index 8909a4e2..5d7dce91 100644 --- a/web/docs/sidebars.ts +++ b/web/docs/sidebars.ts @@ -1,10 +1,43 @@ import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; -// Autogenerated from content/. Order comes from `sidebar_position` frontmatter -// and `_category_.json`, so a manual sidebar here would only add a second -// thing to keep in sync. +// Hand-written so the groups follow the task the reader is doing, not the +// directory a file sits in. Every doc under content/ must appear here once: a +// missing one gets no sidebar. +// +// Groups are plain `html` headings, not categories: a category with no `link` +// renders its label as an <a> without href (fails Lighthouse crawlable-anchors), +// and one with a `link` generates a thin /category/ page. +function group(label: string, items: string[]) { + return [ + {type: 'html' as const, value: label, className: 'sidebar-group', defaultStyle: true}, + ...items, + ]; +} + const sidebars: SidebarsConfig = { - docs: [{type: 'autogenerated', dirName: '.'}], + docs: [ + 'index', + ...group('Getting started', [ + 'getting-started/install', + 'getting-started/first-transfer', + 'getting-started/verify-downloads', + ]), + ...group('Send and receive', [ + 'guide/sending', + 'guide/receiving', + 'guide/code-phrases', + 'guide/send-as-link', + ]), + ...group('Customize', [ + 'guide/settings', + 'guide/history', + 'guide/menu-bar', + 'guide/shortcuts', + ]), + ...group('Help', ['troubleshooting', 'faq', 'security-and-privacy', 'uninstall']), + ...group('Reference', ['reference/croc-cli-interop']), + 'contribute', + ], }; export default sidebars; diff --git a/web/docs/src/css/custom.css b/web/docs/src/css/custom.css index bb857b0f..9deec8f1 100644 --- a/web/docs/src/css/custom.css +++ b/web/docs/src/css/custom.css @@ -15,8 +15,9 @@ @import './tokens.css'; :root { - /* Accent as a fill. --color-accent is 3.41:1 on white, fine for fills, - icons and borders, never for a word: link color takes --color-text-link. + /* Accent as a fill. --color-accent is 3.41:1 on white, fine for icons and + borders, never for a word: link color takes --color-text-link. A filled + button takes --color-accent-solid (the .button--primary rule below). The ladder is the aliases, which already flip per theme. Infima asks for three darker steps and three lighter ones; the tokens define one pressed step and one tint, so steps repeat rather than invent a shade. */ @@ -102,6 +103,15 @@ --docusaurus-highlighted-code-line-bg: var(--color-fill-tertiary); } +/* A filled primary button (only the theme's error page draws one) takes the + solid step so its --color-on-accent label clears AA. Infima derives the + hover and active fills from --ifm-color-primary-dark/-darker, already the + pressed alias. Scoped to the button: the global ladder stays on the accent. */ +.button--primary { + --ifm-color-primary: var(--color-accent-solid); + --ifm-button-color: var(--color-on-accent); +} + /* Hover is the pressed background only, and only where a pointer exists (design/components.md → States). Without the gate a touch screen keeps the last tapped row filled. */ @@ -118,12 +128,6 @@ } } -/* tokens.css defaults body to the app's grouped fill. Both web surfaces take - the base surface instead (design/web.md → Page fill). */ -body { - background: var(--ifm-background-color); -} - /* Headings: the web display scale. h1 takes section, not hero, to keep a docs page calm; h3 drops to the app's headline so the three stay distinct at phone width, where section and sub clamp close together. The longhand @@ -194,6 +198,39 @@ h3 { text-underline-offset: var(--space-1); } +/* Sidebar group headings (sidebars.ts `group`): plain text, not links. */ +.sidebar-group { + margin-block-start: var(--space-5); + font-size: var(--type-footnote-size); + line-height: var(--type-footnote-lh); + font-weight: var(--weight-semibold); + color: var(--color-text-secondary); +} + +/* Infima sizes the logo by height only; the width attribute would otherwise + stretch it off its 1:1 ratio. */ +.navbar__logo img { + width: auto; +} + +/* prism-react-renderer types fontWeight as a literal keyword, so a token + cannot go through the theme object. */ +.token.keyword, +.token.atrule, +.token.selector, +.token.tag, +.token.builtin { + font-weight: var(--weight-semibold); +} + +/* Prose links on a fill surface. Inline code (an `a > code` link) and striped + table rows paint --color-fill-tertiary, on which --color-accent-text is + 4.28:1; the on-tint step clears AA there (colors.md rules 1 and 6). */ +.markdown table a, +.markdown a:has(> code) { + color: var(--color-accent-text-on-tint); +} + /* future.v4 layering means tokens.css's unlayered `a { color: ... }` beats every --ifm-*-link-color above and would paint the whole chrome accent. Navigation is not prose: it takes the landing page's secondary text, with @@ -323,6 +360,13 @@ h3 { display: none; } +/* Mac window shots carry their shape in the alpha channel and no system shadow + (screenshots.md), so a light window on the light page has no edge. A + drop-shadow follows that alpha outline where a border would draw a box. */ +.markdown img:not([alt*='on iOS']) { + filter: drop-shadow(0 0 var(--border-hairline) var(--color-separator)); +} + /* Portrait phone shots are more than twice as tall as they are wide; at full content width they push the surrounding prose off the screen. Docusaurus rewrites every /img/screenshots/ path to a hashed /assets/images/ one, so diff --git a/web/docs/src/prismTheme.ts b/web/docs/src/prismTheme.ts index 9e7dba74..fba27958 100644 --- a/web/docs/src/prismTheme.ts +++ b/web/docs/src/prismTheme.ts @@ -19,7 +19,7 @@ const prismTheme: PrismTheme = { }, { types: ['keyword', 'atrule', 'selector', 'tag', 'builtin'], - style: {color: 'var(--color-accent-text)', fontWeight: '600'}, + style: {color: 'var(--color-accent-text)'}, }, { types: ['string', 'char', 'attr-value', 'template-string', 'url'], diff --git a/web/docs/static/.nojekyll b/web/docs/static/.nojekyll deleted file mode 100644 index e69de29b..00000000 diff --git a/web/docs/static/img/apple-touch-icon.png b/web/docs/static/img/apple-touch-icon.png deleted file mode 100644 index 1e9cfd20..00000000 Binary files a/web/docs/static/img/apple-touch-icon.png and /dev/null differ diff --git a/web/docs/static/img/favicon.ico b/web/docs/static/img/favicon.ico deleted file mode 100644 index 4cdf856e..00000000 Binary files a/web/docs/static/img/favicon.ico and /dev/null differ diff --git a/web/docs/static/img/og.jpg b/web/docs/static/img/og.jpg deleted file mode 100644 index 3b1897fd..00000000 Binary files a/web/docs/static/img/og.jpg and /dev/null differ diff --git a/web/docs/static/img/screenshots/iphone/onboarding-dark.png b/web/docs/static/img/screenshots/iphone/onboarding-dark.png deleted file mode 100644 index f1f3a66d..00000000 Binary files a/web/docs/static/img/screenshots/iphone/onboarding-dark.png and /dev/null differ diff --git a/web/docs/static/img/screenshots/iphone/onboarding-light.png b/web/docs/static/img/screenshots/iphone/onboarding-light.png deleted file mode 100644 index 04267b1b..00000000 Binary files a/web/docs/static/img/screenshots/iphone/onboarding-light.png and /dev/null differ diff --git a/web/docs/static/img/screenshots/iphone/receive-incoming-dark.png b/web/docs/static/img/screenshots/iphone/receive-incoming-dark.png deleted file mode 100644 index d25c4f52..00000000 Binary files a/web/docs/static/img/screenshots/iphone/receive-incoming-dark.png and /dev/null differ diff --git a/web/docs/static/img/screenshots/iphone/receive-incoming-light.png b/web/docs/static/img/screenshots/iphone/receive-incoming-light.png deleted file mode 100644 index fd0249ea..00000000 Binary files a/web/docs/static/img/screenshots/iphone/receive-incoming-light.png and /dev/null differ diff --git a/web/docs/static/img/screenshots/iphone/settings-dark.png b/web/docs/static/img/screenshots/iphone/settings-dark.png deleted file mode 100644 index 22095892..00000000 Binary files a/web/docs/static/img/screenshots/iphone/settings-dark.png and /dev/null differ diff --git a/web/docs/static/img/screenshots/iphone/settings-light.png b/web/docs/static/img/screenshots/iphone/settings-light.png deleted file mode 100644 index 6d35316c..00000000 Binary files a/web/docs/static/img/screenshots/iphone/settings-light.png and /dev/null differ diff --git a/web/docs/static/img/screenshots/mac/history-dark.png b/web/docs/static/img/screenshots/mac/history-dark.png deleted file mode 100644 index 71a22fd2..00000000 Binary files a/web/docs/static/img/screenshots/mac/history-dark.png and /dev/null differ diff --git a/web/docs/static/img/screenshots/mac/history-light.png b/web/docs/static/img/screenshots/mac/history-light.png deleted file mode 100644 index 561efeed..00000000 Binary files a/web/docs/static/img/screenshots/mac/history-light.png and /dev/null differ diff --git a/web/docs/static/img/screenshots/mac/send-code-dark.png b/web/docs/static/img/screenshots/mac/send-code-dark.png deleted file mode 100644 index 3bd380bc..00000000 Binary files a/web/docs/static/img/screenshots/mac/send-code-dark.png and /dev/null differ diff --git a/web/docs/static/img/screenshots/mac/send-code-light.png b/web/docs/static/img/screenshots/mac/send-code-light.png deleted file mode 100644 index 35840573..00000000 Binary files a/web/docs/static/img/screenshots/mac/send-code-light.png and /dev/null differ diff --git a/web/docs/static/img/screenshots/mac/send-files-dark.png b/web/docs/static/img/screenshots/mac/send-files-dark.png deleted file mode 100644 index 3739ae75..00000000 Binary files a/web/docs/static/img/screenshots/mac/send-files-dark.png and /dev/null differ diff --git a/web/docs/static/img/screenshots/mac/send-files-light.png b/web/docs/static/img/screenshots/mac/send-files-light.png deleted file mode 100644 index 7ded2bea..00000000 Binary files a/web/docs/static/img/screenshots/mac/send-files-light.png and /dev/null differ diff --git a/web/docs/static/img/screenshots/mac/settings-dark.png b/web/docs/static/img/screenshots/mac/settings-dark.png deleted file mode 100644 index f8b111ae..00000000 Binary files a/web/docs/static/img/screenshots/mac/settings-dark.png and /dev/null differ diff --git a/web/docs/static/img/screenshots/mac/settings-light.png b/web/docs/static/img/screenshots/mac/settings-light.png deleted file mode 100644 index 1f380cdf..00000000 Binary files a/web/docs/static/img/screenshots/mac/settings-light.png and /dev/null differ diff --git a/web/landing/404.html b/web/landing/404.html index ec43339a..387ddd47 100644 --- a/web/landing/404.html +++ b/web/landing/404.html @@ -3,6 +3,7 @@ <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'none'; form-action 'none'" /> <title>Page not found | CrocApp + + + - - diff --git a/web/landing/app.js b/web/landing/app.js index fdca7429..da3036eb 100644 --- a/web/landing/app.js +++ b/web/landing/app.js @@ -54,7 +54,23 @@ currentTheme() === "dark" ? "Switch to light theme" : "Switch to dark theme" ); + /* A source cannot read [data-theme], so a pinned theme rewrites + each source's media condition: "all" always matches (dark pinned), "not + all" never does (light pinned). Unpinned, the shipped prefers-color-scheme + condition comes back and the OS decides. A pin that disagrees with the OS + downloads the OS variant first; that is the only double fetch. */ + const sources = [...document.querySelectorAll("source[data-theme-source]")]; + for (const source of sources) source.dataset.media = source.getAttribute("media"); + + const syncPictures = () => { + const pinned = root.dataset.theme; + for (const source of sources) { + source.setAttribute("media", pinned ? (pinned === "dark" ? "all" : "not all") : source.dataset.media); + } + }; + syncChrome(); + syncPictures(); relabel(); toggle.hidden = false; @@ -62,6 +78,7 @@ const next = currentTheme() === "dark" ? "light" : "dark"; root.dataset.theme = next; syncChrome(); + syncPictures(); relabel(); try { localStorage.setItem("theme", next); @@ -74,127 +91,4 @@ to follow it too. */ osDark.addEventListener("change", relabel); }); - - /* ---- GitHub star count ---- - - The page's only third-party request. Unauthenticated api.github.com allows - 60/hr per IP, and a carrier NAT shares one address between every visitor - behind it, so the cache is the source and the network is only the refresh: - a cached value paints before the request goes out, a value under MAX_AGE - skips the request, and a failure leaves whatever the cache painted. */ - - feature(() => { - const slot = document.getElementById("stars-count"); - const wrap = document.getElementById("stars"); - if (!slot || !wrap) return; - - const KEY = "stars:bakirgdev/CrocApp"; - const MAX_AGE = 6 * 60 * 60 * 1000; - const TIMEOUT = 6000; - - /* GitHub's own abbreviation, never wider than four characters, which is what - lets the slot size itself to its contents. Truncated, not rounded: a count - that reads higher than the repository has is the error worth ruling out. */ - const abbreviate = (n) => { - if (n < 1000) return String(n); - - const [value, digits, suffix] = - n < 1e4 ? [n / 1e3, 1, "k"] : n < 1e6 ? [n / 1e3, 0, "k"] : [n / 1e6, 1, "M"]; - - const truncated = Math.floor(value * 10 ** digits) / 10 ** digits; - return (Number.isInteger(truncated) ? String(truncated) : truncated.toFixed(digits)) + suffix; - }; - - /* Zero is shown: hiding it made an empty slot mean both "no stars yet" and - "the request failed". Only a non-count keeps the slot empty. */ - const show = (n) => { - if (!Number.isFinite(n) || n < 0) return; - slot.textContent = abbreviate(Math.floor(n)); - wrap.classList.remove("is-empty"); - }; - - const read = () => { - try { - const raw = localStorage.getItem(KEY); - if (!raw) return null; - const entry = JSON.parse(raw); - /* Anything else under this key is a tampered or foreign value. */ - if (typeof entry.count !== "number" || typeof entry.at !== "number") return null; - return entry; - } catch (e) { - return null; - } - }; - - const cached = read(); - if (cached) show(cached.count); - if (cached && Date.now() - cached.at < MAX_AGE) return; - - /* Without a bound a hung connection leaves a first visit's slot empty for as - long as the tab is open. */ - const abort = new AbortController(); - const timer = setTimeout(() => abort.abort(), TIMEOUT); - - fetch("https://api.github.com/repos/bakirgdev/CrocApp", { - headers: { Accept: "application/vnd.github+json" }, - signal: abort.signal, - }) - .then((r) => (r.ok ? r.json() : Promise.reject(r.status))) - .then((data) => { - const n = data.stargazers_count; - if (typeof n !== "number") return; - try { - localStorage.setItem(KEY, JSON.stringify({ count: n, at: Date.now() })); - } catch (e) { - /* Storage disabled: every load refetches, which still works. */ - } - show(n); - }) - .catch(() => {}) - .finally(() => clearTimeout(timer)); - }); - - /* ---- Current section in the nav ---- */ - - feature(() => { - if (!("IntersectionObserver" in window)) return; - - const linkFor = new Map(); - const sections = []; - - for (const link of document.querySelectorAll(".nav__link")) { - const href = link.getAttribute("href"); - if (!href.startsWith("#")) continue; - const section = document.getElementById(href.slice(1)); - if (!section) continue; - linkFor.set(section, link); - sections.push(section); - } - - if (!sections.length) return; - - const visible = new Set(); - - const observer = new IntersectionObserver( - (entries) => { - for (const entry of entries) { - if (entry.isIntersecting) visible.add(entry.target); - else visible.delete(entry.target); - } - - /* Topmost visible section wins, so scrolling up and down agree. */ - const active = sections.find((section) => visible.has(section)); - - for (const [section, link] of linkFor) { - /* "location", not "true": these are places within one page. */ - if (section === active) link.setAttribute("aria-current", "location"); - else link.removeAttribute("aria-current"); - } - }, - /* Top band only: current once the heading nears the nav. */ - { rootMargin: "-20% 0px -70% 0px" } - ); - - for (const section of sections) observer.observe(section); - }); })(); diff --git a/web/landing/assets/img/favicon/apple-touch-icon.png b/web/landing/assets/img/favicon/apple-touch-icon.png index 1e9cfd20..af5574e5 100644 Binary files a/web/landing/assets/img/favicon/apple-touch-icon.png and b/web/landing/assets/img/favicon/apple-touch-icon.png differ diff --git a/web/landing/assets/img/favicon/favicon-96x96.png b/web/landing/assets/img/favicon/favicon-96x96.png index ac7a44fb..cfe3fa61 100644 Binary files a/web/landing/assets/img/favicon/favicon-96x96.png and b/web/landing/assets/img/favicon/favicon-96x96.png differ diff --git a/web/landing/assets/img/favicon/favicon.ico b/web/landing/assets/img/favicon/favicon.ico index 4cdf856e..9d5e4fd4 100644 Binary files a/web/landing/assets/img/favicon/favicon.ico and b/web/landing/assets/img/favicon/favicon.ico differ diff --git a/web/landing/assets/img/favicon/web-app-manifest-192x192.png b/web/landing/assets/img/favicon/web-app-manifest-192x192.png index 69fde546..bb187675 100644 Binary files a/web/landing/assets/img/favicon/web-app-manifest-192x192.png and b/web/landing/assets/img/favicon/web-app-manifest-192x192.png differ diff --git a/web/landing/assets/img/favicon/web-app-manifest-512x512.png b/web/landing/assets/img/favicon/web-app-manifest-512x512.png index c60c94e2..015f89d3 100644 Binary files a/web/landing/assets/img/favicon/web-app-manifest-512x512.png and b/web/landing/assets/img/favicon/web-app-manifest-512x512.png differ diff --git a/web/landing/assets/img/og.jpg b/web/landing/assets/img/og.jpg index 3b1897fd..6f434082 100644 Binary files a/web/landing/assets/img/og.jpg and b/web/landing/assets/img/og.jpg differ diff --git a/web/landing/assets/img/screenshots/iphone/send-code-dark.webp b/web/landing/assets/img/screenshots/iphone/send-code-dark.webp new file mode 100644 index 00000000..b72a16c7 Binary files /dev/null and b/web/landing/assets/img/screenshots/iphone/send-code-dark.webp differ diff --git a/web/landing/assets/img/screenshots/iphone/send-code-light.webp b/web/landing/assets/img/screenshots/iphone/send-code-light.webp new file mode 100644 index 00000000..31fe093e Binary files /dev/null and b/web/landing/assets/img/screenshots/iphone/send-code-light.webp differ diff --git a/web/landing/assets/img/screenshots/mac/send-code-dark.png b/web/landing/assets/img/screenshots/mac/send-code-dark.png deleted file mode 100644 index 3bd380bc..00000000 Binary files a/web/landing/assets/img/screenshots/mac/send-code-dark.png and /dev/null differ diff --git a/web/landing/assets/img/screenshots/mac/send-code-dark.webp b/web/landing/assets/img/screenshots/mac/send-code-dark.webp new file mode 100644 index 00000000..aae9498f Binary files /dev/null and b/web/landing/assets/img/screenshots/mac/send-code-dark.webp differ diff --git a/web/landing/assets/img/screenshots/mac/send-code-light.png b/web/landing/assets/img/screenshots/mac/send-code-light.png deleted file mode 100644 index 35840573..00000000 Binary files a/web/landing/assets/img/screenshots/mac/send-code-light.png and /dev/null differ diff --git a/web/landing/assets/img/screenshots/mac/send-code-light.webp b/web/landing/assets/img/screenshots/mac/send-code-light.webp new file mode 100644 index 00000000..d81a63c9 Binary files /dev/null and b/web/landing/assets/img/screenshots/mac/send-code-light.webp differ diff --git a/web/landing/index.html b/web/landing/index.html index 2825965e..4c0822a5 100644 --- a/web/landing/index.html +++ b/web/landing/index.html @@ -3,6 +3,11 @@ + + CrocApp | Send files with a code phrase + + + + @@ -41,18 +56,13 @@ + + + - - - - - stars - (opens in a new tab) @@ -116,9 +121,9 @@
-
+
-

Send files anywhere, end-to-end encrypted

+

Send files with a code phrase

Send files, folders and text to another device with a short code phrase. Free, open source and end-to-end encrypted. @@ -138,6 +143,7 @@

Send files anywhere, end-to-end encrypted
    +
  • iPhone, iPad and Mac
  • End-to-end encrypted @@ -148,21 +154,29 @@

    Send files anywhere, end-to-end encrypted

- +
- The CrocApp send screen on macOS: a code phrase, a Copy Code button, - a QR code for the other device to scan, and an end-to-end encrypted badge. + The CrocApp send screen on Mac and on iPhone: a code phrase, a Copy Code + button, a QR code for the other device to scan, and an end-to-end encrypted badge.
- - - + + + + + + + +
@@ -170,10 +184,10 @@

Send files anywhere, end-to-end encrypted
-

Why this exists

+

Why CrocApp

- Moving a file between two devices is supposed to be solved. It is solved three - different ways, and each one quits under a different condition. + Three common ways to move a file between devices each stop working in a different + situation.

@@ -261,7 +275,7 @@

CrocApp

How it works

-

Three steps on each side. Nothing to sign up for.

+

Three steps. Nothing to sign up for.

    @@ -321,7 +335,7 @@

    Enter it on the other device

    Features

    - Everything croc can do, with a native interface in front of it. + Most of croc's options, in a native app.

    @@ -333,8 +347,9 @@

    Send

  1. Files, several at once
  2. Whole folders
  3. Text and clipboard snippets
  4. -
  5. Send from any app via the share sheet
  6. -
  7. Show a QR code instead of reading it out
  8. +
  9. Send from any app with the share sheet on iPhone and iPad
  10. +
  11. Show a QR code, or share a link, instead of reading the code out
  12. +
  13. Send as Link: upload encrypted files so the receiver can download later
  14. Zip a folder before sending
  15. Exclude patterns, or respect .gitignore
  16. @@ -346,7 +361,8 @@

    Receive

    • Receive with a code phrase
    • Set your own code phrase, six characters or more
    • -
    • Scan a QR code
    • +
    • Scan a QR code on iPhone and iPad
    • +
    • Open a CrocApp link to fill in the code
    • See the file list before you accept
    • Resume interrupted transfers, confirm overwrites
    • Choose where files land
    • @@ -355,11 +371,11 @@

      Receive

      -

      Trust & control

      +

      Trust and control

      • Encryption badge and a plain-language explanation
      • Your own relay, with password and IPv6
      • -
      • Local Network Only setting
      • +
      • Local Network Only setting
      • Auto-accept off by default, and marked when on
      • Ask both devices to confirm
      • Turn compression off
      • @@ -371,12 +387,13 @@

        Trust & control

        Native

        • Progress, speed and cancel, with a Live Activity on iPhone
        • +
        • Quick send from the Mac menu bar
        • +
        • Shortcuts and Siri actions
        • Transfer history that stays on your device
        • -
        • Automatic race between local network and relay
        • +
        • Tries the local network and the relay at once
        • Files app integration
        • Drag and drop on Mac
        • -
        • Light and dark
        • -
        • Dynamic Type and VoiceOver
        • +
        • Dynamic Type
@@ -387,18 +404,32 @@

Native

Download

-

Free, and free of charge. No trial, no tier, no account.

+

Free. No account, no tiers. The Mac disk image is available now; the App Store versions are coming.

-
-

iPhone & iPad

-

Coming to the App Store.

+

iPhone and iPad

+

Coming soon to the App Store.

iPhone & iPad

-

Mac

-

Coming to the Mac App Store.

+

Mac App Store

+

Coming soon to the Mac App Store.

Mac decoding="async" />
- -
- -

Mac, direct

-

Get the disk image for Apple silicon.

- - - Latest Release - (opens in a new tab) - -

- iOS 26 or later · macOS 26 or later. The Mac disk image (version 1.0.0 or later) and the App Store versions - arrive at launch. + Needs iOS 26 or later, or macOS 26 or later on Apple silicon. + Release notes (opens in a new tab) + and + how to verify a download.
Receive in a browser: Powered by croc -

-
-
-

How it was made

-
- -
-

- croc's Go library is compiled to an XCFramework with gomobile and driven from a Swift - actor. It is not a subprocess, because iOS does not allow those. That is why the Android - clients' architecture does not port to Apple platforms. -

-

SwiftUI throughout, targeting iOS 26 and macOS 26.

-
-
-
- -
-
-
-

Inspirations

-

- CrocApp exists because of these. Some are the foundation, some showed what good looks - like on other platforms. -

-
- -
    -
  • -

    - croc -

    -

    - The engine, and the protocol. Everything CrocApp does, croc does underneath. -

    -
  • -
  • -

    - magic-wormhole -

    -

    - The original code-phrase transfer, and croc's own inspiration. -

    -
  • -
  • -

    - LocalSend -

    -

    - Proof that a cross-platform transfer app can be genuinely pleasant to use. -

    -
  • -
  • -

    - croc-app -

    -

    - The Android client. The best mobile reference for what a croc GUI should feel like. -

    -
  • -
  • -

    - crock -

    -

    A desktop croc GUI, and where the QR deeplink idea comes from.

    -
  • -
  • -

    - crocgui -

    -

    The long-running cross-platform croc GUI.

    -
  • -
-
-
-
@@ -568,8 +513,8 @@

Questions

Transfers are end-to-end encrypted, the code phrase authenticates both devices, and - the relay only ever sees ciphertext. That is the whole claim, and it is croc's - design rather than anything CrocApp adds. + the relay only ever sees ciphertext. That is croc's design rather than anything + CrocApp adds.

CrocApp has not had a formal third-party security audit. The code is open if you @@ -640,7 +585,8 @@

Questions

Not from CrocApp, which is an Apple-platform app. Use the croc CLI, which runs - everywhere, or one of the other clients listed under Inspirations. They all speak + everywhere, or one of the other croc clients, listed under + Inspirations in the docs. They all speak the same protocol.

@@ -679,13 +625,16 @@

Contribute

alone.

- After that: VoiceOver and Dynamic Type passes, translations once the copy settles, and - anything in the issue tracker marked help wanted. + After that: accessibility testing with VoiceOver and larger text, translations once + the copy settles, and anything in the issue tracker marked help wanted. +

+

+ Read how it was made and + what inspired it.

- +
-
+
- + diff --git a/web/landing/r/receive.js b/web/landing/r/receive.js new file mode 100644 index 00000000..6349037b --- /dev/null +++ b/web/landing/r/receive.js @@ -0,0 +1,27 @@ +(function () { + function readCode() { + try { + return decodeURIComponent(location.hash.slice(1)); + } catch (e) { + /* A malformed escape in the fragment: treat it as no code. */ + return ""; + } + } + + function render() { + var code = readCode(); + // croc rejects shorter codes (crocmobile minCodeLength); a stray + // fragment such as "#top" must not read as one. + var valid = code.length >= 6 && !/\s/.test(code); + document.getElementById("has-code").hidden = !valid; + document.getElementById("no-code").hidden = valid; + if (!valid) return; + var encoded = encodeURIComponent(code); + document.getElementById("code").textContent = code; + document.getElementById("open-app").href = "crocapp://receive?code=" + encoded; + document.getElementById("open-browser").href = "https://getcroc.com/?code=" + encoded; + } + + render(); + addEventListener("hashchange", render); +})(); diff --git a/web/landing/sitemap.xml b/web/landing/sitemap.xml index 92dddc4d..6d7f1d83 100644 --- a/web/landing/sitemap.xml +++ b/web/landing/sitemap.xml @@ -2,14 +2,14 @@ https://crocapp.dev/ - 1.0 + 2026-10-20 https://crocapp.dev/support/ - 0.5 + 2026-10-20 https://crocapp.dev/privacy/ - 0.3 + 2026-10-20 diff --git a/web/landing/styles.css b/web/landing/styles.css index 3ea0b885..08c8e566 100644 --- a/web/landing/styles.css +++ b/web/landing/styles.css @@ -120,14 +120,12 @@ html { /* min() keeps the column floor from overflowing a 375px viewport. */ .grid, -.steps, -.inspo { +.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(var(--grid-min-card-web), 100%), 1fr)); } -.grid, -.inspo { +.grid { gap: var(--space-5); } @@ -168,7 +166,7 @@ html { padding-inline: var(--space-5); font-weight: var(--weight-semibold); color: var(--color-on-accent); - background: var(--color-accent); + background: var(--color-accent-solid); border-radius: var(--radius-sm); } @@ -236,14 +234,6 @@ html { } } -/* WCAG 1.4.1: the current section cannot be colour alone. Underline rather than - weight, which would reflow the row on every scroll. */ -.nav__link[aria-current] { - color: var(--color-text-primary); - text-decoration: underline; - text-underline-offset: var(--space-2); -} - /* Breakpoints are literals by necessity: a custom property does not resolve inside a media condition. design/spacing-layout.md → Breakpoints is the only place these numbers are defined. @@ -251,7 +241,7 @@ html { Dropping every link on a phone would take Download with it, and the footer carries Docs at every width. */ @media (width < 48rem) { - .nav__link:not(.nav__link--primary) { + .nav__links--sections .nav__link:not(.nav__link--primary) { display: none; } } @@ -344,7 +334,7 @@ html { .btn--prominent { color: var(--color-on-accent); - background: var(--color-accent); + background: var(--color-accent-solid); box-shadow: var(--shadow-sm); } @@ -547,17 +537,6 @@ html { flex: none; } -/* The slot is exactly as wide as its number; the formatter caps that at four - characters, so a late-arriving count can only move the row by a little. */ -.nav__stars { - font-variant-numeric: tabular-nums; - color: var(--color-text-secondary); -} - -.nav__stars.is-empty { - display: none; -} - /* The glyph shows the theme you would switch to, so light shows a moon. A display swap cannot ride light-dark(), hence the media mirror below. */ .theme-toggle__sun { @@ -620,7 +599,7 @@ html { /* Two columns only once the mockup can hold its cap beside a readable measure. */ @media (width >= 64rem) { .hero__inner { - grid-template-columns: 1fr auto; + grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-11); } } @@ -646,45 +625,62 @@ html { margin-block-start: var(--space-2); } -/* Hero screenshot. The window shape and its rounded corners are in the PNG's - alpha, so this adds no frame of its own. */ +/* Hero screenshots. The Mac window's shape and corners are in the image's alpha, so + this adds no frame of its own. Widths 1.6 : 1 make the two shots about the same + height (Mac 4:5, iPhone 660:1434). */ .hero__mockup { display: flex; justify-content: center; + align-items: center; + gap: var(--space-5); + max-width: var(--content-max-width-prose-web); margin: 0; + margin-inline: auto; } +/* components.md → Card: a hairline plus the card shadow, on a radius, so a + screenshot on the page fill still has an edge in light. No device bezel. The + wrapper clips the image, which also rounds the iPhone shot's square corners. */ .hero__shot { - width: 100%; - max-width: var(--content-max-width); - height: auto; + display: block; + flex: 1 1 0; + min-width: 0; + overflow: hidden; + border: var(--border-hairline) solid var(--color-separator); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-md); } -/* Mirrors tokens.css: the OS decides by default, [data-theme] wins in both - directions. A could not do the second half. */ -.hero__shot--dark { - display: none; +.hero__shot--iphone { + border-radius: var(--radius-xl); } -@media (prefers-color-scheme: dark) { - .hero__shot--light { - display: none; +/* Side by side the shots shrink to unreadable on a phone: stack them, each wide + enough to read the code phrase. */ +@media (width < 40rem) { + .hero__mockup { + flex-direction: column; } - .hero__shot--dark { - display: block; + .hero__shot { + flex: none; + width: 100%; + } + + .hero__shot--iphone { + max-width: var(--phone-shot-max-width-web); } } -[data-theme="light"] .hero__shot--light, -[data-theme="dark"] .hero__shot--dark { - display: block; +.hero__shot--mac { + flex-grow: 1.6; } -[data-theme="light"] .hero__shot--dark, -[data-theme="dark"] .hero__shot--light { - display: none; +.hero__shot img { + display: block; + width: 100%; + height: auto; } /* Content sections */ @@ -756,6 +752,16 @@ html { color: var(--color-text-primary); } +/* On a phone the nowrap cells push "No account needed" off screen with nothing + to say so. Let the cells wrap instead, so all three columns fit. */ +@media (width < 40rem) { + .compare th, + .compare td { + padding: var(--space-3); + white-space: normal; + } +} + /* Steps */ .steps { @@ -873,16 +879,16 @@ html { } .croc .card__body, -.support .card__body { +.sponsor .card__body { color: var(--color-text-primary); } .contribute__actions, -.support__actions { +.sponsor__actions { margin-block-start: var(--stack-web); } -.support__actions { +.sponsor__actions { margin-block-start: var(--space-6); } @@ -1004,6 +1010,16 @@ html { margin-inline-start: auto; } +/* Alone on a row under the text, the links wrap from the start edge instead of + hanging off the end of a half-empty line. */ +@media (width < 40rem) { + .footer__links { + flex-basis: 100%; + /* The links' own padding sits inside the text's left edge. */ + margin-inline-start: calc(var(--space-2) * -1); + } +} + .footer__links a { display: inline-flex; align-items: center; diff --git a/web/landing/support/index.html b/web/landing/support/index.html index 5526f258..4f14f429 100644 --- a/web/landing/support/index.html +++ b/web/landing/support/index.html @@ -3,6 +3,7 @@ + Support | CrocApp + + + + + + + + + + + + + + + + + + + + + - - @@ -142,7 +156,7 @@

Privacy