Ram2005 commited on
Commit
dfb0010
·
verified ·
1 Parent(s): 9eed0b2

fix: Data accuracy — labels, funding format, disclaimers

Browse files

Label fixes (prevents misinformation):
- StatsBar: 'Total' → 'Mapped' with tooltip 'Curated entities in our database'
- StatsBar: 'Startups' tooltip → 'Mapped startups (India has 223K+ DPIIT-registered)'
- StatsBar: 'Women-led' tooltip → 'In our dataset (India has 102K+ women-led startups)'
- StatsBar: 'Funding' tooltip → 'Mapped entities only — not total Indian startup funding'
- AnalyticsPanel: 'Total' → 'Mapped', subtitle → 'Curated dataset — not total Indian ecosystem'
- AnalyticsPanel: Added disclaimer banner with real national figures
- AnalyticsPanel: 'Women-led*' asterisk to indicate dataset subset
- Geography/Trends headers now say '(mapped)' to clarify scope

Funding format (K Cr bug):
- Removed 'K Cr' entirely from both backend format_funding and frontend formatFunding
- ≥10,000 Cr → Lakh Cr (e.g. ₹27.52 Lakh Cr)
- 100–9,999 Cr → ₹X,XXX Cr (with Indian comma formatting)
- SearchBar suggestions: now use proper tiered formatting instead of raw ₹{crores}Cr

Disclaimer:
- App.jsx: more prominent glass-backed banner with real national figures for startups and women-led
- index.html: meta description updated with '2.23 lakh+' phrasing

backend/directory.py CHANGED
@@ -29,14 +29,10 @@ def format_funding(amount_inr: float) -> str:
29
  if not amount_inr or amount_inr == 0:
30
  return "Bootstrapped"
31
  crores = amount_inr / 10000000
32
- if crores >= 100000:
33
- return f"₹{crores / 100000:.1f} Lakh Cr"
34
  if crores >= 10000:
35
  return f"₹{crores / 100000:.2f} Lakh Cr"
36
- if crores >= 1000:
37
- return f"₹{crores / 1000:.1f}K Cr"
38
  if crores >= 100:
39
- return f"₹{crores:.0f} Cr"
40
  if crores >= 1:
41
  return f"₹{crores:.1f} Cr"
42
  lakhs = amount_inr / 100000
 
29
  if not amount_inr or amount_inr == 0:
30
  return "Bootstrapped"
31
  crores = amount_inr / 10000000
 
 
32
  if crores >= 10000:
33
  return f"₹{crores / 100000:.2f} Lakh Cr"
 
 
34
  if crores >= 100:
35
+ return f"₹{crores:,.0f} Cr"
36
  if crores >= 1:
37
  return f"₹{crores:.1f} Cr"
38
  lakhs = amount_inr / 100000
backend/routes/entities.py CHANGED
@@ -41,14 +41,10 @@ def format_funding(amount_inr: float) -> str:
41
  if not amount_inr or amount_inr == 0:
42
  return "Bootstrapped"
43
  crores = amount_inr / 10000000
44
- if crores >= 100000:
45
- return f"₹{crores / 100000:.1f} Lakh Cr"
46
  if crores >= 10000:
47
  return f"₹{crores / 100000:.2f} Lakh Cr"
48
- if crores >= 1000:
49
- return f"₹{crores / 1000:.1f}K Cr"
50
  if crores >= 100:
51
- return f"₹{crores:.0f} Cr"
52
  if crores >= 1:
53
  return f"₹{crores:.1f} Cr"
54
  lakhs = amount_inr / 100000
 
41
  if not amount_inr or amount_inr == 0:
42
  return "Bootstrapped"
43
  crores = amount_inr / 10000000
 
 
44
  if crores >= 10000:
45
  return f"₹{crores / 100000:.2f} Lakh Cr"
 
 
46
  if crores >= 100:
47
+ return f"₹{crores:,.0f} Cr"
48
  if crores >= 1:
49
  return f"₹{crores:.1f} Cr"
50
  lakhs = amount_inr / 100000
frontend/index.html CHANGED
@@ -3,7 +3,7 @@
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <meta name="description" content="Curated mapping platform for India's startup ecosystem — startups, unicorns, SMEs, E-Cells, incubators. India has 223,000+ DPIIT-registered startups." />
7
  <meta name="keywords" content="India startups, startup map, Indian unicorns, DPIIT startups, tech ecosystem India" />
8
  <link rel="preconnect" href="https://fonts.googleapis.com" />
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
 
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta name="description" content="Curated map of India's startup ecosystem — featured startups, 125 unicorns, SMEs, E-Cells, incubators. India has 2.23 lakh+ DPIIT-registered startups; this atlas maps a curated subset." />
7
  <meta name="keywords" content="India startups, startup map, Indian unicorns, DPIIT startups, tech ecosystem India" />
8
  <link rel="preconnect" href="https://fonts.googleapis.com" />
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
frontend/src/App.jsx CHANGED
@@ -407,10 +407,14 @@ export default function App() {
407
 
408
  {/* Data Disclaimer */}
409
  {overview && (
410
- <div className="absolute bottom-[90px] sm:bottom-[100px] left-1/2 -translate-x-1/2 z-10 pointer-events-none">
411
- <p className="text-[10px] text-atlas-muted/70 text-center whitespace-nowrap">
412
- Curated dataset of {overview.total_entities?.toLocaleString()} entities · India has 223,000+ DPIIT-registered startups · Source: DPIIT, Tracxn, Crunchbase
413
- </p>
 
 
 
 
414
  </div>
415
  )}
416
 
 
407
 
408
  {/* Data Disclaimer */}
409
  {overview && (
410
+ <div className="absolute bottom-[90px] sm:bottom-[100px] left-1/2 -translate-x-1/2 z-10 pointer-events-none max-w-lg px-2">
411
+ <div className="glass rounded-lg px-3 py-1.5 text-center">
412
+ <p className="text-[10px] text-atlas-muted/80 leading-relaxed">
413
+ Curated dataset of <span className="text-atlas-text font-medium">{overview.total_entities?.toLocaleString()}</span> mapped entities.
414
+ India has <span className="text-atlas-text font-medium">2.23 lakh+</span> DPIIT-registered startups and <span className="text-atlas-text font-medium">1.02 lakh+</span> women-led ventures.
415
+ <span className="text-atlas-muted/50"> · Source: DPIIT, Tracxn, Crunchbase</span>
416
+ </p>
417
+ </div>
418
  </div>
419
  )}
420
 
frontend/src/components/AnalyticsPanel.jsx CHANGED
@@ -38,8 +38,8 @@ export default function AnalyticsPanel({ onClose }) {
38
  <div className="glass rounded-2xl shadow-2xl w-full max-w-3xl max-h-[85vh] flex flex-col overflow-hidden">
39
  <div className="flex items-center justify-between px-4 sm:px-6 py-3 sm:py-4 border-b border-atlas-border flex-shrink-0">
40
  <div>
41
- <h2 className="text-base sm:text-lg font-bold text-atlas-text">📊 Ecosystem Analytics</h2>
42
- <p className="text-[10px] sm:text-xs text-atlas-muted mt-0.5">India's Startup Landscape</p>
43
  </div>
44
  <button onClick={onClose} className="p-2 hover:bg-atlas-surface rounded-lg transition-colors">
45
  <X size={20} className="text-atlas-muted" />
@@ -71,11 +71,20 @@ export default function AnalyticsPanel({ onClose }) {
71
  <>
72
  {activeTab === 'overview' && overview && (
73
  <>
 
 
 
 
 
 
 
 
 
74
  <div className="grid grid-cols-2 sm:grid-cols-4 gap-2 sm:gap-3">
75
- <StatCard label="Total" value={overview.total_entities?.toLocaleString()} color="#6366F1" />
76
  <StatCard label="Unicorns" value={overview.unicorn_count} color="#F97316" />
77
- <StatCard label="Women-led" value={overview.women_led_count} color="#EC4899" />
78
- <StatCard label="Funding" value={overview.total_funding_display} color="#F59E0B" />
79
  </div>
80
 
81
  {/* Entity Type Pie Chart */}
@@ -113,7 +122,7 @@ export default function AnalyticsPanel({ onClose }) {
113
 
114
  {activeTab === 'sectors' && sectorData && (
115
  <div>
116
- <h3 className="text-sm font-semibold text-atlas-muted uppercase mb-3">Startups by Sector</h3>
117
  <div className="h-72 sm:h-96">
118
  <ResponsiveContainer width="100%" height="100%">
119
  <BarChart data={sectorData.slice(0, 15).map(s => ({ name: s.sector.replace('_', ' '), count: s.count, funding: s.total_employees }))} layout="vertical" margin={{ left: 80, right: 20 }}>
@@ -125,7 +134,6 @@ export default function AnalyticsPanel({ onClose }) {
125
  </ResponsiveContainer>
126
  </div>
127
 
128
- {/* Sector cards below chart */}
129
  <div className="space-y-2 mt-4">
130
  {sectorData.slice(0, 10).map((s, i) => (
131
  <div key={s.sector} className="flex items-center gap-3 bg-atlas-surface/30 rounded-lg px-3 py-2">
@@ -142,7 +150,7 @@ export default function AnalyticsPanel({ onClose }) {
142
  {activeTab === 'geography' && overview && (
143
  <div className="space-y-6">
144
  <div>
145
- <h3 className="text-sm font-semibold text-atlas-muted uppercase mb-3">Top States</h3>
146
  <div className="h-64 sm:h-80">
147
  <ResponsiveContainer width="100%" height="100%">
148
  <BarChart data={(overview.top_states || []).map(s => ({ name: s.state, count: s.count }))} layout="vertical" margin={{ left: 90, right: 20 }}>
@@ -160,7 +168,7 @@ export default function AnalyticsPanel({ onClose }) {
160
  </div>
161
 
162
  <div>
163
- <h3 className="text-sm font-semibold text-atlas-muted uppercase mb-3">Top Cities</h3>
164
  <div className="grid grid-cols-2 gap-2">
165
  {(overview.top_cities || []).map((c, i) => (
166
  <div key={c.city} className="bg-atlas-surface/40 rounded-lg px-3 py-2 border border-atlas-border/30">
@@ -178,7 +186,7 @@ export default function AnalyticsPanel({ onClose }) {
178
 
179
  {activeTab === 'trends' && overview && (
180
  <div>
181
- <h3 className="text-sm font-semibold text-atlas-muted uppercase mb-3">Founding Trend (2005–Present)</h3>
182
  {overview.founding_trend?.length > 0 && (
183
  <div className="h-56 sm:h-72">
184
  <ResponsiveContainer width="100%" height="100%">
@@ -192,7 +200,7 @@ export default function AnalyticsPanel({ onClose }) {
192
  <XAxis dataKey="founded_year" stroke="#64748B" fontSize={10} />
193
  <YAxis stroke="#64748B" fontSize={10} />
194
  <Tooltip content={<CustomTooltip />} />
195
- <Area type="monotone" dataKey="count" name="Startups Founded" stroke="#F97316" strokeWidth={2} fill="url(#colorCount)" />
196
  </AreaChart>
197
  </ResponsiveContainer>
198
  </div>
 
38
  <div className="glass rounded-2xl shadow-2xl w-full max-w-3xl max-h-[85vh] flex flex-col overflow-hidden">
39
  <div className="flex items-center justify-between px-4 sm:px-6 py-3 sm:py-4 border-b border-atlas-border flex-shrink-0">
40
  <div>
41
+ <h2 className="text-base sm:text-lg font-bold text-atlas-text">📊 Analytics</h2>
42
+ <p className="text-[10px] sm:text-xs text-atlas-muted mt-0.5">Curated dataset — not total Indian ecosystem</p>
43
  </div>
44
  <button onClick={onClose} className="p-2 hover:bg-atlas-surface rounded-lg transition-colors">
45
  <X size={20} className="text-atlas-muted" />
 
71
  <>
72
  {activeTab === 'overview' && overview && (
73
  <>
74
+ {/* Disclaimer */}
75
+ <div className="bg-amber-500/5 border border-amber-500/10 rounded-lg px-3 py-2">
76
+ <p className="text-[10px] text-amber-400/80">
77
+ ⚠ Curated dataset of {overview.total_entities?.toLocaleString()} mapped entities.
78
+ India has 223,000+ DPIIT-recognized startups and 102,000+ women-led ventures.
79
+ Figures below reflect our database only.
80
+ </p>
81
+ </div>
82
+
83
  <div className="grid grid-cols-2 sm:grid-cols-4 gap-2 sm:gap-3">
84
+ <StatCard label="Mapped" value={overview.total_entities?.toLocaleString()} color="#6366F1" />
85
  <StatCard label="Unicorns" value={overview.unicorn_count} color="#F97316" />
86
+ <StatCard label="Women-led*" value={overview.women_led_count} color="#EC4899" />
87
+ <StatCard label="Funding*" value={overview.total_funding_display} color="#F59E0B" />
88
  </div>
89
 
90
  {/* Entity Type Pie Chart */}
 
122
 
123
  {activeTab === 'sectors' && sectorData && (
124
  <div>
125
+ <h3 className="text-sm font-semibold text-atlas-muted uppercase mb-3">Mapped Entities by Sector</h3>
126
  <div className="h-72 sm:h-96">
127
  <ResponsiveContainer width="100%" height="100%">
128
  <BarChart data={sectorData.slice(0, 15).map(s => ({ name: s.sector.replace('_', ' '), count: s.count, funding: s.total_employees }))} layout="vertical" margin={{ left: 80, right: 20 }}>
 
134
  </ResponsiveContainer>
135
  </div>
136
 
 
137
  <div className="space-y-2 mt-4">
138
  {sectorData.slice(0, 10).map((s, i) => (
139
  <div key={s.sector} className="flex items-center gap-3 bg-atlas-surface/30 rounded-lg px-3 py-2">
 
150
  {activeTab === 'geography' && overview && (
151
  <div className="space-y-6">
152
  <div>
153
+ <h3 className="text-sm font-semibold text-atlas-muted uppercase mb-3">Top States (mapped)</h3>
154
  <div className="h-64 sm:h-80">
155
  <ResponsiveContainer width="100%" height="100%">
156
  <BarChart data={(overview.top_states || []).map(s => ({ name: s.state, count: s.count }))} layout="vertical" margin={{ left: 90, right: 20 }}>
 
168
  </div>
169
 
170
  <div>
171
+ <h3 className="text-sm font-semibold text-atlas-muted uppercase mb-3">Top Cities (mapped)</h3>
172
  <div className="grid grid-cols-2 gap-2">
173
  {(overview.top_cities || []).map((c, i) => (
174
  <div key={c.city} className="bg-atlas-surface/40 rounded-lg px-3 py-2 border border-atlas-border/30">
 
186
 
187
  {activeTab === 'trends' && overview && (
188
  <div>
189
+ <h3 className="text-sm font-semibold text-atlas-muted uppercase mb-3">Founding Trend (mapped entities, 2005–Present)</h3>
190
  {overview.founding_trend?.length > 0 && (
191
  <div className="h-56 sm:h-72">
192
  <ResponsiveContainer width="100%" height="100%">
 
200
  <XAxis dataKey="founded_year" stroke="#64748B" fontSize={10} />
201
  <YAxis stroke="#64748B" fontSize={10} />
202
  <Tooltip content={<CustomTooltip />} />
203
+ <Area type="monotone" dataKey="count" name="Founded" stroke="#F97316" strokeWidth={2} fill="url(#colorCount)" />
204
  </AreaChart>
205
  </ResponsiveContainer>
206
  </div>
frontend/src/components/EntityDetail.jsx CHANGED
@@ -13,10 +13,8 @@ const ENTITY_LABELS = {
13
  function formatFunding(v) {
14
  if (!v || v === 0) return 'Bootstrapped'
15
  const cr = v / 10000000
16
- if (cr >= 100000) return `₹${(cr/100000).toFixed(1)} Lakh Cr`
17
  if (cr >= 10000) return `₹${(cr/100000).toFixed(2)} Lakh Cr`
18
- if (cr >= 1000) return `₹${(cr/1000).toFixed(1)}K Cr`
19
- if (cr >= 100) return `₹${cr.toFixed(0)} Cr`
20
  if (cr >= 1) return `₹${cr.toFixed(1)} Cr`
21
  return `₹${(v/100000).toFixed(0)} L`
22
  }
 
13
  function formatFunding(v) {
14
  if (!v || v === 0) return 'Bootstrapped'
15
  const cr = v / 10000000
 
16
  if (cr >= 10000) return `₹${(cr/100000).toFixed(2)} Lakh Cr`
17
+ if (cr >= 100) return `₹${cr.toLocaleString('en-IN', { maximumFractionDigits: 0 })} Cr`
 
18
  if (cr >= 1) return `₹${cr.toFixed(1)} Cr`
19
  return `₹${(v/100000).toFixed(0)} L`
20
  }
frontend/src/components/SearchBar.jsx CHANGED
@@ -100,7 +100,14 @@ export default function SearchBar({ value, onChange, onEntitySelect }) {
100
  </div>
101
  </div>
102
  {s.funding_crores > 0 && (
103
- <span className="text-[10px] text-atlas-muted/60 flex-shrink-0">₹{s.funding_crores}Cr</span>
 
 
 
 
 
 
 
104
  )}
105
  </button>
106
  ))}
 
100
  </div>
101
  </div>
102
  {s.funding_crores > 0 && (
103
+ <span className="text-[10px] text-atlas-muted/60 flex-shrink-0">
104
+ {s.funding_crores >= 10000
105
+ ? `₹${(s.funding_crores / 100000).toFixed(2)} L Cr`
106
+ : s.funding_crores >= 100
107
+ ? `₹${s.funding_crores.toLocaleString('en-IN')} Cr`
108
+ : `₹${s.funding_crores.toFixed(1)} Cr`
109
+ }
110
+ </span>
111
  )}
112
  </button>
113
  ))}
frontend/src/components/StatsBar.jsx CHANGED
@@ -13,16 +13,16 @@ export default function StatsBar({ overview, viewportSummary, featureCount, load
13
  desc: 'Entities visible on map',
14
  },
15
  {
16
- label: 'Total',
17
  value: overview.total_entities,
18
  icon: '🏢',
19
- desc: 'All ecosystem entities',
20
  },
21
  {
22
  label: 'Startups',
23
  value: overview.by_type?.startup || 0,
24
  icon: '🚀',
25
- desc: 'Active startups',
26
  },
27
  {
28
  label: 'Unicorns',
@@ -34,13 +34,13 @@ export default function StatsBar({ overview, viewportSummary, featureCount, load
34
  label: 'Women-led',
35
  value: overview.women_led_count || 0,
36
  icon: '👩',
37
- desc: 'Women founders',
38
  },
39
  {
40
  label: 'Funding',
41
  value: overview.total_funding_display,
42
  icon: '💰',
43
- desc: 'Total raised',
44
  isText: true,
45
  },
46
  ]
 
13
  desc: 'Entities visible on map',
14
  },
15
  {
16
+ label: 'Mapped',
17
  value: overview.total_entities,
18
  icon: '🏢',
19
+ desc: 'Curated entities in our database',
20
  },
21
  {
22
  label: 'Startups',
23
  value: overview.by_type?.startup || 0,
24
  icon: '🚀',
25
+ desc: 'Mapped startups (India has 223K+ DPIIT-registered)',
26
  },
27
  {
28
  label: 'Unicorns',
 
34
  label: 'Women-led',
35
  value: overview.women_led_count || 0,
36
  icon: '👩',
37
+ desc: 'In our dataset (India has 102K+ women-led startups)',
38
  },
39
  {
40
  label: 'Funding',
41
  value: overview.total_funding_display,
42
  icon: '💰',
43
+ desc: 'Mapped entities only — not total Indian startup funding',
44
  isText: true,
45
  },
46
  ]