<?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: keke lele</title>
    <description>The latest articles on DEV Community by keke lele (@keke_lele_1c5122e6c3a87d9).</description>
    <link>https://dev.to/keke_lele_1c5122e6c3a87d9</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3688022%2Ff85965ce-af79-4a55-bc5b-25ca6e918b6e.png</url>
      <title>DEV Community: keke lele</title>
      <link>https://dev.to/keke_lele_1c5122e6c3a87d9</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/keke_lele_1c5122e6c3a87d9"/>
    <language>en</language>
    <item>
      <title>Building 21 AI Tool Pages in 6 Weeks: Lessons from a Solo Dev</title>
      <dc:creator>keke lele</dc:creator>
      <pubDate>Fri, 08 May 2026 02:25:44 +0000</pubDate>
      <link>https://dev.to/keke_lele_1c5122e6c3a87d9/building-21-ai-tool-pages-in-6-weeks-lessons-from-a-solo-dev-3m65</link>
      <guid>https://dev.to/keke_lele_1c5122e6c3a87d9/building-21-ai-tool-pages-in-6-weeks-lessons-from-a-solo-dev-3m65</guid>
      <description>&lt;p&gt;Six weeks ago I shipped the first version of &lt;a href="https://melodycraftai.com/?utm_source=devto" rel="noopener noreferrer"&gt;MelodyCraft AI&lt;/a&gt;, a&lt;br&gt;
  single-page AI music generator. Today there are 21 tool pages live — rap generators, name generators, a lyrics-to-song&lt;br&gt;
   workflow, an 8-page band-name cluster, and a few experiments that worked despite my better judgment.&lt;/p&gt;

&lt;p&gt;I'm a solo dev. No co-founder, no design team. The whole thing runs on Next.js 15 (App Router), Drizzle ORM, Better&lt;br&gt;
  Auth, Tailwind 4, and a thin abstraction over two AI providers. One Git repo, deployed on Vercel.&lt;/p&gt;

&lt;p&gt;This is a brain dump of what I'd tell myself before week 1. Not a brag list — half of it is mistakes. Some of these&lt;br&gt;
  are technical, some are product, some are weirdly specific to the way solo devs accidentally make their own lives&lt;br&gt;
  harder.&lt;/p&gt;

&lt;p&gt;Here's the rundown.&lt;/p&gt;




&lt;p&gt;## 1. The stack matters less than the page checklist&lt;/p&gt;

&lt;p&gt;Everyone obsesses over stack selection. I did too — Next.js 15 vs SvelteKit, Drizzle vs Prisma, Better Auth vs&lt;br&gt;
  NextAuth vs roll-your-own. In the end the stack delta was maybe 2-3 days over 6 weeks. What actually saved me was a&lt;br&gt;
  checklist.&lt;/p&gt;

&lt;p&gt;After page #2 I noticed I kept missing the same things — meta tags wrong, og:image not 1200x630, internal links&lt;br&gt;
  rendering grey-on-grey, hreflang missing, schema.org missing. So I wrote a 100-item checklist split into 11 buckets:&lt;br&gt;
  SEO, Performance, Accessibility, Mobile, Internal Links, Schema, OG, Analytics, Anti-Abuse, Copy QA, Credits/Pricing.&lt;/p&gt;

&lt;p&gt;Every new tool page has to pass the checklist before it hits main. Sounds bureaucratic. It is. But pages 3-21 took&lt;br&gt;
  roughly half the time of pages 1-2 each, and the post-deploy bug rate dropped to almost zero.&lt;/p&gt;

&lt;p&gt;If you're a solo dev, write the checklist after page 2. Earlier is wasted effort; later is too late.&lt;/p&gt;

&lt;p&gt;## 2. Don't multi-provider until you have to&lt;/p&gt;

&lt;p&gt;Early on I plugged in two AI providers behind a TypeScript interface:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
ts
  interface AIProvider {
    createTask(params: TaskParams): Promise&amp;lt;Task&amp;gt;;
    getTaskStatus(taskId: string): Promise&amp;lt;TaskStatus&amp;gt;;
  }

  const provider = getProvider(env.PROVIDER || "evolink");

  The reasoning was "what if A goes down?" Sounded responsible. In practice for the first 5 weeks I used exactly one
  provider, the abstraction added friction every time the two APIs diverged (different param names, different error
  shapes, different webhook payloads), and I built glue code I never used.

  Premature provider abstraction is a YAGNI tax. Build for one provider, ship, abstract when the second one actually
  earns its keep. The interface is a 30-minute refactor when you genuinely need it — not before.

  3. A bad polling pattern can burn $200 in 24 hours

  This one stings.

  Around week 4 I rewrote the lyrics-to-song page (https://melodycraftai.com/lyrics-to-song?utm_source=devto). The new
  client polled the task status endpoint every 1 second instead of every 5. I tested locally with one task, it worked, I
   shipped.

  Next morning Vercel sent me an email: Edge Requests at 99.7% of the monthly quota. By dinner I'd been auto-upgraded to
   Pro and was watching the meter tick. The fix took 3 minutes — bump the interval, add exponential backoff, gate the
  polling behind tab visibility. The damage was real money.

  What I should have done: back-of-envelope math before shipping. (active users × poll frequency × avg duration × 30
  days). I now keep a polling-budget.md next to the code that updates whenever a polling rate changes.

  If you don't track polling math, your Edge function bill will track it for you.

  4. One template, eight pages — the band-name cluster

  After page 13 I stopped writing tool pages from scratch. A search-volume scan turned up 8 viable band-name generator
  queries — metal band name, kpop band name, punk band name generator, etc. Each was 200-1000 monthly searches on its
  own, low difficulty, no obvious dominant ranker.

  So I extracted a NameToolTemplate component:

  &amp;lt;NameToolTemplate
    genre="Metal"
    promptPrefix="Generate aggressive, dark band names suitable for thrash/death metal..."
    examples={metalBandExamples}
    schemaDescription="Free metal band name generator..."
  /&amp;gt;

  8 pages shipped in 2 days. Each one ranks for its specific query without cannibalizing the others, because the page
  content is genuinely different — different examples, different FAQ, different prompt seed — even though the shell is
  identical.

  When you see ≥ 5 pages with the same shape, build the template. Anything less, hand-write it. The break-even is
  sharper than it looks.

  5. Programmatic SEO almost killed the blog plan

  I had this idea: programmatically generate ~50 /blog posts from a genre × use-case matrix. Looked clean on paper,
  would have shipped in a weekend.

  Then I read the 2024-2026 Google Helpful Content + Spam Updates more carefully. Programmatic content with thin
  variation now actively hurts site-wide rankings, not just the offending pages. So 50 templated blog posts could drag
  the 21 tool pages down with them.

  I killed the idea last week. Replaced it with one hand-crafted long-form blog per week. Lower volume, much higher
  ceiling, no Google risk. The bandwidth I freed went into a YouTube channel — different distribution, different
  algorithm, doesn't compete with the main SEO thread.

  Templates are great for tool pages where the user actually wants the tool. Templates for content — where the user
  wants information — are a Google trap in 2026.

  6. Anti-abuse: gate the gift, not the user

  I had a fingerprint + card dedup that auto-banned users looking like duplicates. Felt smart. Wasn't.

  A reference SaaS in the same niche ran the same logic and later discovered, via angry support tickets, that the
  "duplicates" were often a single VIP customer using multiple devices and multiple cards (work card, personal card,
  family card). Banning them killed revenue.

  I refactored. The dedup now runs at exactly one place: the new-user free credit gift. Same fingerprint or same card on
   signup → no second free gift. But you can still register, log in, buy credits, and use the tool normally. This stops
  free-credit cycling without burning real customers.

  Small product call. Difference between "we lose ~$0 to abuse" and "we lose 30% of VIP revenue to false positives" is
  purely where the gate sits.

  7. Internal links are weirdly hard

  The dumbest lesson, listed last because it's a real one.

  After shipping the blog index (https://melodycraftai.com/blog?utm_source=devto), I noticed a few internal links
  rendered the same color as body text — grey on white. Users (and Googlebot) couldn't tell they were clickable.

  I'd assumed Tailwind's prose class handled this. It does — for external links. The way my MDX renderer wired up the
  &amp;lt;a&amp;gt; component stripped the color class on internal anchors specifically.

  Fix was 4 lines. But it had been live for 5 days and nobody had clicked through.

  Every time you ship a new content surface, click 3 internal links yourself, on mobile, in incognito. The cost is 10
  seconds. The cost of not doing it is invisible CTR loss for a week.

  ---
  What I'd do differently next time

  - Page checklist on day 1, not after page 2
  - One AI provider until you literally cannot ship without a second
  - Polling math is a checklist item, not an optimization
  - Hand-crafted blog from day 1 — programmatic is for tool pages, not for content
  - Anti-abuse logic gates on gifts, not on signups
  - Click your own internal links every release

  Source layout for the 21 tools is in this open repo: https://github.com/kekelele19851224-lgtm/melodycraft-ai-public-.
  It's a README index — useful as a reference if you're building a similar AI tool catalog.

  If you're a solo dev shipping AI tools, the meta-lesson is: most of the work is plumbing, not the AI part. The AI
  providers are a stable interface you call. The hard parts are the 100 tiny things that make a page rank, convert, and
  not blow up your Vercel bill at 3 AM.

  That, and not getting too clever before week 6.

  ---
  MelodyCraft AI is at melodycraftai.com (https://melodycraftai.com/?utm_source=devto). Happy to write up specific
  subsystems — the credit system FIFO logic, the polling backoff, the NameToolTemplate generator — if there's interest.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>ai</category>
      <category>solodev</category>
    </item>
    <item>
      <title>How I Built an AI Rap Name Generator with Next.js 15 + Gemini 2.5 Flash</title>
      <dc:creator>keke lele</dc:creator>
      <pubDate>Fri, 24 Apr 2026 06:28:09 +0000</pubDate>
      <link>https://dev.to/keke_lele_1c5122e6c3a87d9/how-i-built-an-ai-rap-name-generator-with-nextjs-15-gemini-25-flash-jci</link>
      <guid>https://dev.to/keke_lele_1c5122e6c3a87d9/how-i-built-an-ai-rap-name-generator-with-nextjs-15-gemini-25-flash-jci</guid>
      <description>&lt;p&gt;A few weeks ago I shipped an &lt;a href="https://melodycraftai.com/rap-name-generator?utm_source=devto" rel="noopener noreferrer"&gt;AI Rap Name Generator&lt;/a&gt; as&lt;br&gt;
   part of a multi-tool music app. It looks dead simple from the outside — pick a genre, pick a few "vibes," click&lt;br&gt;
  generate, get 6 rapper names back. Behind that simplicity there were three things that took longer than I expected to&lt;br&gt;
  get right. Sharing in case you're building something similar.&lt;/p&gt;

&lt;p&gt;## The stack&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 15&lt;/strong&gt; (App Router, RSC where possible)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini 2.5 Flash&lt;/strong&gt; for the LLM (fast + cheap, perfect for short-form structured generation)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drizzle ORM&lt;/strong&gt; + Postgres for credit tracking&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zod&lt;/strong&gt; for input validation&lt;/li&gt;
&lt;li&gt;TypeScript everywhere&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total cost per 6-name generation: roughly $0.0002 with Gemini Flash. That's basically free, which is why I could&lt;br&gt;
  afford a generous free tier without going broke.&lt;/p&gt;

&lt;p&gt;## Tricky part #1: Prompt engineering for strict JSON output&lt;/p&gt;

&lt;p&gt;LLMs love to add chatty prefixes and trailing markdown fences. Out of the box, the model would happily return:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sure! Here are 6 rapper names for you:&lt;br&gt;
&lt;code&gt;\&lt;/code&gt;&lt;code&gt;json&lt;br&gt;
[{"name": "...", "vibe": "..."}]&lt;br&gt;
\&lt;/code&gt;&lt;code&gt;\&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That breaks &lt;code&gt;JSON.parse()&lt;/code&gt;. The fix was twofold — strict instruction in the prompt + defensive parsing on the way out:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
  return&lt;/code&gt;You are a creative rap name specialist. Generate exactly 6 unique rapper stage names.&lt;/p&gt;

&lt;p&gt;Genre: ${p.genre}&lt;br&gt;
  Vibe: ${vibeStr}&lt;br&gt;
  Gender: ${genderStr}&lt;/p&gt;

&lt;p&gt;Rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Names must authentically fit the ${p.genre} genre&lt;/li&gt;
&lt;li&gt;Each name should be 1–3 words, memorable, and original&lt;/li&gt;
&lt;li&gt;No slurs or offensive language&lt;/li&gt;
&lt;li&gt;Vary the style: some single-word, some two-word, some with numbers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Return ONLY a valid JSON array with exactly 6 objects, no other text:&lt;br&gt;
  [{"name":"Example Name","vibe":"Short vibe description here"},...]&lt;code&gt;;&lt;br&gt;
  \&lt;/code&gt;&lt;code&gt;\&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And the parser:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
  const jsonMatch = rawText.match(/\[[\s\S]*\]/);&lt;br&gt;
  const names = jsonMatch ? JSON.parse(jsonMatch[0]) : [];&lt;br&gt;
  \&lt;/code&gt;&lt;code&gt;\&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The regex grabs the first &lt;code&gt;[...]&lt;/code&gt; block in the response and ignores whatever fluff came before or after. Catches ~99%&lt;br&gt;
  of cases. The remaining 1% (Gemini occasionally truncates if &lt;code&gt;maxOutputTokens&lt;/code&gt; is too low) gets handled by the user&lt;br&gt;
  just clicking generate again — and crucially, they don't get charged for it (more on that below).&lt;/p&gt;

&lt;p&gt;## Tricky part #2: Gemini's 503s&lt;/p&gt;

&lt;p&gt;About 1 in 30 requests come back with a 503 ("Service Unavailable" / "high demand"). First time I shipped without&lt;br&gt;
  retry logic, my support inbox filled up within a day.&lt;/p&gt;

&lt;p&gt;The fix is a simple retry with backoff:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
  let data;&lt;br&gt;
  for (let attempt = 0; attempt &amp;lt; 3; attempt++) {&lt;br&gt;
    if (attempt &amp;gt; 0) await new Promise((r) =&amp;gt; setTimeout(r, 1500));&lt;br&gt;
    const res = await fetch(GEMINI_URL, { method: "POST", body: geminiBody });&lt;br&gt;
    if (res.status === 503 &amp;amp;&amp;amp; attempt &amp;lt; 2) continue;&lt;br&gt;
    if (!res.ok) throw new Error(&lt;/code&gt;Gemini API error ${res.status}&lt;code&gt;);&lt;br&gt;
    data = await res.json();&lt;br&gt;
    break;&lt;br&gt;
  }&lt;br&gt;
  \&lt;/code&gt;&lt;code&gt;\&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;3 attempts, 1.5s sleep between. Brings effective failure rate from ~3% to under 0.1%.&lt;/p&gt;

&lt;p&gt;## Tricky part #3: The credit freeze/settle/release pattern&lt;/p&gt;

&lt;p&gt;Users buy credits up front. A naive flow would be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Deduct credits&lt;/li&gt;
&lt;li&gt;Call Gemini&lt;/li&gt;
&lt;li&gt;Return result&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But what if Gemini fails on attempt 3 of 3? You've charged the user for nothing. Refunding adds support overhead. The&lt;br&gt;
  right pattern:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
  const holdUuid =&lt;/code&gt;rapname_${nanoid(21)}`;&lt;/p&gt;

&lt;p&gt;await creditService.freeze({&lt;br&gt;
    userId: user.id,&lt;br&gt;
    credits: RAP_NAME_GENERATION_CREDITS,&lt;br&gt;
    videoUuid: holdUuid,&lt;br&gt;
  });&lt;/p&gt;

&lt;p&gt;try {&lt;br&gt;
    // ... call Gemini, parse result ...&lt;br&gt;
    await creditService.settle(holdUuid);  // success → actually consume&lt;br&gt;
  } catch (err) {&lt;br&gt;
    await creditService.release(holdUuid); // failure → refund&lt;br&gt;
    throw err;&lt;br&gt;
  }&lt;br&gt;
  `&lt;code&gt;\&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Three states for credits: &lt;strong&gt;available&lt;/strong&gt;, &lt;strong&gt;frozen&lt;/strong&gt;, &lt;strong&gt;consumed&lt;/strong&gt;. Frozen credits are reserved (so concurrent requests&lt;br&gt;
   can't double-spend) but not yet charged. On success they settle into consumed; on failure they release back to&lt;br&gt;
  available.&lt;/p&gt;

&lt;p&gt;The user-facing payoff is one sentence in the error response:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The AI is experiencing high demand right now. &lt;strong&gt;No credits were deducted&lt;/strong&gt; — please try again in a few minutes."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That sentence — "no credits were deducted" — single-handedly killed about 80% of refund requests.&lt;/p&gt;

&lt;p&gt;This pattern also scaled well when I added long-running jobs (music generation, where the AI provider takes 60+&lt;br&gt;
  seconds). Same primitives, different durations.&lt;/p&gt;

&lt;p&gt;## Lessons&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Design the failure path before the happy path.&lt;/strong&gt; Retries, refunds, friendly errors. The happy path is one
if-statement; the failure paths are 80% of the work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Defensive parsing &amp;gt; strict prompts.&lt;/strong&gt; You can ask the LLM nicely to return clean JSON, but always parse like it
lied to you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make the cheapest model your default.&lt;/strong&gt; Gemini 2.5 Flash is plenty for short-form structured output. Save the
expensive models for tasks that actually benefit.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want to try the live tool, it's at&lt;br&gt;
  &lt;a href="https://melodycraftai.com/rap-name-generator?utm_source=devto" rel="noopener noreferrer"&gt;melodycraftai.com/rap-name-generator&lt;/a&gt;. Curious what&lt;br&gt;
  other tricky parts people have hit when shipping LLM features — drop them in the comments.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>nextjs</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I Built a Free Tool to Generate Beautiful Arabic Calligraphy - Here's How It Works</title>
      <dc:creator>keke lele</dc:creator>
      <pubDate>Thu, 22 Jan 2026 10:28:56 +0000</pubDate>
      <link>https://dev.to/keke_lele_1c5122e6c3a87d9/i-built-a-free-tool-to-generate-beautiful-arabic-calligraphy-heres-how-it-works-3iba</link>
      <guid>https://dev.to/keke_lele_1c5122e6c3a87d9/i-built-a-free-tool-to-generate-beautiful-arabic-calligraphy-heres-how-it-works-3iba</guid>
      <description>&lt;p&gt;Introduction&lt;br&gt;
Arabic calligraphy is one of the world's most beautiful art forms, with a history spanning over 1,400 years. As a developer, I wanted to make this ancient art accessible to everyone - designers, students, and anyone curious about Arabic script.&lt;br&gt;
That's why I built Arabic Calligraphy Generator - a free online tool that transforms text into stunning Arabic calligraphy.&lt;br&gt;
The Problem I Wanted to Solve&lt;br&gt;
Many people face these challenges when working with Arabic calligraphy:&lt;/p&gt;

&lt;p&gt;Language barrier: Most people can't write Arabic by hand&lt;br&gt;
Font limitations: Standard Arabic fonts lack the artistic beauty of traditional calligraphy&lt;br&gt;
Expensive software: Professional calligraphy tools often require paid subscriptions&lt;br&gt;
Export options: Getting high-quality exports for design work is difficult&lt;/p&gt;

&lt;p&gt;What the Tool Does&lt;br&gt;
The Arabic Calligraphy Generator offers:&lt;br&gt;
11 Traditional Calligraphy Styles&lt;/p&gt;

&lt;p&gt;Thuluth (ثلث) - Elegant, often used in mosque decorations&lt;br&gt;
Naskh (نسخ) - The most common style for printed Arabic&lt;br&gt;
Kufi (كوفي) - Angular, geometric style&lt;br&gt;
Diwani (ديواني) - Flowing, cursive Ottoman style&lt;br&gt;
Ruq'ah (رقعة) - Simple, everyday handwriting style&lt;br&gt;
Maghrebi (مغربي) - North African style&lt;br&gt;
And 5 more traditional styles...&lt;/p&gt;

&lt;p&gt;Key Features&lt;/p&gt;

&lt;p&gt;English to Arabic Translation - Type in English, get Arabic calligraphy&lt;br&gt;
Multiple Export Formats - PNG, JPG, and SVG for any use case&lt;br&gt;
Completely Free - No sign-up, no watermarks, no limits&lt;br&gt;
Instant Preview - See your calligraphy in real-time&lt;/p&gt;

&lt;p&gt;Use Cases&lt;br&gt;
This tool is perfect for:&lt;/p&gt;

&lt;p&gt;Graphic designers creating logos or artwork with Arabic elements&lt;br&gt;
Tattoo artists designing Arabic calligraphy tattoos&lt;br&gt;
Students learning about Islamic art and culture&lt;br&gt;
Content creators making social media graphics&lt;br&gt;
Developers who need Arabic text assets&lt;/p&gt;

&lt;p&gt;Technical Highlights&lt;br&gt;
Building this tool involved some interesting challenges:&lt;/p&gt;

&lt;p&gt;Handling right-to-left (RTL) text rendering&lt;br&gt;
Ensuring proper Arabic letter connections (Arabic letters change shape based on position)&lt;br&gt;
Optimizing SVG output for scalability&lt;br&gt;
Making the interface intuitive for users unfamiliar with Arabic&lt;/p&gt;

&lt;p&gt;Try It Out&lt;br&gt;
If you're working on any project involving Arabic text or calligraphy, give it a try:&lt;br&gt;
👉 arabiccalligraphygenerator.online&lt;br&gt;
I'd love to hear your feedback! Drop a comment below or reach out if you have suggestions for new features.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>design</category>
    </item>
    <item>
      <title>How I Built a Free Arabic Calligraphy Generator with SVG Export</title>
      <dc:creator>keke lele</dc:creator>
      <pubDate>Sat, 17 Jan 2026 12:21:23 +0000</pubDate>
      <link>https://dev.to/keke_lele_1c5122e6c3a87d9/how-i-built-a-free-arabic-calligraphy-generator-with-svg-export-3d16</link>
      <guid>https://dev.to/keke_lele_1c5122e6c3a87d9/how-i-built-a-free-arabic-calligraphy-generator-with-svg-export-3d16</guid>
      <description>&lt;p&gt;As a developer fascinated by Arabic typography, I built a free tool that lets anyone create beautiful Arabic calligraphy online. Here's what I learned and how it works.&lt;br&gt;
The Problem&lt;br&gt;
Arabic calligraphy has a rich 1,400+ year history, but most online tools either require paid subscriptions, don't support vector exports, or offer limited font choices. I wanted to create something accessible to everyone.&lt;br&gt;
Key Features&lt;br&gt;
My solution at &lt;a href="//arabiccalligraphygenerator.online"&gt;arabiccalligraphygenerator.online&lt;/a&gt; includes:&lt;/p&gt;

&lt;p&gt;11 authentic calligraphy fonts (Thuluth, Naskh, Kufi, Diwani, Nastaliq, and more)&lt;br&gt;
English to Arabic translation for non-Arabic speakers&lt;br&gt;
SVG vector export for scalable designs&lt;br&gt;
Canvas manipulation with drag positioning, rotation, and opacity controls&lt;br&gt;
Harakat (diacritics) support for proper pronunciation marks&lt;/p&gt;

&lt;p&gt;Technical Approach&lt;br&gt;
The generator uses HTML5 Canvas for rendering and leverages Google Fonts' Arabic font collection. For SVG export, I convert the canvas rendering to vector paths, ensuring designs can scale infinitely without quality loss.&lt;br&gt;
The translation feature uses an API to convert English text to Arabic script, making the tool accessible to designers worldwide who want to incorporate Arabic calligraphy into their work.&lt;br&gt;
Why SVG Matters&lt;br&gt;
Most calligraphy tools only export raster images. SVG export is crucial for:&lt;/p&gt;

&lt;p&gt;Logo design (scalable to any size)&lt;br&gt;
Print materials (high resolution)&lt;br&gt;
Web graphics (small file size)&lt;/p&gt;

&lt;p&gt;Try It Out&lt;br&gt;
The tool is 100% free, no signup required: arabiccalligraphygenerator.online&lt;br&gt;
I'd love to hear your feedback or feature requests!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>design</category>
    </item>
    <item>
      <title>I Built a Free Arabic Calligraphy Generator - Transform Text into Beautiful Islamic Art</title>
      <dc:creator>keke lele</dc:creator>
      <pubDate>Sun, 11 Jan 2026 10:15:41 +0000</pubDate>
      <link>https://dev.to/keke_lele_1c5122e6c3a87d9/i-built-a-free-arabic-calligraphy-generator-transform-text-into-beautiful-islamic-art-4h62</link>
      <guid>https://dev.to/keke_lele_1c5122e6c3a87d9/i-built-a-free-arabic-calligraphy-generator-transform-text-into-beautiful-islamic-art-4h62</guid>
      <description>&lt;p&gt;Hey DEV community! 👋&lt;/p&gt;

&lt;p&gt;I want to share a free tool I built: &lt;a href="https://arabiccalligraphygenerator.online/" rel="noopener noreferrer"&gt;Arabic Calligraphy Generator&lt;/a&gt; - a web app that transforms any text into beautiful Arabic calligraphy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Built This
&lt;/h2&gt;

&lt;p&gt;Arabic calligraphy (الخط العربي) is one of the most beautiful art forms in the world. But for most people, creating authentic Arabic calligraphy is nearly impossible without years of practice or expensive software.&lt;/p&gt;

&lt;p&gt;I wanted to make this art form accessible to everyone - designers, developers, content creators, or anyone who appreciates beautiful typography.&lt;/p&gt;

&lt;h2&gt;
  
  
  What It Does
&lt;/h2&gt;

&lt;p&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.amazonaws.com%2Fuploads%2Farticles%2Finv0f0nab82q5ryclz3w.png" 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.amazonaws.com%2Fuploads%2Farticles%2Finv0f0nab82q5ryclz3w.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The generator offers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;11 Traditional Font Styles&lt;/strong&gt; - Including Thuluth (ثلث), Naskh (نسخ), Kufi (كوفي), Diwani (ديواني), and more&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto Translation&lt;/strong&gt; - Just type in English, it translates to Arabic automatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple Export Formats&lt;/strong&gt; - Download as PNG, JPG, or SVG&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customization&lt;/strong&gt; - Adjust colors, sizes, and backgrounds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;100% Free&lt;/strong&gt; - No registration, no watermarks&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Font Styles Preview
&lt;/h2&gt;

&lt;p&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.amazonaws.com%2Fuploads%2Farticles%2Fmggql3wgembql6hl69dz.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fmggql3wgembql6hl69dz.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&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.amazonaws.com%2Fuploads%2Farticles%2Fb9fg4bbiagueo2hjcne2.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fb9fg4bbiagueo2hjcne2.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&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.amazonaws.com%2Fuploads%2Farticles%2F6o07l4kvte6vm8v7dl24.png" 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.amazonaws.com%2Fuploads%2Farticles%2F6o07l4kvte6vm8v7dl24.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each style has its own character:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Style&lt;/th&gt;
&lt;th&gt;Character&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Thuluth&lt;/td&gt;
&lt;td&gt;Elegant, decorative&lt;/td&gt;
&lt;td&gt;Titles, logos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Naskh&lt;/td&gt;
&lt;td&gt;Clean, readable&lt;/td&gt;
&lt;td&gt;Body text, Quran&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kufi&lt;/td&gt;
&lt;td&gt;Geometric, angular&lt;/td&gt;
&lt;td&gt;Modern design&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Diwani&lt;/td&gt;
&lt;td&gt;Flowing, cursive&lt;/td&gt;
&lt;td&gt;Invitations, art&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Use Cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🎨 &lt;strong&gt;Designers&lt;/strong&gt; - Create unique logos and graphics&lt;/li&gt;
&lt;li&gt;🕌 &lt;strong&gt;Islamic content&lt;/strong&gt; - Quran verses, religious quotes&lt;/li&gt;
&lt;li&gt;✨ &lt;strong&gt;Social media&lt;/strong&gt; - Eye-catching posts&lt;/li&gt;
&lt;li&gt;🎁 &lt;strong&gt;Personalized gifts&lt;/strong&gt; - Names in Arabic calligraphy&lt;/li&gt;
&lt;li&gt;💻 &lt;strong&gt;Developers&lt;/strong&gt; - Generate assets for apps&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Demo
&lt;/h2&gt;

&lt;p&gt;Check out this tutorial to see how it works:&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/o646nDzc80w"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3 simple steps:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enter your text (English or Arabic)&lt;/li&gt;
&lt;li&gt;Choose a calligraphy style&lt;/li&gt;
&lt;li&gt;Download in your preferred format&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it! No signup required.&lt;/p&gt;

&lt;p&gt;No signup required!&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Out
&lt;/h2&gt;

&lt;p&gt;👉 &lt;a href="https://arabiccalligraphygenerator.online/" rel="noopener noreferrer"&gt;arabiccalligraphygenerator.online&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd love to hear your feedback! What features would you like to see added? Drop a comment below 👇&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you found this useful, a ❤️ would mean a lot!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>webdev</category>
      <category>opensource</category>
      <category>design</category>
    </item>
    <item>
      <title>How I Built a Free Arabic Calligraphy Generator with HTML, CSS &amp; JavaScript</title>
      <dc:creator>keke lele</dc:creator>
      <pubDate>Thu, 01 Jan 2026 03:08:32 +0000</pubDate>
      <link>https://dev.to/keke_lele_1c5122e6c3a87d9/how-i-built-a-free-arabic-calligraphy-generator-with-html-css-javascript-6m4</link>
      <guid>https://dev.to/keke_lele_1c5122e6c3a87d9/how-i-built-a-free-arabic-calligraphy-generator-with-html-css-javascript-6m4</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Arabic calligraphy is one of the most beautiful art forms in the world. I wanted to create a simple web tool that lets anyone generate Arabic calligraphy from English text — no design skills needed.&lt;/p&gt;

&lt;p&gt;In this post, I'll share how I built &lt;a href="https://arabiccalligraphygenerator.online" rel="noopener noreferrer"&gt;Arabic Calligraphy Generator&lt;/a&gt; using just HTML, CSS, and vanilla JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge
&lt;/h2&gt;

&lt;p&gt;Building this tool came with some interesting challenges:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Right-to-Left (RTL) text rendering&lt;/strong&gt; — Arabic reads from right to left&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Font loading&lt;/strong&gt; — Arabic calligraphy fonts are large files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Translation&lt;/strong&gt; — Converting English input to Arabic script&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export options&lt;/strong&gt; — Users need to download their creations&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;I kept it simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTML5 Canvas for rendering&lt;/li&gt;
&lt;li&gt;Vanilla JavaScript (no frameworks)&lt;/li&gt;
&lt;li&gt;Google Fonts for Arabic typefaces&lt;/li&gt;
&lt;li&gt;Canvas API for PNG/JPG export&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Implementation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Handling RTL Text
&lt;/h3&gt;

&lt;p&gt;The most important CSS rule for Arabic text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.arabic-text&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rtl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'Noto Naskh Arabic'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;serif&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;h3&gt;
  
  
  2. Loading Arabic Fonts
&lt;/h3&gt;

&lt;p&gt;I used multiple calligraphy styles. Here's how to preload them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Canvas Export Function
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;exportAsImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;format&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;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;calligraphy-canvas&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;link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;download&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`calligraphy.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;format&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;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDataURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`image/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;format&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;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&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;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Start simple&lt;/strong&gt; — I launched with 3 fonts, now it has 11&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance matters&lt;/strong&gt; — Arabic fonts are heavy, lazy loading helps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User feedback is gold&lt;/strong&gt; — Real users found bugs I never imagined&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try It Out
&lt;/h2&gt;

&lt;p&gt;You can check out the live tool here: &lt;a href="https://arabiccalligraphygenerator.online" rel="noopener noreferrer"&gt;Arabic Calligraphy Generator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's completely free — no signup required. Just type your text, choose a style, and download.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;I'm planning to add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More calligraphy styles (Diwani, Maghrebi)&lt;/li&gt;
&lt;li&gt;Custom color options&lt;/li&gt;
&lt;li&gt;Social sharing features&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Thanks for reading! If you have questions about building multilingual web tools, drop a comment below. 👇&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
