Committee Management
Complete step-by-step guide for managing committee members
Asset management in Astro involves understanding where to place files and how they’re processed. The FiNAN website uses two directories for assets, each with different purposes.
finan-website/├── src/assets/ # Processed by Astro (optimized)│ └── images/│ └── committee/ # Committee member photos└── public/ # Served as-is (not processed) ├── images/ ├── favicon.svg └── robots.txtUse src/assets/ for images that need optimization.
When you import an image from src/assets/, Astro:
---import type { CommitteeMember } from '@/data/representation/committee/types';
interface Props { members: CommitteeMember[];}
const { members } = Astro.props;---
<div class="members-grid"> {members.map(member => ( <div class="member-card"> <!-- Image is optimized automatically --> <img src={member.photo.src} alt={member.name} width={member.photo.width} height={member.photo.height} /> <h3>{member.name}</h3> <p>{member.position}</p> </div> ))}</div>import type { CommitteeData } from './types';
// Import images from src/assets/import photoJohnDoe from '@/assets/images/committee/finland/john-doe.jpg';import photoJaneSmith from '@/assets/images/committee/finland/jane-smith.jpg';
export const finlandCommittee: CommitteeData = { members: [ { name: 'John Doe', position: 'President', photo: photoJohnDoe, // ImageMetadata object country: 'Finland', }, { name: 'Jane Smith', position: 'Secretary', photo: photoJaneSmith, // ImageMetadata object country: 'Finland', }, ], established: '2015', description: 'Supporting Filipino nurses in Finland',};When you import an image, you get an ImageMetadata object:
import myPhoto from '@/assets/images/committee/finland/john-doe.jpg';
console.log(myPhoto);// {// src: "/_astro/john-doe.a1b2c3d4.jpg",// width: 800,// height: 1000,// format: "jpg"// }This metadata is used for:
width and height attributes (prevents layout shift)srcset for different screen sizesUse public/ for assets that should be served as-is without processing.
favicon.svg or favicon.icorobots.txtsitemap.xmlog-image.jpg)Files in public/ are:
/public/image.jpg becomes /image.jpg/image.jpg not @/public/image.jpg---const seo = { title: 'FiNAN', description: 'Filipino Nurses Association in the Nordic Region', ogImage: '/images/og-image.jpg', // Served from public/images/og-image.jpg};---
<head> <meta property="og:image" content={seo.ogImage} /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" /></head>If you’re a content editor adding images, use this decision tree:
Is this a committee member photo? └─ YES → src/assets/images/committee/[country]/
Is this a logo or partner image? └─ YES → src/assets/images/partners/ or logos/
Is this a hero background or banner? └─ YES → src/assets/images/heroes/
Is this an Open Graph image for social media? └─ YES → public/images/
Is this a favicon or robots.txt? └─ YES → public/Most important for content editors!
src/assets/images/committee/├── finland/│ ├── john-doe.jpg│ ├── jane-smith.jpg│ └── mike-johnson.jpg├── sweden/│ ├── anna-svensson.jpg│ └── lars-andersson.jpg├── norway/│ └── ...└── [other countries]/john-doe.jpgjane-smith.jpgmaria-garcia.jpganna-svensson.jpgJohn Doe.jpg # Has spacesjohn_doe.jpg # Uses underscoresJohnDoe.jpg # Not lowercasejohn-doe.png # Inconsistent format (prefer .jpg).jpg) preferred for photosPrepare the photo
.jpg)john-doe.jpgUpload to correct country folder
Navigate to src/assets/images/committee/[country]/ and add your photo.
Example for Finland: src/assets/images/committee/finland/john-doe.jpg
Import in committee data file
Open the committee file (e.g., src/data/representation/committee/finlandCommittee.ts):
// Add at the top with other importsimport photoJohnDoe from '@/assets/images/committee/finland/john-doe.jpg';Add member to array
export const finlandCommittee: CommitteeData = { members: [ { name: 'John Doe', position: 'President', photo: photoJohnDoe, // Use the imported variable country: 'Finland', }, // ... other members ], // ...};Verify the build
Run pnpm build to ensure no errors. If successful, your image is properly configured!
❌ Wrong:
{ name: 'John Doe', photo: '/images/committee/finland/john-doe.jpg', // String path}✅ Correct:
import photoJohnDoe from '@/assets/images/committee/finland/john-doe.jpg';
{ name: 'John Doe', photo: photoJohnDoe, // Imported ImageMetadata object}❌ Wrong:
import photoJohnDoe from '@/assets/committee/finland/john-doe.jpg';// Missing "images" in path✅ Correct:
import photoJohnDoe from '@/assets/images/committee/finland/john-doe.jpg';❌ Confusing:
import johnDoe from '@/assets/images/committee/finland/john-doe.jpg';✅ Clear:
import photoJohnDoe from '@/assets/images/committee/finland/john-doe.jpg';Convention: Use photo prefix for all committee member photo imports.
❌ Wrong:
import photoJohnDoe from '@/assets/images/committee/finland/john-doe.png';// File is actually .jpg✅ Correct:
import photoJohnDoe from '@/assets/images/committee/finland/john-doe.jpg';When you build the site:
Format Conversion
Responsive Sizes
Content Hashing
john-doe.a1b2c3d4.jpgMetadata Extraction
For more control, use Astro’s <Image> component:
---import { Image } from 'astro:assets';import heroImage from '@/assets/images/heroes/main-hero.jpg';---
<Image src={heroImage} alt="FiNAN Hero" width={1920} height={1080} format="webp" quality={80} loading="lazy"/>Benefits:
srcset generationError:
Cannot find module '@/assets/images/committee/finland/john-doe.jpg'Solutions:
@/assets/ not @/public/Problem: Image shows broken link icon
Solutions:
photo property uses imported variable, not stringpnpm build to see if there are type errorsError:
Type 'string' is not assignable to type 'ImageMetadata'Solution: You’re using a string path instead of imported image:
// ❌ Wrongphoto: '/path/to/image.jpg'
// ✅ Correctimport photoName from '@/assets/images/committee/country/name.jpg';photo: photoNameCommittee Management
Complete step-by-step guide for managing committee members
Data Configuration
Learn how committee data is structured and typed
Creating Components
Learn how components use optimized images