The AI-Powered Classifieds Stack That Posts in Seconds
Users can upload a photo to 24ad.info. AI assists with the listing details.
The ad goes live before any manual steps are complete. Here's how the stack works.
The Pipeline
1. Vision Processing (OpenRouter + Gemini 2.5 Flash)
When you upload photos:
// Simplified image analysis flow
const analysis = await openRouter.chat.completions.create({
model: "google/gemini-2.5-flash",
messages: [{
role: "user",
content: [
{ type: "image_url", url: uploadedImage },
"Describe this item for a classified ad. Identify make/model, condition, and realistic price."
]
}]
});
Key observations:
- Processes images quickly
- Handles mixed content
- Price suggestions draw on available data
2. Category Assignment
The system first tries keyword matching. If uncertain, it queries the classification options.
Two clever bits:
- Dormant category reactivation - Instead of creating duplicate categories, it finds and revives inactive ones
- Custom field generation - For categories like Cars, AI suggests relevant fields
3. Multilingual Output
Using the same call flow, translations are generated.
The response lands in our locales/ directory with i18n keys.
The Stack That Makes It Possible
Frontend
- React 19 + Vite 7 - For the instant form updates
- shadcn/ui - Pre-built components with Tailwind
- wouter v3 - Lightweight routing (no React Router bloat)
Critical UX details:
- File upload starts analysis during selection
- Price/category suggestions appear as editable previews
- Location auto-fills from browser geolocation or IP
Backend
- tRPC v11 - Keeps frontend/backend types in sync
- Drizzle ORM - For type-safe MySQL queries
-
Express 4 - Handles the traffic types:
- User requests (API/SSR)
- Googlebot HTML injection
- Health checks (
/api/system-health)
Infrastructure
- Caddy v2 - Wildcard subdomains with HSTS
- PM2 cluster mode with 4 instances - load-balanced
- MariaDB - Heavily indexed for search (title, location, price)
CREATE TABLE `posts` (
`id` bigint AUTO_INCREMENT PRIMARY KEY,
`title` varchar(191),
`price` decimal(17,2),
`country_code` varchar(2),
`latitude` float,
`longitude` float
-- geolocation uses standard B-tree index on latitude/longitude
);
Pain Points We Solved
1. AI Latency
Initial versions waited for all AI steps sequentially. Now:
- Parallel processing - Fire all AI requests simultaneously
- Fallback caching - Common items use template descriptions if needed
2. Location Handling
Early users saw unexpected placement. Fixed by:
- Subdomain locking - Forces location based on subdomain
- Clear labels - Shows target country
3. Spam Protection
Current defenses include:
- AI content check - Flags suspicious patterns
- IP/email blacklist - Shared across country subdomains
- Stripe verification - Premium ads require validated payment
The Admin Toolkit
Moderators get bulk tools plus:
- AI banner rotator - Generates event-specific graphics
- Health monitor - Checks subsystems including font rendering and upload permissions
Performance
Median ad creation time is low. Category handling is accurate.
Lessons Learned
AI isn't magic - Pricing suggestions benefit from additional rules.
Condition detection - The AI spots visible details in photos.
Speed matters - The entire process must fit within user attention.
Try it yourself: 24ad.info.
Top comments (0)