@lucasygu/yc-cli 0.1.0 → 0.2.0

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.
@@ -0,0 +1,82 @@
1
+ /**
2
+ * South Park Commons (SPC) application client.
3
+ *
4
+ * SPC uses Airtable Interface forms for applications.
5
+ * Since these are fully client-rendered SPAs, we use Playwright
6
+ * to navigate, fill, and submit the form programmatically.
7
+ *
8
+ * Field labels were extracted from the rendered form via Playwright
9
+ * and confirmed with getByLabel() — each label uniquely identifies its input.
10
+ *
11
+ * Important Airtable quirks:
12
+ * - Rich text fields use contenteditable="plaintext-only" divs
13
+ * - Location is a combobox with a search popup
14
+ * - "How did you hear" is a visible listbox with clickable options
15
+ * - Filling the "Which idea" field triggers progressive reveal of sub-questions
16
+ */
17
+ export declare const SPC_APP_ID = "appxDXHfPCZvb75qk";
18
+ export declare const SPC_FORMS: {
19
+ readonly founderFellowship: {
20
+ readonly pageId: "pagyqQLVvYMoPT9pg";
21
+ readonly url: "https://airtable.com/appxDXHfPCZvb75qk/pagyqQLVvYMoPT9pg/form";
22
+ readonly name: "Founder Fellowship";
23
+ readonly description: "For founders committed to starting a venture-scale company. $400K for 7% + $600K follow-on.";
24
+ };
25
+ readonly memberResidency: {
26
+ readonly pageId: "pagKjgMU7TbgeAYVb";
27
+ readonly url: "https://airtable.com/appxDXHfPCZvb75qk/pagKjgMU7TbgeAYVb/form";
28
+ readonly name: "Community Membership";
29
+ readonly description: "For technologists in the -1 to 0 phase. Up to 6 months exploring ideas at SPC.";
30
+ };
31
+ };
32
+ export type SpcFormType = keyof typeof SPC_FORMS;
33
+ export declare const HOW_HEARD_OPTIONS: readonly ["I am an SPC Member", "From an SPC Member", "From an SPC Team Member", "Internet Search", "LinkedIn", "X", "SPC Event", "Word of Mouth", "Other"];
34
+ export interface SpcFounder {
35
+ fullName: string;
36
+ email: string;
37
+ linkedin: string;
38
+ phone?: string;
39
+ }
40
+ export interface SpcApplication {
41
+ founders: SpcFounder[];
42
+ roles: string;
43
+ location: string;
44
+ howHeard: string;
45
+ howHeardElaborate?: string;
46
+ financingHistory?: string;
47
+ accomplishments: string;
48
+ riskiestDecision: string;
49
+ threeRecruits: string;
50
+ ideasRanked: string;
51
+ ideaDetail: string;
52
+ whyExcited?: string;
53
+ expertise?: string;
54
+ progress?: string;
55
+ demoLink?: string;
56
+ secondIdea?: string;
57
+ optionalChanges?: string;
58
+ backupIdeas?: string;
59
+ stayInTouch?: boolean;
60
+ }
61
+ export declare class SpcError extends Error {
62
+ constructor(message: string);
63
+ }
64
+ export interface SpcFillOptions {
65
+ formType?: SpcFormType;
66
+ headed?: boolean;
67
+ dryRun?: boolean;
68
+ slowMo?: number;
69
+ onStatus?: (msg: string) => void;
70
+ }
71
+ /**
72
+ * Fill the SPC Airtable form using Playwright.
73
+ *
74
+ * The form is filled in stages because Airtable progressively reveals
75
+ * new fields as earlier ones are completed. Each stage fills a group
76
+ * of fields, then waits for the form to potentially update.
77
+ */
78
+ export declare function fillSpcForm(application: SpcApplication, options?: SpcFillOptions): Promise<{
79
+ submitted: boolean;
80
+ screenshotPath?: string;
81
+ }>;
82
+ //# sourceMappingURL=spc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spc.d.ts","sourceRoot":"","sources":["../../src/lib/spc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,eAAO,MAAM,UAAU,sBAAsB,CAAC;AAE9C,eAAO,MAAM,SAAS;;;;;;;;;;;;;CAaZ,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,SAAS,CAAC;AAEjD,eAAO,MAAM,iBAAiB,6JAUpB,CAAC;AAIX,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAE7B,QAAQ,EAAE,UAAU,EAAE,CAAC;IAGvB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IAGjB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAG3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IAGtB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAID,qBAAa,QAAS,SAAQ,KAAK;gBACrB,OAAO,EAAE,MAAM;CAI5B;AAID,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,WAAW,EAAE,cAAc,EAC3B,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAoI1D"}
@@ -0,0 +1,240 @@
1
+ /**
2
+ * South Park Commons (SPC) application client.
3
+ *
4
+ * SPC uses Airtable Interface forms for applications.
5
+ * Since these are fully client-rendered SPAs, we use Playwright
6
+ * to navigate, fill, and submit the form programmatically.
7
+ *
8
+ * Field labels were extracted from the rendered form via Playwright
9
+ * and confirmed with getByLabel() — each label uniquely identifies its input.
10
+ *
11
+ * Important Airtable quirks:
12
+ * - Rich text fields use contenteditable="plaintext-only" divs
13
+ * - Location is a combobox with a search popup
14
+ * - "How did you hear" is a visible listbox with clickable options
15
+ * - Filling the "Which idea" field triggers progressive reveal of sub-questions
16
+ */
17
+ import { chromium } from "playwright";
18
+ // --- Constants ---
19
+ export const SPC_APP_ID = "appxDXHfPCZvb75qk";
20
+ export const SPC_FORMS = {
21
+ founderFellowship: {
22
+ pageId: "pagyqQLVvYMoPT9pg",
23
+ url: "https://airtable.com/appxDXHfPCZvb75qk/pagyqQLVvYMoPT9pg/form",
24
+ name: "Founder Fellowship",
25
+ description: "For founders committed to starting a venture-scale company. $400K for 7% + $600K follow-on.",
26
+ },
27
+ memberResidency: {
28
+ pageId: "pagKjgMU7TbgeAYVb",
29
+ url: "https://airtable.com/appxDXHfPCZvb75qk/pagKjgMU7TbgeAYVb/form",
30
+ name: "Community Membership",
31
+ description: "For technologists in the -1 to 0 phase. Up to 6 months exploring ideas at SPC.",
32
+ },
33
+ };
34
+ export const HOW_HEARD_OPTIONS = [
35
+ "I am an SPC Member",
36
+ "From an SPC Member",
37
+ "From an SPC Team Member",
38
+ "Internet Search",
39
+ "LinkedIn",
40
+ "X",
41
+ "SPC Event",
42
+ "Word of Mouth",
43
+ "Other",
44
+ ];
45
+ // --- Error ---
46
+ export class SpcError extends Error {
47
+ constructor(message) {
48
+ super(message);
49
+ this.name = "SpcError";
50
+ }
51
+ }
52
+ /**
53
+ * Fill the SPC Airtable form using Playwright.
54
+ *
55
+ * The form is filled in stages because Airtable progressively reveals
56
+ * new fields as earlier ones are completed. Each stage fills a group
57
+ * of fields, then waits for the form to potentially update.
58
+ */
59
+ export async function fillSpcForm(application, options = {}) {
60
+ const { formType = "founderFellowship", headed = false, dryRun = false, slowMo = 50, onStatus = () => { }, } = options;
61
+ const form = SPC_FORMS[formType];
62
+ const browser = await chromium.launch({ headless: !headed, slowMo });
63
+ try {
64
+ const page = await browser.newPage();
65
+ onStatus(`Navigating to ${form.name} form...`);
66
+ await page.goto(form.url, { waitUntil: "networkidle" });
67
+ // Wait for the form to render (Airtable SPA)
68
+ await page.waitForSelector("textarea, input", { timeout: 30000 });
69
+ onStatus("Form loaded. Filling fields...");
70
+ // === Stage 1: Contact & Team (textarea/input fields) ===
71
+ for (let i = 0; i < application.founders.length && i < 4; i++) {
72
+ const f = application.founders[i];
73
+ const n = i + 1;
74
+ await fillField(page, `Full Name (Founder #${n})`, f.fullName);
75
+ await fillField(page, `Email (Founder #${n})`, f.email);
76
+ await fillField(page, `LinkedIn (Founder #${n})`, f.linkedin);
77
+ if (f.phone) {
78
+ await fillField(page, `Phone number (Founder #${n})`, f.phone);
79
+ }
80
+ }
81
+ await fillField(page, "What roles do you", application.roles);
82
+ // Location combobox — special handling
83
+ await fillCombobox(page, application.location);
84
+ // How did you hear — visible listbox with clickable options
85
+ await selectListboxOption(page, application.howHeard);
86
+ if (application.howHeardElaborate) {
87
+ await fillField(page, "briefly elaborate", application.howHeardElaborate);
88
+ }
89
+ if (application.financingHistory) {
90
+ await fillField(page, "financing history", application.financingHistory);
91
+ }
92
+ onStatus("Stage 1 (contact & team) done.");
93
+ await page.waitForTimeout(500);
94
+ // === Stage 2: Background (contenteditable fields) ===
95
+ // These are rich text fields. We click to focus, then type via keyboard.
96
+ await fillRichText(page, "accomplishment", application.accomplishments);
97
+ await fillRichText(page, "riskiest decision", application.riskiestDecision);
98
+ await fillRichText(page, "three people you would recruit", application.threeRecruits);
99
+ onStatus("Stage 2 (background) done.");
100
+ await page.waitForTimeout(500);
101
+ // === Stage 3: Ideas (contenteditable fields) ===
102
+ await fillRichText(page, "List out the specific", application.ideasRanked);
103
+ await fillRichText(page, "Which idea from the list", application.ideaDetail);
104
+ // Wait for progressive reveal of idea sub-questions
105
+ await page.waitForTimeout(1500);
106
+ // Sub-questions that appear after filling "Which idea from the list"
107
+ if (application.whyExcited) {
108
+ await fillRichText(page, "Why are you excited", application.whyExcited);
109
+ }
110
+ if (application.expertise) {
111
+ await fillRichText(page, "What expertise do you have", application.expertise);
112
+ }
113
+ if (application.progress) {
114
+ await fillRichText(page, "What progress have you made", application.progress);
115
+ }
116
+ if (application.demoLink) {
117
+ await fillRichText(page, "Link us to something", application.demoLink);
118
+ }
119
+ if (application.secondIdea) {
120
+ await fillRichText(page, "another idea you have explored", application.secondIdea);
121
+ }
122
+ if (application.optionalChanges) {
123
+ await fillRichText(page, "did anything change", application.optionalChanges);
124
+ }
125
+ if (application.backupIdeas) {
126
+ await fillRichText(page, "none of your current ideas", application.backupIdeas);
127
+ }
128
+ onStatus("Stage 3 (ideas) done.");
129
+ // === Stage 4: Opt-in ===
130
+ if (application.stayInTouch) {
131
+ const checkbox = page.getByRole("checkbox");
132
+ if (await checkbox.count() > 0) {
133
+ await checkbox.first().check();
134
+ }
135
+ }
136
+ onStatus("All fields filled.");
137
+ // Screenshot for review
138
+ const screenshotPath = `/tmp/spc-form-${Date.now()}.png`;
139
+ await page.screenshot({ path: screenshotPath, fullPage: true });
140
+ onStatus(`Screenshot saved: ${screenshotPath}`);
141
+ if (dryRun) {
142
+ onStatus("Dry run — not submitting.");
143
+ return { submitted: false, screenshotPath };
144
+ }
145
+ // Submit
146
+ const submitBtn = page.getByRole("button", { name: /submit/i });
147
+ if (await submitBtn.count() > 0) {
148
+ await submitBtn.click();
149
+ await page.waitForTimeout(3000);
150
+ const afterScreenshot = `/tmp/spc-form-submitted-${Date.now()}.png`;
151
+ await page.screenshot({ path: afterScreenshot, fullPage: true });
152
+ onStatus("Form submitted!");
153
+ return { submitted: true, screenshotPath: afterScreenshot };
154
+ }
155
+ else {
156
+ throw new SpcError("Submit button not found");
157
+ }
158
+ }
159
+ finally {
160
+ await browser.close();
161
+ }
162
+ }
163
+ // --- Field helpers ---
164
+ /**
165
+ * Fill a standard text field (input or textarea) by partial label match.
166
+ */
167
+ async function fillField(page, labelSubstring, value) {
168
+ const locator = page.getByLabel(labelSubstring, { exact: false }).first();
169
+ if (await locator.count() === 0)
170
+ return;
171
+ await locator.fill(value);
172
+ }
173
+ /**
174
+ * Fill a rich text field (contenteditable div) by clicking and typing.
175
+ * Playwright's fill() works on contenteditable but can be unreliable
176
+ * in Airtable's SPA — click + keyboard.type is more robust.
177
+ */
178
+ async function fillRichText(page, labelSubstring, value) {
179
+ const locator = page.getByLabel(labelSubstring, { exact: false }).first();
180
+ if (await locator.count() === 0)
181
+ return;
182
+ await locator.click();
183
+ await page.waitForTimeout(100);
184
+ await page.keyboard.type(value, { delay: 5 });
185
+ // Click away to commit the value
186
+ await page.locator("body").click({ position: { x: 10, y: 10 } });
187
+ await page.waitForTimeout(100);
188
+ }
189
+ /**
190
+ * Handle Airtable's location combobox.
191
+ * Clicks the trigger, types in the search popup (input[type=search]),
192
+ * then selects from the controlled listbox (via aria-controls).
193
+ */
194
+ async function fillCombobox(page, value) {
195
+ const combobox = page.getByRole("combobox").first();
196
+ if (await combobox.count() === 0)
197
+ return;
198
+ await combobox.click();
199
+ await page.waitForTimeout(500);
200
+ // The search input is type="search" with placeholder="Find an option"
201
+ const searchInput = page.locator('input[type="search"]').first();
202
+ if (await searchInput.count() === 0)
203
+ return;
204
+ // Search with city name only (strip state/country after comma)
205
+ const searchTerm = value.split(",")[0].trim();
206
+ await searchInput.fill(searchTerm);
207
+ await page.waitForTimeout(800);
208
+ // Select from the controlled listbox (not the "How did you hear" listbox)
209
+ const listboxId = await searchInput.getAttribute("aria-controls");
210
+ if (listboxId) {
211
+ const option = page.locator(`[id="${listboxId}"] [role="option"]`).first();
212
+ if (await option.count() > 0) {
213
+ await option.click();
214
+ return;
215
+ }
216
+ }
217
+ // Fallback
218
+ await page.keyboard.press("Enter");
219
+ }
220
+ /**
221
+ * Select an option from Airtable's visible listbox.
222
+ * The "How did you hear" field renders all options as clickable items.
223
+ */
224
+ async function selectListboxOption(page, value) {
225
+ // The listbox options might conflict with combobox options, so scope to the listbox
226
+ const listbox = page.getByRole("listbox").first();
227
+ if (await listbox.count() === 0)
228
+ return;
229
+ const option = listbox.getByRole("option", { name: value, exact: true }).first();
230
+ if (await option.count() > 0) {
231
+ await option.click();
232
+ return;
233
+ }
234
+ // Fallback: find by text
235
+ const item = listbox.getByText(value, { exact: true }).first();
236
+ if (await item.count() > 0) {
237
+ await item.click();
238
+ }
239
+ }
240
+ //# sourceMappingURL=spc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spc.js","sourceRoot":"","sources":["../../src/lib/spc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,QAAQ,EAAa,MAAM,YAAY,CAAC;AAEjD,oBAAoB;AAEpB,MAAM,CAAC,MAAM,UAAU,GAAG,mBAAmB,CAAC;AAE9C,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,iBAAiB,EAAE;QACjB,MAAM,EAAE,mBAAmB;QAC3B,GAAG,EAAE,+DAA+D;QACpE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EAAE,6FAA6F;KAC3G;IACD,eAAe,EAAE;QACf,MAAM,EAAE,mBAAmB;QAC3B,GAAG,EAAE,+DAA+D;QACpE,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EAAE,gFAAgF;KAC9F;CACO,CAAC;AAIX,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,oBAAoB;IACpB,oBAAoB;IACpB,yBAAyB;IACzB,iBAAiB;IACjB,UAAU;IACV,GAAG;IACH,WAAW;IACX,eAAe;IACf,OAAO;CACC,CAAC;AA4CX,gBAAgB;AAEhB,MAAM,OAAO,QAAS,SAAQ,KAAK;IACjC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAYD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,WAA2B,EAC3B,UAA0B,EAAE;IAE5B,MAAM,EACJ,QAAQ,GAAG,mBAAmB,EAC9B,MAAM,GAAG,KAAK,EACd,MAAM,GAAG,KAAK,EACd,MAAM,GAAG,EAAE,EACX,QAAQ,GAAG,GAAG,EAAE,GAAE,CAAC,GACpB,GAAG,OAAO,CAAC;IAEZ,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAErE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QACrC,QAAQ,CAAC,iBAAiB,IAAI,CAAC,IAAI,UAAU,CAAC,CAAC;QAC/C,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC;QAExD,6CAA6C;QAC7C,MAAM,IAAI,CAAC,eAAe,CAAC,iBAAiB,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAClE,QAAQ,CAAC,gCAAgC,CAAC,CAAC;QAE3C,0DAA0D;QAE1D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9D,MAAM,CAAC,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YAClC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAChB,MAAM,SAAS,CAAC,IAAI,EAAE,uBAAuB,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;YAC/D,MAAM,SAAS,CAAC,IAAI,EAAE,mBAAmB,CAAC,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;YACxD,MAAM,SAAS,CAAC,IAAI,EAAE,sBAAsB,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;YAC9D,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;gBACZ,MAAM,SAAS,CAAC,IAAI,EAAE,0BAA0B,CAAC,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;QAED,MAAM,SAAS,CAAC,IAAI,EAAE,mBAAmB,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;QAE9D,uCAAuC;QACvC,MAAM,YAAY,CAAC,IAAI,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;QAE/C,4DAA4D;QAC5D,MAAM,mBAAmB,CAAC,IAAI,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;QAEtD,IAAI,WAAW,CAAC,iBAAiB,EAAE,CAAC;YAClC,MAAM,SAAS,CAAC,IAAI,EAAE,mBAAmB,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAAC;QAC5E,CAAC;QACD,IAAI,WAAW,CAAC,gBAAgB,EAAE,CAAC;YACjC,MAAM,SAAS,CAAC,IAAI,EAAE,mBAAmB,EAAE,WAAW,CAAC,gBAAgB,CAAC,CAAC;QAC3E,CAAC;QAED,QAAQ,CAAC,gCAAgC,CAAC,CAAC;QAC3C,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;QAE/B,uDAAuD;QACvD,yEAAyE;QAEzE,MAAM,YAAY,CAAC,IAAI,EAAE,gBAAgB,EAAE,WAAW,CAAC,eAAe,CAAC,CAAC;QACxE,MAAM,YAAY,CAAC,IAAI,EAAE,mBAAmB,EAAE,WAAW,CAAC,gBAAgB,CAAC,CAAC;QAC5E,MAAM,YAAY,CAAC,IAAI,EAAE,gCAAgC,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;QAEtF,QAAQ,CAAC,4BAA4B,CAAC,CAAC;QACvC,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;QAE/B,kDAAkD;QAElD,MAAM,YAAY,CAAC,IAAI,EAAE,uBAAuB,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;QAC3E,MAAM,YAAY,CAAC,IAAI,EAAE,0BAA0B,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;QAE7E,oDAAoD;QACpD,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAEhC,qEAAqE;QACrE,IAAI,WAAW,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,YAAY,CAAC,IAAI,EAAE,qBAAqB,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;QAC1E,CAAC;QACD,IAAI,WAAW,CAAC,SAAS,EAAE,CAAC;YAC1B,MAAM,YAAY,CAAC,IAAI,EAAE,4BAA4B,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;QAChF,CAAC;QACD,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;YACzB,MAAM,YAAY,CAAC,IAAI,EAAE,6BAA6B,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;QAChF,CAAC;QACD,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;YACzB,MAAM,YAAY,CAAC,IAAI,EAAE,sBAAsB,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;QACzE,CAAC;QAED,IAAI,WAAW,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,YAAY,CAAC,IAAI,EAAE,gCAAgC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;QACrF,CAAC;QACD,IAAI,WAAW,CAAC,eAAe,EAAE,CAAC;YAChC,MAAM,YAAY,CAAC,IAAI,EAAE,qBAAqB,EAAE,WAAW,CAAC,eAAe,CAAC,CAAC;QAC/E,CAAC;QACD,IAAI,WAAW,CAAC,WAAW,EAAE,CAAC;YAC5B,MAAM,YAAY,CAAC,IAAI,EAAE,4BAA4B,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;QAClF,CAAC;QAED,QAAQ,CAAC,uBAAuB,CAAC,CAAC;QAElC,0BAA0B;QAE1B,IAAI,WAAW,CAAC,WAAW,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YAC5C,IAAI,MAAM,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC;gBAC/B,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC;YACjC,CAAC;QACH,CAAC;QAED,QAAQ,CAAC,oBAAoB,CAAC,CAAC;QAE/B,wBAAwB;QACxB,MAAM,cAAc,GAAG,iBAAiB,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC;QACzD,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,QAAQ,CAAC,qBAAqB,cAAc,EAAE,CAAC,CAAC;QAEhD,IAAI,MAAM,EAAE,CAAC;YACX,QAAQ,CAAC,2BAA2B,CAAC,CAAC;YACtC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC;QAC9C,CAAC;QAED,SAAS;QACT,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QAChE,IAAI,MAAM,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC;YAChC,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;YACxB,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;YAChC,MAAM,eAAe,GAAG,2BAA2B,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC;YACpE,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YACjE,QAAQ,CAAC,iBAAiB,CAAC,CAAC;YAC5B,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,eAAe,EAAE,CAAC;QAC9D,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,QAAQ,CAAC,yBAAyB,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC;AAED,wBAAwB;AAExB;;GAEG;AACH,KAAK,UAAU,SAAS,CAAC,IAAU,EAAE,cAAsB,EAAE,KAAa;IACxE,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IAC1E,IAAI,MAAM,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;QAAE,OAAO;IACxC,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,YAAY,CAAC,IAAU,EAAE,cAAsB,EAAE,KAAa;IAC3E,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IAC1E,IAAI,MAAM,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;QAAE,OAAO;IAExC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACtB,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IAC9C,iCAAiC;IACjC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACjE,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,YAAY,CAAC,IAAU,EAAE,KAAa;IACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,CAAC;IACpD,IAAI,MAAM,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;QAAE,OAAO;IAEzC,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;IACvB,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IAE/B,sEAAsE;IACtE,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC,KAAK,EAAE,CAAC;IACjE,IAAI,MAAM,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC;QAAE,OAAO;IAE5C,+DAA+D;IAC/D,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,MAAM,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACnC,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IAE/B,0EAA0E;IAC1E,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;IAClE,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,SAAS,oBAAoB,CAAC,CAAC,KAAK,EAAE,CAAC;QAC3E,IAAI,MAAM,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACrB,OAAO;QACT,CAAC;IACH,CAAC;IAED,WAAW;IACX,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,mBAAmB,CAAC,IAAU,EAAE,KAAa;IAC1D,oFAAoF;IACpF,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,CAAC;IAClD,IAAI,MAAM,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;QAAE,OAAO;IAExC,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IACjF,IAAI,MAAM,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO;IACT,CAAC;IAED,yBAAyB;IACzB,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IAC/D,IAAI,MAAM,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;AACH,CAAC"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * a16z Speedrun API client.
3
+ *
4
+ * No authentication required — all endpoints are plain JSON POSTs
5
+ * to Next.js API routes at speedrun.a16z.com.
6
+ */
7
+ export interface SpeedrunCeo {
8
+ first_name: string;
9
+ last_name: string;
10
+ email: string;
11
+ phone_number: string;
12
+ city: string;
13
+ state?: string;
14
+ country: string;
15
+ citizenship: string;
16
+ college: string;
17
+ highest_education: string;
18
+ years_of_experience: number;
19
+ is_technical: boolean;
20
+ linkedin_url: string;
21
+ github_url?: string;
22
+ x_url?: string;
23
+ portfolio_url?: string;
24
+ }
25
+ export interface SpeedrunCofounder {
26
+ first_name: string;
27
+ last_name: string;
28
+ email: string;
29
+ phone_number?: string;
30
+ linkedin_url: string;
31
+ }
32
+ export interface SpeedrunInvestor {
33
+ name: string;
34
+ email: string;
35
+ amount_usd?: number;
36
+ }
37
+ export interface SpeedrunFunding {
38
+ funding_total_usd: number;
39
+ post_money_valuation_usd: number;
40
+ burn_monthly_usd: number;
41
+ runway_months: number;
42
+ investors: SpeedrunInvestor[];
43
+ }
44
+ export interface SpeedrunFundraise {
45
+ fundraising_target_amount_usd: number;
46
+ fundraising_start_date: string;
47
+ fundraising_target_description: string;
48
+ }
49
+ export interface SpeedrunUserMetrics {
50
+ daily_active_users: number;
51
+ weekly_active_users: number;
52
+ monthly_active_users: number;
53
+ user_growth_rate_monthly: number;
54
+ }
55
+ export interface SpeedrunRetentionMetrics {
56
+ d1_retention: number;
57
+ d7_retention: number;
58
+ d30_retention: number;
59
+ m1_retention: number;
60
+ }
61
+ export interface SpeedrunRevenueMetrics {
62
+ annual_recurring_revenue_usd: number;
63
+ avg_annual_contract_value_usd: number;
64
+ net_dollar_retention: number;
65
+ revenue_growth_rate_monthly: number;
66
+ }
67
+ export interface SpeedrunMetrics {
68
+ launch_date: string;
69
+ user_metrics?: SpeedrunUserMetrics;
70
+ retention_metrics?: SpeedrunRetentionMetrics;
71
+ revenue_metrics?: SpeedrunRevenueMetrics;
72
+ metrics_description?: string;
73
+ }
74
+ export interface SpeedrunReferral {
75
+ name: string;
76
+ email: string;
77
+ linkedin_url: string;
78
+ }
79
+ export interface SpeedrunApplication {
80
+ company_name: string;
81
+ one_liner: string;
82
+ company_description: string;
83
+ primary_category: string;
84
+ secondary_category: string;
85
+ company_city: string;
86
+ company_state?: string;
87
+ company_country: string;
88
+ founding_date: string;
89
+ website_url?: string;
90
+ other_description?: string;
91
+ is_full_time: boolean;
92
+ num_full_time_founders: string;
93
+ num_full_time_employees: number;
94
+ team_description: string;
95
+ ceo: SpeedrunCeo;
96
+ other_founders: SpeedrunCofounder[];
97
+ deck_gcs_url?: string;
98
+ has_funding: boolean;
99
+ funding?: SpeedrunFunding;
100
+ is_fundraising: boolean;
101
+ current_fundraise?: SpeedrunFundraise;
102
+ has_metrics: boolean;
103
+ metrics?: SpeedrunMetrics;
104
+ has_referral: boolean;
105
+ referral?: SpeedrunReferral;
106
+ learned_about_speedrun?: string;
107
+ }
108
+ export declare const CATEGORIES: readonly ["B2B / Enterprise Applications", "Consumer Applications", "Deep Tech", "Gaming / Entertainment Studio", "Infrastructure / Dev Tools", "Healthcare", "GovTech", "Web3", "Other"];
109
+ export declare const EDUCATION_LEVELS: readonly ["High School Degree", "Bachelor's Degree (BA, BS)", "Master's / Professional Degree (MD, MBA, JD, etc.)", "Doctoral Degree (PhD)"];
110
+ export declare class SpeedrunApiError extends Error {
111
+ statusCode?: number | undefined;
112
+ response?: string | undefined;
113
+ constructor(message: string, statusCode?: number | undefined, response?: string | undefined);
114
+ }
115
+ export declare class SpeedrunClient {
116
+ submitEmail(email: string): Promise<unknown>;
117
+ submitApplication(application: SpeedrunApplication): Promise<unknown>;
118
+ getUploadUrl(fileType: string, expectedSizeBytes: number, applicationId?: string): Promise<{
119
+ url: string;
120
+ [key: string]: unknown;
121
+ }>;
122
+ uploadFile(url: string, file: Uint8Array, contentType: string): Promise<void>;
123
+ submitVideo(data: Record<string, unknown>): Promise<unknown>;
124
+ }
125
+ //# sourceMappingURL=speedrun.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speedrun.d.ts","sourceRoot":"","sources":["../../src/lib/speedrun.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * a16z Speedrun API client.
3
+ *
4
+ * No authentication required — all endpoints are plain JSON POSTs
5
+ * to Next.js API routes at speedrun.a16z.com.
6
+ */
7
+ const BASE_URL = "https://speedrun.a16z.com";
8
+ export const CATEGORIES = [
9
+ "B2B / Enterprise Applications",
10
+ "Consumer Applications",
11
+ "Deep Tech",
12
+ "Gaming / Entertainment Studio",
13
+ "Infrastructure / Dev Tools",
14
+ "Healthcare",
15
+ "GovTech",
16
+ "Web3",
17
+ "Other",
18
+ ];
19
+ export const EDUCATION_LEVELS = [
20
+ "High School Degree",
21
+ "Bachelor's Degree (BA, BS)",
22
+ "Master's / Professional Degree (MD, MBA, JD, etc.)",
23
+ "Doctoral Degree (PhD)",
24
+ ];
25
+ // --- Error ---
26
+ export class SpeedrunApiError extends Error {
27
+ statusCode;
28
+ response;
29
+ constructor(message, statusCode, response) {
30
+ super(message);
31
+ this.statusCode = statusCode;
32
+ this.response = response;
33
+ this.name = "SpeedrunApiError";
34
+ }
35
+ }
36
+ // --- Client ---
37
+ export class SpeedrunClient {
38
+ async submitEmail(email) {
39
+ const res = await fetch(`${BASE_URL}/api/apply/submit_email`, {
40
+ method: "POST",
41
+ headers: { "Content-Type": "application/json" },
42
+ body: JSON.stringify({ email }),
43
+ });
44
+ if (!res.ok) {
45
+ const text = await res.text().catch(() => res.statusText);
46
+ throw new SpeedrunApiError(`Email submission failed: ${res.status}`, res.status, text);
47
+ }
48
+ return res.json();
49
+ }
50
+ async submitApplication(application) {
51
+ const res = await fetch(`${BASE_URL}/api/apply/submit-application`, {
52
+ method: "POST",
53
+ headers: { "Content-Type": "application/json" },
54
+ body: JSON.stringify(application),
55
+ });
56
+ if (!res.ok) {
57
+ const body = await res.json().catch(() => ({ message: res.statusText }));
58
+ throw new SpeedrunApiError(`Application submission failed: ${body.message || "Unknown error"}`, res.status, JSON.stringify(body));
59
+ }
60
+ return res.json();
61
+ }
62
+ async getUploadUrl(fileType, expectedSizeBytes, applicationId) {
63
+ const body = {
64
+ file_type: fileType,
65
+ expected_size_bytes: expectedSizeBytes,
66
+ };
67
+ if (applicationId)
68
+ body.application_id = applicationId;
69
+ const res = await fetch(`${BASE_URL}/api/apply/get-upload-url`, {
70
+ method: "POST",
71
+ headers: { "Content-Type": "application/json" },
72
+ body: JSON.stringify(body),
73
+ });
74
+ if (!res.ok) {
75
+ throw new SpeedrunApiError(`Failed to get upload URL: ${res.statusText}`, res.status);
76
+ }
77
+ return res.json();
78
+ }
79
+ async uploadFile(url, file, contentType) {
80
+ const blob = new Blob([file], { type: contentType });
81
+ const res = await fetch(url, {
82
+ method: "PUT",
83
+ headers: { "Content-Type": contentType },
84
+ body: blob,
85
+ });
86
+ if (!res.ok) {
87
+ const text = await res.text().catch(() => res.statusText);
88
+ throw new SpeedrunApiError(`Upload failed: ${res.status}`, res.status, text);
89
+ }
90
+ }
91
+ async submitVideo(data) {
92
+ const res = await fetch(`${BASE_URL}/api/apply/submit_video`, {
93
+ method: "POST",
94
+ headers: { "Content-Type": "application/json" },
95
+ body: JSON.stringify(data),
96
+ });
97
+ if (!res.ok) {
98
+ const body = await res.json().catch(() => ({ message: res.statusText }));
99
+ throw new SpeedrunApiError(`Video submission failed: ${body.message || "Unknown error"}`, res.status);
100
+ }
101
+ return res.json();
102
+ }
103
+ }
104
+ //# sourceMappingURL=speedrun.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speedrun.js","sourceRoot":"","sources":["../../src/lib/speedrun.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lucasygu/yc-cli",
3
- "version": "0.1.0",
4
- "description": "CLI tool for Y Combinator Startup School — submit weekly updates, track progress, manage your YC journey from the terminal",
3
+ "version": "0.2.0",
4
+ "description": "CLI for YC Startup School + a16z Speedrun — weekly updates, dashboard, applications from the terminal",
5
5
  "type": "module",
6
6
  "main": "./dist/lib/client.js",
7
7
  "exports": {
@@ -33,6 +33,8 @@
33
33
  "ycombinator",
34
34
  "yc",
35
35
  "startup-school",
36
+ "a16z",
37
+ "speedrun",
36
38
  "cli",
37
39
  "claude-code",
38
40
  "claude-code-skill"
@@ -49,7 +51,8 @@
49
51
  "dependencies": {
50
52
  "@steipete/sweet-cookie": "^0.1.0",
51
53
  "commander": "^13.1.0",
52
- "kleur": "^4.1.5"
54
+ "kleur": "^4.1.5",
55
+ "playwright": "^1.58.2"
53
56
  },
54
57
  "devDependencies": {
55
58
  "@types/node": "^22.0.0",