@vatvaghool/create-ipl-dashboard 0.1.12 → 0.1.14

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 CHANGED
@@ -6,7 +6,7 @@ Scaffold a full-featured IPL fantasy cricket dashboard in seconds.
6
6
  npx @vatvaghool/create-ipl-dashboard my-league
7
7
  ```
8
8
 
9
- Follow the prompts to enter your MongoDB URI, fantasy league URL, and team names — then get a ready-to-run Next.js dashboard with standings charts, performance trackers, AI roasts, and more.
9
+ Follow the prompts to enter your MongoDB URI, fantasy league URL, collection name, and team names — you get a ready-to-run Next.js dashboard with standings charts, performance trackers, AI roasts, and more.
10
10
 
11
11
  ## Usage
12
12
 
@@ -26,11 +26,12 @@ npx @vatvaghool/create-ipl-dashboard [project-name] [options]
26
26
 
27
27
  | Prompt | Description |
28
28
  |--------|-------------|
29
- | MongoDB URI | Your main app database connection string (or leave blank for file-based fallback) |
29
+ | Project name | Directory to scaffold into |
30
+ | MongoDB URI | Your MongoDB connection string (press Enter for a default) |
30
31
  | League URL | The fantasy.iplt20.com league page URL |
31
- | League DB URI | Separate database for league registry (optional — creates a collection per league) |
32
- | League name | Display name for your league (used as the collection name in the league DB) |
33
- | Teams | Team names (and optional owners) in your league |
32
+ | Collection name | MongoDB collection to store this league's data (e.g. `ipl_2025_office_league`) |
33
+ | League name | Display name for your league |
34
+ | Teams | Team names (and optional owners) in your league
34
35
 
35
36
  If `--scrape` is provided, the CLI attempts to extract team names from the league page HTML. If that fails, it falls back to manual entry.
36
37
 
@@ -71,7 +72,7 @@ A full Next.js 16 project with:
71
72
  - **AI roasting** — generated commentary in multiple languages
72
73
  - **Stock ticker** — fantasy stocks with sparklines
73
74
  - **Live updates** — bookmarklet or Playwright scraper for live sync
74
- - **MongoDB persistence** — optional, with file-based fallback for dev
75
+ - **MongoDB persistence** — auto-configured database connection
75
76
 
76
77
  ## Quick start after scaffold
77
78
 
@@ -95,11 +96,39 @@ Open http://localhost:3000 to see your dashboard.
95
96
  The CLI:
96
97
 
97
98
  1. Copies a pre-built Next.js app template
98
- 2. Writes your `.env` with MongoDB URI, league DB URI, league URL, and league name
99
+ 2. Writes your `.env` with the `MONGODB_URI`, `COLLECTION_NAME`, league URL, and league name
99
100
  3. Generates `app/data/teams.ts` with your team roster
100
101
  4. Generates `app/data/league.ts` with league metadata
101
102
  5. Creates a placeholder `app/data/match-points.ts` (auto-populates as you sync)
102
103
  6. Installs dependencies
103
- 7. If a league DB URI was provided, runs `seed:league` to create a **collection named after your league** in that database, storing league metadata (name, URL, teams, timestamps)
104
+ 7. Runs `seed:league` to create a **document in your specified collection** in the pre-configured database, storing league metadata (name, URL, teams, timestamps)
105
+
106
+ Each league gets its own collection — run `create-ipl-dashboard` again with a different collection name to add another league.
104
107
 
105
108
  The template includes all dashboard components, API endpoints, scrapers, and tests from the [ipl-dashboard](https://github.com/anomalyco/ipl-dashboard) project.
109
+
110
+ ---
111
+
112
+ ## Next Steps
113
+
114
+ ### Adding more leagues
115
+
116
+ ```bash
117
+ npx @vatvaghool/create-ipl-dashboard another-league
118
+ ```
119
+
120
+ Provide a different collection name (e.g. `ipl_2025_friends_league`) and the new league will be stored in its own collection — data stays fully isolated.
121
+
122
+ ### Viewing seeded data
123
+
124
+ Connect to the MongoDB instance with any MongoDB client. Each league appears as a separate collection containing a document with `type: "league"` and all the metadata (name, URL, teams, timestamps).
125
+
126
+ ### Production deployment
127
+
128
+ ```bash
129
+ cd my-league
130
+ npm run build
131
+ npx vercel --prod
132
+ ```
133
+
134
+ Set `IPL_POST_SECRET` in your Vercel dashboard. The `MONGODB_URI` and `COLLECTION_NAME` are already populated in the scaffolded `.env`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vatvaghool/create-ipl-dashboard",
3
- "version": "0.1.12",
3
+ "version": "0.1.14",
4
4
  "description": "Scaffold an IPL fantasy cricket dashboard project",
5
5
  "type": "module",
6
6
  "bin": {
package/src/index.mjs CHANGED
@@ -3,10 +3,12 @@
3
3
  import { join } from "node:path";
4
4
  import { existsSync } from "node:fs";
5
5
  import { mkdir } from "node:fs/promises";
6
- import { getProjectName, getMongoUri, getLeagueUrl, getLeagueDbUri, getLeagueName, getTeams, close } from "./prompts.mjs";
6
+ import { getProjectName, getMongoUri, getLeagueUrl, getCollectionName, getLeagueName, getTeams, close } from "./prompts.mjs";
7
7
  import { scaffoldProject } from "./scaffold.mjs";
8
8
  import { scrapeTeamsFromUrl } from "./scraper.mjs";
9
9
 
10
+ const DEFAULT_MONGODB_URI = "mongodb+srv://admin:admin@cricket.ptjjrub.mongodb.net/?appName=cricket";
11
+
10
12
  function printHelp(exitCode) {
11
13
  console.log(`
12
14
  create-ipl-dashboard [project-name] [options]
@@ -59,9 +61,9 @@ async function main() {
59
61
 
60
62
  await mkdir(projectPath, { recursive: true });
61
63
 
62
- const mongoUri = await getMongoUri();
64
+ const mongoUri = await getMongoUri(DEFAULT_MONGODB_URI);
63
65
  const leagueUrl = await getLeagueUrl();
64
- const leagueDbUri = await getLeagueDbUri();
66
+ const collectionName = await getCollectionName();
65
67
  const leagueName = await getLeagueName();
66
68
  let teams;
67
69
 
@@ -80,7 +82,7 @@ async function main() {
80
82
 
81
83
  close();
82
84
 
83
- await scaffoldProject(projectPath, { mongoUri, leagueUrl, leagueDbUri, leagueName, teams, skipInstall: flags.skipInstall });
85
+ await scaffoldProject(projectPath, { mongoUri, leagueUrl, collectionName, leagueName, teams, skipInstall: flags.skipInstall });
84
86
 
85
87
  console.log("");
86
88
  console.log(" Next steps:");
package/src/prompts.mjs CHANGED
@@ -33,12 +33,13 @@ export async function getProjectName(args) {
33
33
  return (await prompt("Project name: ")).trim() || "ipl-dashboard";
34
34
  }
35
35
 
36
- export async function getMongoUri() {
36
+ export async function getMongoUri(defaultUri) {
37
37
  if (!isTTY) {
38
38
  await consumeAllLines();
39
- return (pipedLines[promptIndex++] || "").trim();
39
+ return (pipedLines[promptIndex++] || defaultUri || "").trim();
40
40
  }
41
- return (await prompt("MongoDB URI (or press Enter to skip, can be set later): ")).trim();
41
+ const answer = (await prompt(`MongoDB URI (press Enter for default): `)).trim();
42
+ return answer || defaultUri || "";
42
43
  }
43
44
 
44
45
  export async function getLeagueUrl() {
@@ -49,12 +50,12 @@ export async function getLeagueUrl() {
49
50
  return (await prompt("IPL fantasy league URL (or press Enter to skip, can be set later): ")).trim();
50
51
  }
51
52
 
52
- export async function getLeagueDbUri() {
53
+ export async function getCollectionName() {
53
54
  if (!isTTY) {
54
55
  await consumeAllLines();
55
- return (pipedLines[promptIndex++] || "").trim();
56
+ return (pipedLines[promptIndex++] || "league_data").trim();
56
57
  }
57
- return (await prompt("League DB URI (separate database for league registry, press Enter to skip): ")).trim();
58
+ return (await prompt("MongoDB collection name for league data (e.g. ipl_2025_office_league): ")).trim() || "league_data";
58
59
  }
59
60
 
60
61
  export async function getLeagueName() {
package/src/scaffold.mjs CHANGED
@@ -8,7 +8,10 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
8
8
  const PACKAGE_ROOT = join(__dirname, "..");
9
9
  const TEMPLATE_DIR = join(PACKAGE_ROOT, "template");
10
10
 
11
- export async function scaffoldProject(projectPath, { mongoUri, leagueUrl, leagueDbUri, leagueName, teams, skipInstall = false }) {
11
+ export async function scaffoldProject(
12
+ projectPath,
13
+ { mongoUri, leagueUrl, collectionName, leagueName, teams, skipInstall = false },
14
+ ) {
12
15
  console.log(`\nCreating project at ${projectPath}...`);
13
16
 
14
17
  await mkdir(projectPath, { recursive: true });
@@ -19,44 +22,69 @@ export async function scaffoldProject(projectPath, { mongoUri, leagueUrl, league
19
22
  console.log(" (no template directory found, generating from scratch)");
20
23
  }
21
24
 
22
- for (const f of ["AGENTS.md", "tsconfig.tsbuildinfo", "tsconfig.buildinfo", "package-lock.json"]) {
23
- try { await rm(join(projectPath, f)); } catch {}
25
+ for (const f of [
26
+ "AGENTS.md",
27
+ "tsconfig.tsbuildinfo",
28
+ "tsconfig.buildinfo",
29
+ "package-lock.json",
30
+ ]) {
31
+ try {
32
+ await rm(join(projectPath, f));
33
+ } catch {}
24
34
  }
25
35
 
26
- await writeEnvFile(projectPath, { mongoUri, leagueUrl, leagueDbUri, leagueName });
36
+ await writeEnvFile(projectPath, {
37
+ mongoUri,
38
+ leagueUrl,
39
+ collectionName,
40
+ leagueName,
41
+ });
27
42
  await writeTeamData(projectPath, teams);
28
43
  await writeLeagueData(projectPath, { leagueName, leagueUrl, teams });
29
44
  await writeMatchPointsPlaceholder(projectPath);
30
45
  await updatePackageJson(projectPath);
31
46
 
32
- for (const f of ["app/api/ipl/live-snapshot.json", "app/api/ipl/transfers/live-snapshot.json"]) {
33
- try { await rm(join(projectPath, f)); } catch {}
47
+ for (const f of [
48
+ "app/api/ipl/live-snapshot.json",
49
+ "app/api/ipl/transfers/live-snapshot.json",
50
+ ]) {
51
+ try {
52
+ await rm(join(projectPath, f));
53
+ } catch {}
34
54
  }
35
55
 
36
56
  if (!skipInstall) {
37
57
  console.log(" Running npm install...");
38
58
  execSync("npm install", { cwd: projectPath, stdio: "inherit" });
39
59
 
40
- if (leagueDbUri && leagueName) {
60
+ if (mongoUri && leagueName) {
41
61
  console.log(" Seeding league metadata into MongoDB...");
42
62
  try {
43
- execSync(`npm run seed:league -- "${leagueName}"`, { cwd: projectPath, stdio: "inherit" });
63
+ execSync(`npm run seed:league -- "${leagueName}" "${collectionName}"`, {
64
+ cwd: projectPath,
65
+ stdio: "inherit",
66
+ });
44
67
  } catch {
45
68
  console.log(" League seed skipped (MongoDB may not be reachable yet)");
46
69
  }
47
70
  }
48
71
  } else {
49
- console.log(" Skipping npm install (run manually: cd <project> && npm install)");
72
+ console.log(
73
+ " Skipping npm install (run manually: cd <project> && npm install)",
74
+ );
50
75
  }
51
76
 
52
77
  console.log("\n Done! Your project is ready at:", projectPath);
53
78
  }
54
79
 
55
- async function writeEnvFile(projectPath, { mongoUri, leagueUrl, leagueDbUri, leagueName }) {
80
+ async function writeEnvFile(
81
+ projectPath,
82
+ { mongoUri, leagueUrl, collectionName, leagueName },
83
+ ) {
56
84
  const envPath = join(projectPath, ".env");
57
85
  const lines = [
58
86
  `MONGODB_URI=${mongoUri || ""}`,
59
- `LEAGUE_DB_URI=${leagueDbUri || ""}`,
87
+ `COLLECTION_NAME=${collectionName || "league_data"}`,
60
88
  `IPL_LEAGUE_URL=${leagueUrl || ""}`,
61
89
  `IPL_LEAGUE_NAME=${leagueName || ""}`,
62
90
  `IPL_POST_SECRET=`,
@@ -115,7 +143,7 @@ async function writeLeagueData(projectPath, { leagueName, leagueUrl, teams }) {
115
143
  await mkdir(dir, { recursive: true });
116
144
 
117
145
  const teamEntries = teams
118
- .map((t, i) => ` { id: ${t.id}, name: "${t.name}", owner: "${t.owner}" }`)
146
+ .map((t) => ` { id: ${t.id}, name: "${t.name}", owner: "${t.owner}" }`)
119
147
  .join(",\n");
120
148
 
121
149
  const content = `export type LeagueInfo = {
@@ -27,9 +27,11 @@ async function main() {
27
27
  process.exit(1);
28
28
  }
29
29
 
30
- const uri = process.env.LEAGUE_DB_URI;
30
+ const collectionName = process.argv[3] || process.env.COLLECTION_NAME?.trim() || sanitizeCollectionName(leagueName);
31
+
32
+ const uri = process.env.MONGODB_URI;
31
33
  if (!uri) {
32
- console.log("LEAGUE_DB_URI not set. Skipping league seed.");
34
+ console.log("MONGODB_URI not set. Skipping league seed.");
33
35
  return;
34
36
  }
35
37
 
@@ -54,8 +56,6 @@ async function main() {
54
56
  }
55
57
  }
56
58
 
57
- const collectionName = sanitizeCollectionName(leagueName);
58
-
59
59
  const { MongoClient } = await import("mongodb");
60
60
  const client = new MongoClient(uri);
61
61