Daily fresh job postings tracked in a sheet, with a Slack recap
Every weekday morning, surface new job postings that match your search profiles, log them to a tracking sheet, and post a short Slack recap.
Build me a deterministic code workflow that delivers a daily list of fresh job postings into a Google Sheets tracker and posts a short Slack recap. No AI summarization in the loop, fixed columns, fixed query templates.
Trigger: cron, every weekday (Monday through Friday) at 7:00am in the user's timezone.
Inputs the workflow should expose as configuration: (1) a list of search profiles, where each profile has fields role_title, location, seniority, keywords, and a human-readable profile name; (2) the Google Sheets spreadsheet ID and the sheet/tab name for the tracker; (3) the Slack channel ID for the recap; (4) an optional list of preferred job board domains to bias the search toward (default to a sensible set like linkedin.com, greenhouse.io, lever.co, ashbyhq.com, workable.com, indeed.com, weworkremotely.com, ycombinator.com).
Step 1 — Search per profile. For each profile in the configured list, call Tavily Search once. Build the query deterministically from the profile fields using a fixed template like "{role_title} {seniority} jobs in {location} {keywords}". Pass time_range="day" so only postings from the last 24 hours come back, set search_depth="basic", max_results around 20, and pass the configured job board domains as include_domains. Do not call Tavily's answer/LLM features. Collect the raw results per profile, tagging each result with the profile name it came from.
Step 2 — Read existing rows. Call Google Sheets Get Values once on the tracker sheet, reading the full data range (for example A:G of the configured tab). Extract the set of URLs already present in the URL column to use as a dedupe set. If the sheet is empty or only has a header row, treat the dedupe set as empty.
Step 3 — Dedupe and shape rows. Iterate through all Tavily results across all profiles, normalize each URL (strip query params and trailing slashes when comparing), and drop any result whose normalized URL is already in the dedupe set. For each remaining result, build a fixed-shape row with exactly these seven columns in this order: title, company, location, url, posted_date, source, profile. Title and url come from the Tavily result. Company and location should be parsed from the result title or content when obviously present, otherwise left blank. Posted_date should be today's date in YYYY-MM-DD format (since we filtered to the last 24 hours). Source should be the result's domain (for example "greenhouse.io"). Profile is the profile name that produced the result. Also dedupe within the current batch so the same URL surfaced by two profiles is only written once.
Step 4 — Append new rows. If there are zero new rows after dedupe, skip the append. Otherwise call Google Sheets Append Values once with all new rows as a single batch, targeting the same tab, using valueInputOption="USER_ENTERED" and insertDataOption="INSERT_ROWS".
Step 5 — Slack recap. If zero new rows, do nothing (no Slack message — keep slow days quiet). If one or more new rows, call Slack Send a Message to the configured channel with a short message: a one-line header like "7 new job postings today", a link to the tracking sheet, and up to five example listings shown as "{title} — {company or source} ({profile})" with the title hyperlinked to the posting URL. Use Slack markdown formatting.
Keep the workflow strictly deterministic: no LLM nodes, no AI rewriting of titles or descriptions, no dynamic prompt construction beyond the fixed template above. Handle Tavily errors per profile gracefully (skip that profile, continue the rest) and log how many results came back per profile for debugging.
Additional information
What does this prompt do?
- Runs every weekday at 7am and searches the web for job postings that match each of your saved profiles (role, location, seniority, keywords).
- Filters results to the last 24 hours so you only see fresh listings, biased toward real job boards.
- Skips any posting whose URL is already in your tracking sheet and appends only the new ones with consistent columns.
- Posts a short Slack recap with the count of new listings and a few examples that link back to the sheet, or stays quiet on slow days.
What do I need to use this?
- A Tavily account for the web search.
- A Google account with access to the spreadsheet you want to use as your job tracker.
- A Slack workspace and the channel where you want the daily recap to land.
- A short list of search profiles (role title, location, seniority, keywords) you want to monitor.
How can I customize it?
- Change the run time or frequency, for example switch from weekday mornings to twice a day or only Mondays.
- Edit your list of search profiles to add new roles, target different cities, or tune keywords like remote, contract, or specific tech stacks.
- Swap the recap destination from a public channel to a DM, or change which columns get written to the sheet.
Frequently asked questions
Will I get the same job twice?
What happens on a slow day with no new jobs?
Can I track more than one role or city at the same time?
Can multiple people share the same tracker?
Do I need to write any code or summaries?
Stop refreshing job boards every morning.
Connect Tavily, Google Sheets, and Slack once, and Geni delivers a clean list of fresh postings every weekday at 7am.