🐴 How I built an SEO tool with AI (and what it taught me about programming)
Lessons and tips for anyone with little coding experience
Last week, I shared how I built a tool to convert Doc to Slides.
Today, I’ll take a deeper dive into another tool I built with the assistance of AI—an SEO description tool.
I’ll take you behind the scenes, sharing the key lessons and insights learned from the development process.
Here’s what I’ll cover:
Demo
The Problem
How It Works
Key Learnings
Unexpected Surprises
Let’s jump in!
Demo
Step 1: Paste Newsletter draft into the tool → Provide keywords → Generate
Step 2: Three options generated → Choose one → Copy and paste into the setting
Done. Simple as that.
The Problem
Why building a SEO description tool?
It's one of those tedious yet helpful tasks for bloggers who aim to improve the organic reach of their articles.
The SEO description, also known as the meta description, acts as a brief summary of an article on Google’s search result pages.
By default, blog platforms like Substack and Medium use the article subtitle, which is not good.
So I always write the SEO description by myself right before publishing.
An effective SEO description:
Includes keywords that are relevant to the article and your target audience.
Has a character count between 120 and 160.
It doesn’t take that much time for me, but having to do it every time before publishing an article is tedious. I wish this repetitive task could be automated.
How It Works
Here is a flowchart explaining how the tool works:
Step 1, 2, 7 are the frontend user interaction, as shown in the Demo; Step 3-6 are what happened behind the scene:
Step 3: Content sent to backend
The pasted text is sent from the app’s frontend (the part the user interacts with) to the backend (a server running in the background).
Step 4: Backend requests SEO descriptions
The backend uses the API "SEO Generator API" to process the request.
It sends the user’s content to "Mistral AI Model" (an open source AI model that I downloaded in my local computer) to create the SEO descriptions.
Step 5: AI Generates Descriptions
The AI Model takes the input text and creates SEO descriptions accordingly.
It sends the generated descriptions back to the backend.
Step 6: Backend returns descriptions
The backend takes the descriptions created by the AI and sends them back to the frontend.
Key Learnings
1. The benefit of separation
Separating frontend, backend, and external service into distinct parts with different ports allows for flexibility and easier debugging.
Each runs independently without interference, but they can also talk to each other.
Frontend (Port 3000): http://localhost:3000, where I get to see the UI
Backend (Port 3001): http://localhost:3001, where the server lives
External Service (Port 11434): The AI model/service I use
For example, if I want to change another AI service in the future, I can just go to that port without touching could be swapped out but the backend stays the same.
2. Working with the Terminal
Open the Terminal on Mac: Command + Space → Type "Terminal" → Enter
The Terminal is a text-based interface that lets us interact with our computers’ operating system by typing commands.
I had to use Terminal a lot for this tool to perform tasks like:
Install libraries and dependencies.
Start and stop the development servers.
Debug and view logs.
💡 Lessons:
Start the servers first for initializing the environment.
Command to start React app (Frontend): npm start
Command to start the server (Backend): node server.js
Use separate terminal windows/tabs for Frontend and Backend.
Each new Terminal window/tab is independent. Command + T = New tab
Keep the servers running during development.
I had run into errors because I closed the backend terminal accidentally.
Ctrl + C = Stop a running command that is currently running in the server.
This is useful because it allows me to stop a long-running process without having to stare at the computer or force quitting the terminal
3. The file structure of the project
The separation of frontend and backend also resulted in the file structure below.
Claude suggested using React for the frontend and Node.js for the backend based on my tool.
seo-tool/
├── frontend/ # React app (Port 3000)
│ ├── package.json # Frontend dependencies
│ ├── public/
│ └── src/
│ ├── App.js # Main React component
│ ├── components/ # UI components
│ └── services/ # API calls to backend
│
├── backend/ # Express server (Port 3001)
├── package.json # Backend dependencies
├── server.js # Main server file
└── routes/ # API endpoint definitions
💡 Lessons:
The file structure is important because a common error I ran into often early on came from running commands in the incorrect directory.
For example, when executing frontend-related commands, I need to first make sure the Terminal is pointing to the fronted project folder, then run the command I want to run.
❌ cd /Users/Xinran/seo-tool/;
✅ cd /Users/Xinran/seo-tool/frontend ;
I can just type “cd” in the Terminal, then drag and drop the target folder in the Terminal window to add that path directly instead of manually typing everything.
Sometimes, the server may not terminate properly, so I had to identify what was occupying the server and terminate it.
Command to find out what process is using the server: lsof -i :3001
Command to kill the process based on the ID: kill -9 [Process ID]
4. Coding Best Practice 101
Although I used AI to help me code, having very basic coding knowledge is essential.
At least it helps me understand where to place code and reduce the chances of introducing unnecessary bugs.
This is probably the only thing I still remember after learning very basic coding over a decade ago.
💡 Lessons:
Define Functions and Constants at the top.
XXX( ) is calling/executing the function that was defined earlier.
function XXX() {}
function YYY() {}
const ZZZ = 120;
const WWW = 160;
XXX();
Use proper punctuation.
One time, when I inserted code from Claude into my VS Code editor, I forgot to add a comma and that caused an error.
The comma adds separation.
Without a comma, the code would run properties together.
Line breaks and indentation are just for human readability.
That said, the last property doesn't need comma.
❌ const user = {
name: "Xinran" // Missing comma!
favorite_food: avocado
}
✅ const user = {
name: "John", // Added comma
favorite_food: avocado
}; // Added semicolon
Key Surprises
Running an AI model on a local machine was slower than I expected. That said, I chose the open-source AI model route as an experiment. I can explain more in a future newsletter.
My initial design idea was that users could simply paste a webpage URL instead of manually pasting text. However, I was surprised that fetching information from Substack was tricky. I explored the Substack API, but the outcome was unsatisfactory. That’s why I ultimately pivoted to a simpler and more versatile solution of manually pasting the text.
The whole process took much longer than I expected—countless hours over weekends fixing countless errors. But I’m glad I made it and learned a ton.
Thanks for reading.
Until next week,
Xinran
I was exactly looking for this kind of AI tool. Very glad to know about mistral. Definately going to build something with this. Already working on a project. When that is done the next thing is this for sure.