[{"data":1,"prerenderedAt":222},["ShallowReactive",2],{"project-en-frontend-jobs-radar":3,"recommendation-mention-sources":160},{"id":4,"title":5,"body":6,"category":125,"context":126,"cover":127,"coverAlt":128,"demo":129,"description":130,"extension":131,"featured":132,"locale":133,"meta":134,"navigation":135,"order":136,"path":137,"published":135,"repository":129,"results":138,"role":148,"seo":149,"slug":150,"stack":151,"stem":157,"year":158,"__hash__":159},"projects\u002Fen\u002Fprojects\u002Ffrontend-jobs-radar.md","Frontend Jobs Radar: a job channel with a cheap AI check before every post",{"type":7,"value":8,"toc":110},"minimark",[9,14,18,29,33,36,40,45,48,51,55,64,68,71,74,78,81,85,98,102],[10,11,13],"h2",{"id":12},"the-problem","The problem",[15,16,17],"p",{},"Looking for a Vue role in 2026 meant reading the same listings on several boards, scrolling past outdated posts, scams and promotions, and opening vacancies that mentioned Vue once and were really about something else. I wanted the search itself to be automated, so that I only read roles worth reading.",[15,19,20,21,28],{},"The same sources also carry React, Angular and other frontend roles that don't fit me but could fit someone else. So the project has two outputs: a narrow personal feed for my own search, and a public Telegram channel, ",[22,23,27],"a",{"href":24,"rel":25},"https:\u002F\u002Ft.me\u002Ffrontendjobsradar",[26],"nofollow","Frontend Jobs Radar",", for frontend jobs in general.",[10,30,32],{"id":31},"my-role","My role",[15,34,35],{},"A side project I started in September 2026, after leaving inSales. I designed, built and run it on my own: sources, filtering, the AI checks, publishing, the database and releases.",[10,37,39],{"id":38},"what-i-built","What I built",[41,42,44],"h3",{"id":43},"collection-and-original-sources","Collection and original sources",[15,46,47],{},"A TypeScript service on Cloudflare Workers with a D1 database collects vacancies on a schedule from company career pages and ATS platforms, job boards and Telegram. The Telegram collector is a separate worker. It reads 20 configured channels, keeps its session encrypted, and handles pagination, rate limits and work that has to resume after an interruption.",[15,49,50],{},"Collecting turned out to be the smaller part. The same job appears on several boards, often through aggregators, so the service looks for the original listing, removes duplicates and keeps a link to the source. Work that can't finish in one run goes through durable queues instead of being dropped.",[41,52,54],{"id":53},"two-filters-for-two-audiences","Two filters for two audiences",[15,56,57,58,63],{},"Keyword rules were not enough. A real frontend role can miss the words I expect, and an irrelevant post can mention \"frontend\" somewhere in the text. So before a vacancy goes out, ",[22,59,62],{"href":60,"rel":61},"https:\u002F\u002Ftypesafe.ai\u002F",[26],"JEV",", a small and cheap model from TypeSafe AI built for this kind of decision, answers one yes-or-no question about it. For the public channel the question is: is this actually a frontend job, with enough detail to be useful? For my personal feed it is a different one: is this worth my time? A role that doesn't fit me can still be right for someone in the channel.",[41,65,67],{"id":66},"english-posts-within-a-budget","English posts within a budget",[15,69,70],{},"When a vacancy passes, a separate language model writes a short English post with the role, stack, location, work arrangement, and salary or hiring restrictions when the listing has them, plus links to the vacancy and its original source. Generated text goes through automated checks before publishing: valid Telegram markup, English, and facts that the source actually contains.",[15,72,73],{},"The public channel's AI spending has a hard budget of $3 per calendar month. Each call reserves its maximum cost before it runs, and the reservation is settled from the usage the provider confirms. If the outcome is unknown, the reservation is kept instead of the call being retried blindly. When the budget runs out or a post fails validation, the vacancy waits in the queue instead of going out as unedited text.",[41,75,77],{"id":76},"publishing-without-duplicates","Publishing without duplicates",[15,79,80],{},"Posts go out on a schedule. The bot can edit an existing message, for example when a vacancy is withdrawn, and it sends me daily and weekly reports. If Telegram doesn't confirm a delivery, the service doesn't simply send again, because a duplicate post in a public channel is worse than a delayed one. Database changes are rehearsed on a fresh backup first, and schedules are paused and restored around releases.",[10,82,84],{"id":83},"results","Results",[86,87,88,92,95],"ul",{},[89,90,91],"li",{},"The public channel has published new vacancies on 32 of the 34 days since it opened on 20 September 2026, counted from its public archive on 23 October 2026. Both gaps are Sundays.",[89,93,94],{},"One JEV relevance check of about 2,000 input tokens costs about $0.00008, roughly eight cents per thousand checks. That made a model check practical on every vacancy, where a general-purpose LLM would have been too expensive.",[89,96,97],{},"The filtering isn't perfect: an occasional non-frontend role still gets through, and I keep adjusting sources and questions.",[10,99,101],{"id":100},"where-to-see-it","Where to see it",[15,103,104,105,109],{},"The channel is public: ",[22,106,108],{"href":24,"rel":107},[26],"t.me\u002Ffrontendjobsradar",". The source code is private.",{"title":111,"searchDepth":112,"depth":112,"links":113},"",2,[114,115,116,123,124],{"id":12,"depth":112,"text":13},{"id":31,"depth":112,"text":32},{"id":38,"depth":112,"text":39,"children":117},[118,120,121,122],{"id":43,"depth":119,"text":44},3,{"id":53,"depth":119,"text":54},{"id":66,"depth":119,"text":67},{"id":76,"depth":119,"text":77},{"id":83,"depth":112,"text":84},{"id":100,"depth":112,"text":101},"Side projects","Side project","\u002Fimages\u002Fwork\u002Ffrontend-jobs-radar\u002Fchannel-post.webp","A Frontend Jobs Radar post: Senior Frontend Engineer (Vue.js) at Dyflexis in The Hague, with the role, requirements, publication date and links to the vacancy and its source",null,"A TypeScript service on Cloudflare Workers that collects frontend vacancies, checks each one with JEV and posts short English summaries to a public Telegram channel. New roles went out on 32 of 34 days since launch.","md",false,"en",{},true,4,"\u002Fen\u002Fprojects\u002Ffrontend-jobs-radar",[139,142,145],{"value":140,"label":141},"32 of 34","days with new vacancies in the public channel, 20 Sep – 23 Oct 2026",{"value":143,"label":144},"≈$0.00008","per JEV relevance check of about 2,000 input tokens",{"value":146,"label":147},"20","Telegram channels in the collector, next to career pages, ATS platforms and job boards","Sole developer, from collecting sources and filtering to AI integration, publishing and operations",{"title":5,"description":130},"frontend-jobs-radar",[152,153,154,62,155,156],"TypeScript","Cloudflare Workers","Cloudflare D1","AI Integration","Telegram Bot API","en\u002Fprojects\u002Ffrontend-jobs-radar","Sep 2026 – present","zzCroQcbzsvSZg1UIRnng5zxSu-K-oyOol7YS1ag9_4",[161,172,177,192,202,207,212,217],{"stem":162,"name":163,"date":164,"featured":112,"published":135,"mentions":165},"recommendations\u002Fandrey-stikheev","Andrey Stikheev","2026-09-08",[166,169],{"project":167,"quote":168},"product-image-editor","Among his most notable projects was a sophisticated browser-based image editor built with TypeScript and Fabric.js, now used by thousands of merchants.",{"project":170,"quote":171},"abandoned-carts","He also developed the frontend for a paid abandoned-cart product and contributed to the production migration from Vue 2 to Vue 3.",{"stem":173,"name":174,"date":175,"featured":129,"published":135,"mentions":176},"recommendations\u002Fdaniil-churakov","Daniil Churakov","2026-08-27",[],{"stem":178,"name":179,"date":180,"featured":119,"published":135,"mentions":181},"recommendations\u002Fdmitry-sadovsky","Dmitry Sadovsky","2026-08-22",[182,185,187,190],{"project":183,"quote":184},"visual-storefront","For years he was the driving force behind our visual storefront editor — a large, complex application where merchants build their online stores.",{"project":167,"quote":186},"It became the tool merchants use to design product images right inside the admin panel — the kind of component companies usually buy rather than build.",{"project":188,"quote":189},"image-editor","What impressed me most was the infographic editor he built essentially from scratch: a full canvas-based graphic editor with artboards, shapes, text styling, templates, and undo\u002Fredo history, powered by an editor core he developed himself.",{"project":170,"quote":191},"Our abandoned carts functionality — with multi-channel customer messaging, communication history, and analytics — was largely his work, from UI down to the details of how requests are cancelled and states stay in sync.",{"stem":193,"name":194,"date":195,"featured":196,"published":135,"mentions":197},"recommendations\u002Fegor-fedkin","Egor Fedkin","2026-08-31",1,[198,200],{"project":167,"quote":199},"Today, the tool is actively used by around 3,000 users.",{"project":170,"quote":201},"It has already generated approximately twice the revenue needed to cover its development costs.",{"stem":203,"name":204,"date":205,"featured":129,"published":135,"mentions":206},"recommendations\u002Femmanuel-stephen","Emmanuel Stephen","2026-10-11",[],{"stem":208,"name":209,"date":210,"featured":129,"published":135,"mentions":211},"recommendations\u002Fevgeny-lonshakov","Евгений Лоншаков","2026-09-21",[],{"stem":213,"name":214,"date":215,"featured":129,"published":135,"mentions":216},"recommendations\u002Froman-gorbachev","Роман Горбачев","2026-09-17",[],{"stem":218,"name":219,"date":220,"featured":129,"published":135,"mentions":221},"recommendations\u002Fvladimir-bedarev","Bedarev Vladimir","2026-09-16",[],1793195987925]