惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Recent Announcements
Recent Announcements
J
Java Code Geeks
雷峰网
雷峰网
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
腾讯CDC
博客园 - 司徒正美
B
Blog RSS Feed
博客园 - 三生石上(FineUI控件)
I
InfoQ
N
Netflix TechBlog - Medium
L
LangChain Blog
博客园_首页
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
T
Tailwind CSS Blog
MyScale Blog
MyScale Blog
美团技术团队
The Cloudflare Blog
爱范儿
爱范儿
Stack Overflow Blog
Stack Overflow Blog
博客园 - 聂微东
H
Help Net Security
Martin Fowler
Martin Fowler
V
Visual Studio Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Building a 35-tool privacy-first hub with Next.js 15: les...
Farhan Murta · 2026-05-07 · via DEV Community

After 2 weeks of evenings and weekends, I shipped Toolsfluent: a free hub of 35+ online tools (calculators, converters, generators) targeting privacy-conscious users in South Asia, the Gulf, and globally.

Sharing the technical learnings here, not the marketing version. If you're a solo dev shipping a content-heavy site, this might save you a few weeks.

The stack

  • Framework: Next.js 15 (App Router, RSC, ISR)
  • Language: TypeScript
  • Styling: Tailwind CSS
  • Icons: lucide-react
  • Fonts: Inter (body) + Sora (brand) via next/font/google
  • Theme: next-themes
  • Hosting: Vercel (Hobby tier)

Static generation for every tool page. No database. No auth. Currency converter is the only thing that hits an external API (exchangerate-api.com free tier).

What worked unexpectedly well

1. Single source-of-truth for tools

Every tool's metadata lives in one TypeScript array:

export const TOOLS: Tool[] = [
  {
    slug: "mortgage-calculator",
    name: "Mortgage Calculator",
    description: "...",
    category: "finance",
    keywords: [...],
    icon: "Home",
    featured: true,
    howToSteps: [...],
    faqs: [...],
    relatedTools: [...]
  },
  // ... 34 more
];

Enter fullscreen mode Exit fullscreen mode

Adding a new tool means: add the entry, create a folder, write the calculator component. Sitemap, JSON-LD schema, search index, navigation, related tools, and category pages auto-update from the array.

This single decision saved hours per tool. By tool 20, I was shipping new tools in under an hour.

2. JSON-LD structured data on everything

Every tool ships:

  • SoftwareApplication schema
  • FAQPage schema (from FAQs in the data array)
  • BreadcrumbList

Categories ship CollectionPage. Site root ships WebSite + Organization.

Google takes JSON-LD seriously for tool pages. Without it, you're invisible. With it, your tool can show up with rating stars, FAQs in SERP, and "free" pricing badge.

Build a single buildToolJsonLd(tool) helper and you're done.

3. Per-tool meta description, canonical, OG tags via one helper

export function buildMetadata({title, description, path, keywords, image}) {
  const url = `${SITE_URL}${path}`;
  return {
    title: `${title} | ${SITE_NAME}`,
    description,
    keywords: keywords.join(", "),
    metadataBase: new URL(SITE_URL),
    alternates: { canonical: url },
    openGraph: {
      title, description, url,
      images: [{ url: image, width: 1200, height: 630 }]
    },
    twitter: { card: "summary_large_image" },
    robots: { index: true, follow: true }
  };
}

Enter fullscreen mode Exit fullscreen mode

Every page calls this. Zero metadata bugs. Easy to verify in view-source.

What surprised me

Em-dashes flagged as AI content

Google's Helpful Content classifier flags em-dashes (—) as a strong signal of AI-generated content. Removed all of them site-wide via sed and replaced with commas / colons / periods. Sounds silly but it's a real ranking heuristic.

Authoritative source citations matter on YMYL

Every health and finance blog post got 2-3 citations to authoritative sources (CDC, WHO, NIST, IRS, CFPB, RBI, GST Council India, HMRC). YMYL (Your Money or Your Life) content without citations gets de-ranked by Google's Quality Rater Guidelines.

Took an extra hour per post to research and cite properly. Made a measurable difference in indexing speed.

Canonical tag with vs without trailing slash

Spent hours debugging "Alternate page with proper canonical tag" warnings in GSC. Turned out my SITE_URL had no trailing slash but Google was crawling URLs with trailing slash. Both worked but Google was confused which one to canonicalize.

Fix: be consistent. Pick one and stick with it everywhere.

Image compressor as a Canvas API trick

Most image compressors upload to a server. The privacy-first version is just:

const img = new Image();
img.onload = () => {
  const canvas = document.createElement('canvas');
  canvas.width = img.width;
  canvas.height = img.height;
  canvas.getContext('2d').drawImage(img, 0, 0);
  canvas.toBlob(blob => downloadBlob(blob), 'image/jpeg', 0.8);
};
img.src = URL.createObjectURL(file);

Enter fullscreen mode Exit fullscreen mode

Quality knob is just the third arg to toBlob. Done. No upload, no server, no privacy concerns.

What's next

  • More Pakistani / Indian / UAE niche tools (Marla converter, UAE gratuity, Pakistani GPA already shipped)
  • WhatsApp share button site-wide (huge in PK / IN, ignored by most western tool sites)
  • AI-augmented text tools using Claude API (cover letter generator, code explainer, etc.) — text only, no image gen because paid API costs would exceed AdSense revenue at this stage

Honest numbers

35 tools live, 17 blog posts, all legal pages, GA4 + Bing + GSC verified. Indexed in Google within 24 hours of launch.

Traffic so far: a handful of visits from my own testing. Distribution is the next problem to solve, not the build.

If you want to see the production version: https://www.toolsfluent.com

Honest feedback welcome — especially on schema markup gotchas, perf optimization wins I'm missing, or tools you'd actually use.