Commit Graph
2024 Commits
Author SHA1 Message Date
SnapOtterandGitHub 190d4c2a00 fix(auth): close the MFA policy lockout and add self-service enrollment (#531)
Fixes #529 (opened investigating #515).

Setting MFA policy to "required"/"admins only" saved regardless of whether the mfa enterprise feature was licensed, and there was no enrollment UI at all, so any instance that flipped the toggle locked every unenrolled user out with no way back in. The login page and Settings save also both collapsed the resulting error into a generic message, hiding the real reason.

- Reject saving mfaPolicy to admins_only/required server-side unless mfa is licensed
- Surface the specific server error on login and on a failed settings save instead of a generic fallback
- Add a self-service two-factor authentication enrollment flow (QR code, manual entry, recovery codes, verify, disable) so a licensed admin can actually satisfy the policy before it's enforced
- Fix a pending-enrollment dead end, silent error swallowing in verify/disable, and a silent clipboard-copy failure on the recovery codes screen
- Add the integration test that actually proves the fix: a real login attempt returns 403 MFA_ENROLLMENT_REQUIRED
2026-07-16 18:07:27 +08:00
SnapOtterandGitHub d88999e7a9 feat(resize): add aspect-ratio proportion presets (#530)
Add a proportion chip row (Free, Original, 1:1, 4:3, 3:2, 16:9, 3:4, 9:16) to the Resize tool's Custom tab. Picking a ratio locks width and height so editing one recomputes the other, and prefills the largest box of that ratio that fits the source so it never upscales. Free stays the default, preserving existing behavior. Replaces the previously non-functional lock-aspect button. Frontend only, no backend or schema change; adds strings to all 21 locales.
2026-07-16 16:12:08 +08:00
SnapOtterandGitHub 0e608e1524 chore(landing): load LiftOff badge from their remote URL (#524)
Switch the footer LiftOff badge image to lift-off.sh's hosted webp so their launch-verification step passes. Removes the unused self-hosted copy; the do-follow link is unchanged.
2026-07-16 15:26:23 +08:00
SnapOtterandGitHub e43c072602 chore(landing): add LiftOff launch badge to footer (#523)
Self-host the LiftOff badge webp under public/badges/ and add it to the footer featured-on row with a do-follow link to lift-off.sh/p/snapotter.
2026-07-16 15:18:24 +08:00
SnapOtterandGitHub 7d938af1f9 fix(compress-pdf): land close to the target size, honestly (#522)
Target-size compression had only a coarse DPI lever, so it undershot badly (a 350KB target could land at 216KB) and silently missed unreachable targets. Adds JPEG quality as a second lever (forced re-encode so it bites on JPEG scans), folds both into one monotonic quality axis that target-size binary-searches, reports targetMet honestly in the panel across 21 locales, and flips the tool to async for the extra passes. Quality-mode output sizes shift intentionally (slider now drives JPEG quality at full resolution in its top half).
2026-07-16 15:08:21 +08:00
SnapOtterandGitHub f858c4cea0 feat: clearer, disambiguated tool names across all surfaces (#520)
Renames 18 ambiguous or hard-to-search tool names so image tools self-qualify like the other modalities ("Compress" becomes "Compress Image"), and cleans up a few awkward names. Propagated across search (constants.ts), display (en.ts + 20 locales), the OpenAPI base spec + 20 locale specs, and the docs tool-page headings in 21 languages. Removes the duplicate "Normalize Audio" summary shared by the video and audio endpoints. Tool ids and routes are unchanged, so no API paths or bookmarks break.
2026-07-15 21:55:51 +08:00
SnapOtterandGitHub 991c981529 fix: make OCR portable and reliable across AMD64 and ARM64 (#519)
* fix: make OCR portable and reliable

* fix: harden OCR installation portability

* fix: pin OCR partials across downloads

* fix: make OCR execution reliably asynchronous

* fix: harden OCR portability and docs routes

* fix: preserve decoder and docs safeguards
2026-07-15 03:34:24 +08:00
Matt Van HornandGitHub 58121f205f fix: give remove-background job timeouts an actionable failure message (#518)
Extends the worker.ts timeout failure detail with actionable guidance (first-run model download, input too large for CPU inference, or busy/unavailable worker) while preserving the "Timed out after Ns" prefix so error_code classification, SSE terminal replay, and existing timeout assertions keep working. Adds a test assertion for the guidance.

Fixes #494
2026-07-14 22:43:08 +08:00
dependabot[bot]andGitHub 73e48c24d1 chore(deps): bump the production-deps group with 17 updates (#509) 2026-07-13 20:26:06 +08:00
dependabot[bot]andGitHub ec72ff100d chore(deps-dev): bump the dev-deps group with 10 updates (#510) 2026-07-13 19:52:48 +08:00
dependabot[bot]andGitHub a39b3fe47f chore(deps): bump node from c601a46 to a25c993 in /docker (#506) 2026-07-13 19:52:46 +08:00
SnapOtterandGitHub 30d36d7949 fix(security): bump Pillow to 12.3.0, fixes 5 disclosed CVEs (#517) 2026-07-13 19:27:16 +08:00
SnapOtterandGitHub 5bd052286c fix(landing): stop mangling #hash fragments in localized links (#516) 2026-07-13 18:17:27 +08:00
SnapOtterandGitHub 74e7d23aba fix(landing): rework footer badge/switcher layout (#514) 2026-07-13 17:39:29 +08:00
SnapOtterandGitHub 2dee9ead0b feat(landing): move language switcher from navbar to footer (#513) 2026-07-13 16:59:09 +08:00
SnapOtterandGitHub ce54d06e79 feat(landing): add Twelve Tools and Wired Business footer badges (#512) 2026-07-13 16:49:01 +08:00
SnapOtterandGitHub e1b8c24e5d feat(analytics): instance census, full capture, richer error context (#511)
Add a once-per-boot instance_started event (arch, os, deploy_mode,
gpu_present) so the fleet architecture mix is measurable. It reuses the
existing per-instance instance_id and is exempt from the volume sample
rate, since a census that fires once per boot must not be thinned.

Restore useful capture depth now that the sponsored plan removes the
quota pressure behind the earlier hardening:

- PostHog sample rate 0.1 to 1.0 (full analytics when enabled); the
  property allowlist still blocks file data.
- Sentry per-instance ceiling 20 to 500/hr, breadcrumb trail restored
  (sanitized: urls/paths redacted, data payloads dropped), full stack
  paths kept; local vars, request bodies, and PII still dropped. Both
  api and web.

Honor ANALYTICS_ENABLED=false as an opt-out alias: it was documented on
the Docker Hub README but never wired in 2.x, so anyone who set it was
still tracked.

All capture stays behind the analytics opt-out gate.
2026-07-13 14:23:16 +08:00
SnapOtterandGitHub b6fdabaea8 ci(release): keep image attestations in GitHub's API, drop provenance sidecars (#504)
Stop pushing SLSA attestations to the registries as OCI referrer tags (attest.yml: push-to-registry: false) and disable buildx's default provenance sidecars (release.yml: provenance: false). GHCR rendered both as package versions / unknown-unknown architecture entries on the package page. The release/publish flow (publish-images gate, RELEASE_TOKEN, web Sentry DSN) is unchanged.
2026-07-12 05:02:15 +08:00
SnapOtterandGitHub c06a672313 chore: make AGPL license detectable (#467)
Replace the root LICENSE file's custom preamble with the verbatim AGPL-3.0 text so GitHub's license detector and directory scrapers recognize the repo as AGPL-3.0. The dual-license/commercial explanation moves to LICENSING.md.
2026-07-12 00:00:50 +08:00
SnapOtterandGitHub 601557edae feat(erase-object): add freeform lasso selection mode (#503)
Adds a Brush | Lasso toggle to the object eraser. Lasso lets the user drag a freeform loop that auto-closes and fills into the mask, so they select around a subject instead of painting every pixel. Frontend-only; the mask contract is unchanged. Also un-skips the erase-object e2e suite via a shared mockAiFeaturesInstalled helper (7 tests now run; 2 multi-file tests fixme'd for a pre-existing tool-page remount bug). Closes #492.
2026-07-11 22:27:51 +08:00
SnapOtterandGitHub 380419dd06 fix(erase-object): crop-based HD inpainting to remove ghosting and blur (#501)
Dilate the mask, crop a padded box around it, run LaMa on the crop at 512, and composite back cleanly. Fixes the ghost remnants (#491) and sharpens small/medium-object fills in high-res images (#141 core). Same model, still offline, no new bundle. Closes #491.
2026-07-11 22:27:35 +08:00
SnapOtterandGitHub cb5db59f77 feat(tools): remove background from animated GIFs (WebP, APNG) (#502)
Adds a dedicated remove-gif-background AI tool: removes the background from an animated GIF, WebP, or APNG frame by frame and reassembles a transparent (or composited) animation in WebP, APNG, or GIF, with full per-frame effects. Reuses the background-removal bundle. Verified end-to-end with the real rembg model.

Closes #496.
2026-07-11 19:53:00 +08:00
SnapOtterandGitHub e7cfc00fe1 fix: preserve colored blocks in PDF-to-Word (#500) 2026-07-11 19:20:32 +08:00
SnapOtterandGitHub 430b87eda0 feat(onboarding): collect install method and friction area in the usage survey (#499)
Adds install method and hardest-setup-area as two optional questions to the first-login usage survey, so these fields are collected at onboarding scale instead of only via the low-traffic admin installer card. Both stay null until chosen and are omitted from the payload when unanswered. No API change and no new i18n; reuses the shared feedback schema and existing locale strings.
2026-07-11 16:46:28 +08:00
SnapOtterandGitHub b457596649 fix(telemetry): sharpen Sentry signal for v2.1.0 residual defects (#498)
Follow-ups to the v2.1.0 Sentry telemetry overhaul, found by reviewing live release:2.1.0 events:

- error_code tag was empty because reportError read only the top-level err.code; add extractErrorCode() to walk the cause chain (pg SQLSTATE, node E-code, else first short code).
- InputValidationError from a tool's processV2 in the worker was logged as error_class=bug; classify it as expected for any source. Worker-side ZodError stays a bug (schema drift).
- AI dispatcher timeouts rejected with a bare Error, which the sanitizer scrubbed to a message-less "Error: Error"; reject with an operational SafeError (code "timeout") at both timeout sites.

Each fix written failing-test-first; affected and adjacent unit suites green plus full CI (integration + e2e).
2026-07-11 16:18:26 +08:00
SnapOtterandGitHub b8c3700c15 fix(landing-i18n): commit missed landing-seo re-translation (remove.bg comparison)
The remove.bg comparison + tweaked alternatives rows, re-translated into all 20 languages but missed in the merge PR. Admin-merged (landing-only PR, skipped Integration matrix contexts never report; known repo deadlock). pnpm i18n:check passes on all 4 surfaces; landing build clean.
2026-07-11 15:12:42 +08:00
SnapOtterandGitHub 1bc9fe93ec feat(landing-i18n): recall a returning visitor's chosen language
Render-blocking head script that routes a returning visitor to the language they explicitly picked (stored on switch). Only on default English pages; skips English-only tool-detail pages; crawler-safe. Admin-merged: landing-only PR, the skipped Integration matrix jobs never report the required contexts (known repo deadlock). Logic verified across 10 scenarios; landing build + typecheck clean.
2026-07-11 15:00:13 +08:00
SnapOtterandGitHub 4963ab3bbd feat(docs-i18n): translate all documentation into 20 languages
All 181 docs markdown files translated into 20 languages (apps/docs/<locale>/**). Companion to the i18n code PR; admin-merged because the file count exceeds GitHub's per-PR CI trigger limit. Validated by pnpm i18n:check (all surfaces, 0 stale/missing) and a clean all-locale docs build.
2026-07-11 13:52:47 +08:00
SnapOtterandGitHub 00b651c9f8 feat(i18n): 21-language pipeline, landing/docs/API wiring, landing+API translations
Shared Claude Code translation pipeline (scripts/i18n, no API key) plus Astro/VitePress/Scalar i18n wiring. Landing and API reference translated into all 20 languages; docs i18n wiring + English source anchors. The translated docs markdown (apps/docs/<locale>/**, 3,620 files) follows in a companion PR because it exceeds GitHub's per-PR CI file limit.
2026-07-11 13:01:55 +08:00
SnapOtterandGitHub 2e91368816 ci(release): authenticate main pushes with an admin RELEASE_TOKEN (#486)
Point semantic-release's version-bump push and the docs-changelog push at a RELEASE_TOKEN admin PAT so they clear the 16 required checks (default token is rejected). Falls back to the default token, so no change until the secret is set. Documents creating/rotating the token in RELEASE.md.
2026-07-11 12:49:02 +08:00
SnapOtterandGitHub 4a5a6718e6 docs: point home modality chips at the sectioned tool pages (#485)
The tool reference moved to /tools/<section>/<toolId>, but the five modality chips on the docs home still linked to the old flat paths. A full page load survives via the Cloudflare _redirects shim, but VitePress client-side navigation bypasses it and lands on the 404 page.

A dist-wide internal link check confirms these five were the only remaining stale links in the built site. The homepage e2e spec now pins all five chip hrefs and click-navigates one chip client-side, which is exactly the path that broke.
2026-07-11 12:39:26 +08:00
SnapOtterandGitHub 4426c733e7 docs: declutter the docs home hero and fix the enterprise door CTA (#483)
The repositioning in #469 pushed the full marketing pitch into the docs home hero: eyebrow badge, marketing h1, a bolded two-sentence value prop, and a second paragraph, all before the install command. The hero now states what the page is and gets out of the way: "SnapOtter Documentation" plus one line that keeps the self-hosted file-processing positioning, then the one-command install and quick links.

The Enterprise door CTA said "Evaluate for your org" but linked to /guide/architecture, already the first link in that same card. It now says "See enterprise features" and points at https://snapotter.com/enterprise, where the evaluation journey (features, pricing, demo booking) actually lives.

Also repairs the docs homepage e2e spec, which still asserted pre-2.0 copy and has been failing nightly since the hero changed, and adds coverage for both door CTAs.
2026-07-11 11:43:08 +08:00
SnapOtterandGitHub b369b4fb41 ci(release): gate image publish behind a manual approval (#482)
Attach the manifest job to a publish-images GitHub Environment so Docker Hub + GHCR tags only go live after a maintainer approves the release run. Build + Trivy scan still run automatically; approval is the last step. Adds RELEASE.md runbook.
2026-07-11 11:09:53 +08:00
SnapOtterandGitHub d572b5c33c chore(branding): reframe assets to self-hosted infrastructure positioning (#479)
Regenerate the social/OG card (200+ tools, Private file processing, self-hosted infrastructure) and sync to landing/web/docs; update banner, press kit, package + OpenAPI + Docker Hub descriptions, a leaked docs count, and the English About string.
2026-07-11 02:07:15 +08:00
semantic-release-bot c6baf6018d chore(release): 2.1.0 [skip ci]
# [2.1.0](https://github.com/snapotter-hq/snapotter/compare/v2.0.0...v2.1.0) (2026-07-10)

### Bug Fixes

* **demo:** boot to dashboard, sample-data notice, robust mobile editor icon ([#464](https://github.com/snapotter-hq/snapotter/issues/464)) ([a94b69b](https://github.com/snapotter-hq/snapotter/commit/a94b69b14f783c07abfe757e21314f580fbda556))
* **demo:** point banner "Self-host SnapOtter" link at the docs guide ([#466](https://github.com/snapotter-hq/snapotter/issues/466)) ([463ccff](https://github.com/snapotter-hq/snapotter/commit/463ccff5cb91c4b2d0f2c7309ea77789544ad2c3))
* **demo:** populate admin data, fix settings crash and mobile editor icon ([#463](https://github.com/snapotter-hq/snapotter/issues/463)) ([7329bc6](https://github.com/snapotter-hq/snapotter/commit/7329bc6a1334b925cf95384d6ddc172f04a86610))
* error-only Sentry telemetry, storm-proof capture, and crash fixes ([#476](https://github.com/snapotter-hq/snapotter/issues/476)) ([ae6a4c8](https://github.com/snapotter-hq/snapotter/commit/ae6a4c8b7c9275ccd8930251d429181568f83453))
* **landing:** clarify OIDC is free, SAML is enterprise on pricing ([#461](https://github.com/snapotter-hq/snapotter/issues/461)) ([c2c9a9e](https://github.com/snapotter-hq/snapotter/commit/c2c9a9ed9bea9c66efec84b9e0b9b2ebbf863073))
* **landing:** fix top nav overflow and text overlap ([#473](https://github.com/snapotter-hq/snapotter/issues/473)) ([ffeacd4](https://github.com/snapotter-hq/snapotter/commit/ffeacd4b3c7b5858d9048c2521569256e3569490))
* **landing:** green the landing e2e suite ([#470](https://github.com/snapotter-hq/snapotter/issues/470)) ([10ae6d1](https://github.com/snapotter-hq/snapotter/commit/10ae6d1d3d6ce8a527937bfa31e76ba392bc09e0))
* **landing:** highlight Open Source as Most Popular tier ([#462](https://github.com/snapotter-hq/snapotter/issues/462)) ([e468cef](https://github.com/snapotter-hq/snapotter/commit/e468cef6c0e28b4736dee32d2cf8c2ab1968a59c))
* **landing:** reposition residual meta framing and demote homepage tool count ([#471](https://github.com/snapotter-hq/snapotter/issues/471)) ([958c3e8](https://github.com/snapotter-hq/snapotter/commit/958c3e8513eb3a4c3be7488894981fc8794b1c5f))
* reliable, self-healing AI feature-bundle installs ([#472](https://github.com/snapotter-hq/snapotter/issues/472)) ([a731c3d](https://github.com/snapotter-hq/snapotter/commit/a731c3d1fe8303296e90cd138a01e903df871bb7))
* restyle sponsor button ([37a3cfc](https://github.com/snapotter-hq/snapotter/commit/37a3cfc84477c10831f9ae61f183f4ab4ef45d50))
* reword sponsor button to "Support us" ([#468](https://github.com/snapotter-hq/snapotter/issues/468)) ([331e3bf](https://github.com/snapotter-hq/snapotter/commit/331e3bfde04035151612275d9ae269909fed87a8))
* update python protobuf dependency ([780624e](https://github.com/snapotter-hq/snapotter/commit/780624e168cfda5abf3b2501455fe62674550fcf))

### Features

* **demo:** populate the Files library with sample files ([#465](https://github.com/snapotter-hq/snapotter/issues/465)) ([a6e8f75](https://github.com/snapotter-hq/snapotter/commit/a6e8f75074e38b8e5d856311d4423e8a936ae690))
* **landing:** add dismissible 2.0 launch banner ([ea7a671](https://github.com/snapotter-hq/snapotter/commit/ea7a671ccf29bcbab7a94c28efcbf6e1b9506b34))
* **landing:** add Product dropdown to nav ([#475](https://github.com/snapotter-hq/snapotter/issues/475)) ([3d1744a](https://github.com/snapotter-hq/snapotter/commit/3d1744aec84049f1f296f1cce8f6fb726cf7f835))
* **landing:** restore Developers nav link, swap out Features anchor ([#474](https://github.com/snapotter-hq/snapotter/issues/474)) ([a08afbc](https://github.com/snapotter-hq/snapotter/commit/a08afbc80afefb11cbc13e629d31225a6dceda2f))
* reposition to self-hosted file-processing infrastructure ([#469](https://github.com/snapotter-hq/snapotter/issues/469)) ([af011d5](https://github.com/snapotter-hq/snapotter/commit/af011d55381f8b57797984b1c5b2ca974a033d1c))
v2.1.0
2026-07-10 13:55:46 +00:00
SnapOtterandGitHub ae6a4c8b7c fix: error-only Sentry telemetry, storm-proof capture, and crash fixes (#476)
Removes Sentry tracing entirely (BullMQ idle polling burned 4.8M transactions in 2 days at the baked 0.1 rate), decouples PostHog sampling, and replaces the type-only error scrub with a vetted-field sanitizer plus SafeError/ToolInputError contracts. One classified capture path with per-signature throttles and a per-process ceiling makes storms impossible (NODE-1E was 4,541 events from one 30s loop). Browser errors move to a dedicated web Sentry project with their own source maps. Adds the SNAPOTTER_TELEMETRY runtime kill switch and silences test fleets.

Crash fixes: remote 204/304 SSRF process kill (NODE-20), conversion-preset boot crash loop (NODE-21), Redis version preflight + unhandled subscribe rejection (NODE-1T), Sign PDF on plain-http origins (NODE-1K/1M), wavesurfer/pdf.js teardown rejections (NODE-1P/1N), bundle-import ZlibError to 400 (NODE-1Z), chart-maker input errors declassified (NODE-1H/1J), asset requests skip the session DB lookup (NODE-1D).
2026-07-10 21:41:49 +08:00
SnapOtterandGitHub 3d1744aec8 feat(landing): add Product dropdown to nav (#475)
Adds a CSS-only Product dropdown (Developers, Self-hosted tools, Alternatives) to the top nav and restores the lg breakpoint. Mobile menu lists items flat. Updated homepage e2e (navbar + dropdown-hover tests, footer scope). Verified at 1024/1280px, 63/63 landing e2e.
2026-07-10 20:09:57 +08:00
SnapOtterandGitHub a08afbc80a feat(landing): restore Developers nav link, swap out Features anchor (#474)
Restores Developers to the top nav by swapping out the Features homepage anchor. Nav is now Enterprise, Pricing, Alternatives, Developers, Docs, Talk to a human. Updated two e2e assertions that checked for a Features nav link. Verified visually at 1120/1280px and 62/62 landing e2e.
2026-07-10 16:00:56 +08:00
SnapOtterandGitHub a731c3d1fe fix: reliable, self-healing AI feature-bundle installs (#472)
Make on-demand AI feature-bundle installs reliable and self-healing, closing
the failure modes behind most "some tool doesn't work" reports.

Multi-bundle installs: tools needing more than one bundle (Passport Photo,
Enhance Faces) install every required bundle from one action and stay
not-installed until all are present. Verified across all 19 AI tools.

Downloads: self-heal the accelerated Hugging Face (Xet) client so an upgraded
venv no longer silently falls back to slow urllib; restart instead of
corrupting a resumed partial when a proxy ignores Range and returns 200;
verify the completed size; fail fast on disk-full and HTTP 4xx; retry
transient errors five times; add hf_transfer fallback and document Xet egress.

Install integrity: crash-atomic venv writes so a killed or out-of-space
install can no longer tear the shared venv and break other tools; a boot
breadcrumb reseeds a torn venv to a clean state automatically; a post-install
smoke import test refuses to record a bundle whose libraries cannot load; an
install watchdog stops a wedged installer that would otherwise hold the venv
writer lock forever.

Adds unit and end-to-end tests for every failure mode above.
2026-07-10 07:32:48 +00:00
SnapOtterandGitHub ffeacd4b3c fix(landing): fix top nav overflow and text overlap (#473)
Fixes the broken top navbar (logo/Features collision, wrapping CTAs). Removes the Developers link (kept in footer), adds shrink-0/whitespace-nowrap, and shows the horizontal nav at min-[1120px] with a hamburger below. Verified visually at 1024/1120/1152/1280px; 62/62 e2e, build green. Admin merge: landing-src-only, required matrix contexts path-skip and never report.
2026-07-10 15:18:33 +08:00
SnapOtterandGitHub 958c3e8513 fix(landing): reposition residual meta framing and demote homepage tool count (#471)
Follow-up to #469. Homepage/enterprise/FAQ JSON-LD and meta now say 'file-processing infrastructure' (not 'suite'), and the visible homepage counts (ToolGrid subtitle, Pricing bullet) plus SEO meta say '200+'. Removed the orphaned toolCount/TOOLS references. Leaves the /tools catalog and ToolGrid filter-tab functional counts exact. Admin merge: landing-src-only PR, required matrix contexts path-skip and never report.
2026-07-10 15:00:55 +08:00
SnapOtterandGitHub 10ae6d1d3d fix(landing): green the landing e2e suite (#470)
Repairs 6 pre-existing landing Playwright failures: launch-banner external-link noopener, one-h1 assertion auto-wait, nav label drift to 'Talk to a human', privacy 'Analytics' heading, and pricing 'Let's talk' CTA.
2026-07-10 14:03:29 +08:00
SnapOtterandGitHub af011d5538 feat: reposition to self-hosted file-processing infrastructure (#469)
Leads public copy with self-hosted file-processing infrastructure and demotes tool count to a proof point across README, docs, llms.txt, DockerHub, and the landing site. Adds a /self-hosted hub plus 7 job-intent SEO pages with a build-time validator, deepens the flagship /alternatives pages, adds a remove.bg page, three shared components, and landing e2e coverage.
2026-07-10 13:26:41 +08:00
SnapOtterandGitHub 331e3bfde0 fix: reword sponsor button to "Support us" (#468)
Reword the top-nav sponsor button from "Keep it free" to "Support us" across all 21 locales and update the e2e assertion.
2026-07-10 03:34:20 +00:00
SnapOtter 780624e168 fix: update python protobuf dependency 2026-07-08 13:11:46 +08:00
SnapOtter 37a3cfc844 fix: restyle sponsor button 2026-07-08 12:25:46 +08:00
SnapOtter c1667f5b02 docs: mention analytics opt-out in getting started 2026-07-08 11:56:47 +08:00
SnapOtterandGitHub 463ccff5cb fix(demo): point banner "Self-host SnapOtter" link at the docs guide (#466)
The demo banner link now opens docs.snapotter.com/guide/getting-started in a new tab instead of the GitHub repo.
2026-07-08 00:22:08 +08:00
SnapOtter f4da5ae3c7 docs: highlight layer-based image editor 2026-07-08 00:02:19 +08:00
SnapOtterandGitHub a6e8f75074 feat(demo): populate the Files library with sample files (#465)
Seed eight sample files across modalities in the demo Files library and mock the list (search + pagination), details with version history, bulk delete, and thumbnails. Thumbnails are generated colour-coded SVG tiles served through the interceptable fetch path, so the grid always renders with no real file bytes. Uploads/processing stay disabled.
2026-07-07 23:49:05 +08:00