sikhaid-routing
Use when adding routes, navigation, or understanding URL structure in SikhAid project. Covers SvelteKit file-based routing, dynamic routes with slugs, layout hierarchy, admin routes, and navigation patterns.
When & Why to Use This Skill
This Claude skill provides a comprehensive framework for managing routing and navigation within the SikhAid project. It leverages SvelteKit's file-based routing system to handle dynamic slugs, nested layout hierarchies, and protected admin dashboards. By centralizing URL structures and navigation patterns, it ensures architectural consistency and simplifies the process of expanding the application's page structure.
Use Cases
- Case 1: Adding new public pages or features (e.g., a new 'Impact' page) by following the established SvelteKit file-based routing conventions.
- Case 2: Implementing dynamic routing for campaigns or blog posts to automatically generate SEO-friendly URLs based on content slugs.
- Case 3: Managing protected admin routes, including dashboard access, form submission views, and content management sections with built-in authentication checks.
- Case 4: Configuring layout hierarchies to conditionally render global components like headers and footers based on the current route (e.g., hiding them for admin views).
- Case 5: Implementing advanced navigation patterns such as programmatic redirects, active link highlighting in menus, and smooth scroll behaviors.
| name | sikhaid-routing |
|---|---|
| description | Use when adding routes, navigation, or understanding URL structure in SikhAid project. Covers SvelteKit file-based routing, dynamic routes with slugs, layout hierarchy, admin routes, and navigation patterns. |
| allowed-tools | Read, Write, Edit, Glob |
SikhAid Routing & Navigation
SvelteKit File-Based Routing
Routing Convention
- File:
src/routes/[path]/+page.svelte→ URL:/[path] - Layout:
+layout.sveltewraps all child routes - Dynamic:
[param]creates dynamic route segments
Route Structure Overview
src/routes/
├── +layout.svelte → Wraps ALL routes
├── +page.svelte → / (home)
│
├── about/
│ └── +page.svelte → /about
│
├── campaigns/
│ ├── +page.svelte → /campaigns (all campaigns)
│ └── [slug]/
│ └── +page.svelte → /campaigns/:slug (dynamic)
│
├── blog/
│ ├── +page.svelte → /blog (all posts)
│ └── [slug]/
│ └── +page.svelte → /blog/:slug (dynamic)
│
├── contact/
│ └── +page.svelte → /contact
│
├── donate/
│ └── +page.svelte → https://donate.sikhaid.ngo/
│
├── volunteering/
│ └── +page.svelte → /volunteering
│
├── csr/
│ └── +page.svelte → /csr (CSR partnerships)
│
├── payment/
│ ├── success/
│ │ └── +page.svelte → /payment/success
│ └── failure/
│ └── +page.svelte → /payment/failure
│
└── admin/
├── +layout.svelte → Nested admin layout
├── +page.svelte → /admin (dashboard)
├── formsubmissions/
│ └── +page.svelte → /admin/formsubmissions
├── blogs/
│ └── +page.svelte → /admin/blogs
├── campaigns/
│ └── +page.svelte → /admin/campaigns
├── donations/
│ └── +page.svelte → /admin/donations (Added Nov 2025)
└── content/
└── +page.svelte → /admin/content (Added Nov 2025)
All Routes Reference
Public Routes
| URL | File | Purpose | Navigation Link |
|---|---|---|---|
/ |
routes/+page.svelte |
Home page with hero, campaigns, impact | Header logo |
/about |
routes/about/+page.svelte |
About organization | Header nav |
/campaigns |
routes/campaigns/+page.svelte |
All campaigns listing | Header nav |
/campaigns/:slug |
routes/campaigns/[slug]/+page.svelte |
Single campaign details | Campaign cards |
/blog |
routes/blog/+page.svelte |
All blog posts | Header nav |
/blog/:slug |
routes/blog/[slug]/+page.svelte |
Single blog post | Blog cards |
https://donate.sikhaid.ngo/ |
routeshttps://donate.sikhaid.ngo//+page.svelte |
Donation page with payment form | Header CTA, Hero CTA |
/contact |
routes/contact/+page.svelte |
Contact form | Footer |
/volunteering |
routes/volunteering/+page.svelte |
Volunteer opportunities & form | Header dropdown |
/csr |
routes/csr/+page.svelte |
CSR partnership inquiry | Header dropdown |
/payment/success |
routes/payment/success/+page.svelte |
Payment success confirmation | Razorpay redirect |
/payment/failure |
routes/payment/failure/+page.svelte |
Payment failure page | Razorpay redirect |
Protected Admin Routes
| URL | File | Purpose | Access |
|---|---|---|---|
/admin |
routes/admin/+page.svelte |
Admin dashboard | Login required |
/admin/formsubmissions |
routes/admin/formsubmissions/+page.svelte |
View all form submissions | Login required |
/admin/blogs |
routes/admin/blogs/+page.svelte |
Manage blog posts | Login required |
/admin/campaigns |
routes/admin/campaigns/+page.svelte |
Manage campaigns | Login required |
/admin/donations |
routes/admin/donations/+page.svelte |
View all donations (Added Nov 2024) | Login required |
/admin/content |
routes/admin/content/+page.svelte |
Manage celebrity endorsements and testimonials (Added Nov 2025) | Login required |
Layout Hierarchy
Root Layout
File: src/routes/+layout.svelte
Wraps: All routes
Contains:
- Header component (conditionally hidden on admin routes)
- Footer component (conditionally hidden on admin routes)
- Razorpay script loader
- Page slot:
<slot />
Key Logic:
<script lang="ts">
import { page } from '$app/stores';
import Header from '$lib/components/Header.svelte';
import Footer from '$lib/components/Footer.svelte';
$: isAdminRoute = $page.url.pathname.startsWith('/admin');
</script>
{#if !isAdminRoute}
<Header />
{/if}
<slot />
{#if !isAdminRoute}
<Footer />
{/if}
Admin Nested Layout
File: src/routes/admin/+layout.svelte
Wraps: All /admin/* routes
Contains:
- Admin-specific styling
- Admin navigation (if any)
- Inherits from root layout
Dynamic Routes
Campaign Dynamic Route
File: src/routes/campaigns/[slug]/+page.svelte
Purpose: Display individual campaign based on URL slug
Pattern:
<script lang="ts">
import { page } from '$app/stores';
import { campaigns } from '$lib/data/campaigns';
import type { Campaign } from '$lib/types/campaign';
// Extract slug from URL
$: slug = $page.params.slug;
// Find campaign by slug
$: campaign = campaigns.find((c: Campaign) => c.slug === slug);
// Handle not found
$: if (!campaign) {
// Optionally redirect or show 404
}
</script>
<div>
<h1>{campaign.title}</h1>
<p>{campaign.fullDescription}</p>
<!-- Campaign content -->
</div>
Example URLs:
/campaigns/langar-aid→ Shows Langar Aid campaign/campaigns/blanket-distribution→ Shows Blanket Distribution campaign/campaigns/punjab-floods-2025→ Shows Punjab Floods campaign
Blog Dynamic Route
File: src/routes/blog/[slug]/+page.svelte
Purpose: Display individual blog post based on URL slug
Pattern: Same as campaigns, uses $page.params.slug
Example URLs:
/blog/langar-seva-impact→ Shows specific blog post/blog/winter-relief-2024→ Shows another blog post
Navigation Patterns
Programmatic Navigation
<script lang="ts">
import { goto } from '$app/navigation';
function navigateToCampaign(slug: string) {
goto(`/campaigns/${slug}`);
}
function goBack() {
goto(-1); // Go back one page
}
</script>
<button on:click={() => goto('https://donate.sikhaid.ngo/')}>
Donate Now
</button>
<button on:click={() => navigateToCampaign('langar-aid')}>
View Campaign
</button>
Link Navigation (Standard)
<a href="/about">About Us</a>
<a href="/campaigns">View Campaigns</a>
<a href={`/campaigns/${campaign.slug}`}>View {campaign.title}</a>
Active Route Highlighting
<script lang="ts">
import { page } from '$app/stores';
$: currentPath = $page.url.pathname;
$: isActive = (path: string) => currentPath === path;
</script>
<nav>
<a
href="/about"
class="nav-link"
class:active={isActive('/about')}
>
About
</a>
<a
href="/campaigns"
class="nav-link"
class:active={isActive('/campaigns')}
>
Campaigns
</a>
</nav>
<style>
.nav-link.active {
color: var(--orange);
font-weight: 600;
}
</style>
Dropdown Menu Navigation
Example from Header.svelte:
<script lang="ts">
let isDropdownOpen = false;
</script>
<div class="relative">
<button
on:click={() => isDropdownOpen = !isDropdownOpen}
class="dropdown-trigger"
>
Get Involved
</button>
{#if isDropdownOpen}
<div class="dropdown-menu">
<a href="/volunteering" on:click={() => isDropdownOpen = false}>
Volunteer
</a>
<a href="/csr" on:click={() => isDropdownOpen = false}>
CSR Partnerships
</a>
</div>
{/if}
</div>
Admin Authentication Flow
Login Process
- User clicks "Admin" in Footer
- Modal popup with password input
- Password validation:
Raunak@123(hardcoded in Footer.svelte:29) - On success: Set cookie
admin_session=raunak_${timestamp} - Cookie expires after 3600 seconds (1 hour)
- Navigate to
/admin
Cookie Check (Client-Side)
// Check if admin session exists
const cookies = document.cookie.split(';');
const hasAdminSession = cookies.some(cookie =>
cookie.trim().startsWith('admin_session=')
);
if (!hasAdminSession) {
// Redirect to home or show login
goto('/');
}
Logout
// Clear cookie
document.cookie = 'admin_session=; max-age=0; path=/';
goto('/');
Header Navigation Structure
File: src/lib/components/Header.svelte
Desktop Navigation
Logo | About | Campaigns | Blog | [Get Involved ▼] | Donate (CTA)
├─ Volunteer
└─ CSR Partnerships
Mobile Navigation
Logo [☰ Menu]
[When menu open:]
├─ About
├─ Campaigns
├─ Blog
├─ Get Involved
│ ├─ Volunteer
│ └─ CSR
└─ Donate
Footer Navigation Structure
File: src/lib/components/Footer.svelte
Sections
- About Section - Organization description
- Quick Links
- Home
- About Us
- Campaigns
- Contact
- Get Involved
- Volunteer
- CSR Partnerships
- Contact Info
- Address
- Phone
- Social Media Links
- Admin Login (hidden link/button)
Scroll Behaviors
Smooth Scroll to Section
<script lang="ts">
function scrollToDonation() {
const element = document.getElementById('donation-form');
element?.scrollIntoView({ behavior: 'smooth' });
}
</script>
<button on:click={scrollToDonation}>
Donate Now
</button>
Scroll to Top on Navigation
<script lang="ts">
import { afterNavigate } from '$app/navigation';
afterNavigate(() => {
window.scrollTo(0, 0);
});
</script>
Route Parameters & Query Strings
Accessing Route Parameters
<script lang="ts">
import { page } from '$app/stores';
// URL: /campaigns/langar-aid
$: slug = $page.params.slug; // 'langar-aid'
</script>
Accessing Query Parameters
<script lang="ts">
import { page } from '$app/stores';
// URL: /campaigns?category=education&status=ongoing
$: category = $page.url.searchParams.get('category'); // 'education'
$: status = $page.url.searchParams.get('status'); // 'ongoing'
</script>
Setting Query Parameters
<script lang="ts">
import { goto } from '$app/navigation';
function filterCampaigns(category: string) {
goto(`/campaigns?category=${category}`);
}
</script>
<button on:click={() => filterCampaigns('education')}>
Education Campaigns
</button>
Preloading Patterns
Hover Preload (Default)
SvelteKit automatically preloads routes on hover (configured in app.html):
<body data-sveltekit-preload-data="hover">
Programmatic Preload
<script lang="ts">
import { preloadData } from '$app/navigation';
async function preloadCampaign(slug: string) {
await preloadData(`/campaigns/${slug}`);
}
</script>
<a
href="/campaigns/langar-aid"
on:mouseenter={() => preloadCampaign('langar-aid')}
>
Langar Aid Campaign
</a>
Adding New Routes
Step-by-Step: Add New Public Page
Create route file:
src/routes/new-page/+page.svelteAdd basic page structure:
<script lang="ts"> // Imports and logic </script> <main class="container mx-auto px-4 py-16"> <h1 class="text-5xl font-bold text-navy-custom mb-8"> New Page Title </h1> <!-- Page content --> </main>Add to Header navigation: Open
src/lib/components/Header.svelte, add link:<a href="/new-page" class:active={isActive('/new-page')}> New Page </a>Test route:
- Navigate to
http://localhost:5173/new-page - Verify Header/Footer appear
- Check mobile responsiveness
- Navigate to
Step-by-Step: Add Dynamic Route
Create dynamic route folder:
src/routes/resources/[id]/+page.svelteAccess parameter:
<script lang="ts"> import { page } from '$app/stores'; $: resourceId = $page.params.id; </script>Fetch or filter data:
<script lang="ts"> import { resources } from '$lib/data/resources'; $: resource = resources.find(r => r.id === resourceId); </script>
Step-by-Step: Add Admin Route
Create route under admin:
src/routes/admin/new-section/+page.svelteAdd authentication check:
<script lang="ts"> import { onMount } from 'svelte'; import { goto } from '$app/navigation'; onMount(() => { const hasSession = document.cookie.includes('admin_session='); if (!hasSession) { goto('/'); } }); </script>Add to admin navigation (if admin has nav menu)
Route automatically inherits admin layout (no Header/Footer)
Common Routing Patterns
Redirect After Action
<script lang="ts">
import { goto } from '$app/navigation';
async function handleSubmit() {
await submitForm();
goto('/thank-you');
}
</script>
Conditional Navigation
<script lang="ts">
import { goto } from '$app/navigation';
function navigateBasedOnRole(role: string) {
if (role === 'admin') {
goto('/admin');
} else {
goto('/dashboard');
}
}
</script>
External Links
<!-- Opens in new tab -->
<a href="https://example.com" target="_blank" rel="noopener noreferrer">
External Link
</a>
<!-- Programmatic -->
<button on:click={() => window.open('https://example.com', '_blank')}>
Open External
</button>
Route-Specific Metadata
Page Title & Meta Tags
<svelte:head>
<title>Campaign Name - Sikh Aid</title>
<meta name="description" content="Campaign description..." />
<meta property="og:title" content="Campaign Name" />
<meta property="og:image" content="/images/campaign.jpg" />
</svelte:head>
<main>
<!-- Page content -->
</main>
When to Use This Skill
- Adding new pages or routes
- Creating dynamic routes with parameters
- Understanding navigation structure
- Implementing navigation patterns
- Setting up admin routes
- Working with route parameters or query strings
- Configuring layouts and route hierarchies
Related Skills
sikhaid-overview- Project structure and setupsikhaid-components- Header and navigation componentssikhaid-data- Data loading for dynamic routes