स्वास्थ्य सेवा प्रदाता खोजने वाला नक्शा उन सबसे महत्वपूर्ण मैप्स में से एक है जो एक developer बना सकता है। इसका इस्तेमाल करने वाले मरीज़ अक्सर घबराए हुए होते हैं, दर्द में होते हैं, या किसी अनजान सिस्टम से गुज़र रहे होते हैं। एक नक्शा जो धीरे load होता है, अप्रासंगिक परिणाम देता है, या चुपचाप उनका postcode किसी US-based third-party service को भेज देता है, वह सिर्फ़ एक खराब user experience नहीं है, बल्कि एक संभावित GDPR उल्लंघन भी है।
यह tutorial एक production-ready provider finder बनाता है: specialty filter, Geocoding API के ज़रिए postcode search, "20 मिनट के भीतर doctors" दिखाने वाला isochrone overlay, और MapAtlas Maps API से बनाया गया एक काम करता हुआ नक्शा, और यह सब GDPR compliance के साथ शुरू से ही architecture में बना हुआ है, बाद में जोड़ा हुआ नहीं।
पूरा implementation vanilla JavaScript में है, किसी framework की ज़रूरत नहीं। यह किसी भी stack पर काम करता है: React, Vue, plain HTML, WordPress, या किसी hospital का legacy CMS। Tutorial EU regulatory context, UK CQC data, German Kassenärztliche Vereinigung, और French CNAM को भी cover करता है, ताकि आप जानें कि provider data को कानूनी रूप से कहाँ से source करें।
Healthcare Location Apps के पास अतिरिक्त GDPR Obligations क्यों होती हैं
सामान्य apps personal data इकट्ठा करते हैं (नाम, email, usage)। Healthcare apps पर एक दूसरा risk होता है: location data से health information का अनुमान लगाना।
जब कोई user "cardiologists near SE1 7PB" search करता है, तो उसका postcode personal data है। Postcode और medical specialty का संयोजन GDPR Article 9(1) के तहत संभावित special category data बन जाता है, यानी ऐसा data जो health condition को उजागर करता है। यह तब भी सच है जब आप कभी कोई user account नहीं बनाते या profile store नहीं करते।
Risks ठोस हैं:
- एक client-side geocoding API call जिसमें user का type किया हुआ postcode शामिल होता है, वह किसी third-party server को भेज दी जाती है। वह server postcode, search की गई specialty, और IP address देखता है। बिना DPA और EU data residency गारंटी के, यह एक problematic transfer है।
- Browser autocomplete और history user के device पर typed postcode और specialist query को save कर सकते हैं, जो आपके control से बाहर है, लेकिन आपकी privacy information में इसका ज़िक्र करना ज़रूरी है।
- अगर आप server-side पर API responses log करते हैं (debugging के लिए आम बात है), तो आप बिना सोचे-समझे postcode + specialty combinations log कर रहे हो सकते हैं।
इसका हल backend proxying है: आपका server search receive करता है, MapAtlas Geocoding API को call करता है, और सिर्फ़ coordinates return करता है, और patient के browser से typed query को कभी third-party API को नहीं भेजता। Implementation section में इस पर और detail में बात करेंगे।
Provider Data Structure
Provider data authoritative आधिकारिक sources से आना चाहिए, scraped datasets से नहीं:
- UK: NHS Digital का NHS Choices API और CQC registered provider lists
- Germany: Kassenärztliche Bundesvereinigung (KBV) open data और Arztsuche API
- France: CNAM का Ameli API और répertoire RPPS
हर provider को एक GeoJSON feature की तरह structure करें:
const providers = {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: { type: "Point", coordinates: [4.9051, 52.3680] },
properties: {
id: "prov-001",
name: "Dr. Maria van den Berg",
specialty: "general-practitioner",
accepting: true,
address: "Prinsengracht 263, 1016 GV Amsterdam",
phone: "+31 20 423 5678",
languages: ["Dutch", "English"],
nextAvailable: "2026-02-18"
}
},
{
type: "Feature",
geometry: { type: "Point", coordinates: [4.8890, 52.3610] },
properties: {
id: "prov-002",
name: "Dr. Jan Smits",
specialty: "cardiologist",
accepting: false,
address: "Leidseplein 15, 1017 PS Amsterdam",
phone: "+31 20 612 3456",
languages: ["Dutch"],
nextAvailable: null
}
},
{
type: "Feature",
geometry: { type: "Point", coordinates: [4.9200, 52.3750] },
properties: {
id: "prov-003",
name: "Anna Fischer, MD",
specialty: "dermatologist",
accepting: true,
address: "Plantage Middenlaan 14, 1018 DD Amsterdam",
phone: "+31 20 789 0123",
languages: ["Dutch", "English", "German"],
nextAvailable: "2026-02-20"
}
}
]
};
Step 1: Specialty Filter के साथ Map Initialise करें
नक्शे और एक specialty dropdown से शुरुआत करें। यह filter visible markers को client-side update करता है, बिना किसी network request के।
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';
const map = new mapmetricsgl.Map({
container: 'provider-map',
style: 'https://tiles.mapatlas.eu/styles/basic/style.json?key=YOUR_API_KEY',
center: [4.9041, 52.3676],
zoom: 13
});
map.on('load', () => {
map.addSource('providers', {
type: 'geojson',
data: providers
});
// Provider markers, green = accepting, grey = full
map.addLayer({
id: 'provider-markers',
type: 'circle',
source: 'providers',
paint: {
'circle-radius': 10,
'circle-color': [
'case',
['==', ['get', 'accepting'], true], '#16A34A',
'#9CA3AF'
],
'circle-stroke-width': 2,
'circle-stroke-color': '#ffffff'
}
});
buildList(providers.features);
});
// Specialty filter
document.getElementById('specialty-select').addEventListener('change', (e) => {
const specialty = e.target.value;
if (specialty === 'all') {
map.setFilter('provider-markers', null);
} else {
map.setFilter('provider-markers', ['==', ['get', 'specialty'], specialty]);
}
});
Step 2: Backend Proxy के ज़रिए Postcode Search
Browser से सीधे Geocoding API को call करने के बजाय (जो patient का postcode किसी third-party server के सामने उजागर कर देता है), geocoding request को अपने ही backend endpoint के ज़रिए route करें। आपका server MapAtlas को call करेगा और सिर्फ़ coordinates वापस लौटाएगा।
Frontend (patient का browser):
async function geocodePostcode(postcode) {
// Call YOUR backend, not the geocoding API directly
const res = await fetch(`/api/geocode?q=${encodeURIComponent(postcode)}`);
const { lat, lng } = await res.json();
return { lat, lng };
}
document.getElementById('postcode-form').addEventListener('submit', async (e) => {
e.preventDefault();
const postcode = document.getElementById('postcode-input').value.trim();
const { lat, lng } = await geocodePostcode(postcode);
map.flyTo({ center: [lng, lat], zoom: 13 });
fetchIsochrone(lat, lng);
});
Backend proxy (Node.js/Express):
// /api/geocode, server-side only, postcode never leaves your infrastructure
app.get('/api/geocode', async (req, res) => {
const url = new URL('https://api.mapatlas.eu/geocoding/v1/search');
url.searchParams.set('text', req.query.q);
url.searchParams.set('key', process.env.MAPATLAS_API_KEY); // server-side key
url.searchParams.set('size', '1');
const upstream = await fetch(url.toString());
const data = await upstream.json();
if (!data.features?.length) {
return res.status(404).json({ error: 'Postcode not found' });
}
const [lng, lat] = data.features[0].geometry.coordinates;
// Return ONLY coordinates, no postcode logged, no specialty in response
res.json({ lat, lng });
});
आपकी API key server पर ही रहती है और patient का raw postcode query कभी किसी third party को नहीं भेजा जाता।
Step 3: Isochrone Overlay, "20 मिनट के भीतर Doctors"
एक isochrone polygon हर उस point को दिखाता है जहाँ दिए गए drive time के भीतर पहुँचा जा सकता है। Provider finder पर इसे दिखाना सबसे व्यावहारिक patient सवाल का जवाब देता है: "मैं असल में कितने doctors तक पहुँच सकता हूँ?"
async function fetchIsochrone(lat, lng) {
// Call through your backend proxy for the same privacy reasons
const res = await fetch(
`/api/isochrone?lat=${lat}&lng=${lng}&minutes=20&profile=driving`
);
const geojson = await res.json();
// Remove existing isochrone layer if present
if (map.getLayer('isochrone-fill')) map.removeLayer('isochrone-fill');
if (map.getLayer('isochrone-border')) map.removeLayer('isochrone-border');
if (map.getSource('isochrone')) map.removeSource('isochrone');
map.addSource('isochrone', { type: 'geojson', data: geojson });
map.addLayer({
id: 'isochrone-fill',
type: 'fill',
source: 'isochrone',
paint: {
'fill-color': '#16A34A',
'fill-opacity': 0.12
}
}, 'provider-markers'); // Insert below markers so pins render on top
map.addLayer({
id: 'isochrone-border',
type: 'line',
source: 'isochrone',
paint: {
'line-color': '#16A34A',
'line-width': 2,
'line-dasharray': [3, 2]
}
}, 'provider-markers');
}
Backend isochrone proxy:
app.get('/api/isochrone', async (req, res) => {
const { lat, lng, minutes, profile } = req.query;
const url = new URL('https://api.mapatlas.eu/v1/isochrone');
url.searchParams.set('lat', lat);
url.searchParams.set('lng', lng);
url.searchParams.set('time', minutes * 60); // seconds
url.searchParams.set('profile', profile || 'driving');
url.searchParams.set('key', process.env.MAPATLAS_API_KEY);
const upstream = await fetch(url.toString());
const data = await upstream.json();
res.json(data); // GeoJSON polygon
});
Isochrone Maps Explained लेख isochrone use cases पर और गहराई से जाता है, जिसमें public transit isochrones (उन patients के लिए जिनके पास कार नहीं है) और multi-time-band overlays शामिल हैं, जो 10, 20 और 30-minute zones को एक साथ दिखाते हैं।
Step 4: Provider Detail Popup
जब कोई patient किसी doctor marker पर click करे, तो ज़रूरी details दिखाएँ: नाम, specialty, accepting status, languages, और next available appointment।
map.on('click', 'provider-markers', (e) => {
const {
name, specialty, accepting, address, phone, languages, nextAvailable
} = e.features[0].properties;
const coords = e.features[0].geometry.coordinates.slice();
const statusBadge = accepting
? '<span style="color:#16A34A;font-weight:600">Accepting patients</span>'
: '<span style="color:#9CA3AF">Not accepting new patients</span>';
const apptLine = accepting && nextAvailable
? `<p style="margin:4px 0">Next available: <strong>${nextAvailable}</strong></p>`
: '';
new mapmetricsgl.Popup({ maxWidth: '280px' })
.setLngLat(coords)
.setHTML(`
<strong style="font-size:15px">${name}</strong>
<p style="margin:4px 0;text-transform:capitalize">${specialty.replace('-', ' ')}</p>
${statusBadge}
${apptLine}
<p style="margin:6px 0;font-size:13px;color:#64748b">${address}</p>
<p style="margin:4px 0;font-size:13px">
Languages: ${Array.isArray(languages) ? languages.join(', ') : languages}
</p>
<a href="tel:${phone}" style="color:#2563EB">${phone}</a>
`)
.addTo(map);
});
map.on('mouseenter', 'provider-markers', () => { map.getCanvas().style.cursor = 'pointer'; });
map.on('mouseleave', 'provider-markers', () => { map.getCanvas().style.cursor = ''; });
Step 5: Map के साथ Synced List Panel
नक्शे के साथ-साथ एक list view उन users की मदद करता है जो screen readers इस्तेमाल करते हैं और उन लोगों की भी जो pins पर click करने के बजाय scroll करना पसंद करते हैं।
function buildList(features) {
const list = document.getElementById('provider-list');
list.innerHTML = '';
features.forEach(({ properties, geometry }) => {
const { name, specialty, accepting, address, nextAvailable } = properties;
const card = document.createElement('div');
card.className = `provider-card ${accepting ? 'accepting' : 'full'}`;
card.innerHTML = `
<strong>${name}</strong>
<p>${specialty.replace('-', ' ')}</p>
<p style="font-size:12px;color:#64748b">${address}</p>
<small>${accepting ? `Next: ${nextAvailable || 'call to confirm'}` : 'Not accepting'}</small>
`;
card.addEventListener('click', () => {
map.flyTo({ center: geometry.coordinates, zoom: 15 });
});
list.appendChild(card);
});
}
GDPR Implementation Checklist
EU healthcare developers के लिए, इसे न्यूनतम compliance checklist की तरह मानें:
- Backend proxy for geocoding: Patient postcodes को client-side से किसी third-party API को नहीं भेजा जाना चाहिए।
- Search terms का कोई session logging नहीं: अगर आप debugging के लिए requests log करते हैं, तो logs में लिखने से पहले postcode हटा दें।
- Privacy notice: आपके app के privacy notice में यह बताया जाना चाहिए कि location data को आस-पास के providers ढूँढने के लिए process किया जाता है, साथ ही legal basis (legitimate interest या explicit consent) और retention period भी।
- Location access के लिए consent: अगर आप browser Geolocation API (
navigator.geolocation.getCurrentPosition) इस्तेमाल करते हैं, तो browser permission prompt trigger करने से पहले एक स्पष्ट purpose statement दिखाएँ। - Data residency: MapAtlas सभी API requests को EU के भीतर ही process करता है। अपने Records of Processing Activities पूरे करते समय MapAtlas DPA का reference दें।
- Retention: अगर आप performance के लिए isochrone results या search coordinates को server-side cache करते हैं, तो एक retention period तय करें (जैसे 24 घंटे) और deletion को automate करें।
EU Developer's Guide to GDPR-Compliant Map APIs processor agreements, data residency और consent patterns को पूरी तरह से cover करता है। Healthcare Services industry page उन MapAtlas features को list करता है जो digital health applications के लिए ख़ास तौर पर relevant हैं।
आगे क्या Build करें
- एक free MapAtlas API key के लिए sign up करें, maps, geocoding, routing और isochrones के लिए एक ही key
- Store Locator tutorial pattern को उन multi-clinic networks के लिए जोड़ें जिनमें कई locations हों
- Geocoding API capabilities page को postcode lookup, reverse geocoding और batch provider address validation के लिए explore करें
Frequently Asked Questions
क्या GDPR एक doctor finder map पर तब भी लागू होता है जब मैं patient data store नहीं करता?
Healthcare finder पर एक patient की search location यह बताती है कि वे कहाँ रहते हैं और अनुमान से, उन्हें कौन सी health conditions हो सकती हैं (जैसे किसी postcode के पास oncologists खोजना)। GDPR Article 9 के तहत, location data से health से जुड़े अनुमान special category data के रूप में योग्य हो सकते हैं। Profiles store न करते हुए भी, third-party APIs को client-side भेजी गई real-time geocoding requests एक processing record बनाती हैं, जिसके लिए legal basis और disclosure ज़रूरी है।
Isochrone क्या होता है और यह एक provider finder के लिए क्यों उपयोगी है?
Isochrone एक polygon होता है जो हर उस point को दिखाता है जहाँ किसी starting location से दिए गए travel time के भीतर पहुँचा जा सकता है। Healthcare finder पर एक isochrone overlay इस सवाल का जवाब देता है कि "20 मिनट में car से कौन से doctors तक पहुँचा जा सकता है?", जो raw distance से कहीं ज़्यादा उपयोगी सवाल है, क्योंकि यह roads, speed limits और traffic patterns को ध्यान में रखता है।
क्या मैं किसी patient-facing NHS या public health application के लिए MapAtlas इस्तेमाल कर सकता हूँ?
जी हाँ। MapAtlas EU-hosted है, ISO 27001 certified है, और Article 28 के तहत एक GDPR-compliant Data Processing Agreement देता है। यह आम public sector procurement requirements को पूरा करता है। UK NHS Digital और Germany (DSGVO) तथा France (CNIL) में इसी तरह की संस्थाएँ EU/UK के भीतर data residency माँगती हैं, जिसे MapAtlas पूरा करता है।
अक्सर पूछे जाने वाले प्रश्न
क्या GDPR एक doctor finder map पर तब भी लागू होता है जब मैं patient data store नहीं करता?
Healthcare finder पर एक patient की search location यह बताती है कि वे कहाँ रहते हैं और अनुमान से, उन्हें कौन सी health conditions हो सकती हैं (जैसे किसी postcode के पास oncologists खोजना)। GDPR Article 9 के तहत, location data से health से जुड़े अनुमान special category data के रूप में योग्य हो सकते हैं। Profiles store न करते हुए भी, third-party APIs को client-side भेजी गई real-time geocoding requests एक processing record बनाती हैं, जिसके लिए legal basis और disclosure ज़रूरी है।
Isochrone क्या होता है और यह एक provider finder के लिए क्यों उपयोगी है?
Isochrone एक polygon होता है जो हर उस point को दिखाता है जहाँ किसी starting location से दिए गए travel time के भीतर पहुँचा जा सकता है। Healthcare finder पर एक isochrone overlay इस सवाल का जवाब देता है कि '20 मिनट में car से कौन से doctors तक पहुँचा जा सकता है?', जो raw distance से कहीं ज़्यादा उपयोगी सवाल है, क्योंकि यह roads, speed limits और traffic patterns को ध्यान में रखता है।
क्या मैं किसी patient-facing NHS या public health application के लिए MapAtlas इस्तेमाल कर सकता हूँ?
जी हाँ। MapAtlas EU-hosted है, ISO 27001 certified है, और Article 28 के तहत एक GDPR-compliant Data Processing Agreement देता है। यह आम public sector procurement requirements को पूरा करता है। UK NHS Digital और Germany (DSGVO) तथा France (CNIL) में इसी तरह की संस्थाएँ EU/UK के भीतर data residency माँगती हैं, जिसे MapAtlas पूरा करता है।

