Commit Graph
89 Commits
Author SHA1 Message Date
SnapOtterandGitHub ef342c268b docs: clarify nvidia cuda ai support (#378) 2026-06-29 21:29:00 +08:00
SnapOtter 1d99acf9ee feat: merge PostHog customer feedback 2026-06-29 18:19:18 +08:00
SnapOtter 649e65b035 feat: add PostHog customer feedback 2026-06-29 18:16:33 +08:00
SnapOtter c6319cf8a9 fix(security): harden auth and outbound fetches 2026-06-29 17:54:12 +08:00
SnapOtterandGitHub 084a9c9faa feat: all-in-one embedded single-container mode (#377)
Embedded Postgres 17 + Redis via s6-overlay when DATABASE_URL/REDIS_URL are unset; restores the one-command docker run for 2.0. EMBEDDED=0 disables; Compose stays the production path. Verified arm64 (14/14 lifecycle + Compose regression) and amd64 (build + embedded smoke).
2026-06-29 15:49:09 +08:00
SnapOtterandGitHub 19b515dc5f chore: use "200+ tools" for the tool-count claim across public surfaces (#364)
* fix(landing): correct PDF tool count to 28 in alternatives copy

The pdf section has 28 tools (section.test.ts asserts bySection('pdf')=28). PR #363 corrected the docs breakdown but the alternatives pages still said 40 PDF tools (the document-modality count, not the pdf section) with 200 for the rest. Update to 28 PDF tools and 212 for the non-PDF remainder.

* chore: use "200+ tools" for the tool-count claim across public surfaces

Replaces the exact '240 tools' count (which drifts as tools are added) with the stable '200+ tools' on README, the Docker Hub overview, landing pages, the docs site (meta, homepage, search), the API self-description, the demo OG tag, llms.txt, package.json, the branding readme, and the en/nl app strings. Per-modality breakdown tables stay exact. Leaves the architecture doc's technical 'tool routes' figure, an internal vitest comment, and a QA report line unchanged. Updates the two tests that assert the docs strings.
2026-06-28 21:49:14 +08:00
SnapOtterandGitHub 63a03d26f2 feat: pipeline templates, analytics opt-out, 83 conversion presets, positioning + e2e modernization
Lands five integrated branches: pipeline templates (#355), analytics opt-out (#354), 83 conversion presets bringing the catalog to 240 tools (#356), self-hosted positioning (#353), and e2e modernization (#351).

Integration fixes: aligned stale web analytics tests with the opt-out/allow-list model, closed 3 CodeQL incomplete-sanitization alerts in the i18n generator, resolved settings/index/docs/format-matrix conflicts, and corrected tool counts to 240.
2026-06-28 18:57:53 +08:00
SnapOtterandGitHub 8f4235d2c6 fix(enterprise): ship enterprise package in prod image + S3, analytics, tracing, queue fixes (#342)
* fix(enterprise): ship enterprise pkg in prod image, full license features, tracing key fallback

docker/Dockerfile: COPY packages/enterprise manifest+src into the production stage.
Without it, apps/api's workspace link to @snapotter/enterprise dangles and every
import() throws (silently caught), so all 19 enterprise features failed closed
(enterprise.active=false) regardless of a valid license.

scripts/generate-license.mjs: sync PLAN_FEATURES with packages/enterprise/src/license.ts
so a --plan enterprise license unlocks all 19 features (was 8) and team unlocks 8.

apps/api/src/tracing.ts: accept SNAPOTTER_LICENSE_KEY as a fallback to LICENSE_KEY so
distributed_tracing activates with the same key as the rest of the app.

* fix(docker): keep scripts/bake-analytics.mjs in build context

.dockerignore excluded the whole scripts/ dir (PR #82, V1 hardening), but
docker/Dockerfile later added 'COPY scripts/bake-analytics.mjs' for the analytics
bake step. A clean production image build therefore fails with
'scripts/bake-analytics.mjs: not found'. The published image build is gated off in
CI so this latent break went unnoticed. Exclude scripts/* but re-include the one
file the Dockerfile needs.

* fix: S3 upload stream, analytics bake reaches API, dedupe retention field, reconcile orphan jobs

storage-s3.ts: wrap the upload AsyncIterable in Readable.from() so @aws-sdk/lib-storage
accepts it. STORAGE_MODE=s3 file uploads failed with 'Body Data is unsupported format'
for every tool because a bare async generator is not a Readable.

docker/Dockerfile: COPY the builder-baked analytics baked.ts into the API runtime stage.
The API re-copied the committed (off) baked.ts from the build context, so the
SNAPOTTER_ANALYTICS build arg had no effect on the API -- and since the SPA reads
/api/v1/config/analytics, analytics was off everywhere regardless of the arg.

settings-dialog.tsx: remove the duplicate tempFileMaxAgeHours control under Data
Retention; it bound the same setting key as the File Management control with a different
default, so editing either silently overwrote the other.

apps/api/src/index.ts: reconcile orphaned job rows (empty tool_id, never enqueued to
BullMQ) at boot so they don't sit in processing/queued forever and inflate the per-user
concurrent-job count and the upgrade-check in-flight gate.

* fix(web): style the SSO login buttons (they referenced undefined theme tokens)

The OIDC/SAML 'Sign in with <provider>' buttons used bg-secondary /
text-secondary-foreground, which the web theme never defines (it has primary,
background, foreground, muted, border, card, primary-subtle). Those classes resolved
to nothing, so the buttons rendered as bare unstyled text on the login page.

Restyle: the optional (non-enforced) buttons become white-card outline buttons with a
key icon and an orange hover tint, secondary to the primary Login button; the
SSO-enforced buttons become solid primary with the icon.

* fix: gate S3 behind license, custom-role enterprise perms, wire retention UI, cleanup

S3 is a licensed feature, but shipping packages/enterprise in every image removed the
implicit gate, so STORAGE_MODE=s3 worked without a license. Enforce
isFeatureEnabled('s3_storage') at boot and fail fast if unlicensed.

Custom roles can now be granted security:manage / compliance:manage / webhooks:manage
(roles.ts ALL_PERMISSIONS + the Roles UI) so admins can build least-privilege
compliance/security roles instead of only the built-in admin role.

retentionSweep now reads the jobsRetentionDays / auditRetentionDays DB settings the
System Settings UI writes (env vars become the fallback default), mirroring how the
temp-file sweep reads tempFileMaxAgeHours. Previously those two UI controls were no-ops.

Cleanup: drop the never-set snapotter_storage_bytes gauge and the unused
MAX_WORKSPACE_SIZE_GB env var; emit tool_client_error to PostHog from the web
ErrorBoundary (client crashes were not reaching analytics); add the Python
OpenTelemetry packages so the innermost sidecar.<script> span exports; fix the stale
'only local storage' line in the docs; delete two e2e-analytics specs that tested the
removed consent UI.

* fix(env): restore MAX_WORKSPACE_SIZE_GB default

security-auth-hardening.test.ts asserts env.MAX_WORKSPACE_SIZE_GB defaults to 10, so
the var is an intentional (tested) default, not dead code. Removing it in the cleanup
commit broke that unit test. Keep the declaration.
2026-06-24 17:27:59 +08:00
SnapOtterandGitHub b2104fcde6 chore: docs retention wording, demo analytics mock cleanup, gitignore fix (#343)
* docs: clarify file retention vs saved-library persistence

FILE_MAX_AGE_HOURS only affects unsaved processing results (raw uploads
and tool outputs). Files saved to the Files library persist until the
user deletes them. Spell that out in the configuration table and the
getting-started Files section.

* chore(demo): drop removed per-user analytics from the mock API

#336 deleted the per-user analytics consent system (the DB columns, the
PUT /api/v1/user/analytics endpoint, and the consent UI in apps/web). The
demo mock still simulated them: a PUT handler, the analyticsEnabled /
analyticsConsentShownAt state fields, and analytics fields on the session
user. Nothing reads them anymore, so remove them. The current
GET /api/v1/config/analytics mock stays (that endpoint still exists).

* fix(gitignore): anchor demo ignore to root so apps/demo stays trackable

A bare 'demo' pattern matched any dir named demo, including the tracked
apps/demo workspace. New files under apps/demo were silently ignored and
lint-staged choked re-adding it. Root demo/ (the intended target) no
longer exists; anchor the rule to /demo. Build artifacts under apps/demo
stay ignored via the global dist/ and .turbo/ rules.
2026-06-24 15:58:08 +08:00
SnapOtterandGitHub 5dac40d782 docs: detailed per-format tables for all modalities (#339)
Rewrite the video, audio, document, and file sections of the supported
formats page into per-format tables matching the image section (format,
extensions, codec/engine, notes), plus a dedicated subtitles table.

Also correct output claims to match the code: video output is MP4/MOV
(H.264) and WebM (VP9) with GIF/WebP from dedicated tools; audio output
is MP3, WAV, FLAC, OGG, M4A. Inputs verified against VIDEO_INPUTS,
AUDIO_INPUTS, DOCUMENT_INPUTS, and FILE_INPUTS.
2026-06-24 12:29:07 +08:00
SnapOtterandGitHub 607c24895b Improve docs search UX, dash cleanup, and colored modality tool icons (#338)
* feat(docs): improve search UX

- Hide the 'Search by Pagefind' branding in the search dialog footer
- Replace the 'No results found.' message shown before any query with a
  friendly hint (detected via empty-input :placeholder-shown state)
- Tune placeholder, empty-state, and results-heading copy; show a few
  sub-section matches per result (pageResultCount)

* docs: replace double-dash em-dash substitute with single dash

Swept prose ' -- ' to ' - ' and numeric ranges (e.g. 2--20 to 2-20)
across the documentation. CLI flags and code blocks left untouched.

* fix(landing): show colored category icons on modality tool pages

The /tools/<modality>/ pages rendered bare name+description cards with no
icon or color. Port the colored, category-tinted icon card from /tools/
so modality pages match the main catalog (icon, tint, 'Learn more').
2026-06-24 12:06:31 +08:00
SnapOtter 8e530f2f1b docs: simplify analytics copy across all surfaces 2026-06-24 11:22:34 +08:00
SnapOtter 5c30167bab docs: remove IP address mentions from privacy copy 2026-06-24 11:17:58 +08:00
SnapOtterandGitHub 9378b2caab docs: update privacy and analytics disclosure (#337)
Update README, in-app privacy page, landing privacy page, and
deployment docs to reflect the new analytics model. Remove references
to opt-in consent, Settings toggle, and ANALYTICS_ENABLED env var.
Document the SNAPOTTER_ANALYTICS build arg for disabling.
2026-06-24 11:13:23 +08:00
SnapOtterandGitHub 5d36ac06d8 feat(analytics): build-time bake + telemetry depth (#336)
Bake PostHog + Sentry into the published Docker image (SNAPOTTER_ANALYTICS
build arg, codegen script). Delete entire consent system. Move event emission
to BullMQ worker. Add cross-tier identity stitching, Sentry performance
tracing on both tiers, frontend funnel events. Fix stateful regex bug.

86 files changed, 1593 insertions(+), 3747 deletions(-)
2026-06-24 11:05:39 +08:00
SnapOtterandGitHub 1fec97111b fix(docker): make storage writable under non-root/foreign UIDs (TrueNAS, OpenShift) (#299)
The entrypoint only fixed volume permissions when started as root (chown +
gosu-drop to snapotter). Launched under a non-root/foreign UID (TrueNAS app
user, Kubernetes runAsUser, OpenShift) it did no permission setup, so /data and
/tmp/workspace -- owned by uid 999 from the image -- were not writable by the
running user. Uploads and processing then failed with a cryptic EACCES
("workspace folder is not writable") and AI bundle installs failed the same way,
while health checks still reported the container healthy.

- entrypoint: source new entrypoint-lib.sh; verify writability up front when
  non-root, and as snapotter after chown when root (catches root-squashed
  mounts), failing fast with an actionable message (which dir, uid/gid, how to
  fix) instead of a late, cryptic EACCES
- Dockerfile: own /data and /tmp/workspace as snapotter:0, group-writable with
  setgid, so an arbitrary UID with the root supplementary group (OpenShift /
  Kubernetes fsGroup) can write; keep /opt/venv world-readable for the AI venv
  bootstrap under arbitrary UIDs
- api: assert storage writability at boot (lib/storage-writable.ts), failing
  fast with the same guidance even when the entrypoint is bypassed
- docs: add a Storage permissions section (named volumes, bind mounts, TrueNAS,
  Kubernetes/OpenShift) and cross-link it from the security guide

Fixes #230
2026-06-22 16:58:59 +08:00
SnapOtter 71fefc05b0 feat(modality): rename "file" modality label "Data" -> "Files"
The fifth user-facing group is now Image, Video, Audio, PDF, Files
(internal modality id stays "file"; section.ts "files" was already
"Files"). Updates modality.ts label + comment, all 21 i18n locales
(categories.data "Data Files"->"Files", modalities.documentsAndFiles
"PDF & Data"->"PDF & Files", dead homePage.data), landing cards/hero
search/tools filter, docs headings, and e2e modality-tab assertions
(/^Data/ -> /^Files/, which had been failing).
2026-06-21 02:45:56 +08:00
SnapOtter 9f0b43271c docs: section-prefix tool API endpoints 2026-06-21 00:12:59 +08:00
SnapOtterandGitHub 91ac583e87 feat(docs): Two-Doors home, otter-orange brand, Pagefind search, and enterprise SSO/SCIM/roles guides
Docs site redesign: Two-Doors home, otter-orange brand, Pagefind search, enterprise SSO/SCIM/roles guides.
2026-06-19 18:46:59 +08:00
SnapOtter 60e3008106 docs: deep-audit the API reference pages against code
rest.md: correct the tool response shape (JSON {jobId, downloadUrl, ...} for fast / 202 {jobId, async} for long, not the raw file), fix the SSE jobId source (body, with X-Job-Id only on batch/pipeline ZIP streams), complete the permissions list to all 17, and add ai-canvas-expand.

ai.md: reconcile ~14 AI tool parameter tables to the real Zod schemas (remove-background, upscale, ocr, enhance-faces, colorize, noise-removal, red-eye-removal, restore-photo, passport-photo, erase-object, smart-crop, content-aware-resize, transparency-fixer, image-enhancement), add the 6 missing AI tools (background-replace, blur-background, ocr-pdf, ai-canvas-expand, transcribe-audio, auto-subtitles), and fix the dispatcher script diagram and feature-bundle table.

image-engine.md: add 4 undocumented operations (sharpen, sharpen-advanced, color-blindness, edit-metadata) and fix flip/crop/rotate/convert/compress/strip-metadata/color-channels params, output-format count (13), and the info JSON example. supported-formats.md: output count 14 -> 13. Verified with a clean docs build.
2026-06-18 14:12:28 +08:00
SnapOtter 8532f3227b docs: audit all 157 tool pages against live schemas
Reconcile every tool page's parameters, defaults, and response shape against the tool's Zod settings schema and executionHint in code. Notable fixes: color-palette (add count + format params, hex output, median-cut algorithm), favicon (add 5 params, was documented as having none), qr-generate (add logoDataUri), convert (add ppm/eps/tga formats), video-loudnorm (-16 LUFS not -14), smart-crop (async 202 not sync 200), images-to-video (1080x1080 square), and several output-filename and behavior-note corrections.

Also normalize API endpoint paths to /api/v1/tools/<id> (no modality segment) and standardize curl examples on the Docker API port 1349. Verified with a clean docs build.
2026-06-18 14:12:28 +08:00
SnapOtter d24e244af4 docs: organize tool pages by modality under /tools/<modality>/
Move all 157 tool pages into image/video/audio/pdf/data subfolders so URLs read /tools/<modality>/<id> (e.g. /tools/image/crop). Nest the image sub-categories under an Image group in the sidebar so the nav reads by modality. Add public/_redirects (301, clean + .html forms) mapping every old flat /tools/<id> URL to its new path so inbound links keep working. Rewrite all internal /tools links. Verified with a clean docs build (no dead links).
2026-06-18 14:12:28 +08:00
SnapOtter 609cd6b609 chore(github): redesign issue intake forms and routing
Overhaul the bug report form and restructure issue intake for 2.0:

- Bug report: split actual vs expected behavior, add Affected area and
  Specific tool fields for triage, replace the self-defeating required
  "latest version" checkbox with a Version field that accepts a tag,
  release, or commit (always answerable from any install), modernize
  Docker guidance to the Compose stack, add Host OS, and fix the
  previously required image-tag field that source users could not fill.
- Move feature requests to GitHub Discussions: delete the feature_request
  issue form, rename the orphaned discussion form to ideas.yml so it binds
  to the built-in Ideas category, and point config.yml there.
- Add Translation and Documentation issue forms routed to existing labels.
- Remove the roadmap-update discussion form (roadmap is private).
- Reconcile CONTRIBUTING.md, SUPPORT.md, and the published docs
  contributing guide with the new routing.
2026-06-17 14:21:18 +08:00
SnapOtterandGitHub 17726ae59d docs: multi-modality rebrand, 2.0 architecture accuracy, and full OpenAPI coverage (#254)
* docs: rebrand from image-only to multi-modality across docs and metadata

SnapOtter expanded from image-only to 157 tools across 5 modalities
(image, video, audio, document/PDF, data). Update all product-level
copy, metadata, and i18n that still framed it as an image-only tool.

- README, package.json, root llms.txt: multi-modality framing, 157 tools
- OpenAPI info + tags, generated /llms.txt tagline (docs.ts)
- VitePress docs site: hero, getting-started, architecture, security,
  deployment, configuration, developer, supported-formats
- i18n: 10 product keys across all 21 locales (hero, app description,
  privacy notes, AI features, progress messages, getting-started)
- web/demo/landing meta + privacy copy, COMMUNITY_GUIDE, .env.example

Stale tool counts (53/50+/52/70+/35) corrected to 157 throughout.
Database/container deployment claims left unchanged (out of scope).

* docs: fix stale post-rebrand test assertions and README language list

- tests/e2e-docs/homepage.spec.ts: assert the current docs homepage (file toolkit, 157 tools, 5 modalities) instead of the old image-only strings
- tests/unit/api/docs-route.test.ts: sync the reproduced llms.txt tagline with docs.ts
- README.md: 21 languages with the correct list (add Swedish and Chinese Traditional, drop Czech which is not supported)

* docs: correct 2.0 architecture references (Postgres 17 + Redis 8, 3-container stack)

The docs and metadata still described the 1.x stack (SQLite, single container, p-queue). Update them to the current 2.0 reality.

- README: replace the broken single-container `docker run` quick-start with the real Docker Compose stack (app + Postgres 17 + Redis 8); fix the "no Redis, no Postgres" feature bullet
- package.json: description no longer claims a single container
- apps/docs: rewrite database.md for Postgres; configuration.md DB_PATH -> DATABASE_URL + REDIS_URL; architecture.md SQLite/p-queue/better-sqlite3 -> Postgres/BullMQ/pg and add media-engine + doc-engine; developer/security/deployment/docker-tags/getting-started/contributing compose examples now include postgres + redis; index.md + api/ai.md AI count 16 -> 19
- SECURITY.md: Drizzle (SQLite) -> (PostgreSQL)
- landing: enterprise/FeatureHighlights single-container wording; TrustSignals/ToolGrid 150+ -> 157 (dynamic); Pricing/FAQ 15 -> 19 AI tools

* docs(api): document all video, audio, document, and data tool endpoints in OpenAPI

The spec covered only image tools; the Scalar UI and the generated /llms.txt and /llms-full.txt inherited that gap. Add the 104 missing tool endpoints so the API docs match the code.

- Video: 29 endpoints (most long/async; auto-subtitles is AI)
- Audio: 17 (transcribe-audio is AI)
- Document/PDF: 36 (ocr-pdf is AI; conversions are long/async)
- Data: 10
- Image: 12 newer tools (background-replace, blur-background AI; histogram/lqip-placeholder/sprite-sheet custom responses; barcode-generate uses a JSON body)

Each schema is derived from the tool's Zod validator and executionHint (fast -> 200, long -> 202+SSE, AI adds 501 FeatureNotInstalledError, multi-file inputs as arrays), referencing the existing shared schemas. Tool path entries: 64 -> 168. Spec parses as valid YAML with no duplicate paths and only known $refs.
2026-06-16 18:04:52 +08:00
SnapOtter bfd6d25786 docs: add security and hardening guide
Container hardening, network isolation, Docker secrets, Kubernetes
deployment, backup strategy, and compliance artifacts reference.
2026-06-08 17:48:20 +08:00
SnapOtter 5bcc357725 chore: update tool counts and references for html-to-image (53 tools) 2026-06-06 21:45:39 +08:00
SnapOtterandGitHub 01421640b5 fix: resolve file library Open File bug, upload reliability, and SSE proxy timeouts (#203)
The Open File button in the Files section did nothing due to a race
condition where the home page reset the file store on mount before files
from handleOpenFile could render. Upload on the files page used fetch
with no timeout, progress, or retry, causing silent failures on mobile
and slow connections. SSE connections for job progress had no keepalive
pings, allowing reverse proxies to kill idle streams.
2026-06-05 19:01:40 +08:00
SnapOtter e70fca054a fix: replace hardcoded "52 tools" with "50+" across all copy
Future-proofs marketing text so it doesn't need updating every time
a tool is added.
2026-05-20 14:45:45 +08:00
SnapOtter 228f70d011 feat: add static demo site at demo.snapotter.com
- New apps/demo/ that reuses apps/web components with mocked API layer
- Full UI shell: login, change password, analytics consent, dashboard, all tool pages
- Stateful mock tracks session flow (password change, analytics consent)
- Demo banner with link to GitHub repo
- Processing attempts show info message with GitHub link
- Deployed to Cloudflare Pages as static site (no backend)

Also links demo across all surfaces:
- README: "Live Demo" badge
- Landing navbar: "Try Demo" CTA button (replaces "Book a Demo")
- Landing hero: "No sign-ups. No credit card." tagline
- Docs getting-started: "Try before installing" tip box

Other changes:
- Docs: move NVIDIA GPU section above GHCR, demote GHCR to collapsed details
- Fix before-after slider checkerboard background for transparency
- Fix remove-bg preview reset when no effects applied
2026-05-17 09:25:12 +08:00
SnapOtter 7d617a2675 docs: update docs site to welcome pull requests and translations
Rewrite contributing page to match new CONTRIBUTING.md with PR types,
CLA process, and good-first-issue links. Update translation guide to
encourage direct PRs instead of issue-only workflow.
2026-05-16 16:24:03 +08:00
SnapOtter d025a569e2 docs: add SEO descriptions to all doc pages and update hero subtitle 2026-05-16 12:48:23 +08:00
SnapOtter 3e06d68f4f chore: bump version to 1.17.0 and update docs for release
- Bump all workspace package versions to 1.17.0
- Update APP_VERSION constant and OpenAPI spec
- Update AI tool count from 15 to 16 across docs and i18n
- Update tool table with AI Canvas Expand, Meme Generator, Beautify
- Add image editor, OIDC, and 20 languages to README features
- Add release notes for v1.17.0
- Add JSON-LD structured data and SEO improvements to landing/docs
2026-05-16 12:48:02 +08:00
SnapOtter f86ef124c2 fix: grant admin role to anonymous user and add DEFAULT_TOOL_VIEW env var
When AUTH_ENABLED=false, the anonymous user was assigned the "user" role
which lacks settings:write permission, making all settings saves return
403. Since no admin exists when auth is disabled, settings were
permanently read-only. Promote the anonymous user to "admin" so the
single user has full control of the instance.

Also adds DEFAULT_TOOL_VIEW env var (sidebar|fullscreen) following the
existing DEFAULT_THEME pattern, seeded via ensureDefaultSettings() on
first boot.

Closes #135
2026-05-16 11:37:28 +08:00
SnapOtter 2c45a3a9e8 fix: update tool count to 52 and add ai-canvas-expand to landing page
ai-canvas-expand was added to constants.ts and route files but never
added to the landing page bento grid, causing all hardcoded counts
to remain at 51. This updates all references across source, docs,
i18n, and tests to reflect the correct count of 52 tools.
2026-05-16 10:02:19 +08:00
SnapOtter a01a65e9ac docs: complete API sync and documentation audit
Audit all 52 tools and 119 API operations against the OpenAPI spec.
Fix schema mismatches, add missing endpoints, and update all doc surfaces.

OpenAPI spec (apps/api/src/openapi.yaml):
- Add operationId to all 119 operations for SDK code generation
- Add descriptions to 17 operations that only had summaries
- Fix 9 bare error responses with proper content/schema blocks
- Fix wrong $ref on GET /api/v1/settings/{key} 404 (was UnauthorizedError)
- Fix 10 async AI tools using 200 instead of 202 Accepted
- Add missing JXL format to 9 tool enums (convert, collage, stitch, split,
  svg-to-raster, pdf-to-image, optimize-for-web, erase-object, noise-removal)
- Add 3 missing endpoints: POST /api/v1/fetch-urls, GET /api/v1/config/locale,
  POST /api/v1/tools/ai-canvas-expand
- Add missing meme-templates/fonts/{filename} endpoint
- Fix watermark-image and compose: settings not required (all have defaults)
- Fix compare similarity description (0-100 percentage, not 0-1)
- Fix find-duplicates: add nullable thumbnail, add skippedFiles response field
- Fix upscale format default ("auto" not "png"), add clientJobId fields
- Fix restore-photo: remove phantom mode param, fix denoiseStrength default,
  add missing colorizeStrength
- Fix smart-crop: add 5 missing parameter defaults
- Add missing params: image-enhancement deepEnhance, transparency-fixer
  removeWatermark, image-to-pdf collate, image-to-base64 jxl enum
- Fix files/{id}/thumbnail security (requires auth, was marked public)
- Annotate 7 empty description strings in pipeline/role schemas

Documentation surfaces:
- VitePress config: "50 tools" to "51 tools" (2 locations)
- README: add OIDC/SSO docs link
- getting-started.md: add Color Blindness Simulation to tool table
- database.md: fix hash descriptions (bcrypt/SHA-256 to scrypt)
2026-05-15 23:13:42 +08:00
SnapOtter d38621d7b9 feat: add multi-language support for 20 locales
Add complete i18n infrastructure with 21 supported languages:
English, Simplified Chinese, Traditional Chinese, Japanese, Korean,
Spanish, French, Italian, Brazilian Portuguese, German, Dutch, Swedish,
Russian, Polish, Ukrainian, Arabic (RTL), Turkish, Hindi, Vietnamese,
Indonesian, and Thai.

- I18nProvider context with three-tier locale detection
  (user preference > navigator.languages > instance default > English)
- ~1500 translation keys per locale with TypeScript-enforced completeness
- Dynamic code-splitting: only the active locale is loaded at runtime
- Language selectors in footer, login page, settings, and mobile sidebar
- Arabic RTL support with CSS logical properties across all components
- Tool names, descriptions, and categories translated via i18n helpers
- Public API endpoint GET /api/v1/config/locale for instance default
- Multi-script font stack (CJK, Arabic, Devanagari, Thai, Cyrillic)
- format() and plural() helpers for interpolation and pluralization
- API error translation mapping (translateApiError)
- 36 Playwright e2e tests verifying all 21 locales load correctly
- 25 unit tests for format, plural, locale detection, and completeness
- Updated translations.md docs and CLAUDE.md conventions
2026-05-15 17:02:49 +08:00
SnapOtter eacdb867ac docs: add OIDC setup guide with provider examples 2026-05-13 19:17:14 +08:00
SnapOtter 8598808b3c fix: correct repository name casing in clone instructions 2026-05-10 22:41:52 +08:00
SnapOtter 172c0fa772 fix: update tool count to 51, refresh hero copy and login page
- Update stale tool counts (48/49/50) to 51 across all apps, docs, and tests
- Add Meme Generator to landing page bento grid (was missing)
- Add 12 SEO-friendly rotating phrases to hero typing cursor
- Change landing hero subtitle to "Every image tool you need."
- Replace outdated login page copy with branded hero + rotating phrases
2026-05-10 22:18:11 +08:00
SnapOtter 86a74ab706 fix: replace hardcoded version in deployment docs with placeholder 2026-05-10 20:17:40 +08:00
SnapOtter e118717337 merge: resolve conflict with main branch in README.md 2026-05-08 17:32:16 +08:00
SnapOtter 3d9324b82a chore: update tool count to 50 across all references 2026-05-08 16:33:12 +08:00
SnapOtter 466ef1efb1 docs(beautify): add API docs, OpenAPI spec, LLM docs, update README
Add beautify tool endpoint to OpenAPI spec with full parameter
documentation. Add tool to REST API docs Layout & Composition table.
Update tool count from 49 to 50 across README, docs homepage,
architecture docs, VitePress config, OpenAPI spec, and LLM docs
generator.
2026-05-08 16:31:43 +08:00
SnapOtter 136a4a0752 Merge branch 'feat/format-support-expansion'
# Conflicts:
#	README.md
#	apps/web/src/components/layout/app-layout.tsx
2026-05-08 16:21:11 +08:00
SnapOtter bcdc4bdf82 docs: add color-blindness tool to API docs and update tool counts 2026-05-08 15:23:22 +08:00
SnapOtter bb6d26ffc6 docs: add comprehensive format support documentation 2026-05-08 00:26:56 +08:00
SnapOtter 16af9c573a feat: remove app name and logo customization feature
Users can no longer customize the app name or logo. The branding API
endpoints, permission, frontend UI, env vars (APP_NAME, MAX_LOGO_SIZE_KB),
and all related tests are removed. Includes a migration to clean up
branding data from existing databases.
2026-05-07 19:41:30 +08:00
SnapOtter 84e62e6132 refactor: rename tool display name to "PNG Transparency Fixer" 2026-05-06 18:53:37 +08:00
SnapOtter eb3d0828cb docs: add transparency-fixer endpoint documentation 2026-05-05 23:24:22 +08:00
SnapOtter 6a44c455a3 fix: remove printf banner from docker commands in docs
The printf welcome banner was overflowing code blocks on
docs.snapotter.com, making docker commands hard to read and copy.
2026-05-01 19:42:11 +08:00