From 6e613aad1773373fcc25349ece7d7303acd68e5c Mon Sep 17 00:00:00 2001 From: sasha-astiadi Date: Tue, 22 Jul 2025 15:09:30 +0200 Subject: [PATCH] add people --- docs/adding-people.md | 167 ++++++++----- package.json | 6 +- public/images/people/Malte_Geierhos/index.md | 21 ++ scripts/generate-all-people.js | 230 ++++++++++++++++++ scripts/generate-people-data.js | 127 ++++++++++ src/app/people/Adnan_Fatayerji/page.tsx | 6 +- src/app/people/Malte_Geierhos/page.tsx | 19 ++ src/app/people/alexandre_hannelas/page.tsx | 19 ++ src/app/people/amrit_gayan/page.tsx | 19 ++ src/app/people/chris_camponovo/page.tsx | 19 ++ src/app/people/florian_fournier/page.tsx | 19 ++ src/app/people/gregory_flipo/page.tsx | 19 ++ src/app/people/hugo_mathecowitsch/page.tsx | 19 ++ src/app/people/jan_de_landtsheer/page.tsx | 19 ++ src/app/people/karoline_zizka/page.tsx | 19 ++ src/app/people/kristof_de_spiegeleer/page.tsx | 19 ++ src/app/people/marion_ravarino/page.tsx | 19 ++ src/app/people/michel_coucke/page.tsx | 19 ++ src/app/people/nousrath_bhugeloo/page.tsx | 19 ++ src/app/people/owen_kemp/page.tsx | 19 ++ src/app/people/sacha_obeegadoo/page.tsx | 19 ++ src/app/people/sam_taggart/page.tsx | 19 ++ src/app/people/sasha_astiadi/page.tsx | 19 ++ src/app/people/timur_gordon/page.tsx | 19 ++ src/app/people/vianney_spriet/page.tsx | 19 ++ src/components/PeopleHero.tsx | 7 +- ...le_Adnan.tsx => People_Adnan_Fateryji.tsx} | 2 +- .../people/People_Alexandre_Hannelas.tsx | 21 ++ src/components/people/People_Amrit_Gayan.tsx | 21 ++ .../people/People_Chris_Camponovo.tsx | 21 ++ .../people/People_Florian_Fournier.tsx | 21 ++ .../people/People_Gregory_Flipo.tsx | 21 ++ .../people/People_Hugo_Mathecowitsch.tsx | 21 ++ .../people/People_Jan_De_Landtsheer.tsx | 21 ++ .../people/People_Karoline_Zizka.tsx | 21 ++ .../people/People_Kristof_de_Spiegeleer.tsx | 24 ++ .../people/People_Malte_Geierhos.tsx | 21 ++ .../people/People_Marion_Ravarino.tsx | 21 ++ .../people/People_Michel_Coucke.tsx | 21 ++ .../people/People_Nousrath_Bhugeloo.tsx | 21 ++ src/components/people/People_Owen_Kemp.tsx | 21 ++ .../people/People_Sacha_Obeegadoo.tsx | 21 ++ src/components/people/People_Sam_Taggart.tsx | 21 ++ .../people/People_Sasha_Astiadi.tsx | 21 ++ src/components/people/People_Timur_Gordon.tsx | 21 ++ .../people/People_Vianney_Spriet.tsx | 21 ++ src/lib/peopleData.ts | 201 +++++++++++++-- 47 files changed, 1443 insertions(+), 87 deletions(-) create mode 100644 public/images/people/Malte_Geierhos/index.md create mode 100644 scripts/generate-all-people.js create mode 100644 scripts/generate-people-data.js create mode 100644 src/app/people/Malte_Geierhos/page.tsx create mode 100644 src/app/people/alexandre_hannelas/page.tsx create mode 100644 src/app/people/amrit_gayan/page.tsx create mode 100644 src/app/people/chris_camponovo/page.tsx create mode 100644 src/app/people/florian_fournier/page.tsx create mode 100644 src/app/people/gregory_flipo/page.tsx create mode 100644 src/app/people/hugo_mathecowitsch/page.tsx create mode 100644 src/app/people/jan_de_landtsheer/page.tsx create mode 100644 src/app/people/karoline_zizka/page.tsx create mode 100644 src/app/people/kristof_de_spiegeleer/page.tsx create mode 100644 src/app/people/marion_ravarino/page.tsx create mode 100644 src/app/people/michel_coucke/page.tsx create mode 100644 src/app/people/nousrath_bhugeloo/page.tsx create mode 100644 src/app/people/owen_kemp/page.tsx create mode 100644 src/app/people/sacha_obeegadoo/page.tsx create mode 100644 src/app/people/sam_taggart/page.tsx create mode 100644 src/app/people/sasha_astiadi/page.tsx create mode 100644 src/app/people/timur_gordon/page.tsx create mode 100644 src/app/people/vianney_spriet/page.tsx rename src/components/people/{People_Adnan.tsx => People_Adnan_Fateryji.tsx} (96%) create mode 100644 src/components/people/People_Alexandre_Hannelas.tsx create mode 100644 src/components/people/People_Amrit_Gayan.tsx create mode 100644 src/components/people/People_Chris_Camponovo.tsx create mode 100644 src/components/people/People_Florian_Fournier.tsx create mode 100644 src/components/people/People_Gregory_Flipo.tsx create mode 100644 src/components/people/People_Hugo_Mathecowitsch.tsx create mode 100644 src/components/people/People_Jan_De_Landtsheer.tsx create mode 100644 src/components/people/People_Karoline_Zizka.tsx create mode 100644 src/components/people/People_Kristof_de_Spiegeleer.tsx create mode 100644 src/components/people/People_Malte_Geierhos.tsx create mode 100644 src/components/people/People_Marion_Ravarino.tsx create mode 100644 src/components/people/People_Michel_Coucke.tsx create mode 100644 src/components/people/People_Nousrath_Bhugeloo.tsx create mode 100644 src/components/people/People_Owen_Kemp.tsx create mode 100644 src/components/people/People_Sacha_Obeegadoo.tsx create mode 100644 src/components/people/People_Sam_Taggart.tsx create mode 100644 src/components/people/People_Sasha_Astiadi.tsx create mode 100644 src/components/people/People_Timur_Gordon.tsx create mode 100644 src/components/people/People_Vianney_Spriet.tsx diff --git a/docs/adding-people.md b/docs/adding-people.md index b6ab7f0..bf424b4 100644 --- a/docs/adding-people.md +++ b/docs/adding-people.md @@ -1,14 +1,8 @@ # Adding New People to the Team Page -This guide explains how to add new team members to the website. The system is designed to automatically display people based on existing component files. +This guide explains how to add new team members to the website. The system now features **automated discovery** of people components, so you no longer need to manually update imports! -## Current System - -Currently, only **Adnan Fatayerji** appears on the people page because only his component exists in `src/components/people/People_Adnan.tsx`. - -## How to Add a New Person - -To add a new team member, follow these steps: +## ๐Ÿš€ Quick Start (Automated Workflow) ### 1. Create the Person's Component @@ -71,73 +65,122 @@ export default function JohnDoePage() { } ``` -### 3. Update the People Data Registry - -Add the new person's data import to `src/lib/peopleData.ts`: - -```typescript -// Add import -import { data as johnData } from '@/components/people/People_John' - -// Add to getAllPeopleData function -export function getAllPeopleData(): PersonData[] { - const allPeopleData: PersonData[] = [] - - try { - allPeopleData.push(...adnanData) - allPeopleData.push(...johnData) // Add this line - } catch (error) { - console.error('Error loading people data:', error) - } - - return allPeopleData -} -``` - -### 4. Add Person's Images +### 3. Add Person's Images Add the person's images to: `public/images/people/john_doe/` - `john_doe.jpg` (or .png, .jpeg) -## Template System Benefits +### 4. ๐ŸŽ‰ Automatic Integration -The system now uses a **centralized template** (`PersonTemplate.tsx`) for all individual people pages. This means: +**That's it!** The person will automatically appear on the people page when you build the project. The people data registry is automatically updated during the build process. + +If you want to test locally during development, you can manually run: +```bash +npm run generate-people-data +``` + +## ๐Ÿ”ง How the Automation Works + +The system now includes a Node.js script (`scripts/generate-people-data.js`) that: + +1. **Scans** the `src/components/people/` directory for all `People_*.tsx` files +2. **Generates** the necessary imports and exports in `src/lib/peopleData.ts` +3. **Creates** both synchronous and asynchronous data loading functions +4. **Eliminates** the need for manual import management + +### Available Commands + +- `npm run generate-people-data` - Manually regenerate the people data registry (for development testing) +- `npm run dev` - Start the development server +- `npm run build` - Build for production (automatically runs people data generation first) + +## ๐Ÿ“ File Structure + +``` +src/ +โ”œโ”€โ”€ components/people/ +โ”‚ โ”œโ”€โ”€ People_Adnan.tsx โœ… Auto-discovered +โ”‚ โ”œโ”€โ”€ People_Kristof.tsx โœ… Auto-discovered +โ”‚ โ””โ”€โ”€ People_John.tsx โœ… Auto-discovered (after running script) +โ”œโ”€โ”€ app/people/ +โ”‚ โ”œโ”€โ”€ Adnan_Fatayerji/page.tsx +โ”‚ โ”œโ”€โ”€ kristof_de_spiegeleer/page.tsx +โ”‚ โ””โ”€โ”€ John_Doe/page.tsx +โ”œโ”€โ”€ lib/ +โ”‚ โ””โ”€โ”€ peopleData.ts ๐Ÿค– Auto-generated +โ””โ”€โ”€ ... +``` + +## ๐ŸŽฏ Benefits of the New System + +### โœ… **No Manual Imports** +- Add a new `People_*.tsx` file +- Run `npm run generate-people-data` +- Done! No need to edit `peopleData.ts` manually + +### โœ… **Error Prevention** +- No more forgotten imports +- No more typos in import statements +- Automatic error handling for each component + +### โœ… **Scalable** +- Add as many people as needed +- System automatically discovers all components +- Consistent naming convention enforced + +### โœ… **Developer Friendly** +- Clear feedback when running the script +- Lists all discovered components +- Easy to debug and maintain + +## ๐Ÿ”„ Migration from Manual System + +If you have existing people components that were manually imported: + +1. Ensure all components follow the `People_*.tsx` naming convention +2. Run `npm run generate-people-data` +3. The script will automatically discover and include all existing components + +## ๐Ÿ“‹ Naming Conventions + +- **Component files**: `People_[FirstName].tsx` (e.g., `People_John.tsx`) +- **Page directories**: `[First_Last]/page.tsx` (e.g., `John_Doe/page.tsx`) +- **Image directories**: `first_last/` (e.g., `john_doe/`) +- **Export function**: `People_[FirstName]` (e.g., `People_John`) + +## ๐Ÿšจ Important Notes + +- **Data Structure**: Each person component must export a `data` array with the exact structure shown above +- **Biography Format**: Use HTML string for rich text formatting in the biography +- **Template Usage**: All person components should use `PersonTemplate` for consistency +- **Automatic Discovery**: Components are discovered by filename pattern `People_*.tsx` +- **Script Execution**: Always run `npm run generate-people-data` after adding new people +- **URL Structure**: Individual pages will be accessible at `/people/First_Last` + +## ๐ŸŽจ Template System Benefits + +The system uses a **centralized template** (`PersonTemplate.tsx`) for all individual people pages: - **Global Styling**: Change image size, layout, or styling in `PersonTemplate.tsx` and it applies to ALL people's profiles - **Consistency**: All people pages have the same structure and design - **Easy Maintenance**: Update the template once instead of editing each person's component individually - **Responsive Design**: Template handles all responsive breakpoints uniformly -### Customizing the Template +## ๐Ÿ“Š Current Status -To change styling for all people pages (like image size), edit `src/components/PersonTemplate.tsx`: +- โœ… **Adnan Fatayerji** - Complete (auto-discovered) +- โœ… **Kristof De Spiegeleer** - Complete (auto-discovered) +- โœ… **Automation System** - Active and ready for new additions -```typescript -// Example: To change image aspect ratio for all people -{personData.name} -``` +## ๐Ÿ”ฎ Future Enhancements -## Important Notes +The automation system can be extended to: +- Auto-generate page routes +- Validate image file existence +- Check for required data fields +- Generate TypeScript types from component data +- Create development-time file watchers for instant updates -- **Data Structure**: Each person component must export a `data` array with the exact structure shown above -- **Biography Format**: Use HTML string for rich text formatting in the biography -- **Template Usage**: All person components should use `PersonTemplate` for consistency -- **Naming Convention**: - - Component files: `People_[FirstName].tsx` - - Page directories: `[First_Last]/page.tsx` - - Image directories: `first_last/` -- **Automatic Display**: Once all steps are completed, the person will automatically appear on the main people page -- **URL Structure**: Individual pages will be accessible at `/people/First_Last` +--- -## Current Status - -- โœ… Adnan Fatayerji - Complete (component, page, images) -- โŒ All other team members - Need to be added following the steps above - -The system is designed to be scalable - each new person added will automatically appear on the team page without needing to modify the main PeopleHero component. +**๐ŸŽ‰ The new automated system makes adding team members faster, safer, and more maintainable than ever before!** diff --git a/package.json b/package.json index e83a230..db6674b 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,11 @@ "private": true, "scripts": { "dev": "next dev", - "build": "next build", + "build": "npm run generate-people-data && next build", "start": "next start", - "lint": "next lint" + "lint": "next lint", + "generate-people-data": "node scripts/generate-people-data.js", + "generate-all-people": "node scripts/generate-all-people.js" }, "browserslist": "defaults, not ie <= 11", "dependencies": { diff --git a/public/images/people/Malte_Geierhos/index.md b/public/images/people/Malte_Geierhos/index.md new file mode 100644 index 0000000..2b0e453 --- /dev/null +++ b/public/images/people/Malte_Geierhos/index.md @@ -0,0 +1,21 @@ +--- +title: Malte Geierhos +weight: 2 +description: Team Member +taxonomies: + people: [malte_geierhos] + memberships: [] + categories: [] +extra: + imgPath: malte_geierhos.jpeg + organizations: [] + countries: [] + cities: [] + private: 0 + socialLinks: { + LinkedIn: #, + websites: #, + } +--- + +Malte Geierhos is a valued member of our team, bringing expertise and dedication to their role. diff --git a/scripts/generate-all-people.js b/scripts/generate-all-people.js new file mode 100644 index 0000000..42dd1c6 --- /dev/null +++ b/scripts/generate-all-people.js @@ -0,0 +1,230 @@ +#!/usr/bin/env node + +const fs = require('fs') +const path = require('path') + +// Paths +const peopleImagesDir = path.join(__dirname, '../public/images/people') +const peopleComponentsDir = path.join(__dirname, '../src/components/people') +const peopleAppDir = path.join(__dirname, '../src/app/people') + +// Function to parse markdown frontmatter +function parseFrontmatter(content) { + const frontmatterRegex = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/ + const match = content.match(frontmatterRegex) + + if (!match) return null + + const frontmatter = {} + const body = match[2].trim() + + // Parse YAML-like frontmatter + const lines = match[1].split('\n') + let currentKey = null + + for (const line of lines) { + const trimmed = line.trim() + if (!trimmed) continue + + if (trimmed.includes(':') && !trimmed.startsWith(' ')) { + const [key, ...valueParts] = trimmed.split(':') + const value = valueParts.join(':').trim() + currentKey = key.trim() + + if (value) { + if (value.startsWith('[') && value.endsWith(']')) { + // Array value + frontmatter[currentKey] = value.slice(1, -1).split(',').map(v => v.trim()) + } else if (value.startsWith('{') && value.endsWith('}')) { + // Object value - parse simple key-value pairs + const obj = {} + const objContent = value.slice(1, -1) + const pairs = objContent.split(',') + for (const pair of pairs) { + const [k, v] = pair.split(':').map(s => s.trim()) + if (k && v) { + obj[k] = v + } + } + frontmatter[currentKey] = obj + } else { + frontmatter[currentKey] = value + } + } + } + } + + return { frontmatter, body } +} + +// Function to convert name to component name +function nameToComponentName(name) { + return name.replace(/\s+/g, '_').replace(/[^a-zA-Z0-9_]/g, '') +} + +// Function to convert name to function name +function nameToFunctionName(name) { + return 'People_' + nameToComponentName(name) +} + +// Function to generate people component +function generatePeopleComponent(personData) { + const { name, role, imageUrl, linkedinUrl, description } = personData + const functionName = nameToFunctionName(name) + + return `import { PersonTemplate } from '@/components/PersonTemplate' + +export const data = [ + { + name: '${name}', + role: '${role}', + imageUrl: '${imageUrl}', + xUrl: '#', + linkedinUrl: '${linkedinUrl || '#'}', + }, +] + +const biography = \` +

+ ${description || `${name} is a valued member of our team, bringing expertise and dedication to their role as ${role}.`} +

+\` + +export function ${functionName}() { + return +} +` +} + +// Function to generate page component +function generatePageComponent(personData) { + const { name } = personData + const functionName = nameToFunctionName(name) + const componentName = nameToComponentName(name) + const pageFunctionName = name.replace(/\s+/g, '') + 'Page' + + return `import { CallToAction } from '@/components/CallToAction' +import { Faqs } from '@/components/Faqs' +import { Footer } from '@/components/Footer' +import { Header_darkbg } from '@/components/Header_darkbg' +import { ${functionName} } from '@/components/people/People_${componentName}' + +export default function ${pageFunctionName}() { + return ( + <> + +
+ <${functionName} /> + + +
+