A modern, static data visualization dashboard for the Islam West Africa Collection (IWAC) database. Built with SvelteKit, Svelte 5, shadcn-svelte, and fully prerendered as static HTML for deployment.
This dashboard provides interactive visualizations and analytics for the IWAC dataset from Hugging Face (fmadore/islam-west-africa-collection), featuring:
The dashboard uses a static data generation approach:
scripts/) fetch data from Hugging Facestatic/data/ and build/data//data/[filename].json using fetch()export const prerender = true; for static site generationgenerate_overview_stats.py - Overall statistics and countsgenerate_index_entities.py - Entity data and bar chartsgenerate_language_facets.py - Language distribution datagenerate_treemap.py - Country treemap datagenerate_wordcloud.py - Word frequency datagenerate_timeline.py - Temporal analysis datagenerate_categories.py - Category distribution datagenerate_scary_terms.py - Concerning terminology analysiscd scripts
pip install -r requirements.txt
python generate_overview_stats.py
python generate_index_entities.py
python generate_language_facets.py
python generate_treemap.py
python generate_wordcloud.py
python generate_timeline.py
python generate_categories.py
python generate_scary_terms.py
Install dependencies:
npm install
Start the development server:
npm run dev
# or start and open in browser
npm run dev -- --open
iwac-dashboard/
βββ src/
β βββ lib/
β β βββ components/
β β β βββ controls/ # Controls (toggles)
β β β β βββ LanguageToggle.svelte # EN/FR language switcher
β β β β βββ ThemeToggle.svelte # Dark/light mode toggle
β β β β βββ index.ts # Barrel export
β β β βββ dashboard/ # Dashboard components
β β β β βββ OverviewStatsGrid.svelte # Overview statistics grid
β β β β βββ StatsCard.svelte # Statistics display card
β β β β βββ index.ts
β β β βββ facets/ # Faceted visualizations
β β β β βββ FacetPie.svelte # Pie chart facet
β β β βββ layout/ # Layout components
β β β β βββ AppSidebar.svelte # Navigation sidebar
β β β β βββ FullscreenToggle.svelte # Fullscreen mode toggle
β β β β βββ index.ts
β β β βββ lazy/ # Lazy loading components
β β β β βββ LazyLoad.svelte # Viewport lazy loading
β β β β βββ LazyComponent.svelte # Dynamic import lazy loading
β β β β βββ index.ts
β β β βββ ui/ # shadcn-svelte components
β β β β βββ card/ # Card component
β β β β βββ button/ # Button component
β β β β βββ table/ # Table component
β β β β βββ ... # Other UI components
β β β βββ utilities/ # Utility components
β β β β βββ SafeModeWatcher.svelte # Safe mode watcher
β β β β βββ UrlStateSync.svelte # URL state synchronization
β β β β βββ index.ts
β β β βββ visualizations/ # All visualizations
β β β βββ charts/
β β β β βββ d3/ # D3-based charts
β β β β β βββ BarChartRace.svelte
β β β β β βββ CooccurrenceMatrix.svelte
β β β β β βββ StackedBarChart.svelte
β β β β β βββ TimelineChart.svelte
β β β β β βββ WordAssociations.svelte
β β β β β βββ index.ts
β β β β βββ layerchart/ # LayerChart-based charts
β β β β β βββ Bar.svelte
β β β β β βββ Duration.svelte
β β β β β βββ PieChart.svelte
β β β β β βββ Tooltip.svelte
β β β β β βββ Treemap.svelte
β β β β β βββ index.ts
β β β β βββ utils.ts # Chart utilities
β β β β βββ index.ts
β β β βββ network/ # Network visualizations
β β β β βββ NetworkGraph.svelte
β β β β βββ NetworkControls.svelte
β β β β βββ NetworkNodePanel.svelte
β β β β βββ index.ts
β β β βββ world-map/ # Map visualizations
β β β β βββ WorldMapVisualization.svelte
β β β β βββ Map.svelte
β β β β βββ ChoroplethLayer.svelte
β β β β βββ index.ts
β β β βββ Wordcloud.svelte # Word cloud visualization
β β β βββ index.ts
β β βββ stores/ # Svelte stores
β β β βββ itemsStore.svelte.ts # Global data store
β β β βββ translationStore.svelte.ts # i18n translation store
β β β βββ ...
β β βββ types/ # TypeScript definitions
β β βββ hooks/ # Custom Svelte hooks
β β βββ utils/ # Utility functions
β βββ routes/ # SvelteKit file-based routing
β β βββ +layout.svelte # Root layout with sidebar
β β βββ +page.svelte # Overview dashboard (/)
β β βββ countries/+page.svelte # Country treemap view
β β βββ languages/+page.svelte # Language distribution
β β βββ entities/+page.svelte # Entity index table
β β βββ timeline/+page.svelte # Timeline analysis
β β βββ ...
β βββ app.html # HTML template
β βββ app.css # Global styles with CSS variables
βββ scripts/ # Python data generation scripts
βββ static/data/ # Static JSON data files
βββ build/ # Production build output
To create a production build:
npm run build
The build process:
build/Preview the production build:
npm run preview
npm run dev # Start development server
npm run build # Build for production
npm run preview # Preview production build
npm run check # Type-check with svelte-check
npm run check:watch # Type-check in watch mode
npm run format # Format code with Prettier
npm run lint # Lint code with ESLint and Prettier
npm test # Run all tests
npm run test:unit # Run unit tests with Vitest
npm run test:e2e # Run E2E tests with Playwright
npm run generate-icons # Generate PWA icons
This project uses Svelte 5 with runes mode exclusively:
<script>
// Props
let { count = 0 } = $props();
// State
let items = $state([]);
// Derived values
const doubled = $derived(count * 2);
// Effects
$effect(() => {
console.log('Count changed:', count);
});
</script>
Full bilingual support (English/French) with:
translationStore.ts)$t('key') for translation<script>
import { t, languageStore } from '$lib/stores/translationStore.js';
</script>
<h1>{$t('app.title')}</h1><p>{$t('stats.total_items')}</p>
src/app.css)mode-watcher package for theme managementThis is a fully static site that can be deployed to:
The site is configured for deployment at a subpath (/iwac-dashboard/) using the base path from $app/paths.
/data/*.jsonAlways reference CSS variables from our theme:
<!-- β
Correct -->
<div class="bg-background text-foreground">
<div class="border border-border bg-card text-card-foreground">
<span class="text-muted-foreground">Muted text</span>
</div>
</div>
<!-- β Wrong -->
<div class="bg-blue-500 text-white">
<span class="text-gray-500">Muted</span>
</div>
<script>
import { base } from '$app/paths';
let data = $state([]);
let loading = $state(true);
let error = $state(null);
async function loadData() {
try {
const response = await fetch(`${base}/data/filename.json`);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
data = await response.json();
} catch (e) {
error = e.message;
} finally {
loading = false;
}
}
$effect(() => {
loadData();
});
</script>
| Route | Description |
|---|---|
/ |
Overview dashboard with key statistics and charts |
/countries |
Interactive treemap of document distribution by country |
/languages |
Language distribution with pie charts and facets |
/entities |
Searchable entity index table with sorting and filtering |
/timeline |
Temporal analysis with timeline charts and growth metrics |
/categories |
Document categorization and distribution analysis |
/words |
Word cloud visualization of frequent terms |
/scary |
Analysis of concerning terminology patterns |
This dashboard visualizes the Islam West Africa Collection (IWAC) dataset:
fmadore/islam-west-africa-collection