@timurtekb/tekjobs 0.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +131 -0
- package/LICENSE +21 -0
- package/README.md +145 -0
- package/app/README.md +22 -0
- package/app/dist/assets/index-DzGgV6NF.css +1 -0
- package/app/dist/assets/index-QteuouKv.js +77 -0
- package/app/dist/favicon.svg +1 -0
- package/app/dist/index.html +16 -0
- package/app/server/cover-letter.mjs +243 -0
- package/app/server/index.mjs +113 -0
- package/app/server/mail-check.mjs +234 -0
- package/app/server/mcp.mjs +129 -0
- package/app/server/people.mjs +164 -0
- package/app/server/store.mjs +1131 -0
- package/app/server/tailored-resume.mjs +213 -0
- package/cli.mjs +205 -0
- package/package.json +74 -0
- package/run.cmd +10 -0
- package/run.mjs +201 -0
- package/run.sh +12 -0
- package/samples/vault/Jobs/Basalt Systems - Senior Design Engineer, Growth (1010).md +56 -0
- package/samples/vault/Jobs/Brightline Studio - Design Engineer (1005).md +51 -0
- package/samples/vault/Jobs/Copperleaf - Principal Design Engineer (1006).md +53 -0
- package/samples/vault/Jobs/Example Studio - Senior Design Engineer (1013).md +52 -0
- package/samples/vault/Jobs/Fjord Analytics - Staff Frontend Engineer, Platform (1003).md +58 -0
- package/samples/vault/Jobs/Halcyon Robotics - Senior UX Engineer (1004).md +52 -0
- package/samples/vault/Jobs/Lumen Health - Design Systems Engineer (1002).md +51 -0
- package/samples/vault/Jobs/Meridian Pay - Staff Design Engineer (1009).md +67 -0
- package/samples/vault/Jobs/Northwind Labs - Staff Design Engineer, Design Systems (1000).md +57 -0
- package/samples/vault/Jobs/Orbital Software - Senior Design Engineer (1001).md +52 -0
- package/samples/vault/Jobs/Quill & Co - Design Engineer, Editor (1008).md +55 -0
- package/samples/vault/Jobs/Signalfire Design - Design Engineer (1012).md +53 -0
- package/samples/vault/Jobs/Tessellate - Senior Frontend Engineer, Design Systems (1007).md +52 -0
- package/samples/vault/Jobs/Verdant - UX Engineer (1011).md +51 -0
- package/samples/vault/Logs/2026-09-16.md +13 -0
- package/samples/vault/Logs/2026-09-23.md +13 -0
- package/samples/vault/People/Lee Example (Fjord Analytics).md +22 -0
- package/samples/vault/People/Priya Example (Meridian Pay).md +23 -0
- package/samples/vault/People/Sam Example (Northwind Labs).md +20 -0
- package/samples/vault/Profile/Positioning.md +16 -0
- package/samples/vault/Profile/Profile.md +41 -0
- package/samples/vault/Profile/Resume.md +32 -0
- package/samples/vault/Profile/Voice.md +15 -0
- package/samples/vault/README.md +11 -0
- package/samples/vault/Targets/Companies.md +318 -0
- package/samples/vault/Targets/Search Criteria.md +234 -0
- package/samples/vault/_Home.md +54 -0
- package/scraper/config.mjs +122 -0
- package/scraper/health.mjs +50 -0
- package/scraper/import-link.mjs +281 -0
- package/scraper/profile.mjs +186 -0
- package/scraper/rescore.mjs +236 -0
- package/scraper/resume-sync.mjs +224 -0
- package/scraper/resume.mjs +65 -0
- package/scraper/score.mjs +114 -0
- package/scraper/sources-email.mjs +242 -0
- package/scraper/sources-extra.mjs +558 -0
- package/scraper/sources-sites.mjs +280 -0
- package/scraper/sources.mjs +264 -0
- package/scraper/starter/companies-table.md +306 -0
- package/scraper/starter/criteria.json +56 -0
- package/scraper/starter/profile.md +38 -0
- package/scraper/vault.mjs +212 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
| Company | ATS | Slug | Tier | Status | Notes |
|
|
2
|
+
|---|---|---|---|---|---|
|
|
3
|
+
| Anthropic | greenhouse | anthropic | A | | |
|
|
4
|
+
| OpenAI | ashby | openai | A | | |
|
|
5
|
+
| Vercel | greenhouse | vercel | A | | |
|
|
6
|
+
| Linear | ashby | linear | A | | |
|
|
7
|
+
| Figma | greenhouse | figma | A | | |
|
|
8
|
+
| Notion | ashby | notion | A | | |
|
|
9
|
+
| Stripe | greenhouse | stripe | A | | |
|
|
10
|
+
| Webflow | greenhouse | webflow | A | | |
|
|
11
|
+
| Replit | ashby | replit | A | | |
|
|
12
|
+
| Cursor (Anysphere) | ashby | cursor | A | | |
|
|
13
|
+
| Perplexity | ashby | perplexity | A | | |
|
|
14
|
+
| Ramp | ashby | ramp | A | | |
|
|
15
|
+
| Mercury | greenhouse | mercury | A | | |
|
|
16
|
+
| Supabase | ashby | supabase | A | | |
|
|
17
|
+
| PostHog | ashby | posthog | A | | |
|
|
18
|
+
| Raycast | ashby | raycast | A | | |
|
|
19
|
+
| Sierra | ashby | sierra | A | | |
|
|
20
|
+
| Runway | ashby | runway | A | | |
|
|
21
|
+
| ElevenLabs | ashby | elevenlabs | A | | |
|
|
22
|
+
| Chromatic (Storybook) | ashby | chromatic | A | | |
|
|
23
|
+
| Gamma | ashby | gamma | A | | |
|
|
24
|
+
| Lovable | ashby | lovable | A | | |
|
|
25
|
+
| Tailwind Labs | ashby | tailwind | A | | |
|
|
26
|
+
| Magic Patterns | ashby | magicpatterns | A | | Design-to-code product |
|
|
27
|
+
| Builder.io | greenhouse | builder | A | | Design-to-code product |
|
|
28
|
+
| StackBlitz (Bolt) | greenhouse | stackblitz | A | | |
|
|
29
|
+
| Cohere | ashby | cohere | B | | |
|
|
30
|
+
| Scale AI | greenhouse | scaleai | B | | |
|
|
31
|
+
| Databricks | greenhouse | databricks | B | | |
|
|
32
|
+
| Cloudflare | greenhouse | cloudflare | B | | |
|
|
33
|
+
| Discord | greenhouse | discord | B | | |
|
|
34
|
+
| Dropbox | greenhouse | dropbox | B | | |
|
|
35
|
+
| Coinbase | greenhouse | coinbase | B | | |
|
|
36
|
+
| Brex | greenhouse | brex | B | | |
|
|
37
|
+
| Gusto | greenhouse | gusto | B | | |
|
|
38
|
+
| Plaid | ashby | plaid | B | | |
|
|
39
|
+
| Pinterest | greenhouse | pinterest | B | | |
|
|
40
|
+
| Reddit | greenhouse | reddit | B | | |
|
|
41
|
+
| Robinhood | greenhouse | robinhood | B | | |
|
|
42
|
+
| Zapier | ashby | zapier | B | | |
|
|
43
|
+
| Miro | ashby | miro | B | | |
|
|
44
|
+
| Duolingo | greenhouse | duolingo | B | | |
|
|
45
|
+
| Airbnb | greenhouse | airbnb | B | | |
|
|
46
|
+
| Sourcegraph | greenhouse | sourcegraph91 | B | | |
|
|
47
|
+
| Clerk | ashby | clerk | B | | |
|
|
48
|
+
| Mintlify | ashby | mintlify | B | | |
|
|
49
|
+
| Together AI | greenhouse | togetherai | B | | |
|
|
50
|
+
| Harvey | ashby | harvey | B | | |
|
|
51
|
+
| Glean | greenhouse | gleanwork | B | | |
|
|
52
|
+
| Writer | ashby | writer | B | | |
|
|
53
|
+
| Descript | greenhouse | descript | B | | |
|
|
54
|
+
| Airtable | greenhouse | airtable | B | | |
|
|
55
|
+
| Intercom | greenhouse | intercom | B | | |
|
|
56
|
+
| Asana | greenhouse | asana | B | | |
|
|
57
|
+
| Squarespace | greenhouse | squarespace | B | | |
|
|
58
|
+
| Netlify | greenhouse | netlify | B | | |
|
|
59
|
+
| Render | ashby | render | B | | |
|
|
60
|
+
| Railway | ashby | railway | B | | |
|
|
61
|
+
| Modal | ashby | modal | B | | |
|
|
62
|
+
| Baseten | ashby | baseten | B | | |
|
|
63
|
+
| LangChain | ashby | langchain | B | | |
|
|
64
|
+
| Neon | ashby | neon | B | | |
|
|
65
|
+
| Convex | ashby | convex-dev | B | | |
|
|
66
|
+
| Sentry | ashby | sentry | B | | |
|
|
67
|
+
| Vanta | ashby | vanta | B | | |
|
|
68
|
+
| 1Password | ashby | 1password | B | | |
|
|
69
|
+
| WorkOS | ashby | workos | B | | |
|
|
70
|
+
| Granola | ashby | granola | B | | |
|
|
71
|
+
| Cognition | ashby | cognition | B | | |
|
|
72
|
+
| Warp | ashby | warp | B | | |
|
|
73
|
+
| Zed | ashby | zed | B | | |
|
|
74
|
+
| Attio | ashby | attio | B | | |
|
|
75
|
+
| Clay | ashby | claylabs | B | | |
|
|
76
|
+
| Block | greenhouse | block | B | | |
|
|
77
|
+
| Modern Treasury | ashby | moderntreasury | B | | |
|
|
78
|
+
| Character.AI | ashby | character | B | | |
|
|
79
|
+
| Midjourney | ashby | midjourney | B | | |
|
|
80
|
+
| Resend | ashby | resend | B | | |
|
|
81
|
+
| Fal | ashby | fal-ai | B | | |
|
|
82
|
+
| Browserbase | ashby | browserbase | B | | |
|
|
83
|
+
| Decagon | ashby | decagon | B | | |
|
|
84
|
+
| Fireworks AI | ashby | fireworks | B | | |
|
|
85
|
+
| Anima | ashby | anima | B | | Design-to-code |
|
|
86
|
+
| Bubble | ashby | bubble | B | | |
|
|
87
|
+
| Factory | ashby | factory | B | | |
|
|
88
|
+
| Glide | ashby | glide | B | | |
|
|
89
|
+
| Ideogram | ashby | ideogram | B | | |
|
|
90
|
+
| Krea | ashby | krea | B | | |
|
|
91
|
+
| Oura | greenhouse | oura | B | | |
|
|
92
|
+
| Patreon | ashby | patreon | B | | |
|
|
93
|
+
| Pika | ashby | pika | B | | |
|
|
94
|
+
| Sanity | ashby | sanity | B | | |
|
|
95
|
+
| Speak | ashby | speak | B | | |
|
|
96
|
+
| Storyblok | greenhouse | storyblok | B | | |
|
|
97
|
+
| Strava | ashby | strava | B | | |
|
|
98
|
+
| Substack | ashby | substack | B | | |
|
|
99
|
+
| Suno | ashby | suno | B | | |
|
|
100
|
+
| Thinking Machines | ashby | thinkingmachines | B | | |
|
|
101
|
+
| Pinecone | ashby | pinecone | C | | |
|
|
102
|
+
| Temporal | ashby | temporal | C | | |
|
|
103
|
+
| Apollo GraphQL | ashby | apollo-graphql | C | | |
|
|
104
|
+
| Instacart | greenhouse | instacart | C | | |
|
|
105
|
+
| DoorDash | greenhouse | doordashusa | C | | |
|
|
106
|
+
| Lyft | greenhouse | lyft | C | | |
|
|
107
|
+
| Roblox | greenhouse | roblox | C | | |
|
|
108
|
+
| Amplitude | greenhouse | amplitude | C | | |
|
|
109
|
+
| Mixpanel | greenhouse | mixpanel | C | | |
|
|
110
|
+
| Lattice | greenhouse | lattice | C | | |
|
|
111
|
+
| Carta | greenhouse | carta | C | | |
|
|
112
|
+
| Deel | ashby | deel | C | | |
|
|
113
|
+
| Remote.com | greenhouse | remotecom | C | | |
|
|
114
|
+
| Toast | greenhouse | toast | C | | |
|
|
115
|
+
| Contentful | greenhouse | contentful | C | | |
|
|
116
|
+
| Grafana Labs | greenhouse | grafanalabs | C | | |
|
|
117
|
+
| MongoDB | greenhouse | mongodb | C | | |
|
|
118
|
+
| LaunchDarkly | greenhouse | launchdarkly | C | | |
|
|
119
|
+
| Prisma | greenhouse | prisma | C | | |
|
|
120
|
+
| Klaviyo | greenhouse | klaviyo | C | | |
|
|
121
|
+
| Braze | greenhouse | braze | C | | |
|
|
122
|
+
| Affirm | greenhouse | affirm | C | | |
|
|
123
|
+
| Chime | greenhouse | chime | C | | |
|
|
124
|
+
| Mercor | ashby | mercor | C | | |
|
|
125
|
+
| xAI | greenhouse | xai | C | | |
|
|
126
|
+
| Mistral | lever | mistral | C | | |
|
|
127
|
+
| Assembly AI | greenhouse | assemblyai | C | | |
|
|
128
|
+
| Bland | ashby | bland | C | | |
|
|
129
|
+
| Datadog | greenhouse | datadog | C | | |
|
|
130
|
+
| Deepgram | ashby | deepgram | C | | |
|
|
131
|
+
| Elastic | greenhouse | elastic | C | | |
|
|
132
|
+
| Faire | greenhouse | faire | C | | |
|
|
133
|
+
| Galileo | greenhouse | galileo | C | | |
|
|
134
|
+
| Imbue | greenhouse | imbue | C | | |
|
|
135
|
+
| Nextdoor | greenhouse | nextdoor | C | | |
|
|
136
|
+
| Okta | greenhouse | okta | C | | |
|
|
137
|
+
| Poolside | ashby | poolside | C | | |
|
|
138
|
+
| Snowflake | ashby | snowflake | C | | |
|
|
139
|
+
| Twilio | greenhouse | twilio | C | | |
|
|
140
|
+
| Twitch | greenhouse | twitch | C | | |
|
|
141
|
+
| Udio | greenhouse | udio | C | | |
|
|
142
|
+
| Vapi | ashby | vapi | C | | |
|
|
143
|
+
| Whoop | ashby | whoop | C | | |
|
|
144
|
+
| Abridge | ashby | abridge | B | | |
|
|
145
|
+
| Alloy | greenhouse | alloy | B | | |
|
|
146
|
+
| Ambience | ashby | ambiencehealthcare | B | | |
|
|
147
|
+
| Anchorage | lever | anchorage | B | | |
|
|
148
|
+
| Anduril | greenhouse | andurilindustries | B | | |
|
|
149
|
+
| Anon | ashby | anon | B | | |
|
|
150
|
+
| Anyscale | lever | anyscale | B | | |
|
|
151
|
+
| Arcade | ashby | arcade | B | | |
|
|
152
|
+
| Arize | greenhouse | arizeai | B | | |
|
|
153
|
+
| Ashby | ashby | ashby | A | | |
|
|
154
|
+
| Atlan | ashby | atlan | B | | |
|
|
155
|
+
| Axiom | greenhouse | axiom | B | | |
|
|
156
|
+
| Benchling | ashby | benchling | B | | |
|
|
157
|
+
| BetterUp | ashby | betterup | B | | |
|
|
158
|
+
| Bitwarden | greenhouse | bitwarden | B | | |
|
|
159
|
+
| Brightwheel | ashby | brightwheel | B | | |
|
|
160
|
+
| Calendly | greenhouse | calendly | B | | |
|
|
161
|
+
| Cameo | greenhouse | cameo | B | | |
|
|
162
|
+
| Cartesia | ashby | cartesia | A | | |
|
|
163
|
+
| Cedar | ashby | cedar | B | | |
|
|
164
|
+
| Chainguard | greenhouse | chainguard | B | | |
|
|
165
|
+
| Chalk | ashby | chalk | B | | |
|
|
166
|
+
| Checkr | greenhouse | checkr | B | | |
|
|
167
|
+
| Circle | ashby | circle | B | | |
|
|
168
|
+
| ClickHouse | ashby | clickhouse | B | | |
|
|
169
|
+
| Cockroach Labs | greenhouse | cockroachlabs | B | | |
|
|
170
|
+
| Coder | ashby | coder | B | | |
|
|
171
|
+
| Coframe | ashby | coframe | A | | |
|
|
172
|
+
| Column | ashby | column | B | | |
|
|
173
|
+
| Comet | greenhouse | comet | B | | |
|
|
174
|
+
| Commure | ashby | commure | B | | |
|
|
175
|
+
| Cribl | greenhouse | cribl | B | | |
|
|
176
|
+
| Crusoe | ashby | crusoe | B | | |
|
|
177
|
+
| Current | greenhouse | current | B | | |
|
|
178
|
+
| Dandy | ashby | dandy | B | | |
|
|
179
|
+
| Dave | ashby | dave | B | | |
|
|
180
|
+
| Depot | ashby | depot | B | | |
|
|
181
|
+
| Docker | ashby | docker | A | | |
|
|
182
|
+
| Doppler | ashby | doppler | B | | |
|
|
183
|
+
| Doximity | greenhouse | doximity | B | | |
|
|
184
|
+
| Dremio | greenhouse | dremio | B | | |
|
|
185
|
+
| Dust | ashby | dust | A | | |
|
|
186
|
+
| E2B | ashby | e2b | B | | |
|
|
187
|
+
| Elicit | ashby | elicit | A | | |
|
|
188
|
+
| Ethos | greenhouse | ethoslife | B | | |
|
|
189
|
+
| Exa | ashby | exa | A | | |
|
|
190
|
+
| Fable | ashby | fable | A | | |
|
|
191
|
+
| Fandom | greenhouse | fandom | B | | |
|
|
192
|
+
| Fireblocks | greenhouse | fireblocks | B | | |
|
|
193
|
+
| Fivetran | greenhouse | fivetran | B | | |
|
|
194
|
+
| Flexport | greenhouse | flexport | B | | |
|
|
195
|
+
| Fly.io | lever | fly | B | | |
|
|
196
|
+
| Found | greenhouse | found | B | | |
|
|
197
|
+
| GitLab | greenhouse | gitlab | A | | |
|
|
198
|
+
| Headway | ashby | headway | B | | |
|
|
199
|
+
| Hex | ashby | hex | A | | |
|
|
200
|
+
| Hightouch | greenhouse | hightouch | B | | |
|
|
201
|
+
| Honeycomb | greenhouse | honeycomb | B | | |
|
|
202
|
+
| Included Health | lever | includedhealth | B | | |
|
|
203
|
+
| Inngest | ashby | inngest | B | | |
|
|
204
|
+
| Knock | greenhouse | knock | B | | |
|
|
205
|
+
| Kong | ashby | kong | B | | |
|
|
206
|
+
| Lambda | ashby | lambda | B | | |
|
|
207
|
+
| Lightdash | ashby | lightdash | B | | |
|
|
208
|
+
| Lithic | greenhouse | lithic | B | | |
|
|
209
|
+
| Luma AI | ashby | lumaai | A | | |
|
|
210
|
+
| Match | lever | matchgroup | B | | |
|
|
211
|
+
| Maven | greenhouse | mavenclinic | B | | |
|
|
212
|
+
| Maze | ashby | mazedesign | A | | |
|
|
213
|
+
| Melio | greenhouse | melio | B | | |
|
|
214
|
+
| Mem0 | ashby | mem0 | B | | |
|
|
215
|
+
| Meter | ashby | meter | B | | |
|
|
216
|
+
| Motive | greenhouse | motive | B | | |
|
|
217
|
+
| Mux | ashby | mux | B | | |
|
|
218
|
+
| Navan | greenhouse | tripactions | B | | |
|
|
219
|
+
| Numeric | ashby | numeric | B | | |
|
|
220
|
+
| Nuro | greenhouse | nuro | B | | |
|
|
221
|
+
| Omni | ashby | omni | B | | |
|
|
222
|
+
| One Medical | greenhouse | onemedical | B | | |
|
|
223
|
+
| OpenSea | ashby | opensea | B | | |
|
|
224
|
+
| Orum | ashby | orum | B | | |
|
|
225
|
+
| Oscar | greenhouse | oscar | B | | |
|
|
226
|
+
| Otter | greenhouse | otter | B | | |
|
|
227
|
+
| Outschool | greenhouse | outschool | B | | |
|
|
228
|
+
| Parloa | greenhouse | parloa | B | | |
|
|
229
|
+
| Payoneer | greenhouse | payoneer | B | | |
|
|
230
|
+
| Peloton | greenhouse | peloton | B | | |
|
|
231
|
+
| Pencil | ashby | pencil | A | | |
|
|
232
|
+
| Persona | ashby | persona | B | | |
|
|
233
|
+
| PlanetScale | greenhouse | planetscale | B | | |
|
|
234
|
+
| Pocket FM | lever | pocketfm | B | | |
|
|
235
|
+
| Public | greenhouse | public | B | | |
|
|
236
|
+
| Pylon | ashby | pylon | B | | |
|
|
237
|
+
| Quora | ashby | quora | B | | |
|
|
238
|
+
| Recharge | ashby | recharge | B | | |
|
|
239
|
+
| Relevance AI | ashby | relevanceai | B | | |
|
|
240
|
+
| Rewind | ashby | rewind | B | | |
|
|
241
|
+
| Rho | ashby | rho | B | | |
|
|
242
|
+
| Ro | lever | ro | B | | |
|
|
243
|
+
| Rubrik | greenhouse | rubrik | B | | |
|
|
244
|
+
| Rula | ashby | rula | B | | |
|
|
245
|
+
| Runpod | ashby | runpod | B | | |
|
|
246
|
+
| Samsara | greenhouse | samsara | B | | |
|
|
247
|
+
| Sardine | ashby | sardine | B | | |
|
|
248
|
+
| Scribe | ashby | scribe | B | | |
|
|
249
|
+
| Sigma Computing | greenhouse | sigmacomputing | B | | |
|
|
250
|
+
| Skydio | ashby | skydio | B | | |
|
|
251
|
+
| Snorkel | greenhouse | snorkelai | B | | |
|
|
252
|
+
| SoFi | greenhouse | sofi | B | | |
|
|
253
|
+
| Speakeasy | ashby | speakeasy | B | | |
|
|
254
|
+
| Sprig | ashby | sprig | B | | |
|
|
255
|
+
| Stack AI | ashby | stack-ai | B | | |
|
|
256
|
+
| Starburst | greenhouse | starburst | B | | |
|
|
257
|
+
| Step | greenhouse | step | B | | |
|
|
258
|
+
| Stytch | ashby | stytch | B | | |
|
|
259
|
+
| Synthesia | ashby | synthesia | A | | |
|
|
260
|
+
| Tavus | ashby | tavus | B | | |
|
|
261
|
+
| Tennr | ashby | tennr | B | | |
|
|
262
|
+
| Thumbtack | ashby | thumbtack | B | | |
|
|
263
|
+
| Tinybird | lever | tinybird | B | | |
|
|
264
|
+
| Tldraw | ashby | tldraw | A | | |
|
|
265
|
+
| Tubi | greenhouse | tubi | B | | |
|
|
266
|
+
| Udemy | greenhouse | udemy | B | | |
|
|
267
|
+
| Unify | lever | unify | B | | |
|
|
268
|
+
| Unit | ashby | unit | B | | |
|
|
269
|
+
| Upstart | greenhouse | upstart | B | | |
|
|
270
|
+
| Verkada | greenhouse | verkada | B | | |
|
|
271
|
+
| Vox Media | greenhouse | voxmedia | B | | |
|
|
272
|
+
| Wealthfront | lever | wealthfront | B | | |
|
|
273
|
+
| Zencoder | greenhouse | zencoder | B | | |
|
|
274
|
+
| Zip | ashby | zip | B | | |
|
|
275
|
+
| Zocdoc | greenhouse | zocdoc | B | | |
|
|
276
|
+
| Zscaler | greenhouse | zscaler | B | | |
|
|
277
|
+
| Zus | lever | zushealth | B | | |
|
|
278
|
+
| Adobe | workday | adobe.wd5.myworkdayjobs.com/adobe/external_experienced | A | | Spectrum design system |
|
|
279
|
+
| Autodesk | workday | autodesk.wd1.myworkdayjobs.com/autodesk/Ext | B | | |
|
|
280
|
+
| Salesforce | workday | salesforce.wd12.myworkdayjobs.com/salesforce/External_Career_Site | B | | Lightning design system |
|
|
281
|
+
| Slack | workday | salesforce.wd12.myworkdayjobs.com/salesforce/Slack | A | | |
|
|
282
|
+
| Workday | workday | workday.wd5.myworkdayjobs.com/workday/Workday | C | | |
|
|
283
|
+
| PayPal | workday | paypal.wd1.myworkdayjobs.com/paypal/jobs | C | | |
|
|
284
|
+
| Broadcom (VMware) | workday | broadcom.wd1.myworkdayjobs.com/broadcom/External_Career | C | | |
|
|
285
|
+
| Warner Bros. Discovery | workday | warnerbros.wd5.myworkdayjobs.com/warnerbros/global | B | | CNN design systems role seen |
|
|
286
|
+
| Disney | workday | disney.wd5.myworkdayjobs.com/disney/disneycareer | B | | |
|
|
287
|
+
| Target | workday | target.wd5.myworkdayjobs.com/target/targetcareers | C | | |
|
|
288
|
+
| Capital One | workday | capitalone.wd12.myworkdayjobs.com/capitalone/Capital_One | C | | |
|
|
289
|
+
| Nvidia | workday | nvidia.wd5.myworkdayjobs.com/nvidia/NVIDIAExternalCareerSite | C | | mostly hardware titles |
|
|
290
|
+
| Atlassian | atlassian | - | A | | remote-first; own careers API |
|
|
291
|
+
| GitHub | github | - | A | | remote-first; own careers API |
|
|
292
|
+
| Netflix | eightfold | explore.jobs.netflix.net/netflix.com | A | | top pay bands; keyword-searched |
|
|
293
|
+
| Spotify | spotify | - | B | | work-from-anywhere; API lists no descriptions |
|
|
294
|
+
| Amazon | amazon | - | C | | US only, keyword-searched; rarely remote |
|
|
295
|
+
| Google | google | - | A | | US, keyword-searched from the careers page; no API, no posted dates; mostly on-site |
|
|
296
|
+
| Apple | apple | - | A | | US, keyword-searched via the jobs.apple.com search endpoint; mostly on-site |
|
|
297
|
+
| Canonical | greenhouse | canonical | C | | fully remote, pay usually under floor |
|
|
298
|
+
| Mozilla | greenhouse | mozilla | B | | remote |
|
|
299
|
+
| Wikimedia | greenhouse | wikimedia | C | | remote |
|
|
300
|
+
| Wise | smartrecruiters | Wise | B | | fintech, design eng culture |
|
|
301
|
+
| Ubisoft | smartrecruiters | Ubisoft2 | C | | |
|
|
302
|
+
| Rippling | rippling | rippling | B | | also the ATS platform |
|
|
303
|
+
| Webull | rippling | webull | C | | |
|
|
304
|
+
| Malwarebytes | rippling | malwarebytes | C | | |
|
|
305
|
+
| Alfred | rippling | alfred | C | | |
|
|
306
|
+
| Consensus | rippling | consensus | C | | |
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"minScore": 45,
|
|
3
|
+
"descCap": 35,
|
|
4
|
+
"noTitleMatchPenalty": -40,
|
|
5
|
+
"titleExtraPer": 5,
|
|
6
|
+
"titleExtraCap": 10,
|
|
7
|
+
"titleTerms": {},
|
|
8
|
+
"titleExclude": [
|
|
9
|
+
"intern", "internship", "apprentice", "new grad", "recruit", "account executive", "customer success",
|
|
10
|
+
"manufacturing", "process engineer", "chemical", "biomedical", "automotive", "aerospace"
|
|
11
|
+
],
|
|
12
|
+
"descTerms": {},
|
|
13
|
+
"seniority": {
|
|
14
|
+
"boost": { "senior": 8, "staff": 10, "lead": 10, "principal": 10, "head of": 8, "founding": 8 },
|
|
15
|
+
"penalty": { "junior": -30, "intern": -50, "entry": -25, "associate": -15, "new grad": -40 }
|
|
16
|
+
},
|
|
17
|
+
"salary": { "minAnnual": null, "stretchAnnual": null, "meetsBonus": 10, "abovePer10k": 1, "aboveCap": 8, "stretchPenalty": -8, "belowPenalty": -30 },
|
|
18
|
+
"location": {
|
|
19
|
+
"requireRemote": false,
|
|
20
|
+
"notRemotePenalty": -60,
|
|
21
|
+
"remoteBoost": 15,
|
|
22
|
+
"bayAreaBoost": 0,
|
|
23
|
+
"bayAreaTerms": [],
|
|
24
|
+
"usTerms": ["united states", "usa", "u.s.", "us-", "us ", "(us)", "us)", "north america", "americas", "remote - us", "remote us", "us remote", "anywhere"],
|
|
25
|
+
"nonUsTerms": ["london", "berlin", "paris", "amsterdam", "dublin", "europe", "emea", "uk", "united kingdom", "germany", "france", "netherlands", "spain", "portugal", "poland", "india", "bangalore", "bengaluru", "hyderabad", "singapore", "sydney", "melbourne", "australia", "toronto", "vancouver", "canada", "brazil", "são paulo", "sao paulo", "mexico city", "latam", "apac", "tokyo", "japan", "israel", "tel aviv", "stockholm", "copenhagen", "zurich", "lisbon", "warsaw", "prague", "tallinn", "riga", "riyadh", "saudi arabia", "dubai", "abu dhabi", "uae", "united arab emirates", "middle east", "korea", "seoul", "china", "shanghai", "beijing", "hong kong", "taiwan", "philippines", "vietnam", "indonesia", "nigeria", "south africa", "argentina", "colombia", "chile", "ottawa", "montreal", "waterloo"],
|
|
26
|
+
"nonUsPenalty": -45
|
|
27
|
+
},
|
|
28
|
+
"recency": { "days2": 25, "days7": 15, "days30": 5, "days90": -5, "older": -25 },
|
|
29
|
+
"openSources": {
|
|
30
|
+
"remoteok": true, "hn": true, "email": true, "adzuna": false, "usajobs": false,
|
|
31
|
+
"themuse": true, "remotive": false, "himalayas": true, "jobicy": true,
|
|
32
|
+
"workingnomads": true, "arbeitnow": false, "wwr": true,
|
|
33
|
+
"wellfound": true, "builtin": true
|
|
34
|
+
},
|
|
35
|
+
"adzuna": {
|
|
36
|
+
"_note": "Needs ADZUNA_APP_ID and ADZUNA_APP_KEY in the environment (free at developer.adzuna.com), and openSources.adzuna set to true. Searches for your top titleTerms unless queries is set. Descriptions come back as snippets, so these rows score lower than the same job from its ATS.",
|
|
37
|
+
"countries": ["us"],
|
|
38
|
+
"queries": [],
|
|
39
|
+
"maxQueries": 6,
|
|
40
|
+
"pages": 2,
|
|
41
|
+
"maxDaysOld": 30
|
|
42
|
+
},
|
|
43
|
+
"email": {
|
|
44
|
+
"_note": "Job alert emails you save into the Inbox folder of your profile, as .eml. Nothing contacts the sites; this reads files you put there. Understands LinkedIn, Indeed, Otta and Wellfound alerts, and picks up Greenhouse/Lever/Ashby/Workday links in anything else. Rows are thin — a title, a company, usually a location — so they score below the same job from an ATS.",
|
|
45
|
+
"maxFiles": 200
|
|
46
|
+
},
|
|
47
|
+
"usajobs": {
|
|
48
|
+
"_note": "Needs USAJOBS_API_KEY and USAJOBS_EMAIL in the environment (free at developer.usajobs.gov; the email is the one the key is registered to), and openSources.usajobs set to true. Every US federal posting, with full descriptions and a real application deadline. Searches your top titleTerms as position titles unless searchBy is \"keyword\" or queries is set.",
|
|
49
|
+
"queries": [],
|
|
50
|
+
"maxQueries": 6,
|
|
51
|
+
"pages": 2,
|
|
52
|
+
"datePosted": 30,
|
|
53
|
+
"searchBy": "title"
|
|
54
|
+
},
|
|
55
|
+
"maxDescriptionChars": 6000
|
|
56
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: profile
|
|
3
|
+
updated: {{date}}
|
|
4
|
+
status: draft
|
|
5
|
+
---
|
|
6
|
+
# Candidate profile
|
|
7
|
+
|
|
8
|
+
> Written by the onboarding interview from your resume and your answers. Edit freely; the scraper does not read this note (it reads [[Targets/Search Criteria]]), but every application draft does.
|
|
9
|
+
|
|
10
|
+
## Basics
|
|
11
|
+
- **Name:**
|
|
12
|
+
- **Location / time zone:**
|
|
13
|
+
- **Email:**
|
|
14
|
+
- **Links:**
|
|
15
|
+
- **Current role:**
|
|
16
|
+
|
|
17
|
+
## What you are, in three sentences
|
|
18
|
+
(The interview fills this in: the through-line of the career, what you are strongest at, what you want next.)
|
|
19
|
+
|
|
20
|
+
## Target roles
|
|
21
|
+
| Tier | Titles | Why |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| A | | |
|
|
24
|
+
| B | | |
|
|
25
|
+
|
|
26
|
+
## Constraints & preferences
|
|
27
|
+
- **Work mode:** remote / hybrid / on-site, and where
|
|
28
|
+
- **Employment:** full-time / contract
|
|
29
|
+
- **Pay floor and stretch:**
|
|
30
|
+
- **Company stage / size:**
|
|
31
|
+
- **Industries to avoid:**
|
|
32
|
+
- **Earliest start:**
|
|
33
|
+
|
|
34
|
+
## Proof points
|
|
35
|
+
(Quantified outcomes from the resume, one line each. These are what cover letters are built from.)
|
|
36
|
+
|
|
37
|
+
## Documents
|
|
38
|
+
- Resume source: [[Profile/Resume - Source]]
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { P, VAULT } from './config.mjs';
|
|
4
|
+
import { weightsFingerprint } from './rescore.mjs';
|
|
5
|
+
|
|
6
|
+
const today = () => new Date().toISOString().slice(0, 10);
|
|
7
|
+
const yaml = (v) => JSON.stringify(v ?? '');
|
|
8
|
+
const safe = (s) => (s || '').replace(/[<>:"/\\|?*\x00-\x1f]/g, ' ').replace(/\s+/g, ' ').trim().slice(0, 70);
|
|
9
|
+
// The tail of the id becomes part of the filename, so only word characters may reach it. A link id ends in a
|
|
10
|
+
// URL, and a URL's trailing slash became a path separator on Windows: "Meta - … (2149585\).md" did not exist.
|
|
11
|
+
const shortId = (id) => String(id).split(':').pop().replace(/[^A-Za-z0-9_-]+/g, '').slice(-8) || 'link';
|
|
12
|
+
|
|
13
|
+
export function loadSeen() {
|
|
14
|
+
try { return JSON.parse(fs.readFileSync(P.seen, 'utf8')); } catch { return {}; }
|
|
15
|
+
}
|
|
16
|
+
export function saveSeen(seen) {
|
|
17
|
+
fs.writeFileSync(P.seen, JSON.stringify(seen, null, 2));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The Narrative line the note template used to pre-fill, before it was emptied.
|
|
22
|
+
*
|
|
23
|
+
* It named one person's positioning in every note the scraper wrote, which is wrong for anyone else's vault.
|
|
24
|
+
* Kept here because notes written before the change still carry it, and something has to be able to tell that
|
|
25
|
+
* line apart from a narrative a reader actually chose.
|
|
26
|
+
*/
|
|
27
|
+
export const LEGACY_NARRATIVE_DEFAULT = 'Design Engineer leads, AI work as proof (see [[Profile/Positioning]])';
|
|
28
|
+
|
|
29
|
+
export function jobNotePath(job) {
|
|
30
|
+
return path.join(P.jobs, `${safe(job.company)} - ${safe(job.title)} (${shortId(job.id)}).md`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function writeJobNote(job, scored, criteria) {
|
|
34
|
+
const file = jobNotePath(job);
|
|
35
|
+
// Never overwrite a note that exists: it may carry the person's status and notes. (Guards a lost or reset seen.json.)
|
|
36
|
+
if (fs.existsSync(file)) return file;
|
|
37
|
+
const desc = (job.descriptionText || '').slice(0, criteria.maxDescriptionChars ?? 6000);
|
|
38
|
+
const truncated = (job.descriptionText || '').length > desc.length;
|
|
39
|
+
const posted = job.posted ? String(job.posted).slice(0, 10) : '';
|
|
40
|
+
const fm = [
|
|
41
|
+
'---',
|
|
42
|
+
'type: job',
|
|
43
|
+
'status: new',
|
|
44
|
+
'listing: open',
|
|
45
|
+
`company: ${yaml(job.company)}`,
|
|
46
|
+
`title: ${yaml(job.title)}`,
|
|
47
|
+
`location: ${yaml(job.location)}`,
|
|
48
|
+
`remote: ${job.remote ? 'true' : 'false'}`,
|
|
49
|
+
`source: ${job.source}`,
|
|
50
|
+
`url: ${yaml(job.url)}`,
|
|
51
|
+
`score: ${scored.score}`,
|
|
52
|
+
// Which weights produced that score, so `tekjobs rescore` can tell an adjusted note from an untouched one.
|
|
53
|
+
`weights: ${weightsFingerprint(criteria)}`,
|
|
54
|
+
`posted: ${yaml(posted)}`,
|
|
55
|
+
`found: ${today()}`,
|
|
56
|
+
`salary: ${yaml(job.salary)}`,
|
|
57
|
+
`salary_max: ${job.salaryMax || ''}`,
|
|
58
|
+
`pay_band: ${scored.payBand || 'unknown'}`,
|
|
59
|
+
`department: ${yaml(job.department)}`,
|
|
60
|
+
`job_id: ${yaml(job.id)}`,
|
|
61
|
+
// Only on notes that did not come from the scan, so a scanned note keeps the shape it always had.
|
|
62
|
+
...(job.foundVia ? [`added_by: ${job.addedBy || 'link'}`] : []),
|
|
63
|
+
`tags: [job${scored.payBand === 'stretch' ? ', stretch' : ''}]`,
|
|
64
|
+
'---',
|
|
65
|
+
].join('\n');
|
|
66
|
+
|
|
67
|
+
const body = `
|
|
68
|
+
# ${job.title} @ ${job.company}
|
|
69
|
+
|
|
70
|
+
**[Open posting](${job.url})** · ${job.location || 'location n/a'} · ${job.remote ? 'Remote' : 'On-site/Hybrid'} · score **${scored.score}**${job.salary ? ` · ${job.salary}` : ''}
|
|
71
|
+
|
|
72
|
+
## Why it matched
|
|
73
|
+
${scored.reasons.map((r) => `- ${r}`).join('\n')}
|
|
74
|
+
|
|
75
|
+
## Status log
|
|
76
|
+
- ${today()} — ${job.foundVia || 'found by scraper'} (score ${scored.score}). Set \`status:\` above to \`reviewing\`, \`applying\`, \`applied\`, \`interviewing\`, \`offer\`, \`rejected\`, or \`passed\`.
|
|
77
|
+
|
|
78
|
+
## Notes
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
## Application
|
|
82
|
+
- **Narrative:**
|
|
83
|
+
- **Resume variant:**
|
|
84
|
+
- **Cover letter:**
|
|
85
|
+
- **Applied on:**
|
|
86
|
+
- **Contact / referral:**
|
|
87
|
+
- **Follow-up due:**
|
|
88
|
+
|
|
89
|
+
## Job description
|
|
90
|
+
> Source: ${job.source}${job.thread ? ` · ${job.thread}` : ''}${truncated ? ' · truncated, open the posting for the full text' : ''}
|
|
91
|
+
|
|
92
|
+
${desc}
|
|
93
|
+
`;
|
|
94
|
+
fs.writeFileSync(file, fm + '\n' + body);
|
|
95
|
+
return file;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Minimal frontmatter reader: --- key: value --- */
|
|
99
|
+
export function readFrontmatter(file) {
|
|
100
|
+
let txt;
|
|
101
|
+
try { txt = fs.readFileSync(file, 'utf8'); } catch { return null; }
|
|
102
|
+
const m = txt.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
103
|
+
if (!m) return null;
|
|
104
|
+
const fm = {};
|
|
105
|
+
for (const line of m[1].split(/\r?\n/)) {
|
|
106
|
+
const i = line.indexOf(':');
|
|
107
|
+
if (i < 0) continue;
|
|
108
|
+
const k = line.slice(0, i).trim();
|
|
109
|
+
let v = line.slice(i + 1).trim();
|
|
110
|
+
if (/^".*"$/.test(v)) { try { v = JSON.parse(v); } catch { /* keep */ } }
|
|
111
|
+
fm[k] = v;
|
|
112
|
+
}
|
|
113
|
+
fm._file = file;
|
|
114
|
+
fm._name = path.basename(file, '.md');
|
|
115
|
+
return fm;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function allJobNotes() {
|
|
119
|
+
if (!fs.existsSync(P.jobs)) return [];
|
|
120
|
+
return fs.readdirSync(P.jobs).filter((f) => f.endsWith('.md')).map((f) => readFrontmatter(path.join(P.jobs, f))).filter(Boolean);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Mark notes whose listing vanished from a successfully fetched board. Only touches the `listing:` line. */
|
|
124
|
+
export function markClosedListings(liveIdsByCompanyKey, seen) {
|
|
125
|
+
const closed = [];
|
|
126
|
+
for (const [id, rec] of Object.entries(seen)) {
|
|
127
|
+
if (!rec.path || !fs.existsSync(rec.path)) continue;
|
|
128
|
+
const key = rec.companyKey;
|
|
129
|
+
if (!key || !(key in liveIdsByCompanyKey)) continue; // board not fetched this run
|
|
130
|
+
if (liveIdsByCompanyKey[key].has(id)) continue;
|
|
131
|
+
const txt = fs.readFileSync(rec.path, 'utf8');
|
|
132
|
+
if (!/^listing: open$/m.test(txt)) continue;
|
|
133
|
+
fs.writeFileSync(rec.path, txt.replace(/^listing: open$/m, `listing: closed ${today()}`));
|
|
134
|
+
closed.push(rec);
|
|
135
|
+
}
|
|
136
|
+
return closed;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function appendLog(lines) {
|
|
140
|
+
const file = path.join(P.logs, `${today()}.md`);
|
|
141
|
+
const header = fs.existsSync(file) ? '' : `---\ntype: log\ndate: ${today()}\n---\n# ${today()} — scraper log\n\n`;
|
|
142
|
+
fs.appendFileSync(file, header + lines.join('\n') + '\n\n');
|
|
143
|
+
return file;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const link = (fm) => `[[Jobs/${fm._name}|open]]`;
|
|
147
|
+
const row = (cells) => `| ${cells.map((c) => String(c ?? '').replace(/\|/g, '\\|')).join(' | ')} |`;
|
|
148
|
+
|
|
149
|
+
export function writeDashboard(summary) {
|
|
150
|
+
const notes = allJobNotes();
|
|
151
|
+
const byStatus = {};
|
|
152
|
+
for (const n of notes) (byStatus[n.status || 'new'] ||= []).push(n);
|
|
153
|
+
const order = ['new', 'reviewing', 'applying', 'applied', 'interviewing', 'offer', 'rejected', 'passed'];
|
|
154
|
+
const statuses = [...order.filter((s) => byStatus[s]), ...Object.keys(byStatus).filter((s) => !order.includes(s))];
|
|
155
|
+
|
|
156
|
+
const newOpen = (byStatus.new || []).filter((n) => String(n.listing).startsWith('open')).sort((a, b) => Number(b.score) - Number(a.score));
|
|
157
|
+
const active = notes.filter((n) => ['applying', 'applied', 'interviewing', 'offer'].includes(n.status));
|
|
158
|
+
const closedNew = (byStatus.new || []).filter((n) => String(n.listing).startsWith('closed'));
|
|
159
|
+
|
|
160
|
+
const out = [];
|
|
161
|
+
out.push('---', 'type: dashboard', `generated: ${new Date().toISOString()}`, '---');
|
|
162
|
+
out.push('# TekJobs — Home');
|
|
163
|
+
out.push(`> Generated by the scraper. Edits here get overwritten; write in the job notes or [[Applications/Pipeline Notes]].`);
|
|
164
|
+
out.push('');
|
|
165
|
+
out.push(`**Last run:** ${summary.when} · ${summary.companiesOk}/${summary.companiesTotal} boards fetched (${summary.companiesFailed} failed) · ${summary.totalJobs} postings scanned · **${summary.newMatches} new matches** · log: [[Logs/${today()}]]`);
|
|
166
|
+
out.push('');
|
|
167
|
+
out.push('## Needs you');
|
|
168
|
+
out.push(`- **${newOpen.length}** new matches waiting for a first look (below).`);
|
|
169
|
+
// Only while the profile is still the template: a finished profile has no open questions to nag about.
|
|
170
|
+
const profileMd = (() => { try { return fs.readFileSync(P.profile, 'utf8'); } catch { return ''; } })();
|
|
171
|
+
if (!profileMd || /^status: draft$/m.test(profileMd) || profileMd.includes('(The interview fills this in')) out.push(`- The profile is not written yet: run the onboarding interview, or fill in [[Profile/Profile]] by hand.`);
|
|
172
|
+
if (summary.companiesFailed) out.push(`- ${summary.companiesFailed} company slugs failed; see the Status column in [[Targets/Companies]].`);
|
|
173
|
+
out.push('');
|
|
174
|
+
out.push('## Pipeline');
|
|
175
|
+
out.push(row(['Status', 'Count']), row(['---', '---']));
|
|
176
|
+
for (const s of statuses) out.push(row([s, byStatus[s].length]));
|
|
177
|
+
out.push('');
|
|
178
|
+
out.push(`## New matches — top ${Math.min(40, newOpen.length)} of ${newOpen.length} by score`);
|
|
179
|
+
const bandMark = (n) => ({ floor: '✅ floor', stretch: '↗ stretch', below: '↓ below', unknown: '' })[n.pay_band || 'unknown'];
|
|
180
|
+
out.push(row(['Score', 'Company', 'Role', 'Location', 'Pay', 'Band', 'Posted', 'Note']), row(['---', '---', '---', '---', '---', '---', '---', '---']));
|
|
181
|
+
for (const n of newOpen.slice(0, 40)) out.push(row([n.score, n.company, `[${n.title}](${n.url})`, n.location, n.salary || '', bandMark(n), n.posted, link(n)]));
|
|
182
|
+
const stretch = newOpen.filter((n) => n.pay_band === 'stretch');
|
|
183
|
+
if (stretch.length) {
|
|
184
|
+
out.push('');
|
|
185
|
+
out.push(`## Stretch band — stated pay $180k to $220k (${stretch.length})`);
|
|
186
|
+
out.push('_Visible on purpose, scored slightly down. Senior-level roles that would want a negotiation to reach the floor._');
|
|
187
|
+
out.push(row(['Score', 'Company', 'Role', 'Pay', 'Note']), row(['---', '---', '---', '---', '---']));
|
|
188
|
+
for (const n of stretch.slice(0, 25)) out.push(row([n.score, n.company, `[${n.title}](${n.url})`, n.salary || '', link(n)]));
|
|
189
|
+
}
|
|
190
|
+
out.push('');
|
|
191
|
+
out.push('## Active applications');
|
|
192
|
+
if (!active.length) out.push('_None yet._');
|
|
193
|
+
else {
|
|
194
|
+
out.push(row(['Status', 'Company', 'Role', 'Found', 'Note']), row(['---', '---', '---', '---', '---']));
|
|
195
|
+
for (const n of active) out.push(row([n.status, n.company, `[${n.title}](${n.url})`, n.found, link(n)]));
|
|
196
|
+
}
|
|
197
|
+
out.push('');
|
|
198
|
+
if (closedNew.length) {
|
|
199
|
+
out.push('## Listings that closed before review');
|
|
200
|
+
for (const n of closedNew.slice(0, 20)) out.push(`- ${n.company} — ${n.title} (${n.listing}) ${link(n)}`);
|
|
201
|
+
out.push('');
|
|
202
|
+
}
|
|
203
|
+
out.push('## Map');
|
|
204
|
+
out.push('- [[Profile/Profile]] · [[Profile/Resume - Master]] · [[Profile/Positioning]]');
|
|
205
|
+
out.push('- [[Targets/Search Criteria]] · [[Targets/Companies]]');
|
|
206
|
+
out.push('- [[Templates/Cover Letter]] · [[Templates/Outreach]] · [[Automation/README]]');
|
|
207
|
+
out.push('');
|
|
208
|
+
fs.writeFileSync(P.home, out.join('\n'));
|
|
209
|
+
return { newOpen: newOpen.length, active: active.length };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export { VAULT };
|