Swasthya sewa pradaata khojne ka naksha ek developer ke liye banane wale sabse mahatvapurn nakshon mein se ek hai. Isse use karne wale marij aksar ghbraaye hue, dard mein, ya ek ajoobe sistem se nikal rahe hote hain. Agar naksha dhire load hota hai, asangat parinaam deta hai, ya chhup ke unke postal code ko US-based third-party service ko bhej deta hai, to yah sirf ek buri user experience nahi hai, balki ek GDPR violation ka sanketa hai.
Yah tutorial ek production-ready provider finder banata hai: specialty filter, postal code khoj Geocoding API ke through, isochrone overlay jo "20 minut mein doctors" dikhata hai, aur MapAtlas Maps API ke through ek kam karne wala naksha, sab kuch GDPR compliance ke sath built in architecture se shuru mein, bad mein nahi.
Poora implementation vanilla JavaScript hai, koi framework zaroori nahi. Yah kisi bhi stack par kam karta hai: React, Vue, plain HTML, WordPress, ya hospital ke legacy CMS par. Tutorial EU regulatory context, UK CQC data, German Kassenärztliche Vereinigung, aur French CNAM ko bhi cover karta hai, taki aap jaan sake ki legitimately provider data kahan se source kare.
Swasthya Sthitti Apps ke Kyon Extra GDPR Obligations Hain
Standard apps personal data collect karte hain (naam, email, usage). Healthcare apps ka ek doosra risk hai: location data se health information infer karna.
Jab ek user "cardiologists near SE1 7PB" search karta hai, unka postcode personal data hai. Postcode aur medical specialty ka combination GDPR Article 9(1) ke under special category data ban jata hai, jo health condition ko reveal karta hai. Yah sach hai bhi agar aap kabhi user account nahi bante ya profile store nahi karte.
Risks concrete hain:
- Ek client-side geocoding API call jo user ke typed postcode ko include karta hai, third-party server ko bheja jata hai. Wah server postcode, specialty search, aur IP address dekh sakta hai. Agar DPA aur EU data residency guarantee na ho, to yah ek problematic transfer hai.
- Browser autocomplete aur history user ke device par typed postcode aur specialist query ko persist kar sakte hain, aapke control se bahar lekin aapke privacy information mein note karne yogya hai.
- Agar aap server-side API responses log karte ho (debugging ke liye common), to aap postcode + specialty combinations log kar sakte ho bina realize kiye.
Fix backend proxying hai: aapka server search receive karta hai, MapAtlas Geocoding API ko call karta hai, aur sirf coordinates return karta hai, kabhi bhi typed query ko patient ke browser se third-party API ko nahi bhejta. Implementation section mein isse aur detailed likha gaya hai.
Provider Data Structure
Provider data authorized official sources se aana chahiye, scraped datasets se nahi:
- UK: NHS Digital ka NHS Choices API aur CQC registered provider lists
- Germany: Kassenärztliche Bundesvereinigung (KBV) open data aur Arztsuche API
- France: CNAM ka Ameli API aur répertoire RPPS
Structure each provider as a GeoJSON feature:
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: Map ko Specialty Filter ke Sath Initialize Kare
Naksha aur ek specialty dropdown ke sath start kare. Filter visible markers ko client-side update karta hai bina kisi network request ke.
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 ke Through Postcode Search
Browser se Geocoding API ko call karne ke bajaye (jo patient ke postcode ko third-party server ko expose karta hai), geocoding request ko apne backend endpoint ke through route kare. Aapka server MapAtlas ko call karta hai aur sirf coordinates return karta hai.
Frontend (Patient ka 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 });
});
Aapka API key server par rahta hai aur patient ka raw postcode query kabhi third party ko nahi bheja jata.
Step 3: Isochrone Overlay, "20 Minut Mein Doctors"
Ek isochrone polygon har us point ko dikhata hai jo di hue drive time mein pahuncha ja sakta hai. Provider finder par ek display karna sabse practical patient ke question ka jawab deta hai: "main actually kitne doctors tak pahun sakta hoon?"
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 article isochrone use cases par deeper jata hai, jisme public transit isochrones bhi hain (patients ke liye car without) aur multi-time-band overlays jo 10, 20, aur 30-minute zones ek saath dikhate hain.
Step 4: Provider Detail Popup
Jab patient ek doctor marker par click kare, essential details dikhaye: naam, specialty, accepting status, languages, aur 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 ke Sath Synced List Panel
Naksha ke sath ek list view screen readers wale users aur unhe jo scrolling prefer karti hai pins par click karne se, unhe help deta hai.
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 ke liye, isko minimum compliance checklist maane:
- Backend proxy for geocoding: Patient postcodes client-side ko third-party APIs ko nahi bheje ja sakte.
- Search terms ka no session logging: Agar aap debugging ke liye requests log karte ho, logs mein likhne se pehle postcode nikale.
- Privacy notice: Aapke app ke privacy notice mein disclose hona chahiye ki location data nearby providers dhundne ke liye process ki jati hai, legal basis (legitimate interest ya explicit consent), aur retention period.
- Location access ka consent: Agar aap browser Geolocation API (
navigator.geolocation.getCurrentPosition) use karte ho, browser permission prompt se pehle ek clear purpose statement dikhaye. - Data residency: MapAtlas EU ke andar sab API requests process karta hai. MapAtlas DPA ko apne Records of Processing Activities complete karte hue reference kare.
- Retention: Agar aap performance ke liye isochrone results ya search coordinates ko server-side cache karte ho, ek retention period define kare (jaise 24 hours) aur deletion ko automate kare.
EU Developer's Guide to GDPR-Compliant Map APIs processor agreements, data residency, aur consent patterns ko cover karta hai. Healthcare Services industry page digital health applications ke liye relevant MapAtlas features list karta hai.
Aage Kya Build Kare
- Free MapAtlas API key ke liye sign up kare, maps, geocoding, routing, aur isochrones ke liye ek key
- Store Locator tutorial pattern ko multi-clinic networks ke liye add kare jo zyada locations have
- Geocoding API capabilities page ko explore kare postcode lookup, reverse geocoding, aur batch provider address validation ke liye
Frequently Asked Questions
Why does GDPR apply to a doctor finder map even if I don't store patient data?
A patient's search location on a healthcare finder reveals where they live and, by inference, which conditions they may have (e.g. searching for oncologists near a postcode). Under GDPR Article 9, health-related inferences from location data can qualify as special category data. Even without storing profiles, real-time geocoding requests sent client-side to third-party APIs create a processing record that requires a legal basis and disclosure.
What is an isochrone and why is it useful for a provider finder?
An isochrone is a polygon that shows every point reachable within a given travel time from a starting location. On a healthcare finder, an isochrone overlay answers "which doctors are within 20 minutes by car?", a much more useful question than raw distance, because it accounts for roads, speed limits, and traffic patterns.
Can I use MapAtlas for a patient-facing NHS or public health application?
Yes. MapAtlas is EU-hosted, ISO 27001 certified, and provides a GDPR-compliant Data Processing Agreement under Article 28. This satisfies typical public sector procurement requirements. UK NHS Digital and equivalent bodies in Germany (DSGVO) and France (CNIL) require data residency within the EU/UK, which MapAtlas fulfils.

