<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: CarsonJ</title>
    <description>The latest articles on DEV Community by CarsonJ (@korelyy).</description>
    <link>https://dev.to/korelyy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4007181%2F2836369a-d6b7-4cd1-83c3-7b2c3ec754ac.png</url>
      <title>DEV Community: CarsonJ</title>
      <link>https://dev.to/korelyy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/korelyy"/>
    <language>en</language>
    <item>
      <title>I built a multi-language privacy-first online tool suite, everything runs locally inside your browser</title>
      <dc:creator>CarsonJ</dc:creator>
      <pubDate>Wed, 22 Jul 2026 12:36:43 +0000</pubDate>
      <link>https://dev.to/korelyy/i-built-a-multi-language-privacy-first-online-tool-suite-everything-runs-locally-inside-your-b94</link>
      <guid>https://dev.to/korelyy/i-built-a-multi-language-privacy-first-online-tool-suite-everything-runs-locally-inside-your-b94</guid>
      <description>&lt;h1&gt;
  
  
  I built a multi-language privacy-first online tool suite, everything runs locally inside your browser
&lt;/h1&gt;

&lt;p&gt;If you’ve used random free online tools recently, you’ve probably run into the same frustrations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have to register an account just for a one-time quick task&lt;/li&gt;
&lt;li&gt;Annoying ads and forced watermarks on your exported files&lt;/li&gt;
&lt;li&gt;You upload private photos, PDFs or text data to unknown third-party servers&lt;/li&gt;
&lt;li&gt;Many tools only support English, no multi-language interface&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s why I spent months building &lt;strong&gt;Korelyy Tools&lt;/strong&gt;, a collection of everyday web utilities with a simple core rule:&lt;br&gt;
&lt;strong&gt;All processing happens locally in your browser. Your files never leave your device.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s inside the toolkit
&lt;/h2&gt;

&lt;p&gt;Right now the site includes common utilities for regular users and developers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Image compression &amp;amp; conversion&lt;/li&gt;
&lt;li&gt;QR Code generator &amp;amp; reader&lt;/li&gt;
&lt;li&gt;PDF basic tools&lt;/li&gt;
&lt;li&gt;Emoji mixer&lt;/li&gt;
&lt;li&gt;JSON formatter / validator&lt;/li&gt;
&lt;li&gt;AI text writing helper&lt;/li&gt;
&lt;li&gt;More dev-focused small utilities on the roadmap&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Core design choices I stuck to
&lt;/h3&gt;

&lt;p&gt;✅ No signup, no login required for any tool&lt;br&gt;
✅ Zero watermarks on all outputs&lt;br&gt;
✅ Client-side computation: No file uploads to backend servers&lt;br&gt;
✅ Multi-language support: English, Chinese, Spanish, French, Hindi, Arabic&lt;br&gt;
✅ Static site built on Next.js, low long-term hosting costs&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical challenges I ran into
&lt;/h2&gt;

&lt;p&gt;Building fully client-side tools wasn’t as straightforward as I expected:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Browser memory limits&lt;/strong&gt;&lt;br&gt;
Large images and multi-page PDFs can easily trigger tab crashes. I added chunk processing to avoid out-of-memory errors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Web Worker performance&lt;/strong&gt;&lt;br&gt;
Heavy tasks block the main thread, so I moved compression and document parsing into Web Workers to keep the UI responsive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-language i18n management&lt;/strong&gt;&lt;br&gt;
Maintaining translation strings for six languages adds a lot of repetitive work. I’m still optimizing how I manage localization files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SEO for dozens of independent tool pages&lt;br&gt;
Each small tool needs its own meta title, description and structured content to rank on search engines. It’s a slow ongoing process.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Current status &amp;amp; growth
&lt;/h2&gt;

&lt;p&gt;After launching publicly, the site hit around &lt;strong&gt;1.2k pageviews in the first 28 days&lt;/strong&gt; with zero paid ads. Most traffic comes from organic search at the moment.&lt;/p&gt;

&lt;p&gt;There’s still a long feature list I want to implement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add more developer utilities&lt;/li&gt;
&lt;li&gt;Improve mobile responsive layout&lt;/li&gt;
&lt;li&gt;Expand more language translations&lt;/li&gt;
&lt;li&gt;Optimize bundle size for faster initial load&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m actively collecting feedback to prioritize new tools and improvements.&lt;/p&gt;

&lt;p&gt;If you want to test it out: &lt;a href="https://korelyy.com" rel="noopener noreferrer"&gt;https://korelyy.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’d love to hear your thoughts:&lt;br&gt;
What free web tools do you wish existed without signups, ads or data collection?&lt;br&gt;
What features should I build next?&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3z7wx4aiv5mpoyrlqs0h.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3z7wx4aiv5mpoyrlqs0h.jpg" alt=" " width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>webdev</category>
      <category>nextjs</category>
      <category>sideprojects</category>
    </item>
    <item>
      <title>How I Built an AI Prompt Generator with Next.js 15, Cloudflare Pages, and DeepSeek</title>
      <dc:creator>CarsonJ</dc:creator>
      <pubDate>Sat, 18 Jul 2026 01:26:25 +0000</pubDate>
      <link>https://dev.to/korelyy/how-i-built-an-ai-prompt-generator-with-nextjs-15-cloudflare-pages-and-deepseek-4aak</link>
      <guid>https://dev.to/korelyy/how-i-built-an-ai-prompt-generator-with-nextjs-15-cloudflare-pages-and-deepseek-4aak</guid>
      <description>&lt;h1&gt;
  
  
  How I Built an AI Prompt Generator with Next.js 15, Cloudflare Pages, and DeepSeek
&lt;/h1&gt;

&lt;p&gt;Building AI tools in 2026 is easier than ever — but getting the architecture right takes some thought. Here's how I built a free AI Prompt Generator that supports 4 models, 6 languages, and handles rate limiting at scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;I wanted a prompt builder that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Works offline-first for basic prompt construction&lt;/li&gt;
&lt;li&gt;Uses AI only when explicitly requested (cost control)&lt;/li&gt;
&lt;li&gt;Supports multiple models with different field sets&lt;/li&gt;
&lt;li&gt;Handles rate limiting per IP without a database&lt;/li&gt;
&lt;li&gt;Deploys to a global CDN for free&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Frontend: Next.js 15 Static Export
&lt;/h3&gt;

&lt;p&gt;I used Next.js 15 with &lt;code&gt;output: 'export'&lt;/code&gt; mode — this generates static HTML/CSS/JS that can be served from any CDN. The core prompt building is pure frontend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;PromptField&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;PromptModel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;video&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PromptField&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;join&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zh&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each model has its own field configuration and join function that assembles the prompt. The join function takes the user's selected options and outputs either English or Chinese prompts based on a toggle.&lt;/p&gt;

&lt;h3&gt;
  
  
  Backend: Cloudflare Pages Functions
&lt;/h3&gt;

&lt;p&gt;For the AI refinement, I used Cloudflare Pages Functions as my serverless backend. The key insight here is that Cloudflare Functions run at edge locations worldwide, so latency is minimal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// functions/api/[[path]].ts&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/prompt-refine&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rateLimitResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;checkRateLimit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rateLimitResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blocked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RATE_LIMIT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rateLimitResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;429&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;callDeepseek&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;systemPrompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userPrompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rate Limiting: D1 Database
&lt;/h3&gt;

&lt;p&gt;For rate limiting, I used Cloudflare D1 (a SQLite-compatible serverless database). Each IP gets a counter keyed by &lt;code&gt;${ip}:${day}&lt;/code&gt;. No Redis needed — D1 is fast enough for this use case.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkRateLimit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CF-Connecting-IP&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;day&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;T&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SELECT count FROM ai_usage WHERE key = ?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// ... increment and check&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  AI Integration: DeepSeek API
&lt;/h3&gt;

&lt;p&gt;I chose DeepSeek for its JSON response mode — no parsing markdown or extracting text from code blocks. The system prompt instructs the AI to return valid JSON only:&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I Grew My Free Tool Site from 50 to 1,000+ Tools ??Here's What Actually Changed</title>
      <dc:creator>CarsonJ</dc:creator>
      <pubDate>Wed, 08 Jul 2026 04:48:24 +0000</pubDate>
      <link>https://dev.to/korelyy/i-grew-my-free-tool-site-from-50-to-1000-tools-heres-what-actually-changed-h9b</link>
      <guid>https://dev.to/korelyy/i-grew-my-free-tool-site-from-50-to-1000-tools-heres-what-actually-changed-h9b</guid>
      <description>&lt;h1&gt;
  
  
  I Grew My Free Tool Site from 50 to 1,000+ Tools ??Here's What Actually Changed
&lt;/h1&gt;

&lt;p&gt;Two weeks ago, korelyy.com had 50 tools.&lt;/p&gt;

&lt;p&gt;Today it has over 1,000.&lt;/p&gt;

&lt;p&gt;Here's what I learned scaling a free tool aggregator from 50 to 1,000+ without a team, a budget, or a marketing department.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why 1,000 tools?
&lt;/h2&gt;

&lt;p&gt;After launching with 50 self-built client-side tools (PDF, image compression, JSON formatting, etc.), something unexpected happened: people started asking for more.&lt;/p&gt;

&lt;p&gt;Not more features on existing tools. More categories. "Do you have tools for X?" "What about Y?" "Is there a Z alternative?"&lt;/p&gt;

&lt;p&gt;The pattern was clear ??users don't want five perfect tools. They want one place that covers everything they need, even imperfectly.&lt;/p&gt;

&lt;p&gt;So I built an aggregator layer: curated external tool recommendations alongside the original 50 self-built tools, organized by category, with honest notes on what each one does well and where it falls short.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed from 50 to 1,000
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The curation problem is harder than the technical problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Adding 950 more tools took far more judgment than code. Each external tool needed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A real description (not scraped from the tool's homepage)&lt;/li&gt;
&lt;li&gt;Honest pros/cons ??what it's good for, what it's not&lt;/li&gt;
&lt;li&gt;A link that actually works&lt;/li&gt;
&lt;li&gt;Categorization that makes sense&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wrote descriptions for all of them myself. No AI-generated lists, no scraped content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Client-side tools stay client-side&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The original 50 tools all run in-browser. Files never leave your device. This constraint shaped everything: the architecture, the performance model, the privacy story.&lt;/p&gt;

&lt;p&gt;The external recommendations are links out ??but they're labeled clearly. No confusion about what runs locally vs. what requires uploading to a third party.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Six languages from day one&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The site supports English, Simplified Chinese, Spanish, Hindi, French, and Arabic. Not because I planned a localization strategy ??because I needed it personally. Now 40% of traffic comes from non-English speakers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest numbers after 2 weeks
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;1,000+ tools&lt;/strong&gt; across 50+ categories&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;6 languages&lt;/strong&gt; with consistent coverage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;50 original client-side tools&lt;/strong&gt; (PDF, image, text, code, dev utilities ??all browser-based, zero uploads)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No signup required&lt;/strong&gt; for any built-in tool&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No ads&lt;/strong&gt; interrupting built-in tool usage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;External links clearly labeled&lt;/strong&gt; ??you always know when you're leaving korelyy.com&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I'm not proud of (yet)
&lt;/h2&gt;

&lt;p&gt;The external tool descriptions could be deeper. The category taxonomy will probably change. Some tools will inevitably break or change over time ??maintaining a live aggregator is an ongoing commitment, not a one-time launch.&lt;/p&gt;

&lt;p&gt;But the core promise holds: one place to find the right tool, with honest context, no friction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;?? &lt;strong&gt;&lt;a href="https://korelyy.com" rel="noopener noreferrer"&gt;https://korelyy.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Whether you need one specific utility or want to discover something new ??the built-in tools run locally, the recommendations are human-curated.&lt;/p&gt;

&lt;p&gt;Questions about the build, the curation process, or running a solo tool site? Drop them below.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tools</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I Built 19 Free Tools and Deployed to 6 Languages ??Here's What I Learned</title>
      <dc:creator>CarsonJ</dc:creator>
      <pubDate>Wed, 01 Jul 2026 15:18:06 +0000</pubDate>
      <link>https://dev.to/korelyy/i-built-19-free-tools-and-deployed-to-6-languages-heres-what-i-learned-34oc</link>
      <guid>https://dev.to/korelyy/i-built-19-free-tools-and-deployed-to-6-languages-heres-what-i-learned-34oc</guid>
      <description>&lt;p&gt;I still remember the moment I decided to build Korelyy.&lt;/p&gt;

&lt;p&gt;Not because I had a grand business plan. Not because I did extensive market research.&lt;/p&gt;

&lt;p&gt;But because I was frustrated.&lt;/p&gt;

&lt;p&gt;I'm a developer. I write code every day. And every time I needed a simple tool ??compress a PDF, convert an image, format some JSON ??I had to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Google for a tool&lt;/li&gt;
&lt;li&gt;Upload my file to some random website&lt;/li&gt;
&lt;li&gt;Wait for ads to load&lt;/li&gt;
&lt;li&gt;Worry about privacy&lt;/li&gt;
&lt;li&gt;Repeat for the next tool&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So I built Korelyy. 19 tools. No signup. No ads. No tracking.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Numbers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;19 tools&lt;/strong&gt; (PDF, Image, Text, Code, Math, Color, Network)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;6 languages&lt;/strong&gt; (EN, ZH, ES, HI, FR, AR)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;0 registrations&lt;/strong&gt; required&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;100% free&lt;/strong&gt; (and always will be)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Next.js i18n is powerful (but tricky)
&lt;/h3&gt;

&lt;p&gt;Next.js has built-in i18n support. But deploying to Cloudflare Pages? That's where it gets interesting.&lt;/p&gt;

&lt;p&gt;You need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;next export&lt;/code&gt; for static export&lt;/li&gt;
&lt;li&gt;Configure &lt;code&gt;trailingSlash: true&lt;/code&gt; (Cloudflare Pages doesn't auto-handle trailing slashes)&lt;/li&gt;
&lt;li&gt;Set up &lt;code&gt;wrangler.toml&lt;/code&gt; correctly&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Cloudflare Pages is fast (but has limits)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;??Free tier: generous (500 builds/month)&lt;/li&gt;
&lt;li&gt;??Global CDN: built-in&lt;/li&gt;
&lt;li&gt;??Function timeout: 10ms (for free tier)&lt;/li&gt;
&lt;li&gt;??No Node.js runtime (you're in Cloudflare Workers environment)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. SEO is hard when you're a tools site
&lt;/h3&gt;

&lt;p&gt;Tools sites are hard to rank. Why? Because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Low time-on-page (users get what they need and leave)&lt;/li&gt;
&lt;li&gt;Few backlinks (who links to a PDF compressor?)&lt;/li&gt;
&lt;li&gt;High competition (smallpdf, ilovepdf, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;My solution&lt;/strong&gt;: Build tools that are actually useful, and write blog posts that teach.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: Next.js 14 + TypeScript&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Styling&lt;/strong&gt;: Tailwind CSS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment&lt;/strong&gt;: Cloudflare Pages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics&lt;/strong&gt;: Google Analytics 4&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search&lt;/strong&gt;: Google Search Console&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it out
&lt;/h2&gt;

&lt;p&gt;?? &lt;strong&gt;&lt;a href="https://korelyy.com" rel="noopener noreferrer"&gt;https://korelyy.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No signup. No ads. Just tools that work.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'd love to hear your feedback! What tools should I add next?&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tools</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
