founder-summit-apply 1.0.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.
- package/README.md +20 -0
- package/bin/cli.js +113 -0
- package/package.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# founder-summit-apply
|
|
2
|
+
|
|
3
|
+
Apply to the **2026 Miami Founder Summit** from your terminal.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npx founder-summit-apply
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
It asks a few quick questions, then submits your application. Prefer a browser? Everything also lives at **https://foundersummit.miami**.
|
|
10
|
+
|
|
11
|
+
## How it works
|
|
12
|
+
|
|
13
|
+
The CLI is a thin front door. It fetches the question list from the Summit's backend and submits your answers there — the same backend the website uses. No credentials live in this package; the application data is handled server-side.
|
|
14
|
+
|
|
15
|
+
- Endpoint (override for testing): `FS_APPLY_ENDPOINT`
|
|
16
|
+
- Requires Node.js 18+
|
|
17
|
+
|
|
18
|
+
## License
|
|
19
|
+
|
|
20
|
+
MIT
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Apply to the 2026 Miami Founder Summit from your terminal.
|
|
3
|
+
// The terminal "front door" — it fetches the same question schema the website uses
|
|
4
|
+
// and submits to the same backend. No secrets here; the Airtable token lives only
|
|
5
|
+
// on the server (foundersummit.miami/api/founder-summit-apply).
|
|
6
|
+
|
|
7
|
+
import { input, select, confirm } from "@inquirer/prompts";
|
|
8
|
+
|
|
9
|
+
const ENDPOINT = process.env.FS_APPLY_ENDPOINT || "https://foundersummit.miami/api/founder-summit-apply";
|
|
10
|
+
const FORM_URL = "https://airtable.com/appcdpMJ1zBrvTpcA/pagV9p7bR8hm1pucd/form";
|
|
11
|
+
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
12
|
+
|
|
13
|
+
const pink = (s) => `\x1b[38;5;213m${s}\x1b[0m`;
|
|
14
|
+
const dim = (s) => `\x1b[2m${s}\x1b[0m`;
|
|
15
|
+
const bold = (s) => `\x1b[1m${s}\x1b[0m`;
|
|
16
|
+
const green = (s) => `\x1b[32m${s}\x1b[0m`;
|
|
17
|
+
|
|
18
|
+
async function getQuestions() {
|
|
19
|
+
const res = await fetch(ENDPOINT, { headers: { accept: "application/json" } });
|
|
20
|
+
const data = await res.json();
|
|
21
|
+
if (!data || !Array.isArray(data.questions) || !data.questions.length) {
|
|
22
|
+
throw new Error("empty schema");
|
|
23
|
+
}
|
|
24
|
+
return data.questions;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function run() {
|
|
28
|
+
console.log();
|
|
29
|
+
console.log(" " + bold(pink("Apply to the 2026 Miami Founder Summit")));
|
|
30
|
+
console.log(" " + dim("September 25th, 2026 · 1.30-6pm ET · The LAB Miami"));
|
|
31
|
+
console.log();
|
|
32
|
+
|
|
33
|
+
let questions;
|
|
34
|
+
try {
|
|
35
|
+
questions = await getQuestions();
|
|
36
|
+
} catch {
|
|
37
|
+
console.error(" " + dim(`Couldn't reach the application server. Apply here instead:`));
|
|
38
|
+
console.error(" " + FORM_URL + "\n");
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const total = questions.length;
|
|
43
|
+
const answers = {};
|
|
44
|
+
for (let i = 0; i < total; i++) {
|
|
45
|
+
const q = questions[i];
|
|
46
|
+
const message = `${q.label} ${dim(`(${i + 1}/${total})`)}`;
|
|
47
|
+
if (q.type === "select") {
|
|
48
|
+
answers[q.key] = await select({
|
|
49
|
+
message,
|
|
50
|
+
choices: q.choices.map((c) => ({ name: c, value: c })),
|
|
51
|
+
loop: false,
|
|
52
|
+
});
|
|
53
|
+
} else {
|
|
54
|
+
const v = await input({
|
|
55
|
+
message,
|
|
56
|
+
validate: (val) => {
|
|
57
|
+
val = (val || "").trim();
|
|
58
|
+
if (q.required && !val) return `${q.label} is required.`;
|
|
59
|
+
if (val && q.format === "email" && !EMAIL_RE.test(val)) return "Please enter a valid email.";
|
|
60
|
+
return true;
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
answers[q.key] = (v || "").trim();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
console.log();
|
|
68
|
+
const go = await confirm({ message: "Submit your application?", default: true });
|
|
69
|
+
if (!go) {
|
|
70
|
+
console.log(" " + dim("Cancelled. Nothing was submitted."));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
process.stdout.write(" " + dim("Submitting... "));
|
|
75
|
+
let res, data;
|
|
76
|
+
try {
|
|
77
|
+
res = await fetch(ENDPOINT, {
|
|
78
|
+
method: "POST",
|
|
79
|
+
headers: { "content-type": "application/json" },
|
|
80
|
+
body: JSON.stringify(answers),
|
|
81
|
+
});
|
|
82
|
+
data = await res.json().catch(() => null);
|
|
83
|
+
} catch {
|
|
84
|
+
console.log();
|
|
85
|
+
console.error(" " + dim(`Couldn't reach the server. Apply at ${FORM_URL}`));
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (res.ok && data && data.ok) {
|
|
90
|
+
console.log(green("done"));
|
|
91
|
+
console.log();
|
|
92
|
+
console.log(" " + green("✓") + " Application submitted. Thank you.");
|
|
93
|
+
console.log(" " + dim("We'll be in touch."));
|
|
94
|
+
console.log();
|
|
95
|
+
} else {
|
|
96
|
+
console.log();
|
|
97
|
+
const msg = (data && (data.error || (data.details && data.details.join(" ")))) || "Something went wrong.";
|
|
98
|
+
console.error(" " + msg);
|
|
99
|
+
console.error(" " + dim(`You can also apply at ${FORM_URL}`));
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
run().catch((err) => {
|
|
105
|
+
// graceful Ctrl+C / closed prompt
|
|
106
|
+
const m = (err && (err.name || err.message || "")) + "";
|
|
107
|
+
if (m.includes("ExitPromptError") || m.includes("force closed")) {
|
|
108
|
+
console.log("\n " + dim("Cancelled."));
|
|
109
|
+
process.exit(0);
|
|
110
|
+
}
|
|
111
|
+
console.error(err);
|
|
112
|
+
process.exit(1);
|
|
113
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "founder-summit-apply",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Apply to the 2026 Miami Founder Summit from your terminal.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"founder-summit-apply": "bin/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin"
|
|
11
|
+
],
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=18"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@inquirer/prompts": "^7.2.0"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"founder-summit",
|
|
20
|
+
"miami",
|
|
21
|
+
"founders",
|
|
22
|
+
"apply",
|
|
23
|
+
"cli"
|
|
24
|
+
],
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"author": "Focal VC",
|
|
27
|
+
"homepage": "https://foundersummit.miami"
|
|
28
|
+
}
|