Skip to content

Architecture Overview

The FiNAN website is built on three foundational architectural patterns that work together to create a fast, maintainable, and type-safe application.

The site uses Astro Islands - a pattern where interactive components are isolated islands of interactivity in an otherwise static page.

  1. Static by Default - Pages are pre-rendered as static HTML at build time
  2. Selective Hydration - Only interactive components load JavaScript
  3. Zero JavaScript Baseline - Most pages ship no JavaScript to the browser
  • Fast Page Loads - Static HTML loads instantly
  • Reduced Bundle Size - Only necessary JavaScript is shipped
  • Better SEO - Search engines see fully-rendered HTML
  • Improved Performance - Less JavaScript means better Core Web Vitals
src/components/Blog.astro
---
// This component is static - no JavaScript shipped to browser
import { getBlogPosts } from '@/lib/ghost';
const posts = await getBlogPosts();
---
<section class="blog-section">
{posts.map(post => (
<article>
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
</article>
))}
</section>

For interactive features, use client directives:

---
// Import a framework component (if needed)
import Accordion from './Accordion.jsx';
---
<!-- Load JavaScript only when visible -->
<Accordion client:visible />

The website uses TypeScript interfaces to ensure data consistency across the entire application.

All data is stored in src/data/ with TypeScript types:

src/data/
├── representation/
│ └── committee/
│ ├── types.ts # TypeScript interfaces
│ ├── finlandCommittee.ts # Typed data
│ ├── swedenCommittee.ts # Typed data
│ └── ... # Other countries
├── faqData.ts # FAQ data with types
└── siteConfig.ts # Site-wide configuration

Types are defined in types.ts files:

src/data/representation/committee/types.ts
export interface CommitteeMember {
name: string;
position: string;
photo: ImageMetadata;
country: string;
email?: string;
}
export interface CommitteeData {
members: CommitteeMember[];
established: string;
description: string;
}

Data files import and use these types:

src/data/representation/committee/finlandCommittee.ts
import type { CommitteeData } from './types';
import photoJohnDoe from '@/assets/images/committee/finland/john-doe.jpg';
export const finlandCommittee: CommitteeData = {
members: [
{
name: 'John Doe',
position: 'President',
photo: photoJohnDoe,
country: 'Finland',
email: 'john@example.com',
},
],
established: '2015',
description: 'Supporting Filipino nurses in Finland',
};
  • Compile-Time Validation - Errors caught before deployment
  • IntelliSense Support - Autocomplete in editors
  • Refactoring Safety - Change types, find all affected code
  • Documentation - Types serve as inline documentation

The website is built from reusable, composable components that encapsulate both structure and styling.

Pages (src/pages/)
└─ Layouts (src/layouts/)
└─ Components (src/components/)
  1. Layout Components - Page structure and common elements

    • BaseLayout.astro - HTML boilerplate, SEO, global styles
    • MainLayout.astro - Navigation and footer wrapper
  2. Feature Components - Reusable sections

    • Committee.astro - Committee member grid
    • FAQAccordion.astro - FAQ with expand/collapse
    • HeroHeader.astro - Hero section with background
  3. Utility Components - Small, focused elements

    • StructuredData.astro - JSON-LD schema
    • Navbar.astro - Navigation bar
    • Footer.astro - Site footer

All components use TypeScript for props:

src/components/Committee.astro
---
import type { CommitteeMember } from '@/data/representation/committee/types';
interface Props {
members: CommitteeMember[];
country: string;
showEmail?: boolean;
}
const { members, country, showEmail = false } = Astro.props;
---
<section class="committee">
<h2>{country} Committee</h2>
<div class="members-grid">
{members.map(member => (
<div class="member-card">
<img src={member.photo.src} alt={member.name} />
<h3>{member.name}</h3>
<p>{member.position}</p>
{showEmail && member.email && (
<a href={`mailto:${member.email}`}>{member.email}</a>
)}
</div>
))}
</div>
</section>

Pages compose multiple components:

src/pages/representation/finland.astro
---
import MainLayout from '@/layouts/MainLayout.astro';
import PageHeader from '@/components/PageHeader.astro';
import Committee from '@/components/Committee.astro';
import RepresentationContactSection from '@/components/RepresentationContactSection.astro';
import { finlandCommittee } from '@/data/representation/committee/finlandCommittee';
const seo = {
title: 'Finland Representation | FiNAN',
description: 'Meet the FiNAN Finland committee members',
};
---
<MainLayout seo={seo}>
<PageHeader
title="Finland Representation"
subtitle="Supporting Filipino nurses across Finland"
/>
<Committee
members={finlandCommittee.members}
country="Finland"
showEmail={true}
/>
<RepresentationContactSection country="Finland" />
</MainLayout>
  • Reusability - Write once, use everywhere
  • Maintainability - Changes in one place affect all usages
  • Testability - Components can be tested in isolation
  • Type Safety - Props are validated at build time

Example: Adding a New Committee Member

  1. Type Safety ensures the member object has required fields
  2. Data Layer stores the member in a typed configuration file
  3. Component renders the member using the Committee component
  4. Astro Islands pre-renders the HTML at build time (no JavaScript)

Result: Fast, type-safe, maintainable update.

  • Content-Focused - Perfect for documentation and informational sites
  • Performance - Ships minimal JavaScript by default
  • Developer Experience - Great TypeScript support and tooling
  • SEO-Friendly - Static HTML is ideal for search engines
  • Safety - Catch errors before deployment
  • Tooling - Better editor support and refactoring
  • Documentation - Types document expected data structures
  • Confidence - Refactor with confidence
  • Scalability - Easy to add new pages and features
  • Consistency - Shared components ensure visual consistency
  • Collaboration - Multiple developers can work on different components
  • Maintenance - Changes propagate automatically

Data Configuration

Learn how to create and manage typed data configurations

View Guide →

Asset Management

Understand where to place images and how they’re optimized

View Guide →

Creating Components

Learn the patterns for building reusable components

View Guide →