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.
- Static by Default - Pages are pre-rendered as static HTML at build time
- Selective Hydration - Only interactive components load JavaScript
- 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
// This component is static - no JavaScript shipped to browser
import { getBlogPosts } from '@/lib/ghost';
const posts = await getBlogPosts();
<section class="blog-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:
│ ├── 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:
export interface CommitteeMember {
export interface CommitteeData {
members: CommitteeMember[];
Data files import and use these types:
import type { CommitteeData } from './types';
import photoJohnDoe from '@/assets/images/committee/finland/john-doe.jpg';
export const finlandCommittee: CommitteeData = {
email: 'john@example.com',
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.
└─ Layouts (src/layouts/)
└─ Components (src/components/)
-
Layout Components - Page structure and common elements
BaseLayout.astro - HTML boilerplate, SEO, global styles
MainLayout.astro - Navigation and footer wrapper
-
Feature Components - Reusable sections
Committee.astro - Committee member grid
FAQAccordion.astro - FAQ with expand/collapse
HeroHeader.astro - Hero section with background
-
Utility Components - Small, focused elements
StructuredData.astro - JSON-LD schema
Navbar.astro - Navigation bar
Footer.astro - Site footer
All components use TypeScript for props:
import type { CommitteeMember } from '@/data/representation/committee/types';
members: CommitteeMember[];
const { members, country, showEmail = false } = Astro.props;
<section class="committee">
<h2>{country} Committee</h2>
<div class="members-grid">
<div class="member-card">
<img src={member.photo.src} alt={member.name} />
{showEmail && member.email && (
<a href={`mailto:${member.email}`}>{member.email}</a>
Pages compose multiple components:
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';
title: 'Finland Representation | FiNAN',
description: 'Meet the FiNAN Finland committee members',
title="Finland Representation"
subtitle="Supporting Filipino nurses across Finland"
members={finlandCommittee.members}
<RepresentationContactSection country="Finland" />
- 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
- Type Safety ensures the member object has required fields
- Data Layer stores the member in a typed configuration file
- Component renders the member using the Committee component
- 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 →