chore: reorganize repo structure and update docs

- move temp scripts to scripts/, cv files to cv/, jobs.csv to results/
- update index.ts and recheck.ts CSV path to results/jobs.csv
- fix imports in scripts/ to use ../config.ts and ../fetch.ts
- update CLAUDE.md and README.md to reflect new structure
- add plans/ with LinkedIn post drafts
- update .gitignore: ignore results/, jobs/, cv binaries, .DS_Store
This commit is contained in:
2026-06-03 16:01:32 +02:00
parent bcb6ae5ea3
commit fb67c38edd
40 changed files with 1472 additions and 806 deletions
+55
View File
@@ -0,0 +1,55 @@
#!/usr/bin/env bun
import { KEYWORDS } from "../config.ts";
import { fetchJobs, isEnglishContent } from "../fetch.ts";
import type { SearchConfig } from "../config.ts";
const CSV = "./jobs.csv";
const existingLinks = new Set<string>();
try {
const text = await Bun.file(CSV).text();
for (const line of text.split("\n").slice(1)) {
const url = line.match(/"(https?:\/\/[^"]+)"/)?.[1];
if (url) existingLinks.add(url);
}
} catch {}
const searches: SearchConfig[] = [
{ label: "Switzerland remote (by name)", keywords: KEYWORDS, location: "Switzerland", workType: ["remote"], timePosted: "month" },
{ label: "Basel remote", keywords: KEYWORDS, geoId: "103383283", location: "Basel", workType: ["remote"], timePosted: "month" },
{ label: "Basel Metro remote", keywords: KEYWORDS, geoId: "90009885", location: "Basel Metropolitan Area", workType: ["remote"], timePosted: "month" },
{ label: "Zürich remote", keywords: KEYWORDS, geoId: "102436504", location: "Zürich, Switzerland", workType: ["remote"], timePosted: "month" },
{ label: "Zürich Metro remote", keywords: KEYWORDS, geoId: "107814425", location: "Zürich Metropolitan Area", workType: ["remote"], timePosted: "month" },
{ label: "Zürich Area remote", keywords: KEYWORDS, geoId: "90009888", location: "Zürich Area", workType: ["remote"], timePosted: "month" },
{ label: "Bern remote", keywords: KEYWORDS, location: "Bern, Switzerland", workType: ["remote"], timePosted: "month" },
// seniority-filtered pass for mid-senior+
{ label: "Switzerland remote (mid-senior)", keywords: KEYWORDS, location: "Switzerland", workType: ["remote"], seniority: ["mid-senior", "director"], timePosted: "month" },
];
type Job = { id: string; title: string; company: string; link: string; search: string };
const results: Job[] = [];
const seen = new Set<string>();
for (const config of searches) {
console.log(`\n[${config.label}]`);
const jobs = await fetchJobs(config);
if (jobs.length === 0) { console.log(" no jobs found"); continue; }
let added = 0;
for (const job of jobs) {
if (seen.has(job.id) || existingLinks.has(job.link)) continue;
seen.add(job.id);
process.stdout.write(` ${job.title} @ ${job.company} … `);
const english = await isEnglishContent(job.id);
if (!english) { console.log("dropped"); continue; }
console.log("ok");
results.push({ ...job, search: config.label });
added++;
}
console.log(` => ${added} new`);
}
console.log(`\n=== TOTAL: ${results.length} remote jobs ===\n`);
for (const j of results) {
console.log(`[${j.search}] ${j.title} | ${j.company} | ${j.id} | ${j.link}`);
}