[{"data":1,"prerenderedAt":431},["ShallowReactive",2],{"navigation":3,"\u002Fworks\u002Ftargeter":54},[4],{"title":5,"path":6,"stem":7,"children":8,"page":53},"Works","\u002Fworks","works",[9,13,17,21,25,29,33,37,41,45,49],{"title":10,"path":11,"stem":12},"Arti","\u002Fworks\u002Farti","works\u002Farti",{"title":14,"path":15,"stem":16},"Currencia","\u002Fworks\u002Fcurrencia","works\u002Fcurrencia",{"title":18,"path":19,"stem":20},"Folio Magazine","\u002Fworks\u002Ffolio-magazine","works\u002Ffolio-magazine",{"title":22,"path":23,"stem":24},"Helpr","\u002Fworks\u002Fhelpr","works\u002Fhelpr",{"title":26,"path":27,"stem":28},"IV Patisserie","\u002Fworks\u002Fiv-patisserie","works\u002Fiv-patisserie",{"title":30,"path":31,"stem":32},"Mockline","\u002Fworks\u002Fmockline","works\u002Fmockline",{"title":34,"path":35,"stem":36},"Portfolio","\u002Fworks\u002Fportfolio","works\u002Fportfolio",{"title":38,"path":39,"stem":40},"Raftou - Mobile Game","\u002Fworks\u002Fraftou","works\u002Fraftou",{"title":42,"path":43,"stem":44},"Raycast x Bambulab","\u002Fworks\u002Fraycast-bambulab","works\u002Fraycast-bambulab",{"title":46,"path":47,"stem":48},"Combat Robot","\u002Fworks\u002Frobot","works\u002Frobot",{"title":50,"path":51,"stem":52},"Targeter","\u002Fworks\u002Ftargeter","works\u002Ftargeter",false,{"id":55,"title":50,"authors":56,"body":63,"contextPreview":411,"date":412,"description":413,"extension":414,"image":415,"meta":416,"minRead":417,"navigation":418,"path":51,"roles":419,"seo":422,"stem":52,"teamName":423,"technologies":424,"url":428,"year":429,"__hash__":430},"works\u002Fworks\u002Ftargeter.md",[57],{"name":58,"to":59,"target":60,"avatar":61},"Johann Cavallucci","https:\u002F\u002Fx.com\u002FJohannCVL","_blank",{"src":62,"alt":58},"https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F72015679?v=4",{"type":64,"value":65,"toc":402},"minimark",[66,71,75,78,81,84,88,91,94,163,166,173,177,347,350,356,359,363,366,392,396,399],[67,68,70],"h2",{"id":69},"the-concept","The Concept",[72,73,74],"p",{},"Targeter was born from a real personal need. While actively job hunting, I was juggling fragmented workflows — copying job offers into ChatGPT for summaries, asking AIs to draft cover letters, running scrapers and bots that scored letters and sent back the good ones. Useful, but scattered and full of friction.",[72,76,77],{},"The idea: centralize everything into one product — track applications, act on them, and let AI handle the repetitive cognitive load — so the job seeker can focus on what matters (deciding, applying, preparing) instead of copy-pasting between tools.",[72,79,80],{},"Targeter is a job search organizer designed for people in active search. Positioning: a clean Notion-like base (Kanban + Table) plus a contextual AI layer that knows the user’s profile and applications — not a generic ChatGPT embedded in a UI.",[72,82,83],{},"I own the product end-to-end: Full Stack engineer and UX designer — product, architecture, UI, AI features, and the Chrome extension.",[67,85,87],{"id":86},"design-features","Design & Features",[72,89,90],{},"The design goal is a calm, frictionless UX usable by developers and non-technical job seekers alike. A clean, airy interface inspired by Notion’s simplicity — no getting lost.",[72,92,93],{},"Key features today:",[95,96,97,105,111,117,123,151,157],"ul",{},[98,99,100,104],"li",{},[101,102,103],"strong",{},"Dual views:"," Kanban board with drag-and-drop, plus a Table view with inline Notion-like editing.",[98,106,107,110],{},[101,108,109],{},"Application pipeline:"," Noted → Applied → Interviewing → Rejected \u002F Accepted \u002F Archived.",[98,112,113,116],{},[101,114,115],{},"CSV import"," of existing application data.",[98,118,119,122],{},[101,120,121],{},"Preferences:"," default view, columns, and follow-up reminders after X days.",[98,124,125,128,129],{},[101,126,127],{},"Contextual AI assistant"," that knows the user’s CV, preferences, cover letter template, and applications:\n",[95,130,131,134,137,140,143],{},[98,132,133],{},"Paste a job offer → create an application",[98,135,136],{},"Score an offer against the CV",[98,138,139],{},"Generate a tailored cover letter",[98,141,142],{},"Parse recruiter emails → update status",[98,144,145,146,150],{},"Mentions (",[147,148,149],"code",{},"@company — role",") and slash commands for bounded actions",[98,152,153,156],{},[101,154,155],{},"Chrome extension for Welcome to the Jungle (WTTJ):"," one-click add of a job offer into Targeter while browsing (LinkedIn intentionally out of scope for now).",[98,158,159,162],{},[101,160,161],{},"Product foundations toward SaaS:"," auth, light\u002Fdark theme, AI credits \u002F BYOK model.",[72,164,165],{},"The core product promise: remove friction from the job search loop.",[72,167,168],{},[169,170],"img",{"alt":171,"src":172},"Kanban board","\u002Fassets\u002Fworks\u002Ftargeter\u002Fkaban.png",[67,174,176],{"id":175},"technical-stack-architecture","Technical Stack & Architecture",[178,179,180,193],"table",{},[181,182,183],"thead",{},[184,185,186,190],"tr",{},[187,188,189],"th",{},"Technology",[187,191,192],{},"Role in the project",[194,195,196,207,217,227,237,247,257,267,277,287,297,307,317,327,337],"tbody",{},[184,197,198,204],{},[199,200,201],"td",{},[101,202,203],{},"Nuxt 4",[199,205,206],{},"Full-stack web app (UI + Nitro API)",[184,208,209,214],{},[199,210,211],{},[101,212,213],{},"Vue \u002F Nuxt UI",[199,215,216],{},"Component system and product UI",[184,218,219,224],{},[199,220,221],{},[101,222,223],{},"Tailwind CSS",[199,225,226],{},"Design system styling",[184,228,229,234],{},[199,230,231],{},[101,232,233],{},"TypeScript",[199,235,236],{},"End-to-end type safety (web, API, extension, shared packages)",[184,238,239,244],{},[199,240,241],{},[101,242,243],{},"pnpm monorepo",[199,245,246],{},"Architecture: apps\u002Fweb, apps\u002Fextension, packages\u002Fdb, packages\u002Fshared",[184,248,249,254],{},[199,250,251],{},[101,252,253],{},"Drizzle ORM",[199,255,256],{},"Schema, migrations, typed DB access",[184,258,259,264],{},[199,260,261],{},[101,262,263],{},"PostgreSQL",[199,265,266],{},"Primary relational database (apps, users, AI profile, tokens…)",[184,268,269,274],{},[199,270,271],{},[101,272,273],{},"Better Auth",[199,275,276],{},"Email\u002Fpassword auth and sessions",[184,278,279,284],{},[199,280,281],{},[101,282,283],{},"Vercel AI SDK + AI Gateway",[199,285,286],{},"Contextual assistant (chat, scoring, cover letters, offer parsing)",[184,288,289,294],{},[199,290,291],{},[101,292,293],{},"Zod",[199,295,296],{},"Request\u002Fdata validation",[184,298,299,304],{},[199,300,301],{},[101,302,303],{},"WXT",[199,305,306],{},"Chrome extension toolchain (MV3)",[184,308,309,314],{},[199,310,311],{},[101,312,313],{},"Chrome Extension (content + background)",[199,315,316],{},"Parse WTTJ job pages and POST offers via API tokens",[184,318,319,324],{},[199,320,321],{},[101,322,323],{},"Vitest",[199,325,326],{},"Unit tests (parsers, shared utils)",[184,328,329,334],{},[199,330,331],{},[101,332,333],{},"evlog",[199,335,336],{},"Structured API logging \u002F observability",[184,338,339,344],{},[199,340,341],{},[101,342,343],{},"Figma",[199,345,346],{},"UI\u002FUX exploration and visual consistency",[72,348,349],{},"Architecture angle: intentionally simple and reliable — clear monorepo boundaries, shared types between web and extension, token-based auth for the extension (no cookie dependency), and AI designed as bounded actions with durable context (profile + applications) rather than endless chat history.",[72,351,352],{},[169,353],{"alt":354,"src":355},"Profile settings","\u002Fassets\u002Fworks\u002Ftargeter\u002Fprofil.png",[357,358],"hr",{},[67,360,362],{"id":361},"challenges","Challenges",[72,364,365],{},"Building a product like this solo means the UX bar is as high as the engineering one:",[95,367,368,374,380,386],{},[98,369,370,373],{},[101,371,372],{},"Trustworthy product UX:"," designing a simple architecture where users never feel lost — the hard part is not just shipping features, but making the whole loop feel obvious.",[98,375,376,379],{},[101,377,378],{},"Useful AI, not a chatbot skin:"," grounding the assistant in the user’s real profile and applications, action-oriented (parse \u002F score \u002F letter \u002F status), instead of a generic chat box.",[98,381,382,385],{},[101,383,384],{},"Browser → product bridge:"," the WTTJ extension has to parse offer pages, auth with API tokens, and land cleanly in the Kanban.",[98,387,388,391],{},[101,389,390],{},"Power without exclusion:"," balancing slash commands and mentions for power users with accessibility for non-dev job seekers.",[67,393,395],{"id":394},"conclusion-and-next-steps","Conclusion and Next Steps",[72,397,398],{},"Targeter is actively in progress and already far along: a stable Notion-like core, a working AI MVP, and a WTTJ extension. It already helps me in my own job search — the best validation for a tool built from personal pain.",[72,400,401],{},"Next step: turn it into a SaaS — polish the AI experience, entitlements and billing, and grow beyond the solo workflow into a product others can rely on during their search.",{"title":403,"searchDepth":404,"depth":404,"links":405},"",2,[406,407,408,409,410],{"id":69,"depth":404,"text":70},{"id":86,"depth":404,"text":87},{"id":175,"depth":404,"text":176},{"id":361,"depth":404,"text":362},{"id":394,"depth":404,"text":395},"[object Object]","2026-09-25","AI-powered job search organizer that removes friction from applications — Kanban, contextual assistant, and Chrome extension.","md","\u002Fassets\u002Fworks\u002Ftargeter\u002Fdashboard.png",{},8,true,[420,421],"Full Stack","UI\u002FUX Designer",{"title":50,"description":413},"Author",[203,233,425,263,426,427],"Drizzle","AI","Extension",null,"2026","gt34-h5zGnWgR-n0YnGSwA8EI2FXEqo5JIfUVTz37-c",1790331913033]