add people

This commit is contained in:
sasha-astiadi 2025-07-22 15:09:30 +02:00
parent 5437cae055
commit 6e613aad17
47 changed files with 1443 additions and 87 deletions

View File

@ -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
<img
alt={personData.name}
src={personData.imageUrl}
width={1184}
height={1376}
className="aspect-square w-full rounded-lg object-cover shadow-lg lg:aspect-auto" // Changed from aspect-12/7 to aspect-square
/>
```
## 🔮 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!**

View File

@ -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": {

View File

@ -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.

View File

@ -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 = \`
<p class="text-lg/7">
${description || `${name} is a valued member of our team, bringing expertise and dedication to their role as ${role}.`}
</p>
\`
export function ${functionName}() {
return <PersonTemplate personData={data[0]} biography={biography} />
}
`
}
// 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 (
<>
<Header_darkbg />
<main>
<${functionName} />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}
`
}
// Main function
function main() {
console.log('🔍 Scanning for people data...')
if (!fs.existsSync(peopleImagesDir)) {
console.log('❌ People images directory not found')
return
}
const peopleDirectories = fs.readdirSync(peopleImagesDir)
.filter(dir => {
const dirPath = path.join(peopleImagesDir, dir)
return fs.statSync(dirPath).isDirectory() && dir !== '_index.md'
})
console.log(`✅ Found ${peopleDirectories.length} people directories`)
let generatedCount = 0
let updatedCount = 0
for (const personDir of peopleDirectories) {
try {
const indexPath = path.join(peopleImagesDir, personDir, 'index.md')
if (!fs.existsSync(indexPath)) {
console.log(`⚠️ No index.md found for ${personDir}`)
continue
}
const content = fs.readFileSync(indexPath, 'utf8')
const parsed = parseFrontmatter(content)
if (!parsed) {
console.log(`⚠️ Could not parse frontmatter for ${personDir}`)
continue
}
const { frontmatter, body } = parsed
// Find the actual image file
const imageExtensions = ['jpg', 'jpeg', 'png']
let actualImagePath = frontmatter.extra?.imgPath
if (!actualImagePath) {
// Try to find the image file with different extensions
for (const ext of imageExtensions) {
const imagePath = path.join(peopleImagesDir, personDir, `${personDir}.${ext}`)
if (fs.existsSync(imagePath)) {
actualImagePath = `${personDir}.${ext}`
break
}
}
// Fallback to jpg if no image found
actualImagePath = actualImagePath || `${personDir}.jpg`
}
// Extract person data
const personData = {
name: frontmatter.title || personDir.replace(/_/g, ' '),
role: frontmatter.description || 'Team Member',
imageUrl: `/images/people/${personDir}/${actualImagePath}`,
linkedinUrl: frontmatter.extra?.socialLinks?.LinkedIn || '#',
description: body || `${frontmatter.title} is a valued member of our team.`
}
// Generate component
const componentName = nameToComponentName(personData.name)
const componentPath = path.join(peopleComponentsDir, `People_${componentName}.tsx`)
if (!fs.existsSync(componentPath)) {
const componentContent = generatePeopleComponent(personData)
fs.writeFileSync(componentPath, componentContent, 'utf8')
console.log(`✅ Generated component: People_${componentName}.tsx`)
generatedCount++
}
// Update page.tsx
const pagePath = path.join(peopleAppDir, personDir, 'page.tsx')
if (fs.existsSync(pagePath)) {
const pageContent = generatePageComponent(personData)
fs.writeFileSync(pagePath, pageContent, 'utf8')
console.log(`✅ Updated page: ${personDir}/page.tsx`)
updatedCount++
}
} catch (error) {
console.error(`❌ Error processing ${personDir}:`, error.message)
}
}
console.log(`\n🎉 Generation complete!`)
console.log(` - Generated ${generatedCount} new components`)
console.log(` - Updated ${updatedCount} page files`)
console.log(`\n📝 Run 'npm run generate-people-data' to update the data registry`)
}
// Run the script
if (require.main === module) {
main()
}
module.exports = { main }

View File

@ -0,0 +1,127 @@
#!/usr/bin/env node
const fs = require('fs')
const path = require('path')
// Paths
const peopleComponentsDir = path.join(__dirname, '../src/components/people')
const peopleDataFile = path.join(__dirname, '../src/lib/peopleData.ts')
// Function to get all People_*.tsx files
function getPeopleComponents() {
if (!fs.existsSync(peopleComponentsDir)) {
console.log('People components directory not found')
return []
}
const files = fs.readdirSync(peopleComponentsDir)
return files
.filter(file => file.startsWith('People_') && file.endsWith('.tsx'))
.map(file => {
const componentName = file.replace('.tsx', '')
const importName = componentName.toLowerCase().replace('people_', '')
return {
fileName: file,
componentName,
importName,
importPath: `@/components/people/${componentName}`
}
})
}
// Function to generate the peopleData.ts content
function generatePeopleDataContent(components) {
const imports = components
.map(comp => `import { data as ${comp.importName}Data } from '${comp.importPath}'`)
.join('\n')
const dynamicImports = components
.map(comp => ` () => import('${comp.importPath}'),`)
.join('\n')
const syncDataPush = components
.map(comp => `
try {
allPeopleData.push(...${comp.importName}Data)
} catch (error) {
console.error('Error loading ${comp.importName} data:', error)
}`)
.join('\n')
return `// This file is auto-generated by scripts/generate-people-data.js
// When new people components are added, run: npm run generate-people-data
export interface PersonData {
name: string
role: string
imageUrl: string
xUrl: string
linkedinUrl: string
}
// Function to dynamically get all people data
export async function getAllPeopleData(): Promise<PersonData[]> {
const allPeopleData: PersonData[] = []
// Auto-generated list of all people components
const peopleComponents = [
${dynamicImports}
]
for (const importComponent of peopleComponents) {
try {
const module = await importComponent()
if (module.data && Array.isArray(module.data)) {
allPeopleData.push(...module.data)
}
} catch (error) {
console.error('Error loading people data:', error)
}
}
return allPeopleData
}
// Synchronous version using static imports for immediate data access
${imports}
export function getAllPeopleDataSync(): PersonData[] {
const allPeopleData: PersonData[] = []
${syncDataPush}
return allPeopleData
}
`
}
// Main function
function main() {
console.log('🔍 Scanning for people components...')
const components = getPeopleComponents()
if (components.length === 0) {
console.log('❌ No people components found')
return
}
console.log(`✅ Found ${components.length} people component(s):`)
components.forEach(comp => {
console.log(` - ${comp.componentName}`)
})
console.log('📝 Generating peopleData.ts...')
const content = generatePeopleDataContent(components)
fs.writeFileSync(peopleDataFile, content, 'utf8')
console.log('✅ Successfully updated src/lib/peopleData.ts')
console.log('\n🎉 All people components will now automatically appear on the people page!')
}
// Run the script
if (require.main === module) {
main()
}
module.exports = { main, getPeopleComponents, generatePeopleDataContent }

View File

@ -2,14 +2,14 @@ import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Adnan } from '@/components/people/People_Adnan'
import { People_Adnan_Fateryji } from '@/components/people/People_Adnan_Fateryji'
export default function AdnanFatayerjiPage() {
export default function AdnanFateryjiPage() {
return (
<>
<Header_darkbg />
<main>
<People_Adnan />
<People_Adnan_Fateryji />
<CallToAction />
<Faqs />
</main>

View File

@ -0,0 +1,19 @@
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Malte_Geierhos } from '@/components/people/People_Malte_Geierhos'
export default function MalteGeierhosPage() {
return (
<>
<Header_darkbg />
<main>
<People_Malte_Geierhos />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

View File

@ -0,0 +1,19 @@
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Alexandre_Hannelas } from '@/components/people/People_Alexandre_Hannelas'
export default function AlexandreHannelasPage() {
return (
<>
<Header_darkbg />
<main>
<People_Alexandre_Hannelas />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

View File

@ -0,0 +1,19 @@
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Amrit_Gayan } from '@/components/people/People_Amrit_Gayan'
export default function AmritGayanPage() {
return (
<>
<Header_darkbg />
<main>
<People_Amrit_Gayan />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

View File

@ -0,0 +1,19 @@
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Chris_Camponovo } from '@/components/people/People_Chris_Camponovo'
export default function ChrisCamponovoPage() {
return (
<>
<Header_darkbg />
<main>
<People_Chris_Camponovo />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

View File

@ -0,0 +1,19 @@
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Florian_Fournier } from '@/components/people/People_Florian_Fournier'
export default function FlorianFournierPage() {
return (
<>
<Header_darkbg />
<main>
<People_Florian_Fournier />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

View File

@ -0,0 +1,19 @@
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Gregory_Flipo } from '@/components/people/People_Gregory_Flipo'
export default function GregoryFlipoPage() {
return (
<>
<Header_darkbg />
<main>
<People_Gregory_Flipo />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

View File

@ -0,0 +1,19 @@
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Hugo_Mathecowitsch } from '@/components/people/People_Hugo_Mathecowitsch'
export default function HugoMathecowitschPage() {
return (
<>
<Header_darkbg />
<main>
<People_Hugo_Mathecowitsch />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

View File

@ -0,0 +1,19 @@
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Jan_De_Landtsheer } from '@/components/people/People_Jan_De_Landtsheer'
export default function JanDeLandtsheerPage() {
return (
<>
<Header_darkbg />
<main>
<People_Jan_De_Landtsheer />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

View File

@ -0,0 +1,19 @@
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Karoline_Zizka } from '@/components/people/People_Karoline_Zizka'
export default function KarolineZizkaPage() {
return (
<>
<Header_darkbg />
<main>
<People_Karoline_Zizka />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

View File

@ -0,0 +1,19 @@
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Kristof_de_Spiegeleer } from '@/components/people/People_Kristof_de_Spiegeleer'
export default function KristofdeSpiegeleerPage() {
return (
<>
<Header_darkbg />
<main>
<People_Kristof_de_Spiegeleer />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

View File

@ -0,0 +1,19 @@
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Marion_Ravarino } from '@/components/people/People_Marion_Ravarino'
export default function MarionRavarinoPage() {
return (
<>
<Header_darkbg />
<main>
<People_Marion_Ravarino />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

View File

@ -0,0 +1,19 @@
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Michel_Coucke } from '@/components/people/People_Michel_Coucke'
export default function MichelCouckePage() {
return (
<>
<Header_darkbg />
<main>
<People_Michel_Coucke />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

View File

@ -0,0 +1,19 @@
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Nousrath_Bhugeloo } from '@/components/people/People_Nousrath_Bhugeloo'
export default function NousrathBhugelooPage() {
return (
<>
<Header_darkbg />
<main>
<People_Nousrath_Bhugeloo />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

View File

@ -0,0 +1,19 @@
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Owen_Kemp } from '@/components/people/People_Owen_Kemp'
export default function OwenKempPage() {
return (
<>
<Header_darkbg />
<main>
<People_Owen_Kemp />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

View File

@ -0,0 +1,19 @@
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Sacha_Obeegadoo } from '@/components/people/People_Sacha_Obeegadoo'
export default function SachaObeegadooPage() {
return (
<>
<Header_darkbg />
<main>
<People_Sacha_Obeegadoo />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

View File

@ -0,0 +1,19 @@
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Sam_Taggart } from '@/components/people/People_Sam_Taggart'
export default function SamTaggartPage() {
return (
<>
<Header_darkbg />
<main>
<People_Sam_Taggart />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

View File

@ -0,0 +1,19 @@
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Sasha_Astiadi } from '@/components/people/People_Sasha_Astiadi'
export default function SashaAstiadiPage() {
return (
<>
<Header_darkbg />
<main>
<People_Sasha_Astiadi />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

View File

@ -0,0 +1,19 @@
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Timur_Gordon } from '@/components/people/People_Timur_Gordon'
export default function TimurGordonPage() {
return (
<>
<Header_darkbg />
<main>
<People_Timur_Gordon />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

View File

@ -0,0 +1,19 @@
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header_darkbg } from '@/components/Header_darkbg'
import { People_Vianney_Spriet } from '@/components/people/People_Vianney_Spriet'
export default function VianneySprietPage() {
return (
<>
<Header_darkbg />
<main>
<People_Vianney_Spriet />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

View File

@ -1,13 +1,14 @@
import Link from 'next/link'
import { getAllPeopleData, PersonData } from '@/lib/peopleData'
import { getAllPeopleDataSync, PersonData } from '@/lib/peopleData'
// Function to convert name to URL slug
function nameToSlug(name: string): string {
return name.replace(/\s+/g, '_')
// Convert to lowercase and replace spaces with underscores
return name.replace(/\s+/g, '_').toLowerCase()
}
export function PeopleHero() {
const people = getAllPeopleData()
const people = getAllPeopleDataSync()
return (
<div className="bg-white py-24 sm:py-32">

View File

@ -19,6 +19,6 @@ const biography = `
</p>
`
export function People_Adnan() {
export function People_Adnan_Fateryji() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -0,0 +1,21 @@
import { PersonTemplate } from '@/components/PersonTemplate'
export const data = [
{
name: 'Alexandre Hannelas',
role: 'Finance Manager',
imageUrl: '/images/people/alexandre_hannelas/alexandre_hannelas.jpeg',
xUrl: '#',
linkedinUrl: '#',
},
]
const biography = `
<p class="text-lg/7">
Capable finance specialist with a deep passion in driving lean and innovative business models.
</p>
`
export function People_Alexandre_Hannelas() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -0,0 +1,21 @@
import { PersonTemplate } from '@/components/PersonTemplate'
export const data = [
{
name: 'Amrit Gayan',
role: 'Advisor, Finance & Operations',
imageUrl: '/images/people/amrit_gayan/amrit_gayan.jpeg',
xUrl: '#',
linkedinUrl: '#',
},
]
const biography = `
<p class="text-lg/7">
+20 years experience leading award-winning banks. AI and technology enthusiast.
</p>
`
export function People_Amrit_Gayan() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -0,0 +1,21 @@
import { PersonTemplate } from '@/components/PersonTemplate'
export const data = [
{
name: 'Chris Camponovo',
role: 'Director, Co-Founder of Zanzibar Digital Free Zone',
imageUrl: '/images/people/chris_camponovo/chris_camponovo.jpeg',
xUrl: '#',
linkedinUrl: '#',
},
]
const biography = `
<p class="text-lg/7">
Former white house lawyer and private equity fund founder that drives multinational asset recovery solutions.
</p>
`
export function People_Chris_Camponovo() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -0,0 +1,21 @@
import { PersonTemplate } from '@/components/PersonTemplate'
export const data = [
{
name: 'Florian Fournier',
role: 'Co-Founder',
imageUrl: '/images/people/florian_fournier/florian_fournier.jpeg',
xUrl: '#',
linkedinUrl: '#',
},
]
const biography = `
<p class="text-lg/7">
Experienced social entrepreneur and marketing executive with extensive network in the US and Latam.
</p>
`
export function People_Florian_Fournier() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -0,0 +1,21 @@
import { PersonTemplate } from '@/components/PersonTemplate'
export const data = [
{
name: 'Gregory Flipo',
role: 'Co-Founder, CEO of Sikana',
imageUrl: '/images/people/gregory_flipo/gregory_flipo.jpg',
xUrl: '#',
linkedinUrl: '#',
},
]
const biography = `
<p class="text-lg/7">
Social entrepreneur with 20 years of experience building educational content and platforms used by millions today.
</p>
`
export function People_Gregory_Flipo() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -0,0 +1,21 @@
import { PersonTemplate } from '@/components/PersonTemplate'
export const data = [
{
name: 'Hugo Mathecowitsch',
role: 'Advisor, Product',
imageUrl: '/images/people/hugo_mathecowitsch/hugo_mathecowitsch.jpeg',
xUrl: '#',
linkedinUrl: '#',
},
]
const biography = `
<p class="text-lg/7">
Launched leading fintech startups in South America. Regenerating public goods.
</p>
`
export function People_Hugo_Mathecowitsch() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -0,0 +1,21 @@
import { PersonTemplate } from '@/components/PersonTemplate'
export const data = [
{
name: 'Jan De Landtsheer',
role: 'Advisor, Tech',
imageUrl: '/images/people/jan_de_landtsheer/jan_de_landtsheer.jpeg',
xUrl: '#',
linkedinUrl: '#',
},
]
const biography = `
<p class="text-lg/7">
+30 years experience building deep tech. Co-Founder at ThreeFold.
</p>
`
export function People_Jan_De_Landtsheer() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -0,0 +1,21 @@
import { PersonTemplate } from '@/components/PersonTemplate'
export const data = [
{
name: 'Karoline Zizka',
role: 'HR Coordinator',
imageUrl: '/images/people/karoline_zizka/karoline_zizka.jpeg',
xUrl: '#',
linkedinUrl: '#',
},
]
const biography = `
<p class="text-lg/7">
Passionate about driving people-centric strategies with effective KPIs, supporting venture growth and employee satisfaction.
</p>
`
export function People_Karoline_Zizka() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -0,0 +1,24 @@
import { PersonTemplate } from '@/components/PersonTemplate'
export const data = [
{
name: 'Kristof De Spiegeleer',
role: 'Co-Founder, CEO',
imageUrl: '/images/people/kristof_de_spiegeleer/kristof_de_spiegeleer.jpeg',
xUrl: '#',
linkedinUrl: 'https://www.linkedin.com/in/despiegk/',
},
]
const biography = `
<p class="text-lg/7">
Kristof is a technologist, philosopher, and builder with a long-standing dedication to creating systems that serve the common good. With a background in distributed infrastructure and digital ecosystems, his work is driven by a deep belief in open collaboration, self-sovereignty, and planetary resilience.
</p>
<p class="mt-5">
At OurWorld, Kristof brings together decades of experience in architecture, code, and community-building to lay the groundwork for ventures that are not only scalable and securebut deeply ethical by design. His vision anchors the platform's commitment to aligning technology with life itself.
</p>
`
export function People_Kristof_de_Spiegeleer() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -0,0 +1,21 @@
import { PersonTemplate } from '@/components/PersonTemplate'
export const data = [
{
name: 'Malte Geierhos',
role: 'Team Member',
imageUrl: '/images/people/Malte_Geierhos/Malte_Geierhos.jpeg',
xUrl: '#',
linkedinUrl: '#',
},
]
const biography = `
<p class="text-lg/7">
Malte Geierhos is a valued member of our team, bringing expertise and dedication to their role.
</p>
`
export function People_Malte_Geierhos() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -0,0 +1,21 @@
import { PersonTemplate } from '@/components/PersonTemplate'
export const data = [
{
name: 'Marion Ravarino',
role: 'Project Management',
imageUrl: '/images/people/marion_ravarino/marion_ravarino.jpeg',
xUrl: '#',
linkedinUrl: '#',
},
]
const biography = `
<p class="text-lg/7">
Driven by a natural curiosity for new knowledge. OurWorld's mission and values are perfectly aligned with my vision of a better future for all.
</p>
`
export function People_Marion_Ravarino() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -0,0 +1,21 @@
import { PersonTemplate } from '@/components/PersonTemplate'
export const data = [
{
name: 'Michel Coucke',
role: 'Director',
imageUrl: '/images/people/michel_coucke/michel_coucke.jpg',
xUrl: '#',
linkedinUrl: '#',
},
]
const biography = `
<p class="text-lg/7">
CEO Lancor, a global executive search firm specializing in board-level search mandates including C-level execs and more.
</p>
`
export function People_Michel_Coucke() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -0,0 +1,21 @@
import { PersonTemplate } from '@/components/PersonTemplate'
export const data = [
{
name: 'Nousrath Bhugeloo',
role: 'Director & Executive Chairperson',
imageUrl: '/images/people/nousrath_bhugeloo/nousrath_bhugeloo.jpg',
xUrl: '#',
linkedinUrl: '#',
},
]
const biography = `
<p class="text-lg/7">
Advisor to multinationals, funds, family offices and individual entrepreneurs on their strategies and cross border business.
</p>
`
export function People_Nousrath_Bhugeloo() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -0,0 +1,21 @@
import { PersonTemplate } from '@/components/PersonTemplate'
export const data = [
{
name: 'Owen Kemp',
role: 'Advisor, Business Development',
imageUrl: '/images/people/owen_kemp/owen_kemp.jpeg',
xUrl: '#',
linkedinUrl: '#',
},
]
const biography = `
<p class="text-lg/7">
Former HPE VP Innovation & International Relations. Co-Founder at TF9.
</p>
`
export function People_Owen_Kemp() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -0,0 +1,21 @@
import { PersonTemplate } from '@/components/PersonTemplate'
export const data = [
{
name: 'Sacha Obeegadoo',
role: 'Program Manager',
imageUrl: '/images/people/sacha_obeegadoo/sacha_obeegadoo.jpg',
xUrl: '#',
linkedinUrl: '#',
},
]
const biography = `
<p class="text-lg/7">
Business Developer with experience growing companies across various sectors.
</p>
`
export function People_Sacha_Obeegadoo() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -0,0 +1,21 @@
import { PersonTemplate } from '@/components/PersonTemplate'
export const data = [
{
name: 'Sam Taggart',
role: 'Communication & Community',
imageUrl: '/images/people/sam_taggart/sam_taggart.jpg',
xUrl: '#',
linkedinUrl: '#',
},
]
const biography = `
<p class="text-lg/7">
Communication strategist and global citizen, inspired by the beauty of our differences and humbled by our similarities. Driven to drive collective positive change.
</p>
`
export function People_Sam_Taggart() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -0,0 +1,21 @@
import { PersonTemplate } from '@/components/PersonTemplate'
export const data = [
{
name: 'Sasha Astiadi',
role: 'Web Operations',
imageUrl: '/images/people/sasha_astiadi/sasha_astiadi.png',
xUrl: '#',
linkedinUrl: '#',
},
]
const biography = `
<p class="text-lg/7">
A Human-centered product manager, researcher and UX Designer who puts the planet as her main mission.
</p>
`
export function People_Sasha_Astiadi() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -0,0 +1,21 @@
import { PersonTemplate } from '@/components/PersonTemplate'
export const data = [
{
name: 'Timur Gordon',
role: 'Software Developer',
imageUrl: '/images/people/timur_gordon/timur_gordon.jpg',
xUrl: '#',
linkedinUrl: '#',
},
]
const biography = `
<p class="text-lg/7">
Software developer who loves nature and believes in using tech to help the planet and people. Believer in open source and collective intelligence.
</p>
`
export function People_Timur_Gordon() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -0,0 +1,21 @@
import { PersonTemplate } from '@/components/PersonTemplate'
export const data = [
{
name: 'Vianney Spriet',
role: 'Business Development',
imageUrl: '/images/people/vianney_spriet/vianney_spriet.jpeg',
xUrl: '#',
linkedinUrl: '#',
},
]
const biography = `
<p class="text-lg/7">
Experienced wealth manager, business developer, and former professional skipper with a wide network in Europe.
</p>
`
export function People_Vianney_Spriet() {
return <PersonTemplate personData={data[0]} biography={biography} />
}

View File

@ -1,5 +1,5 @@
// This file dynamically imports all people data from components
// When new people components are added, they will automatically appear
// This file is auto-generated by scripts/generate-people-data.js
// When new people components are added, run: npm run generate-people-data
export interface PersonData {
name: string
@ -9,23 +9,192 @@ export interface PersonData {
linkedinUrl: string
}
// Import all existing people data
import { data as adnanData } from '@/components/people/People_Adnan'
// Function to get all people data
export function getAllPeopleData(): PersonData[] {
// Function to dynamically get all people data
export async function getAllPeopleData(): Promise<PersonData[]> {
const allPeopleData: PersonData[] = []
// Add data from all existing people components
try {
allPeopleData.push(...adnanData)
} catch (error) {
console.error('Error loading Adnan data:', error)
}
// Auto-generated list of all people components
const peopleComponents = [
() => import('@/components/people/People_Adnan_Fateryji'),
() => import('@/components/people/People_Alexandre_Hannelas'),
() => import('@/components/people/People_Amrit_Gayan'),
() => import('@/components/people/People_Chris_Camponovo'),
() => import('@/components/people/People_Florian_Fournier'),
() => import('@/components/people/People_Gregory_Flipo'),
() => import('@/components/people/People_Hugo_Mathecowitsch'),
() => import('@/components/people/People_Jan_De_Landtsheer'),
() => import('@/components/people/People_Karoline_Zizka'),
() => import('@/components/people/People_Kristof_de_Spiegeleer'),
() => import('@/components/people/People_Malte_Geierhos'),
() => import('@/components/people/People_Marion_Ravarino'),
() => import('@/components/people/People_Michel_Coucke'),
() => import('@/components/people/People_Nousrath_Bhugeloo'),
() => import('@/components/people/People_Owen_Kemp'),
() => import('@/components/people/People_Sacha_Obeegadoo'),
() => import('@/components/people/People_Sam_Taggart'),
() => import('@/components/people/People_Sasha_Astiadi'),
() => import('@/components/people/People_Timur_Gordon'),
() => import('@/components/people/People_Vianney_Spriet'),
]
// When new people components are created, add their imports here:
// import { data as newPersonData } from '@/components/people/People_NewPerson'
// allPeopleData.push(...newPersonData)
for (const importComponent of peopleComponents) {
try {
const module = await importComponent()
if (module.data && Array.isArray(module.data)) {
allPeopleData.push(...module.data)
}
} catch (error) {
console.error('Error loading people data:', error)
}
}
return allPeopleData
}
// Synchronous version using static imports for immediate data access
import { data as adnan_fateryjiData } from '@/components/people/People_Adnan_Fateryji'
import { data as alexandre_hannelasData } from '@/components/people/People_Alexandre_Hannelas'
import { data as amrit_gayanData } from '@/components/people/People_Amrit_Gayan'
import { data as chris_camponovoData } from '@/components/people/People_Chris_Camponovo'
import { data as florian_fournierData } from '@/components/people/People_Florian_Fournier'
import { data as gregory_flipoData } from '@/components/people/People_Gregory_Flipo'
import { data as hugo_mathecowitschData } from '@/components/people/People_Hugo_Mathecowitsch'
import { data as jan_de_landtsheerData } from '@/components/people/People_Jan_De_Landtsheer'
import { data as karoline_zizkaData } from '@/components/people/People_Karoline_Zizka'
import { data as kristof_de_spiegeleerData } from '@/components/people/People_Kristof_de_Spiegeleer'
import { data as malte_geierhosData } from '@/components/people/People_Malte_Geierhos'
import { data as marion_ravarinoData } from '@/components/people/People_Marion_Ravarino'
import { data as michel_couckeData } from '@/components/people/People_Michel_Coucke'
import { data as nousrath_bhugelooData } from '@/components/people/People_Nousrath_Bhugeloo'
import { data as owen_kempData } from '@/components/people/People_Owen_Kemp'
import { data as sacha_obeegadooData } from '@/components/people/People_Sacha_Obeegadoo'
import { data as sam_taggartData } from '@/components/people/People_Sam_Taggart'
import { data as sasha_astiadiData } from '@/components/people/People_Sasha_Astiadi'
import { data as timur_gordonData } from '@/components/people/People_Timur_Gordon'
import { data as vianney_sprietData } from '@/components/people/People_Vianney_Spriet'
export function getAllPeopleDataSync(): PersonData[] {
const allPeopleData: PersonData[] = []
try {
allPeopleData.push(...adnan_fateryjiData)
} catch (error) {
console.error('Error loading adnan_fateryji data:', error)
}
try {
allPeopleData.push(...alexandre_hannelasData)
} catch (error) {
console.error('Error loading alexandre_hannelas data:', error)
}
try {
allPeopleData.push(...amrit_gayanData)
} catch (error) {
console.error('Error loading amrit_gayan data:', error)
}
try {
allPeopleData.push(...chris_camponovoData)
} catch (error) {
console.error('Error loading chris_camponovo data:', error)
}
try {
allPeopleData.push(...florian_fournierData)
} catch (error) {
console.error('Error loading florian_fournier data:', error)
}
try {
allPeopleData.push(...gregory_flipoData)
} catch (error) {
console.error('Error loading gregory_flipo data:', error)
}
try {
allPeopleData.push(...hugo_mathecowitschData)
} catch (error) {
console.error('Error loading hugo_mathecowitsch data:', error)
}
try {
allPeopleData.push(...jan_de_landtsheerData)
} catch (error) {
console.error('Error loading jan_de_landtsheer data:', error)
}
try {
allPeopleData.push(...karoline_zizkaData)
} catch (error) {
console.error('Error loading karoline_zizka data:', error)
}
try {
allPeopleData.push(...kristof_de_spiegeleerData)
} catch (error) {
console.error('Error loading kristof_de_spiegeleer data:', error)
}
try {
allPeopleData.push(...malte_geierhosData)
} catch (error) {
console.error('Error loading malte_geierhos data:', error)
}
try {
allPeopleData.push(...marion_ravarinoData)
} catch (error) {
console.error('Error loading marion_ravarino data:', error)
}
try {
allPeopleData.push(...michel_couckeData)
} catch (error) {
console.error('Error loading michel_coucke data:', error)
}
try {
allPeopleData.push(...nousrath_bhugelooData)
} catch (error) {
console.error('Error loading nousrath_bhugeloo data:', error)
}
try {
allPeopleData.push(...owen_kempData)
} catch (error) {
console.error('Error loading owen_kemp data:', error)
}
try {
allPeopleData.push(...sacha_obeegadooData)
} catch (error) {
console.error('Error loading sacha_obeegadoo data:', error)
}
try {
allPeopleData.push(...sam_taggartData)
} catch (error) {
console.error('Error loading sam_taggart data:', error)
}
try {
allPeopleData.push(...sasha_astiadiData)
} catch (error) {
console.error('Error loading sasha_astiadi data:', error)
}
try {
allPeopleData.push(...timur_gordonData)
} catch (error) {
console.error('Error loading timur_gordon data:', error)
}
try {
allPeopleData.push(...vianney_sprietData)
} catch (error) {
console.error('Error loading vianney_spriet data:', error)
}
return allPeopleData
}