Overview
The Services Directory is the flagship feature of Dzaleka Online Services, connecting over 100+ verified organizations with community members seeking healthcare, education, legal support, and business services. It provides a searchable, categorized database of active service providers operating in and around Dzaleka Refugee Camp.
The Services Directory is built using Astro’s content collections, allowing easy content management through Markdown files with frontmatter validation.
User Experience
Discovery & Search
Users can discover services through multiple pathways:
Browse by Category
Filter services by categories like Education, Health, Non-profit Organizations, Advocacy, Humanitarian Aid, Entrepreneurship, Youth, and Cultural services.
Search by Keyword
Real-time search functionality filters services by title as users type.
View Featured Services
Highlighted services appear prominently with verified badges.
Pagination
Browse through services with 6 items per page for optimal viewing.
Service Detail Pages
Each service has a dedicated page showing:
Organization details : Title, description, logo, category
Contact information : Email, phone, operating hours
Location : Address with interactive map coordinates
Social media : Links to Facebook, Twitter, Instagram, LinkedIn, website
Verification status : Verified badge for trusted organizations
Last updated date : Shows when information was refreshed
Real-time Filtering Client-side JavaScript filters services instantly without page reloads
SEO Optimized Rich metadata and structured data (Schema.org) for search engines
Mobile Responsive Adaptive design works seamlessly on phones, tablets, and desktops
100% Free Organizations can register and list their services at no cost
Content Schema
Services are stored as Markdown files in src/content/services/ with YAML frontmatter. Here’s the schema:
title : "Organization Name" # Required
category : "Education" # Required - predefined categories
description : "Brief overview" # Required
status : "active" # active | inactive | pending
location :
address : "Physical address"
city : "Lilongwe"
coordinates :
lat : -13.6628274
lng : 33.8704301
contact :
email : "info@organization.org"
phone : "+265 123 456 789"
hours : "Monday-Friday, 8:00 AM - 5:00 PM"
socialMedia :
facebook : "https://facebook.com/page"
twitter : "https://twitter.com/handle"
instagram : "https://instagram.com/handle"
linkedin : "https://linkedin.com/company/name"
website : "https://website.com"
logo : "https://example.com/logo.png" # Image URL
featured : true # Boolean - shows on homepage
verified : true # Boolean - shows verified badge
lastUpdated : 2024-12-24 # Date in YYYY-MM-DD format
Real Example from Source
Here’s a real service from the codebase (tumaini-letu.md):
title : Tumaini Letu
category : "Cultural & Arts"
description : Cultural events and festivals promoting refugee talents and cultural exchange.
location :
address : Tumaini Letu P.O.Box 1459
city : Lilongwe
coordinates :
lat : -13.6628274
lng : 33.8704301
contact :
email : 'Info@tumainiletu.org'
phone : '+265993380983'
hours : 'Monday-Friday, 8:00 AM - 5:00 PM'
socialMedia :
facebook : 'https://www.facebook.com/tumaini.malawi/'
twitter : 'https://twitter.com/TumainiLetuMW'
instagram : 'https://www.instagram.com/tumaini_letu_mw/'
linkedin : 'https://www.linkedin.com/company/tumaini-letu/'
website : 'https://tumainiletu.org/'
logo : 'https://tumainiletu.org/wp-content/uploads/2021/07/LOGO-tumaini-letu-TEXT-COLOR-png.png'
featured : false
verified : true
status : "active"
lastUpdated : 2024-12-24
How to Add a New Service
Create Markdown File
Create a new .md file in src/content/services/ with a URL-friendly filename: touch src/content/services/new-organization.md
Add Frontmatter
Copy the schema template above and fill in your organization’s details: ---
title : "New Organization Name"
category : "Health"
description : "Provides healthcare services..."
status : "active"
contact :
email : "contact@org.com"
phone : "+265 XXX XXX XXX"
verified : true
lastUpdated : 2025-03-09
---
Add Description (Optional)
Below the frontmatter, add detailed markdown content: ## About Our Organization
Detailed description of services, history, and impact...
### Programs Offered
- Program 1
- Program 2
Test Locally
Run the development server to preview: Navigate to /services to see your new listing.
User Registration Flow
Organizations can self-register through the /services/register page:
Form Submission : Fill out organization details via web form
Email Notification : Submission details sent to admin team
Review Process : Admin verifies information and creates content file
Publication : Service goes live after approval
Confirmation : Organization receives success notification at /services/update-success
Technical Implementation
Data Fetching
Services are fetched using Astro’s Content Collections API:
src/pages/services/index.astro
import { getCollection } from 'astro:content' ;
// Get all services
const allServices = await getCollection ( 'services' );
// Filter and sort
const sortedServices = sortServices ( allServices , 'featured' );
Search & Filter Logic
Client-side filtering uses vanilla JavaScript for performance:
function filterServices () {
let visibleCount = 0 ;
serviceCards . forEach ( card => {
const title = card . dataset . title ;
const category = card . dataset . category ;
const matchesSearch = ! searchTerm || title . includes ( searchTerm . toLowerCase ());
const matchesCategory = ! categoryFilter || category === categoryFilter ;
if ( matchesSearch && matchesCategory ) {
card . style . display = 'block' ;
visibleCount ++ ;
} else {
card . style . display = 'none' ;
}
});
}
Category Routing
Dynamic routes handle category filtering (/services/category/[category]):
src/pages/services/category/[category]/[...page].astro
export async function getStaticPaths( { paginate } ) {
const allServices = await getCollection ( 'services' );
// Group services by category
const categories = [ ... new Set ( allServices . map ( s => s . data . category ))];
return categories . flatMap ( category => {
const categoryServices = allServices . filter (
service => service . data . category === category
);
return paginate ( categoryServices , { params: { category }, pageSize: 6 });
});
}
SEO & Structured Data
The services directory includes comprehensive SEO:
{
"@context" : "https://schema.org" ,
"@type" : "ItemList" ,
"name" : "Dzaleka Services Directory" ,
"description" : "Verified services in Dzaleka Refugee Camp" ,
"itemListElement" : [
{
"@type" : "ListItem" ,
"position" : 1 ,
"url" : "https://services.dzaleka.com/services/tumaini-letu" ,
"name" : "Tumaini Letu"
}
]
}
Statistics & Analytics
The platform tracks key metrics:
src/utils/serviceStats.ts
export function calculateServiceStats ( services ) {
return {
total: services . length ,
active: services . filter ( s => s . data . status === 'active' ). length ,
verified: services . filter ( s => s . data . verified ). length ,
byCategory: services . reduce (( acc , service ) => {
acc [ service . data . category ] = ( acc [ service . data . category ] || 0 ) + 1 ;
return acc ;
}, {})
};
}
View stats at /services/stats for real-time insights.
Best Practices
Keep Information Current Update the lastUpdated field whenever details change. Users rely on accurate contact info.
Use High-Quality Logos Recommended size: 400x400px, PNG format with transparent background.
Write Clear Descriptions Explain what services you offer, who you serve, and how to access your programs.
Verify Contact Details Ensure phone numbers and emails are monitored and responsive.
Common Issues & Solutions
Service not appearing on the website
Check that status: "active" is set in frontmatter
Verify the file is in src/content/services/ directory
Ensure frontmatter follows the correct YAML syntax (proper indentation)
Restart the dev server: npm run dev
Search not finding my service
The search function filters by title only. Ensure your service title contains relevant keywords users might search for.
Map coordinates not working
Use decimal degrees format: coordinates :
lat : -13.6628274 # Latitude (negative for South)
lng : 33.8704301 # Longitude (positive for East)