Added homepage and moved old homepage to aboutme page

This commit is contained in:
becarta
2025-03-03 23:23:14 +01:00
parent 2e4284cba3
commit 9c61657071
16 changed files with 1769 additions and 533 deletions

View File

@@ -0,0 +1,141 @@
---
export const prerender = false;
import Layout from '~/layouts/PageLayout.astro';
import StructuredData from '~/components/common/StructuredData.astro';
import Hero from '~/components/widgets/Hero.astro';
import Content from '~/components/widgets/Content.astro';
import CompactSteps from '~/components/widgets/CompactSteps.astro';
import WorkExperience from '~/components/widgets/WorkExperience.astro';
import CompactCertifications from '~/components/widgets/CompactCertifications.astro';
import CompactSkills from '~/components/widgets/CompactSkills.astro';
import HomePageImage from '~/assets/images/richardbergsma.png'
import { getTranslation, supportedLanguages } from '~/i18n/translations';
export async function getStaticPaths() {
return supportedLanguages.map(lang => ({
params: { lang },
}));
}
const { lang } = Astro.params;
if (!supportedLanguages.includes(lang)) {
return Astro.redirect('/en/aboutme');
}
const t = getTranslation(lang);
const metadata = {
title: 'About Me - ' + t.metadata.title,
};
---
<Layout metadata={metadata}>
<Fragment slot="announcement"></Fragment>
<!-- Person Structured Data for SEO -->
<StructuredData slot="structured-data" data={{
"@context": "https://schema.org",
"@type": "Person",
"name": "Richard Bergsma",
"jobTitle": "IT Systems and Automation Manager",
"description": t.hero.subtitle,
"image": Astro.url.origin + "/images/richardbergsma.png",
"url": Astro.url.origin,
"sameAs": [
"https://www.linkedin.com/in/rrpbergsma",
"https://github.com/rrpbergsma"
],
"knowsAbout": t.skills.items.map(skill => skill.title),
"worksFor": {
"@type": "Organization",
"name": "COFRA Holding C.V.",
"location": "Amsterdam"
}
}} />
<!-- Hero Widget -->
<Hero
id="hero"
title="About Me"
>
<Fragment slot="subtitle">
<strong class="text-3xl md:text-4xl">{t.hero.greeting}</strong><br /><br />{t.hero.subtitle}
</Fragment>
</Hero>
<!-- Content Widget -->
<Content
id="about"
columns={2}
items={[]}
image={{
src: HomePageImage,
alt: 'Richard Bergsma smiling in the mountains of Switzerland holding Revella',
loading: 'lazy',
}}
>
<Fragment slot="content">
<h2 class="text-3xl font-bold tracking-tight sm:text-4xl mb-2">{t.about.title}</h2>
{t.about.content.map((paragraph) => (
<p>{paragraph}</p>
<br />
))}
</Fragment>
<Fragment slot="bg">
<div class="absolute inset-0 bg-blue-50 dark:bg-transparent"></div>
</Fragment>
</Content>
<!-- Work Experience - Modern Timeline Layout -->
<WorkExperience
id="resume"
title={t.resume.title}
compact={true}
items={t.resume.experience.map(exp => ({
title: exp.title,
company: exp.company,
date: exp.period,
location: exp.location,
description: exp.description,
icon: 'tabler:briefcase',
}))}
/>
<!-- Certifications - Compact Layout -->
<CompactCertifications
id="certifications"
title={t.certifications.title}
subtitle={t.certifications.subtitle}
testimonials={t.certifications.items.map((cert) => ({
name: cert.name,
issueDate: cert.issueDate,
description: cert.description,
linkUrl: cert.linkUrl,
image: cert.image
}))}
/>
<!-- Skills - Compact Layout -->
<CompactSkills
id="skills"
title={t.skills.title}
subtitle={t.skills.subtitle}
defaultIcon="tabler:point-filled"
items={t.skills.items.map(item => ({
title: item.title,
description: item.description,
}))}
/>
<!-- Education - Compact Layout -->
<CompactSteps
id="education"
title={t.education.title}
items={t.education.items.map(item => ({
title: item.title,
icon: 'tabler:school'
}))}
/>
</Layout>

View File

@@ -1,24 +1,14 @@
---
export const prerender = false;
import Layout from '~/layouts/PageLayout.astro';
import Header from '~/components/widgets/Header.astro';
import StructuredData from '~/components/common/StructuredData.astro';
import Hero from '~/components/widgets/Hero.astro';
import Hero from '~/components/widgets/Hero2.astro';
import Features from '~/components/widgets/Features.astro';
import Content from '~/components/widgets/Content.astro';
import CompactSteps from '~/components/widgets/CompactSteps.astro';
import WorkExperience from '~/components/widgets/WorkExperience.astro';
import CompactCertifications from '~/components/widgets/CompactCertifications.astro';
import CompactSkills from '~/components/widgets/CompactSkills.astro';
import BlogLatestPosts from '~/components/widgets/BlogLatestPosts.astro';
import HomePageImage from '~/assets/images/richardbergsma.png'
import fetch from 'node-fetch';
import Testimonials from '~/components/widgets/Testimonials.astro';
import CallToAction from '~/components/widgets/CallToAction.astro';
import Contact from '~/components/widgets/Contact.astro';
import { getTranslation, supportedLanguages } from '~/i18n/translations';
interface IpApiResponse {
countryCode: string;
}
export async function getStaticPaths() {
return supportedLanguages.map(lang => ({
params: { lang },
@@ -30,181 +20,212 @@ if (!supportedLanguages.includes(lang)) {
return Astro.redirect('/en/');
}
// Geo-location based redirect
if (Astro.request.headers.get('host') === '365devnet.nl') {
try {
const ip = Astro.clientAddress;
const response = await fetch(`http://ip-api.com/json/${ip}`);
const data = await response.json() as IpApiResponse;
if (data?.countryCode === 'NL') {
return Astro.redirect('/nl/');
}
} catch (error) {
console.error('Geo-location error:', error);
// Fallback: Redirect to default language (English)
return Astro.redirect('/en/');
}
}
const t = getTranslation(lang);
const metadata = {
title: t.metadata.title,
};
---
<Layout metadata={metadata}>
<Fragment slot="announcement"></Fragment>
<!-- Person Structured Data for SEO -->
<StructuredData slot="structured-data" data={{
"@context": "https://schema.org",
"@type": "Person",
"name": "Richard Bergsma",
"jobTitle": "IT Systems and Automation Manager",
"description": t.hero.subtitle,
"image": Astro.url.origin + "/images/richardbergsma.png",
"url": Astro.url.origin,
"sameAs": [
"https://www.linkedin.com/in/rrpbergsma",
"https://github.com/rrpbergsma"
],
"knowsAbout": t.skills.items.map(skill => skill.title),
"worksFor": {
"@type": "Organization",
"name": "COFRA Holding C.V.",
"location": "Amsterdam"
}
}} />
<Fragment slot="header">
<Header
links={[
{ text: t.navigation.home, href: '#hero' },
{ text: t.navigation.about, href: '#about' },
{ text: t.navigation.resume, href: '#resume' },
{ text: t.navigation.certifications, href: '#certifications' },
{ text: t.navigation.skills, href: '#skills' },
{ text: t.navigation.education, href: '#education' },
{ text: t.navigation.blog, href: '#blog' },
]}
isSticky
showToggleTheme
/>
</Fragment>
<script>
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const targetId = this.getAttribute('href').substring(1);
const targetElement = document.getElementById(targetId);
if (targetElement) {
window.scrollTo({
top: targetElement.offsetTop - 50,
behavior: 'smooth'
});
}
});
});
</script>
<!-- Hero Widget -->
<Hero
id="hero"
tagline={t.navigation.home}
title={t.hero.title}
>
<Fragment slot="subtitle">
<strong class="text-3xl md:text-4xl">{t.hero.greeting}</strong><br /><br />{t.hero.subtitle}
</Fragment>
</Hero>
subtitle={t.hero.subtitle}
actions={[
{
variant: 'primary',
text: t.homepage?.actions?.learnMore || 'Learn More',
href: '#services',
icon: 'tabler:arrow-down',
},
{ text: t.homepage?.actions?.contactMe || 'Contact Me', href: '#contact' },
]}
image={{
src: '~/assets/images/richardbergsma.png',
alt: 'Richard Bergsma - IT Systems and Automation Manager',
}}
/>
<!-- Features Widget -->
<Features
id="services"
tagline={t.homepage?.services?.tagline || "Services"}
title={t.homepage?.services?.title || "How I Can Help Your Organization"}
subtitle={t.homepage?.services?.subtitle || "I offer a range of specialized IT services to help businesses optimize their operations and digital infrastructure."}
items={t.homepage?.services?.items || [
{
title: 'Workflow Automation',
description:
'Streamline your business processes with Power Automate solutions that reduce manual effort and increase operational efficiency.',
icon: 'tabler:settings-automation',
},
{
title: 'Intelligent Chatbots',
description:
'Develop smart chatbots in Copilot Studio that enhance user interactions through natural language processing and automated responses.',
icon: 'tabler:message-chatbot',
},
{
title: 'API Integrations',
description:
'Create seamless connections between your applications and services with custom API integrations for efficient data exchange.',
icon: 'tabler:api',
},
{
title: 'Microsoft 365 Management',
description:
'Optimize your Microsoft 365 environment with expert administration, security configurations, and service optimization.',
icon: 'tabler:brand-office',
},
{
title: 'SharePoint Solutions',
description:
'Set up, manage, and optimize SharePoint Online and on-premise deployments for effective document management and collaboration.',
icon: 'tabler:share',
},
{
title: 'IT Infrastructure Oversight',
description:
'Manage global IT infrastructures, including servers, networks, and end-user devices to ensure reliable operations.',
icon: 'tabler:server',
},
].map(item => ({...item, icon: item.icon || 'tabler:check'}))}
/>
<!-- Content Widget -->
<Content
id="about"
columns={2}
items={[]}
isReversed
tagline={t.homepage?.approach?.tagline || "About My Approach"}
title={t.homepage?.approach?.title || "Driving IT Excellence Through Innovation"}
items={t.homepage?.approach?.items || [
{
title: 'User-Centric Solutions',
description:
'I focus on creating solutions that enhance user experience and productivity, ensuring technology serves people effectively.',
},
{
title: 'Continuous Improvement',
description:
'I stay current with emerging technologies and best practices to deliver cutting-edge solutions that evolve with your needs.',
},
{
title: 'Strategic Implementation',
description:
'I approach each project strategically, aligning technical solutions with business objectives for maximum impact.',
},
]}
image={{
src: HomePageImage,
alt: 'Richard Bergsma smiling in the mountains of Switzerland holding Revella',
loading: 'lazy',
src: '~/assets/images/hero-image.png',
alt: 'Digital Transformation Image',
}}
>
<Fragment slot="content">
<h2 class="text-3xl font-bold tracking-tight sm:text-4xl mb-2">{t.about.title}</h2>
{t.about.content.map((paragraph) => (
<p>{paragraph}</p>
<br />
<h3 class="text-2xl font-bold tracking-tight dark:text-white sm:text-3xl mb-2">
{t.homepage?.approach?.missionTitle || "Mission Statement"}
</h3>
{(t.homepage?.approach?.missionContent || [
'My mission is to drive IT excellence by optimizing cloud solutions, automating processes, and providing outstanding technical support. I believe in leveraging technology to solve real business challenges and create value through innovation.',
'With over 15 years of IT experience, I bring a wealth of knowledge in Microsoft technologies, automation tools, and system integration to help organizations transform their digital capabilities and achieve their strategic goals.'
]).map((paragraph) => (
<>
<p>{paragraph}</p>
<br />
</>
))}
</Fragment>
<Fragment slot="bg">
<div class="absolute inset-0 bg-blue-50 dark:bg-transparent"></div>
</Fragment>
</Content>
<!-- Work Experience - Modern Timeline Layout -->
<WorkExperience
id="resume"
title={t.resume.title}
compact={true}
items={t.resume.experience.map(exp => ({
title: exp.title,
company: exp.company,
date: exp.period,
location: exp.location,
description: exp.description,
icon: 'tabler:briefcase',
<!-- Testimonials Widget -->
<Testimonials
tagline={t.homepage?.testimonials?.tagline || "Testimonials"}
title={t.homepage?.testimonials?.title || "What Clients Say About My Work"}
testimonials={(t.homepage?.testimonials?.items || [
{
testimonial:
"Richard's expertise in Power Automate transformed our workflow processes, saving us countless hours and reducing errors significantly.",
name: 'Client Name',
description: 'Position, Company',
},
{
testimonial:
"The SharePoint implementation Richard delivered has revolutionized our document management and team collaboration capabilities.",
name: 'Client Name',
description: 'Position, Company',
},
{
testimonial:
"Richard's technical knowledge combined with his ability to understand our business needs resulted in solutions that truly addressed our challenges.",
name: 'Client Name',
description: 'Position, Company',
},
]).map(item => ({
...item,
image: {
src: '~/assets/images/default.png',
alt: item.name,
}
}))}
/>
<!-- Certifications - Compact Layout -->
<CompactCertifications
id="certifications"
title={t.certifications.title}
subtitle={t.certifications.subtitle}
testimonials={t.certifications.items.map((cert) => ({
name: cert.name,
issueDate: cert.issueDate,
description: cert.description,
linkUrl: cert.linkUrl,
image: cert.image
}))}
/>
<!-- Skills - Compact Layout -->
<CompactSkills
id="skills"
title={t.skills.title}
subtitle={t.skills.subtitle}
defaultIcon="tabler:point-filled"
items={t.skills.items.map(item => ({
title: item.title,
description: item.description,
}))}
/>
<!-- Education - Compact Layout -->
<CompactSteps
id="education"
title={t.education.title}
items={t.education.items.map(item => ({
title: item.title,
icon: 'tabler:school'
}))}
/>
<!-- BlogLatestPost Widget -->
<BlogLatestPosts
id="blog"
title={t.blog.title}
information={t.blog.information}
<!-- CallToAction Widget -->
<CallToAction
callToAction={{
text: t.homepage?.callToAction?.button || 'Contact Me',
href: '#contact',
icon: 'tabler:mail',
}}
>
<Fragment slot="bg">
<div class="absolute inset-0"></div>
<Fragment slot="title">{t.homepage?.callToAction?.title || 'Ready to optimize your IT systems?'}</Fragment>
<Fragment slot="subtitle">
{t.homepage?.callToAction?.subtitle || 'Let\'s discuss how I can help your organization streamline processes, enhance collaboration, and drive digital transformation.'}
</Fragment>
</BlogLatestPosts>
</CallToAction>
<!-- Contact Widget -->
<Contact
id="contact"
title={t.homepage?.contact?.title || "Get in Touch"}
subtitle={t.homepage?.contact?.subtitle || "Have a project in mind or questions about my services? Reach out and let's start a conversation."}
inputs={[
{
type: 'text',
name: 'name',
label: t.homepage?.contact?.nameLabel || 'Name',
placeholder: t.homepage?.contact?.namePlaceholder || 'Your name',
},
{
type: 'email',
name: 'email',
label: t.homepage?.contact?.emailLabel || 'Email',
placeholder: t.homepage?.contact?.emailPlaceholder || 'Your email address',
},
]}
textarea={{
label: t.homepage?.contact?.messageLabel || 'Message',
placeholder: t.homepage?.contact?.messagePlaceholder || 'Your message',
rows: 8,
}}
disclaimer={{
label: t.homepage?.contact?.disclaimer ||
'By submitting this form, you agree to our privacy policy and allow us to use your information to contact you about our services.',
}}
description={t.homepage?.contact?.description || "I'll respond to your message as soon as possible. You can also connect with me on LinkedIn or GitHub."}
/>
<div class="flex justify-center space-x-4 mt-8 mb-12">
<a href="https://www.linkedin.com/in/rrpbergsma" class="text-gray-500 hover:text-blue-600" target="_blank" rel="noopener noreferrer">
<span class="sr-only">LinkedIn</span>
<svg class="h-8 w-8" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.454C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.225 0z"/>
</svg>
</a>
<a href="https://github.com/rrpbergsma" class="text-gray-500 hover:text-gray-900 dark:hover:text-white" target="_blank" rel="noopener noreferrer">
<span class="sr-only">GitHub</span>
<svg class="h-8 w-8" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd"/>
</svg>
</a>
</div>
</Layout>

View File

@@ -1,228 +0,0 @@
---
import Features2 from '~/components/widgets/Features2.astro';
import Features3 from '~/components/widgets/Features3.astro';
import Hero from '~/components/widgets/Hero.astro';
import Stats from '~/components/widgets/Stats.astro';
import Steps2 from '~/components/widgets/Steps2.astro';
import Layout from '~/layouts/PageLayout.astro';
const metadata = {
title: 'About us',
};
---
<Layout metadata={metadata}>
<!-- Hero Widget ******************* -->
<Hero
tagline="About us"
image={{
src: 'https://images.unsplash.com/photo-1559136555-9303baea8ebd?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80',
alt: 'Caos Image',
}}
>
<Fragment slot="title">
Elevate your online presence with our <br />
<span class="text-accent dark:text-white highlight"> Beautiful Website Templates</span>
</Fragment>
<Fragment slot="subtitle">
Donec efficitur, ipsum quis congue luctus, mauris magna convallis mauris, eu auctor nisi lectus non augue. Donec
quis lorem non massa vulputate efficitur ac at turpis. Sed tincidunt ex a nunc convallis, et lobortis nisi tempus.
Suspendisse vitae nisi eget tortor luctus maximus sed non lectus.
</Fragment>
</Hero>
<!-- Stats Widget ****************** -->
<Stats
title="Statistics about us"
stats={[
{ title: 'Offices', amount: '4' },
{ title: 'Employees', amount: '248' },
{ title: 'Templates', amount: '12' },
{ title: 'Awards', amount: '24' },
]}
/>
<!-- Features3 Widget ************** -->
<Features3
title="Our templates"
subtitle="Etiam scelerisque, enim eget vestibulum luctus, nibh mauris blandit nulla, nec vestibulum risus justo ut enim. Praesent lacinia diam et ante imperdiet euismod."
columns={3}
isBeforeContent={true}
items={[
{
title: 'Educational',
description:
'Morbi faucibus luctus quam, sit amet aliquet felis tempor id. Cras augue massa, ornare quis dignissim a, molestie vel nulla.',
icon: 'tabler:template',
},
{
title: 'Interior Design',
description:
'Vivamus porttitor, tortor convallis aliquam pretium, turpis enim consectetur elit, vitae egestas purus erat ac nunc nulla.',
icon: 'tabler:template',
},
{
title: 'Photography',
description:
'Duis sed lectus in nisl vehicula porttitor eget quis odio. Aliquam erat volutpat. Nulla eleifend nulla id sem fermentum.',
icon: 'tabler:template',
},
]}
/>
<!-- Features3 Widget ************** -->
<Features3
columns={3}
isAfterContent={true}
items={[
{
title: 'E-commerce',
description:
'Rutrum non odio at vehicula. Proin ipsum justo, dignissim in vehicula sit amet, dignissim id quam. Sed ac tincidunt sapien.',
icon: 'tabler:template',
},
{
title: 'Blog',
description:
'Nullam efficitur volutpat sem sed fringilla. Suspendisse et enim eu orci volutpat laoreet ac vitae libero.',
icon: 'tabler:template',
},
{
title: 'Business',
description:
'Morbi et elit finibus, facilisis justo ut, pharetra ipsum. Donec efficitur, ipsum quis congue luctus, mauris magna.',
icon: 'tabler:template',
},
{
title: 'Branding',
description:
'Suspendisse vitae nisi eget tortor luctus maximus sed non lectus. Cras malesuada pretium placerat. Nullam venenatis dolor a ante rhoncus.',
icon: 'tabler:template',
},
{
title: 'Medical',
description:
'Vestibulum malesuada lacus id nibh posuere feugiat. Nam volutpat nulla a felis ultrices, id suscipit mauris congue. In hac habitasse platea dictumst.',
icon: 'tabler:template',
},
{
title: 'Fashion Design',
description:
'Maecenas eu tellus eget est scelerisque lacinia et a diam. Aliquam velit lorem, vehicula id fermentum et, rhoncus et purus.',
icon: 'tabler:template',
},
]}
image={{
src: 'https://images.unsplash.com/photo-1504384308090-c894fdcc538d?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1740&q=80',
alt: 'Colorful Image',
}}
/>
<!-- Steps2 Widget ****************** -->
<Steps2
title="Our values"
subtitle="Maecenas eu tellus eget est scelerisque lacinia et a diam. Aliquam velit lorem, vehicula id fermentum et, rhoncus et purus. Nulla facilisi. Vestibulum malesuada lacus."
items={[
{
title: 'Customer-centric approach',
description:
'Donec id nibh neque. Quisque et fermentum tortor. Fusce vitae dolor a mauris dignissim commodo. Ut eleifend luctus condimentum.',
},
{
title: 'Constant Improvement',
description:
'Phasellus laoreet fermentum venenatis. Vivamus dapibus pulvinar arcu eget mattis. Fusce eget mauris leo.',
},
{
title: 'Ethical Practices',
description:
'Vestibulum imperdiet libero et lectus molestie, et maximus augue porta. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.',
},
]}
/>
<!-- Steps2 Widget ****************** -->
<Steps2
title="Achievements"
subtitle="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis lobortis, mi risus tempus nulla, sed porttitor est nibh at nulla."
isReversed={true}
callToAction={{
text: 'See more',
href: '/',
}}
items={[
{
title: 'Global reach',
description: 'Nam malesuada urna in enim imperdiet tincidunt. Phasellus non tincidunt nisi, at elementum mi.',
icon: 'tabler:globe',
},
{
title: 'Positive customer feedback and reviews',
description:
'Cras semper nulla leo, eget laoreet erat cursus sed. Praesent faucibus massa in purus iaculis dictum.',
icon: 'tabler:message-star',
},
{
title: 'Awards and recognition as industry experts',
description:
'Phasellus lacinia cursus velit, eu malesuada magna pretium eu. Etiam aliquet tellus purus, blandit lobortis ex rhoncus vitae.',
icon: 'tabler:award',
},
]}
/>
<!-- Features2 Widget ************** -->
<Features2
title="Our locations"
tagline="Find us"
columns={4}
items={[
{
title: 'EE.UU',
description: '1234 Lorem Ipsum St, 12345, Miami',
},
{
title: 'Spain',
description: '5678 Lorem Ipsum St, 56789, Madrid',
},
{
title: 'Australia',
description: '9012 Lorem Ipsum St, 90123, Sydney',
},
{
title: 'Brazil',
description: '3456 Lorem Ipsum St, 34567, São Paulo',
},
]}
/>
<!-- Features2 Widget ************** -->
<Features2
title="Technical Support"
tagline="Contact us"
columns={2}
items={[
{
title: 'Chat with us',
description:
'Integer luctus laoreet libero, auctor varius purus rutrum sit amet. Ut nec molestie nisi, quis eleifend mi.',
icon: 'tabler:messages',
},
{
title: 'Call us',
description:
'Mauris faucibus finibus orci, in posuere elit viverra non. In hac habitasse platea dictumst. Cras lobortis metus a hendrerit congue.',
icon: 'tabler:headset',
},
]}
/>
</Layout>

32
src/pages/aboutme.astro Normal file
View File

@@ -0,0 +1,32 @@
---
export const prerender = false;
import { supportedLanguages } from '~/i18n/translations';
// Check for language preference in cookies (set by client-side JS)
const cookies = Astro.request.headers.get('cookie') || '';
const cookieLanguage = cookies.split(';')
.map(cookie => cookie.trim())
.find(cookie => cookie.startsWith('preferredLanguage='))
?.split('=')[1];
// Get the user's preferred language from the browser if no cookie
const acceptLanguage = Astro.request.headers.get('accept-language') || '';
// Define the type for supported languages
type SupportedLanguage = typeof supportedLanguages[number];
// Use cookie language if available, otherwise detect from browser
const preferredLanguage =
(cookieLanguage && supportedLanguages.includes(cookieLanguage as SupportedLanguage))
? cookieLanguage
: acceptLanguage
.split(',')
.map(lang => lang.split(';')[0].trim().substring(0, 2))
.find(lang => supportedLanguages.includes(lang as SupportedLanguage)) || 'en';
// Get the hash fragment if present
const url = new URL(Astro.request.url);
const hash = url.hash;
// Redirect to the language-specific about me page
return Astro.redirect(`/${preferredLanguage}/aboutme${hash}`);
---

View File

@@ -1,77 +1,32 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Redirecting...</title>
<style>
/* Example minimal styling */
body {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
font-family: sans-serif;
background-color: #f9fafb;
color: #374151;
}
.container {
text-align: center;
}
</style>
</head>
<body>
<div class="container">
<h1 class="text-2xl font-bold mb-4">Redirecting...</h1>
<p id="redirect-message">
You are being redirected to the <strong></strong> version of our site.
</p>
<p class="mt-4">
If you are not redirected automatically, please
<a id="redirect-link" href="" class="text-blue-500 underline">click here</a>.
</p>
</div>
<script type="module">
// Define the supported languages
const supportedLangs = ['en', 'nl', 'de'];
let chosenLang = 'nl'; // Default language
---
export const prerender = false;
import { supportedLanguages } from '~/i18n/translations';
// Get the user's language from the browser
const userLang = navigator.language || (navigator.languages && navigator.languages[0]);
if (userLang) {
// For example, "en-US" becomes "en"
const preferredLang = userLang.split('-')[0];
if (supportedLangs.includes(preferredLang)) {
chosenLang = preferredLang;
}
}
// Construct the target URL based on the chosen language
const targetURL = `/${chosenLang}`;
console.log("Target URL:", targetURL);
// Check for language preference in cookies (set by client-side JS)
const cookies = Astro.request.headers.get('cookie') || '';
const cookieLanguage = cookies.split(';')
.map(cookie => cookie.trim())
.find(cookie => cookie.startsWith('preferredLanguage='))
?.split('=')[1];
// Update the DOM with the computed language values:
// Update the redirect message to display the chosen language.
const messageEl = document.getElementById('redirect-message');
if (messageEl) {
messageEl.innerHTML = `You are being redirected to the <strong>${chosenLang.toUpperCase()}</strong> version of our site.`;
}
// Get the user's preferred language from the browser if no cookie
const acceptLanguage = Astro.request.headers.get('accept-language') || '';
// Define the type for supported languages
type SupportedLanguage = typeof supportedLanguages[number];
// Update the href for the clickable link.
const linkEl = document.getElementById('redirect-link');
if (linkEl) {
linkEl.href = targetURL;
}
// Use cookie language if available, otherwise detect from browser
const preferredLanguage =
(cookieLanguage && supportedLanguages.includes(cookieLanguage as SupportedLanguage))
? cookieLanguage
: acceptLanguage
.split(',')
.map(lang => lang.split(';')[0].trim().substring(0, 2))
.find(lang => supportedLanguages.includes(lang as SupportedLanguage)) || 'en';
// Option 1: Dynamically add a meta refresh tag.
const metaRefresh = document.createElement("meta");
metaRefresh.httpEquiv = "refresh";
metaRefresh.content = `0; url=${targetURL}`;
document.head.appendChild(metaRefresh);
// Get the hash fragment if present
const url = new URL(Astro.request.url);
const hash = url.hash;
// Option 2: Alternatively, use JavaScript redirection:
// window.location.href = targetURL;
</script>
</body>
</html>
// Redirect to the language-specific homepage
return Astro.redirect(`/${preferredLanguage}/${hash}`);
---