<?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: Kim Len</title>
    <description>The latest articles on DEV Community by Kim Len (@buildwithai).</description>
    <link>https://dev.to/buildwithai</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%2F3874460%2Fd5607842-3c47-4231-8fb1-cd56f84ca963.png</url>
      <title>DEV Community: Kim Len</title>
      <link>https://dev.to/buildwithai</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/buildwithai"/>
    <language>en</language>
    <item>
      <title>I Built an AI Job Board That Deploys in 30 Minutes — Here's How</title>
      <dc:creator>Kim Len</dc:creator>
      <pubDate>Sun, 12 Apr 2026 06:15:50 +0000</pubDate>
      <link>https://dev.to/buildwithai/i-built-an-ai-job-board-that-deploys-in-30-minutes-heres-how-kn6</link>
      <guid>https://dev.to/buildwithai/i-built-an-ai-job-board-that-deploys-in-30-minutes-heres-how-kn6</guid>
      <description>&lt;p&gt;Last month I built a job platform where users upload their CV and AI matches them to real jobs. It worked well, so I packaged it as a template anyone can deploy.&lt;/p&gt;

&lt;p&gt;Here's how it works and what I learned.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Concept
&lt;/h2&gt;

&lt;p&gt;Simple idea: drop your CV, get matched to jobs. No registration needed. AI reads your skills and finds relevant listings from real job APIs.&lt;/p&gt;

&lt;p&gt;The full platform includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Homepage with CV upload and AI matching&lt;/li&gt;
&lt;li&gt;Employer portal (register, post jobs, manage listings)&lt;/li&gt;
&lt;li&gt;Admin dashboard (approve jobs, manage users, view stats)&lt;/li&gt;
&lt;li&gt;AI blog generator (SEO-optimised articles, one click)&lt;/li&gt;
&lt;li&gt;AI social media content generator (7 platforms)&lt;/li&gt;
&lt;/ul&gt;

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

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vanilla JavaScript&lt;/strong&gt; — no React, no Vue, no build step&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel&lt;/strong&gt; — serverless hosting, free tier&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Upstash Redis&lt;/strong&gt; — database, free tier&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anthropic Claude API&lt;/strong&gt; — AI matching and content generation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adzuna API&lt;/strong&gt; — live job listings (free)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total running cost: &lt;strong&gt;$5-20/month&lt;/strong&gt; (only the AI API costs money).&lt;/p&gt;

&lt;p&gt;22 files. No node_modules nightmare. No webpack config. Edit a file, push to GitHub, it deploys.&lt;/p&gt;

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

&lt;p&gt;ai-job-board/&lt;br&gt;
config.js ← all settings in one file&lt;br&gt;
api/&lt;br&gt;
_kv.js ← Upstash Redis helper&lt;br&gt;
chat.js ← Claude AI proxy&lt;br&gt;
jobs.js ← job aggregator (5 APIs supported)&lt;br&gt;
register.js ← employer auth&lt;br&gt;
admin.js ← admin operations&lt;br&gt;
apply.js ← job applications&lt;br&gt;
approved-jobs.js ← public jobs + blog + sitemap + RSS&lt;br&gt;
employer-jobs.js ← employer job management&lt;br&gt;
seeker.js ← job seeker profiles&lt;br&gt;
seeker-apps.js ← application tracking&lt;br&gt;
reset-password.js ← password reset&lt;br&gt;
cron-alerts.js ← weekly email alerts&lt;br&gt;
public/&lt;br&gt;
index.html ← homepage&lt;br&gt;
admin.html ← admin dashboard&lt;br&gt;
employer-portal.html ← employer portal&lt;br&gt;
vercel.json ← routes&lt;/p&gt;

&lt;h2&gt;
  
  
  The Config File
&lt;/h2&gt;

&lt;p&gt;Everything customisable lives in one file. Change the site name, colours, country, job API, and employer plans without touching any other code:&lt;/p&gt;

&lt;p&gt;javascript&lt;br&gt;
module.exports = {&lt;br&gt;
  siteName: "My Job Board",&lt;br&gt;
  siteUrl: "&lt;a href="https://www.myjobboard.com" rel="noopener noreferrer"&gt;https://www.myjobboard.com&lt;/a&gt;",&lt;br&gt;
  colorPrimary: "#10b981",&lt;br&gt;
  defaultCountry: "gb",&lt;br&gt;
  jobAggregator: "adzuna",&lt;br&gt;
  plans: {&lt;br&gt;
    free:  { price: 0,  maxListings: 1,  durationDays: 30 },&lt;br&gt;
    basic: { price: 29, maxListings: 5,  durationDays: 60 },&lt;br&gt;
    pro:   { price: 79, maxListings: -1, durationDays: 90 },&lt;br&gt;
  },&lt;br&gt;
};&lt;/p&gt;

&lt;p&gt;Supporting 5 Job APIs&lt;br&gt;
Not everyone wants Adzuna. So the jobs.js endpoint supports five aggregators through a single config switch:&lt;/p&gt;

&lt;p&gt;API Countries   Cost&lt;br&gt;
Adzuna  15+ Free&lt;br&gt;
JSearch (RapidAPI)  Global  Free tier&lt;br&gt;
Jooble  60+ Free&lt;br&gt;
Careerjet   50+ Free&lt;br&gt;
Reed    UK only Free&lt;br&gt;
Set jobAggregator: "jooble" in config.js and it just works. Or set it to "none" to only show employer-posted jobs.&lt;/p&gt;

&lt;p&gt;The AI Matching Flow&lt;br&gt;
User uploads CV (PDF, DOCX, or TXT)&lt;br&gt;
Client-side JavaScript extracts the text (mammoth.js for DOCX)&lt;br&gt;
POST to /api/chat with the CV text and a matching prompt&lt;br&gt;
Claude AI returns 5 job role suggestions as JSON&lt;br&gt;
For each suggestion, POST to /api/jobs to find live listings&lt;br&gt;
Display results with match percentages and live job links&lt;br&gt;
The prompt asks Claude to analyse skills and suggest specific roles with match percentages, locations, and search queries. The search queries then hit the job aggregator API to find real openings.&lt;/p&gt;

&lt;p&gt;Blog System with SEO&lt;br&gt;
The admin dashboard has a one-click blog generator. AI writes SEO-optimised articles about the job market. Each post gets:&lt;/p&gt;

&lt;p&gt;Its own URL (/blog/how-to-write-a-cv)&lt;br&gt;
Unique meta title and description&lt;br&gt;
Open Graph and Twitter Card tags&lt;br&gt;
Schema.org BlogPosting structured data&lt;br&gt;
Breadcrumb navigation with structured data&lt;br&gt;
There is also a dynamic XML sitemap at /sitemap.xml that auto-includes every blog post with lastmod dates, and an RSS feed at /blog/rss.&lt;/p&gt;

&lt;p&gt;All server-rendered from a single serverless function — no static site generator needed.&lt;/p&gt;

&lt;p&gt;Social Media Generator&lt;br&gt;
The admin panel also generates social media posts for 7 platforms (Twitter, LinkedIn, Facebook, Instagram, TikTok, YouTube, Reddit) with one click. Choose a tone (funny, professional, hype, casual) and a focus topic. It even generates branded images at the correct dimensions for each platform using the Canvas API.&lt;/p&gt;

&lt;p&gt;What I Learned&lt;br&gt;
Vanilla JS is underrated. No build step means instant deploys. No dependency updates. No breaking changes from framework upgrades. The entire codebase is readable by anyone who knows JavaScript.&lt;/p&gt;

&lt;p&gt;One config file changes everything. If someone wants to launch a job board in Germany, they change defaultCountry: "de" and siteName: "MeinJobBoard" and deploy. That decision saved hours of support.&lt;/p&gt;

&lt;p&gt;Serverless free tiers are generous. Vercel hobby tier + Upstash free tier handles thousands of users before you pay anything. The only cost is Claude AI at roughly $0.01-0.05 per CV match.&lt;/p&gt;

&lt;p&gt;AI content generation is a killer feature for admin tools. Nobody wants to write blog posts or social media captions manually. Having the admin dashboard generate them with one click makes the product much more valuable.&lt;/p&gt;

&lt;p&gt;Try It&lt;br&gt;
The template is available on Gumroad. Full source code, documentation, and setup guide. Deploy your own AI job board in 30 minutes.&lt;/p&gt;

&lt;p&gt;Happy to answer questions about the architecture or implementation in the comments.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>ai</category>
      <category>vercel</category>
    </item>
  </channel>
</rss>
