Spaces:
Running
fix: Data accuracy — labels, funding format, disclaimers
Browse filesLabel 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
|
@@ -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
|
|
@@ -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
|
|
@@ -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
|
| 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 />
|
|
@@ -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 |
-
<
|
| 412 |
-
|
| 413 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
|
|
@@ -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">📊
|
| 42 |
-
<p className="text-[10px] sm:text-xs text-atlas-muted mt-0.5">
|
| 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="
|
| 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">
|
| 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="
|
| 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>
|
|
@@ -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 >=
|
| 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 |
}
|
|
@@ -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">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
))}
|
|
@@ -13,16 +13,16 @@ export default function StatsBar({ overview, viewportSummary, featureCount, load
|
|
| 13 |
desc: 'Entities visible on map',
|
| 14 |
},
|
| 15 |
{
|
| 16 |
-
label: '
|
| 17 |
value: overview.total_entities,
|
| 18 |
icon: '🏢',
|
| 19 |
-
desc: '
|
| 20 |
},
|
| 21 |
{
|
| 22 |
label: 'Startups',
|
| 23 |
value: overview.by_type?.startup || 0,
|
| 24 |
icon: '🚀',
|
| 25 |
-
desc: '
|
| 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: '
|
| 38 |
},
|
| 39 |
{
|
| 40 |
label: 'Funding',
|
| 41 |
value: overview.total_funding_display,
|
| 42 |
icon: '💰',
|
| 43 |
-
desc: '
|
| 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 |
]
|