US WARN layoff notices › Watch your employers

Watch your employers for layoff notices

Type the companies you care about. This page checks them against every US WARN Act layoff notice filed in the last 180 days and shows you the matches. No account, no email address, no checkout — the matching runs inside your browser and your list is never sent anywhere.

1,771notices in the last 180 days
1,293distinct employers filing
169,722workers named in them
44states represented

Counted from the free dataset at build time. Latest notice date in the file: 2026-09-22. The whole archive is 61,428 notices back to 1988.

Case-insensitive, and a name matches on whole words, so Boeing finds “Boeing Commercial Airplanes” while Ford does not drag in Stanford, Medford or Rockford — which is what a plain text search of the CSV does. This is the same matcher the paid alerts run.

… or watch whole states

This page only looks when you open it — so take the feeds instead

That is the honest limit of a browser-side tool. After you press Show my matches you can download an .opml file holding one RSS feed per employer you typed — free, no account, no email address — and your reader checks them for you every morning.

This page (free)WARN Watch ($49/year)
Checks your listwhen you open it, or when your feed reader polls the .opmlevery daily refresh, automatically
Tells youon screen, or in your RSS readerit comes to you: private alert page + RSS + calendar (.ics) + optional Slack/Discord/Teams
How many termsas many as you likeup to 500 terms plus whole states
History per matchnotice count & first yearfull filing record — every state, every prior notice, worker totals
Separation reminderagain 14 days before the layoff date

Get WARN Watch — $49/year

One-off, no auto-renew, 14-day refund. See a real alert page first — no email needed to look.

How this works

The file behind this page is watch-recent.json, rebuilt by the same daily pipeline that publishes the free dataset and the source repo. Notices come from official WARN Act filings by 48 state agencies, normalized into one schema; 44 of those states have at least one notice inside the 180-day window. Your watchlist is stored in this browser only (localStorage) and mirrored into this page's own URL, so you can bookmark it or send it to a colleague — it never touches a server of ours. Any page on this site can open the tool pre-filled: watch-now.html?q=Boeing|Kaiser or ?s=CA,TX.

What is counted: three 1×1 images on the public jsDelivr CDN — one when this page opens, one if it opened pre-filled from a link, one the first time a non-empty list is matched. That is a daily total per file, published openly by jsDelivr; no cookie, no ID, and never the names you typed.

Nothing here is legal or financial advice, and a WARN notice is an employer's filing, not a guarantee that a layoff happened as described. Corrections: open an issue on the source repo.

\n\n'; } function render(w){ var rows=match(w), lastSeen=seen0(); var res=$('results'); if(!w.t.length && !w.s.length){ $('stat').textContent=''; res.innerHTML='
Add at least one employer name or tick a state, then press '+ 'Show my matches.
'; return; } if(!USED){USED=true;px('https://cdn.jsdelivr.net/gh/APVentureEngine/warn-act-notices@main/assets/px-tool-used.png');} var fresh=0; rows.forEach(function(r){ if(lastSeen && r[8] && r[8]>lastSeen) fresh++; }); $('stat').innerHTML=''+num(rows.length)+' notice'+(rows.length===1?'':'s')+ ' in the last '+DATA.window_days+' days match your list'+ (fresh?(' · '+num(fresh)+' new since you last looked'):'')+'.'; // c526: the offer, stated on the visitor's OWN list, right under the result. var what=[]; if(w.t.length) what.push(w.t.length===1?'name':num(w.t.length)+' names'); if(w.s.length) what.push(w.s.length===1?'state':num(w.s.length)+' states'); var lst=what.join(' and '), these=((w.t.length+w.s.length)===1?'this ':'these ')+lst; function upsell(n){ var lead = n ? ''+num(n)+(n===1?' notice':' notices')+' matched your '+lst+' today. This page will not look again until you reopen it.' : 'None of your '+lst+' filed a WARN notice in the last '+DATA.window_days+' days. The next one can land tomorrow, and this page will not tell you unless you come back.'; return '

'+lead+'

'+ '

WARN Watch runs this same match after every daily rebuild and sends only what is new to a private alert page, RSS, calendar and Slack — up to 500 names plus whole states.

'+ '
'+ 'Keep '+these+' watched daily — $49/year'+ 'Try it free for 30 days — no card'+ '
'+ '

One-off, no auto-renew, 14-day refund. Your list stays in this browser; you paste it again at checkout.

'; } if(!rows.length){ res.innerHTML='
No WARN notices from those employers in the last '+ DATA.window_days+' days. That is usually good news. '+ 'Search the whole archive back to 1988 '+ 'to see what they have filed before.
'+subBlock(rows,w)+upsell(0); } else { var h=''+ ''; rows.forEach(function(r){ var isNew=(lastSeen && r[8] && r[8]>lastSeen); var hk=(r[1]||'').toLowerCase(), hi=DATA.history[hk]; var hist=''; if(hi && hi[0]>1){ hist=''+num(hi[0])+' notices since '+esc(hi[2])+ ' · '+num(hi[1])+' workers'+(hi[3]>1?(' · '+hi[3]+' states'):'')+''; } h+=''+ ''+ ''+ ''+ ''+ ''+ ''; }); res.innerHTML=h+'
Notice dateEmployerWhereWorkersTypeEffective
'+esc(r[3])+(isNew?'NEW':'')+''+esc(r[0])+''+hist+''+esc(r[7]||'')+(r[2]?(r[7]?', ':'')+esc(r[2]):'')+''+num(r[5])+''+esc(r[6]||'')+''+esc(r[4]||'')+'
'+subBlock(rows,w)+upsell(rows.length); } try{localStorage.setItem(LSEEN,DATA.asof)}catch(e){} } // c526: count clicks on the in-result CTA (either button) — one pixel, no ID, nothing about the list. document.getElementById('results').addEventListener('click',function(e){ var a=e.target; while(a && a.tagName!=='A') a=a.parentNode; if(a && a.className && a.className.indexOf('cta')!==-1) px('https://cdn.jsdelivr.net/gh/APVentureEngine/warn-act-notices@main/assets/px-tool-cta.png'); }); // c601: build the .opml in the browser from the visitor's own matches. The list // never leaves the page — same promise as the matcher itself. document.getElementById('results').addEventListener('click',function(e){ var a=e.target; while(a && a.tagName!=='A') a=a.parentNode; if(!a || a.id!=='opml') return; e.preventDefault(); var txt=opmlDoc(); try{ var b=new Blob([txt],{type:'text/x-opml'}), u=URL.createObjectURL(b), d=document.createElement('a'); d.href=u; d.download='warn-watchlist.opml'; document.body.appendChild(d); d.click(); setTimeout(function(){URL.revokeObjectURL(u); document.body.removeChild(d)},0); }catch(err){ window.location.href='data:text/x-opml;charset=utf-8,'+encodeURIComponent(txt); } px('https://cdn.jsdelivr.net/gh/APVentureEngine/warn-act-notices@main/assets/px-tool-opml.png'); }); function boot(){ var w=load(); writeForm(w); if(DEEP){save(w);px('https://cdn.jsdelivr.net/gh/APVentureEngine/warn-act-notices@main/assets/px-tool-deep.png');} $('go').addEventListener('click',function(){var x=readForm();save(x);render(x)}); $('clear').addEventListener('click',function(){ var x={t:[],s:[]}; writeForm(x); save(x); render(x); }); $('stat').textContent='Loading the last '+180+' days of notices\u2026'; var xhr=new XMLHttpRequest(); xhr.open('GET','data/watch-recent.json',true); xhr.onload=function(){ if(xhr.status>=200&&xhr.status<300){ try{DATA=JSON.parse(xhr.responseText)}catch(e){} } if(!DATA){ $('stat').textContent='Could not load the notice file. Reload the page, or use the search page.'; return; } render(w); }; xhr.onerror=function(){$('stat').textContent='Could not load the notice file. Reload the page, or use the search page.'}; xhr.send(); // c601: the employer->feed map, fetched independently. If it never arrives // the page works exactly as it did before; when it does, re-render so the // free subscribe block appears under results already on screen. var fx=new XMLHttpRequest(); fx.open('GET','data/watch-feeds.json',true); fx.onload=function(){ if(fx.status>=200&&fx.status<300){ try{FEEDS=JSON.parse(fx.responseText)}catch(e){} } if(FEEDS&&DATA){ var v=load(); if((v.t||[]).length||(v.s||[]).length) render(v); } }; fx.send(); } if(document.readyState!=='loading') boot(); else document.addEventListener('DOMContentLoaded',boot); })();