<?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: Fifteen Lee</title>
    <description>The latest articles on DEV Community by Fifteen Lee (@fifteen_lee_ecddd88048aa6).</description>
    <link>https://dev.to/fifteen_lee_ecddd88048aa6</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%2F3994052%2F2740aae8-e24b-4f0b-8231-7b129de9e66c.jpg</url>
      <title>DEV Community: Fifteen Lee</title>
      <link>https://dev.to/fifteen_lee_ecddd88048aa6</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fifteen_lee_ecddd88048aa6"/>
    <language>en</language>
    <item>
      <title>How I Built a 1000-Page Numerology Site with Programmatic SEO</title>
      <dc:creator>Fifteen Lee</dc:creator>
      <pubDate>Sat, 20 Jun 2026 16:00:00 +0000</pubDate>
      <link>https://dev.to/fifteen_lee_ecddd88048aa6/how-i-built-a-1000-page-numerology-site-with-programmatic-seo-2g14</link>
      <guid>https://dev.to/fifteen_lee_ecddd88048aa6/how-i-built-a-1000-page-numerology-site-with-programmatic-seo-2g14</guid>
      <description>&lt;p&gt;I built &lt;a href="https://angelnumber.space" rel="noopener noreferrer"&gt;Angel Number&lt;/a&gt; — a site that gives you the numerology meaning of any repeating number from 000 to 999. Every single number has its own page, its own unique content, and its own SEO metadata. All generated programmatically.&lt;/p&gt;

&lt;p&gt;Here's how programmatic SEO works for a content-heavy niche site.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;## The Challenge&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Angel numbers (111, 222, 333, etc.) are a popular search topic. People type "angel number 111 meaning" into Google every day. The problem is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating 1000+ pages manually is impossible&lt;/li&gt;
&lt;li&gt;Each page needs genuinely unique content, not just find-and-replace&lt;/li&gt;
&lt;li&gt;The content has to be useful enough that people stay and read&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;## The Solution: Programmatic SEO&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of writing 1000 pages by hand, I built a content generation system that creates each page from structured data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;### Data Structure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each number is defined by three layers:&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;AngelNumber&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;      &lt;span class="c1"&gt;// 111, 222, etc.&lt;/span&gt;
  &lt;span class="nl"&gt;baseMeaning&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="c1"&gt;// Core numerology meaning&lt;/span&gt;
  &lt;span class="nl"&gt;keywords&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="c1"&gt;// Related concepts&lt;/span&gt;
  &lt;span class="nl"&gt;combinations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;      &lt;span class="c1"&gt;// For multi-digit analysis&lt;/span&gt;
    &lt;span class="na"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="nl"&gt;meaning&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="nl"&gt;zodiacAffinity&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="c1"&gt;// Optional zodiac tie-in&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;### Page Generation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A single Next.js dynamic route generates all pages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[number] → /111, /222, /333, ... /999
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each page gets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unique title tag (&lt;code&gt;"Angel Number 111 Meaning — Numerology"&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Unique meta description&lt;/li&gt;
&lt;li&gt;JSON-LD structured data (WebPage schema)&lt;/li&gt;
&lt;li&gt;Canonical URL&lt;/li&gt;
&lt;li&gt;Internal links to related numbers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;## The Technical Stack&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 14&lt;/strong&gt; with static generation (ISR)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript&lt;/strong&gt; for type safety&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind CSS&lt;/strong&gt; for responsive design&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel&lt;/strong&gt; for hosting and automatic ISR revalidation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Static generation means all 1000+ pages are pre-rendered at build time. They load instantly — no server-side computation on request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;## SEO Results So Far&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The programmatic approach wins on long-tail coverage. Individual number pages rank for queries like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"angel number 333 meaning love"&lt;/li&gt;
&lt;li&gt;"444 angel number twin flame"&lt;/li&gt;
&lt;li&gt;"what does 111 mean spiritually"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each query might be low volume individually, but 1000+ pages × low-volume queries = consistent traffic.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;### What Worked&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unique content per page&lt;/strong&gt; — Google can detect templated content. Each page needs genuine value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internal linking&lt;/strong&gt; — linking between related numbers keeps users browsing and distributes page authority.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean URLs&lt;/strong&gt; — &lt;code&gt;/333&lt;/code&gt; is better than &lt;code&gt;/number?=333&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;### What I'd Improve&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;User contributions&lt;/strong&gt; — letting users share their experiences with each number would add fresh content automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More media&lt;/strong&gt; — visualization of number patterns or numerology charts would reduce bounce rate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-language&lt;/strong&gt; — angel numbers are searched in every language. Each new language = 1000 more pages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;## Try It&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Search any number at &lt;strong&gt;&lt;a href="https://angelnumber.space" rel="noopener noreferrer"&gt;Angel Number&lt;/a&gt;&lt;/strong&gt; — instant numerology meaning, no sign-up, no ads clutter.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with Next.js 14, TypeScript, and Tailwind CSS. Hosted on Vercel.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>seo</category>
      <category>nextjs</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How I Built a Chinese Zodiac Compatibility Tool with Next.js</title>
      <dc:creator>Fifteen Lee</dc:creator>
      <pubDate>Sat, 20 Jun 2026 12:30:10 +0000</pubDate>
      <link>https://dev.to/fifteen_lee_ecddd88048aa6/how-i-built-a-chinese-zodiac-compatibility-tool-with-nextjs-4ba6</link>
      <guid>https://dev.to/fifteen_lee_ecddd88048aa6/how-i-built-a-chinese-zodiac-compatibility-tool-with-nextjs-4ba6</guid>
      <description>&lt;p&gt;I recently built &lt;a href="https://zodiacmatch.xyz" rel="noopener noreferrer"&gt;ZodiacMatch&lt;/a&gt; — a free tool that lets you pick two Chinese zodiac signs and get an instant compatibility score. No sign-up, no download, no friction.&lt;/p&gt;

&lt;p&gt;Here's how it works under the hood.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;## The Problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Chinese zodiac compatibility is a centuries-old system, but most online tools are either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Oversimplified&lt;/strong&gt; — just "good" or "bad" with no detail&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buried in ads&lt;/strong&gt; — the actual tool is after 3 popups&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slow&lt;/strong&gt; — multiple page loads to get an answer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted something that loads instantly, answers the question in one click, and gives enough depth to be useful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;## The Data Structure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Chinese zodiac has 12 animal signs. That's 66 unique pairings (12 choose 2). Each pairing needed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A base compatibility score (0–100)&lt;/li&gt;
&lt;li&gt;Element interaction modifiers (Five Elements cycle)&lt;/li&gt;
&lt;li&gt;Strengths and challenges&lt;/li&gt;
&lt;li&gt;Communication style assessment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of hardcoding all 66, I structured the data as a matrix with dimension scores that combine dynamically. This makes it easy to tweak any dimension without touching every entry.&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;CompatibilityData&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;baseScore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;elementModifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;strengths&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;challenges&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;communication&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;## Tech Stack&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 14&lt;/strong&gt; (App Router) — file-based routing, SSR for SEO&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript&lt;/strong&gt; — type safety across the board&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind CSS&lt;/strong&gt; — responsive, mobile-first&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel&lt;/strong&gt; — edge deployment with zero config&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;## SEO Approach&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each of the 66 pairings has its own page with unique metadata:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/ratings/rat-ox    → "Rat and Ox Compatibility"
/ratings/tiger-rabbit → "Tiger and Rabbit Compatibility"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every page has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unique title and meta description&lt;/li&gt;
&lt;li&gt;JSON-LD structured data (VideoGame schema with 2-player context)&lt;/li&gt;
&lt;li&gt;Clean URL structure&lt;/li&gt;
&lt;li&gt;Breadcrumb navigation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The homepage targets broad keywords ("Chinese zodiac compatibility"), while individual pairing pages catch long-tail searches ("rat and ox compatibility 2025").&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;## Why No Sign-Up?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The entire tool runs client-side. The compatibility data is a static JSON file — no database, no API calls, no authentication needed. This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero server cost&lt;/strong&gt; for the core feature&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instant load&lt;/strong&gt; — the data is there on page render&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No friction&lt;/strong&gt; — users go from Google search to result in under 2 seconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;## What I'd Do Differently&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Multi-language support&lt;/strong&gt; — Chinese zodiac has huge audiences in Chinese, Vietnamese, and Korean markets. Adding i18n early would have been smart.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More visual&lt;/strong&gt; — the compatibility results are text-heavy. Animated charts or radar diagrams would make it more engaging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content marketing earlier&lt;/strong&gt; — blog posts about each zodiac sign pair drive consistent long-tail traffic.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;You can use it free at &lt;strong&gt;&lt;a href="https://zodiacmatch.xyz" rel="noopener noreferrer"&gt;ZodiacMatch&lt;/a&gt;&lt;/strong&gt; — pick two animals, see your score instantly. No account, no email, no nonsense.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with Next.js 14, TypeScript, and Tailwind CSS. Deployed on Vercel.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
