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.
This commit is contained in:
SnapOtter
2026-05-20 14:45:45 +08:00
parent dfbc4cfd59
commit e70fca054a
21 changed files with 27 additions and 27 deletions
+2 -2
View File
@@ -5,8 +5,8 @@ Live demo, per-tool landing pages, and a batch of polish fixes.
## New features
- **Live demo** -- [demo.snapotter.com](https://demo.snapotter.com) lets people try SnapOtter without installing anything.
- **Tools index page** -- Browse all 52 tools at `/tools` with search and category filters. Navbar links fixed on subpages.
- **52 SEO landing pages** -- Every tool now has a dedicated landing page with FAQs, use cases, and comparison tables for search visibility.
- **Tools index page** -- Browse all 50+ tools at `/tools` with search and category filters. Navbar links fixed on subpages.
- **50+ SEO landing pages** -- Every tool now has a dedicated landing page with FAQs, use cases, and comparison tables for search visibility.
- **Background preview** -- Before-after slider shows a checkered background behind transparent images so you can actually see what changed.
- **Strong password generator** -- One-click button in the Add Members form generates a secure password.
- **Easter eggs** -- Hello from the otter side.
+1 -1
View File
@@ -18,7 +18,7 @@
## Key Features
- **52 image tools:** Resize, crop, compress, convert, watermark, color adjust, beautify screenshots, generate memes, vectorize, create GIFs, find duplicates, generate passport photos, and more. Supports 55+ input formats (including 23 camera RAW formats) and 14 output formats
- **50+ image tools:** Resize, crop, compress, convert, watermark, color adjust, beautify screenshots, generate memes, vectorize, create GIFs, find duplicates, generate passport photos, and more. Supports 55+ input formats (including 23 camera RAW formats) and 14 output formats
- **Image editor:** Layer-based editor with brushes, shapes, adjustments, filters, curves, and keyboard shortcuts. Runs in your browser, processes on your hardware
- **Local AI:** Remove backgrounds, upscale images, restore and colorize old photos, erase objects, blur faces, enhance faces, extract text (OCR), expand canvas, fix transparency. All on your hardware, no internet required
- **OIDC / SSO:** Login with Google, GitHub, Okta, or any OpenID Connect provider
+1 -1
View File
@@ -39,7 +39,7 @@ function generateLlmsTxt(spec: OpenAPISpec): string {
lines.push(`# ${spec.info.title}`);
lines.push("");
lines.push(
"> Self-hosted image processing API with 52 tools. Resize, compress, convert, remove backgrounds, upscale, run OCR, and more.",
"> Self-hosted image processing API with 50+ tools. Resize, compress, convert, remove backgrounds, upscale, run OCR, and more.",
);
lines.push("");
lines.push("## Docs");
+2 -2
View File
@@ -11,8 +11,8 @@ Live demo, per-tool landing pages, and a batch of polish fixes.
### New features
- **Live demo** -- [demo.snapotter.com](https://demo.snapotter.com) lets people try SnapOtter without installing anything.
- **Tools index page** -- Browse all 52 tools at `/tools` with search and category filters.
- **52 SEO landing pages** -- Every tool now has a dedicated landing page with FAQs, use cases, and comparison tables.
- **Tools index page** -- Browse all 50+ tools at `/tools` with search and category filters.
- **50+ SEO landing pages** -- Every tool now has a dedicated landing page with FAQs, use cases, and comparison tables.
- **Background preview** -- Before-after slider shows a checkered background behind transparent images.
- **Strong password generator** -- One-click button in the Add Members form.
+1 -1
View File
@@ -47,7 +47,7 @@ Shared TypeScript types, constants (like `APP_VERSION` and tool definitions), an
### API (`apps/api`)
A Fastify v5 server exposing 52 tool routes (36 standard image operations + 16 AI-powered) that handles:
A Fastify v5 server exposing 50+ tool routes (36 standard image operations + 16 AI-powered) that handles:
- File uploads, temporary workspace management, and persistent file storage
- User file library with version chains (`user_files` table) -- each processed result links back to its source file and records which tool was applied, with auto-generated thumbnails for the Files page
- Tool execution (routes each tool request to the image engine or AI bridge)
+1 -1
View File
@@ -4,7 +4,7 @@ layout: home
hero:
name: "SnapOtter"
text: "A Self Hosted Image Manipulator"
tagline: 52 tools. Local AI. No cloud. Your images never leave your home.
tagline: 50+ tools. Local AI. No cloud. Your images never leave your home.
actions:
- theme: brand
text: Get started
+3 -3
View File
@@ -8,7 +8,7 @@ const nunito = Nunito({ subsets: ["latin"], variable: "--font-nunito" });
export const metadata: Metadata = {
title: "SnapOtter | Self-Hosted Image Processing",
description:
"52 image processing tools with local AI. Runs 100% offline. No data leaves your network. Open source and free forever.",
"50+ image processing tools with local AI. Runs 100% offline. No data leaves your network. Open source and free forever.",
metadataBase: new URL("https://snapotter.com"),
icons: {
icon: [
@@ -24,7 +24,7 @@ export const metadata: Metadata = {
openGraph: {
title: "SnapOtter | Self-Hosted Image Processing",
description:
"52 image processing tools with local AI. Runs 100% offline. No data leaves your network.",
"50+ image processing tools with local AI. Runs 100% offline. No data leaves your network.",
url: "https://snapotter.com",
siteName: "SnapOtter",
type: "website",
@@ -43,7 +43,7 @@ export const metadata: Metadata = {
site: "@SnapOtterHQ",
title: "SnapOtter | Self-Hosted Image Processing",
description:
"52 image processing tools with local AI. Runs 100% offline. No data leaves your network.",
"50+ image processing tools with local AI. Runs 100% offline. No data leaves your network.",
images: ["/og-image.png"],
},
};
+2 -2
View File
@@ -21,7 +21,7 @@ const websiteJsonLd = {
name: "SnapOtter",
url: "https://snapotter.com",
description:
"52 image processing tools with local AI. Runs 100% offline. No data leaves your network.",
"50+ image processing tools with local AI. Runs 100% offline. No data leaves your network.",
publisher: {
"@type": "Organization",
name: "SnapOtter",
@@ -44,7 +44,7 @@ const softwareJsonLd = {
"@type": "SoftwareApplication",
name: "SnapOtter",
description:
"52 image processing tools with local AI. Runs 100% offline. No data leaves your network. Open source and free forever.",
"50+ image processing tools with local AI. Runs 100% offline. No data leaves your network. Open source and free forever.",
applicationCategory: "MultimediaApplication",
operatingSystem: "Linux, macOS, Windows (via Docker)",
offers: {
+1 -1
View File
@@ -392,7 +392,7 @@ export default async function ToolPage({ params }: PageProps) {
Ready to try {tool.name}?
</h2>
<p className="mx-auto mt-4 max-w-lg text-muted">
Deploy SnapOtter in under a minute. All 52 tools included. Open source and free
Deploy SnapOtter in under a minute. All 50+ tools included. Open source and free
forever.
</p>
<div className="mt-8 flex flex-wrap justify-center gap-4">
+1 -1
View File
@@ -36,7 +36,7 @@ export function BentoGrid() {
<div className="mx-auto max-w-6xl">
<FadeIn>
<h2 className="font-[family-name:var(--font-nunito)] text-center text-3xl font-bold tracking-tight md:text-4xl">
52 tools. Zero cloud dependency.
50+ tools. Zero cloud dependency.
</h2>
<p className="mx-auto mt-4 max-w-xl text-center text-lg text-muted">
Search to find exactly what you need. Every tool runs 100% locally.
+1 -1
View File
@@ -119,7 +119,7 @@ export function Hero() {
</h1>
<p className="mt-4 animate-[fadeUp_0.6s_ease-out_0.1s_both] text-base text-muted md:text-lg">
A free, open-source image toolkit with 52 tools that runs entirely on your network.
A free, open-source image toolkit with 50+ tools that runs entirely on your network.
</p>
<p className="mt-4 animate-[fadeUp_0.6s_ease-out_0.2s_both] text-xl font-medium md:text-2xl">
+1 -1
View File
@@ -7,7 +7,7 @@ const freePlan = {
price: "Free",
subtitle: "For everyone. Forever.",
features: [
"All 52 image processing tools",
"All 50+ image processing tools",
"Unlimited usage, no hidden caps",
"Full REST API with OpenAPI docs",
"Pipeline automation",
@@ -11,7 +11,7 @@ const phrases = [
"No limits. No hidden caps.",
"Works fully offline.",
"Unlimited batch processing.",
"52 image tools.",
"50+ image tools.",
"16 AI models. Your hardware.",
"Lightning fast. Built on Sharp.",
"Air-gapped ready.",
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "snapotter",
"version": "1.17.1",
"private": true,
"description": "Self-hosted image processing suite with 52 tools and local AI. Single Docker container, no external services.",
"description": "Self-hosted image processing suite with 50+ tools and local AI. Single Docker container, no external services.",
"homepage": "https://snapotter.com",
"repository": {
"type": "git",
+2 -2
View File
@@ -1611,7 +1611,7 @@ export const en = {
heading: "About",
appName: "SnapOtter",
appDescription:
"A self-hosted, privacy-first image processing suite with 52 tools. Resize, compress, convert, watermark, and automate your image workflows without sending data to the cloud.",
"A self-hosted, privacy-first image processing suite with 50+ tools. Resize, compress, convert, watermark, and automate your image workflows without sending data to the cloud.",
versionLabel: "Version:",
linksHeading: "Links",
githubLink: "GitHub Repository",
@@ -1654,7 +1654,7 @@ export const en = {
"No limits. No hidden caps.",
"Works fully offline.",
"Unlimited batch processing.",
"52 image tools.",
"50+ image tools.",
"16 AI models. Your hardware.",
"Lightning fast. Built on Sharp.",
"Air-gapped ready.",
+1 -1
View File
@@ -1667,7 +1667,7 @@ export const nl: TranslationKeys = {
heading: "Over",
appName: "SnapOtter",
appDescription:
"Een zelf-gehoste, privacy-first beeldverwerkingssuite met 52 tools. Schalen, comprimeren, converteren, watermerken en je beeldworkflows automatiseren zonder data naar de cloud te sturen.",
"Een zelf-gehoste, privacy-first beeldverwerkingssuite met 50+ tools. Schalen, comprimeren, converteren, watermerken en je beeldworkflows automatiseren zonder data naar de cloud te sturen.",
versionLabel: "Versie:",
linksHeading: "Links",
githubLink: "GitHub-repository",
+1 -1
View File
@@ -13,7 +13,7 @@ test.describe("Docs Homepage", () => {
await expect(page.getByText("SnapOtter").first()).toBeVisible();
await expect(page.getByText("A Self Hosted Image Manipulator")).toBeVisible();
await expect(
page.getByText("52 tools. Local AI. No cloud. Your images never leave your home."),
page.getByText("50+ tools. Local AI. No cloud. Your images never leave your home."),
).toBeVisible();
});
+1 -1
View File
@@ -57,7 +57,7 @@ test.describe("Landing Homepage", () => {
});
test("bento grid renders with search and tool count", async ({ page }) => {
await expect(page.getByText("52 tools. Zero cloud dependency.")).toBeVisible();
await expect(page.getByText("50+ tools. Zero cloud dependency.")).toBeVisible();
await expect(page.getByPlaceholder("Search tools...")).toBeVisible();
await expect(page.getByText(/Showing 52 of 52 tools/)).toBeVisible();
});
+1 -1
View File
@@ -47,7 +47,7 @@ function generateLlmsTxt(spec: OpenAPISpec): string {
lines.push(`# ${spec.info.title}`);
lines.push("");
lines.push(
"> Self-hosted image processing API with 52 tools. Resize, compress, convert, remove backgrounds, upscale, run OCR, and more.",
"> Self-hosted image processing API with 50+ tools. Resize, compress, convert, remove backgrounds, upscale, run OCR, and more.",
);
lines.push("");
lines.push("## Docs");
+1 -1
View File
@@ -25,7 +25,7 @@ function getCountText(): string {
describe("BentoGrid", () => {
it("renders the section heading", () => {
render(<BentoGrid />);
expect(screen.getByText("52 tools. Zero cloud dependency.")).toBeDefined();
expect(screen.getByText("50+ tools. Zero cloud dependency.")).toBeDefined();
});
it("renders the search input", () => {
+1 -1
View File
@@ -157,7 +157,7 @@ describe("Pricing", () => {
it("renders free plan features", () => {
render(<Pricing />);
expect(screen.getByText("All 52 image processing tools")).toBeDefined();
expect(screen.getByText("All 50+ image processing tools")).toBeDefined();
expect(screen.getByText("Unlimited usage, no hidden caps")).toBeDefined();
expect(screen.getByText("15 local AI models included")).toBeDefined();
expect(screen.getByText("AGPL-3.0 licensed")).toBeDefined();