iwac-dashboard Svelte Themes

Iwac Dashboard

Interactive data visualization dashboard for the Islam West Africa Collection (IWAC) dataset, built with SvelteKit and featuring charts, treemaps, word clouds, and bilingual support.

IWAC Dashboard

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.

Overview

This dashboard provides interactive visualizations and analytics for the IWAC dataset from Hugging Face (fmadore/islam-west-africa-collection), featuring:

  • πŸ“Š Overview Dashboard - Key statistics and summary cards
  • πŸ—ΊοΈ Country Treemap - Hierarchical visualization of document distribution by country
  • 🌍 Language Analysis - Distribution of documents by language with pie charts
  • πŸ“š Entity Index - Searchable, sortable table of all entities with filtering
  • πŸ“ˆ Timeline View - Temporal analysis of document creation and growth
  • 🏷️ Categories - Document categorization and distribution
  • πŸ” Word Cloud - Most frequent terms across the collection
  • ⚠️ Scary Terms - Analysis of concerning terminology patterns
  • 🌐 Bilingual Support - Full English/French interface with real-time switching
  • 🎨 Dark/Light Mode - Theme switching with system preference detection
  • πŸ“± PWA Support - Progressive Web App with offline capabilities

Data Flow

The dashboard uses a static data generation approach:

  1. Python Scripts (in scripts/) fetch data from Hugging Face
  2. Scripts process and generate static JSON files
  3. JSON files saved to both static/data/ and build/data/
  4. Svelte components fetch from /data/[filename].json using fetch()
  5. All pages use export const prerender = true; for static site generation

Python Data Generators

  • generate_overview_stats.py - Overall statistics and counts
  • generate_index_entities.py - Entity data and bar charts
  • generate_language_facets.py - Language distribution data
  • generate_treemap.py - Country treemap data
  • generate_wordcloud.py - Word frequency data
  • generate_timeline.py - Temporal analysis data
  • generate_categories.py - Category distribution data
  • generate_scary_terms.py - Concerning terminology analysis

Running Data Generation

cd 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

Developing

Install dependencies:

npm install

Start the development server:

npm run dev

# or start and open in browser
npm run dev -- --open

Technology Stack

  • Framework: SvelteKit with Svelte 5 (runes mode) and TypeScript
  • UI Components: shadcn-svelte (Card, Button, Table, Skeleton, etc.)
  • Styling: Tailwind CSS v4 with CSS variables theming
  • Visualizations:
    • LayerChart (preferred for new charts)
    • D3.js (custom visualizations, treemaps, word clouds)
    • ECharts (complex charts with many options)
  • Icons: Lucide Svelte
  • Theme Management: mode-watcher
  • Data Processing: Python scripts generating static JSON files
  • Testing: Vitest (unit) + Playwright (E2E)
  • Build Tool: Vite
  • PWA: @vite-pwa/sveltekit
  • Adapter: @sveltejs/adapter-static (full prerendering)

Project Structure

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

Building

To create a production build:

npm run build

The build process:

  1. Prerenders all pages to static HTML
  2. Copies static assets to build/
  3. Generates service worker for PWA
  4. Creates a fully static site ready for deployment

Preview the production build:

npm run preview

Available Scripts

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

Key Features

Svelte 5 Runes Mode

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>

Internationalization (i18n)

Full bilingual support (English/French) with:

  • Store-based translation system (translationStore.ts)
  • Language toggle component in header
  • All text uses $t('key') for translation
  • Charts and visualizations update reactively with language changes
<script>
    import { t, languageStore } from '$lib/stores/translationStore.js';
</script>

<h1>{$t('app.title')}</h1><p>{$t('stats.total_items')}</p>

Theme System

  • Dark/light mode with system preference detection
  • CSS variables for theming (in src/app.css)
  • mode-watcher package for theme management
  • All colors use CSS variables for theme compatibility

PWA Support

  • Progressive Web App with offline capabilities
  • Service worker for caching
  • Manifest file for installation
  • Generated icons in multiple sizes

Deployment

This is a fully static site that can be deployed to:

  • GitHub Pages
  • Netlify
  • Vercel
  • Any static hosting service

The site is configured for deployment at a subpath (/iwac-dashboard/) using the base path from $app/paths.

Development Guidelines

Critical Rules

  1. Always use Svelte 5 syntax - No Svelte 4 patterns
  2. Use shadcn-svelte components - Never create custom basic UI
  3. Use CSS variables - No hardcoded colors
  4. Static JSON data only - All data from /data/*.json
  5. Bilingual required - All text must support EN/FR
  6. LayerChart preferred - Use LayerChart for new visualizations

Color System

Always 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>

Data Loading Pattern

<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>

Pages Overview

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

Dataset

This dashboard visualizes the Islam West Africa Collection (IWAC) dataset:

  • Source: Hugging Face Dataset fmadore/islam-west-africa-collection
  • Content: Islamic manuscripts, documents, and texts from West Africa
  • Countries: CΓ΄te d'Ivoire, Burkina Faso, Benin, Togo, Niger, Nigeria
  • Languages: Multiple languages including Arabic, French, English, and local languages

Top categories

Loading Svelte Themes