full site update
This commit is contained in:
@@ -1,65 +1,27 @@
|
||||
---
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
import Header from '../components/Header.astro';
|
||||
import Footer from '../components/Footer.astro';
|
||||
import { t } from '../utils/i18n';
|
||||
import BaseLayout from "../layouts/BaseLayout.astro";
|
||||
import Header from "../components/Header.astro";
|
||||
import Footer from "../components/Footer.astro";
|
||||
import { getLangFromUrl, useTranslations } from '../utils/i18n';
|
||||
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
const t = await useTranslations(lang);
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${t('404.title')} | ${t('meta.title')}`}
|
||||
description={t('404.description')}
|
||||
title={`${t("404.title")} | ${t("meta.title")}`}
|
||||
description={t("404.description")}
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<section class="min-h-screen flex items-center justify-center bg-gradient-to-br from-background via-background to-muted">
|
||||
<div class="container-custom">
|
||||
<div class="text-center max-w-2xl mx-auto animate-on-scroll">
|
||||
<!-- 404 Visual -->
|
||||
<div class="text-8xl sm:text-9xl font-bold text-primary/20 mb-8">404</div>
|
||||
|
||||
<!-- Error message -->
|
||||
<h1 class="text-3xl sm:text-4xl lg:text-5xl font-display font-bold text-foreground mb-4">
|
||||
{t('404.title')}
|
||||
</h1>
|
||||
|
||||
<p class="text-lg sm:text-xl text-muted-foreground mb-8">
|
||||
{t('404.description')}
|
||||
</p>
|
||||
|
||||
<!-- Action buttons -->
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center items-center">
|
||||
<a
|
||||
href="/"
|
||||
class="btn-primary px-8 py-4 text-lg font-semibold rounded-xl shadow-lg hover:shadow-xl transition-all duration-300 hover:scale-105 inline-flex items-center group"
|
||||
>
|
||||
<svg class="h-5 w-5 mr-2 group-hover:-translate-x-1 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/>
|
||||
</svg>
|
||||
{t('404.button')}
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="/contact"
|
||||
class="btn-outline px-8 py-4 text-lg font-semibold rounded-xl transition-all duration-300 hover:scale-105"
|
||||
>
|
||||
Get Help
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Helpful links -->
|
||||
<div class="mt-12">
|
||||
<p class="text-muted-foreground mb-4">Or try one of these popular pages:</p>
|
||||
<div class="flex flex-wrap justify-center gap-4">
|
||||
<a href="/services" class="text-primary hover:text-primary/80 transition-colors">Services</a>
|
||||
<span class="text-muted-foreground">•</span>
|
||||
<a href="/about" class="text-primary hover:text-primary/80 transition-colors">About</a>
|
||||
<span class="text-muted-foreground">•</span>
|
||||
<a href="/contact" class="text-primary hover:text-primary/80 transition-colors">Contact</a>
|
||||
<span class="text-muted-foreground">•</span>
|
||||
<a href="https://blog.tiber365.it" target="_blank" rel="noopener noreferrer" class="text-primary hover:text-primary/80 transition-colors">Blog</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<section class="py-20">
|
||||
<div class="container-custom text-center">
|
||||
<h1 class="text-6xl font-bold text-muted-foreground mb-4">404</h1>
|
||||
<h2 class="text-2xl font-semibold text-foreground mb-4">{t("404.title")}</h2>
|
||||
<p class="text-muted-foreground mb-8">{t("404.description")}</p>
|
||||
<a href="/" class="inline-flex items-center px-6 py-3 bg-primary text-primary-foreground rounded-lg hover:bg-primary/90 transition-colors">
|
||||
{t("404.backHome")}
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
34
src/pages/[lang]/404.astro
Normal file
34
src/pages/[lang]/404.astro
Normal file
@@ -0,0 +1,34 @@
|
||||
---
|
||||
import BaseLayout from "../../layouts/BaseLayout.astro";
|
||||
import Header from "../../components/Header.astro";
|
||||
import Footer from "../../components/Footer.astro";
|
||||
import { useTranslations, SUPPORTED_LOCALES } from '../../utils/i18n';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
return SUPPORTED_LOCALES.map(lang => ({ params: { lang } }));
|
||||
}
|
||||
|
||||
const { lang } = Astro.params;
|
||||
const t = await useTranslations(lang as any);
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${t("404.title")} | ${t("meta.title")}`}
|
||||
description={t("404.description")}
|
||||
noindex={true}
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<section class="py-20">
|
||||
<div class="container-custom text-center">
|
||||
<h1 class="text-6xl font-bold text-muted-foreground mb-4">404</h1>
|
||||
<h2 class="text-2xl font-semibold text-foreground mb-4">{t("404.title")}</h2>
|
||||
<p class="text-muted-foreground mb-8">{t("404.description")}</p>
|
||||
<a href="/" class="inline-flex items-center px-6 py-3 bg-primary text-primary-foreground rounded-lg hover:bg-primary/90 transition-colors">
|
||||
{t("404.backHome")}
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
35
src/pages/[lang]/about.astro
Normal file
35
src/pages/[lang]/about.astro
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
import BaseLayout from "../../layouts/BaseLayout.astro";
|
||||
import Header from "../../components/Header.astro";
|
||||
import Footer from "../../components/Footer.astro";
|
||||
import CTA from "../../components/CTA.astro";
|
||||
import { useTranslations, SUPPORTED_LOCALES } from '../../utils/i18n';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
return SUPPORTED_LOCALES.map(lang => ({ params: { lang } }));
|
||||
}
|
||||
|
||||
const { lang } = Astro.params;
|
||||
const t = await useTranslations(lang as any);
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${t("nav.about")} | ${t("meta.title")}`}
|
||||
description={t("meta.description")}
|
||||
keywords={t("meta.keywords")}
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<section class="py-20">
|
||||
<div class="container-custom">
|
||||
<h1 class="text-4xl font-bold mb-8">{t("about.title")}</h1>
|
||||
<div class="prose prose-lg">
|
||||
<p>{t("about.description")}</p>
|
||||
<p>{t("about.mission")}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<CTA />
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
79
src/pages/[lang]/blog/[slug].astro
Normal file
79
src/pages/[lang]/blog/[slug].astro
Normal file
@@ -0,0 +1,79 @@
|
||||
---
|
||||
import BaseLayout from '../../../layouts/BaseLayout.astro';
|
||||
import Header from '../../../components/Header.astro';
|
||||
import Footer from '../../../components/Footer.astro';
|
||||
import { getBlogPostBySlug, getBlogPosts } from '../../../utils/directus';
|
||||
import { getLangFromUrl, useTranslations } from '../../../utils/i18n';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const posts = await getBlogPosts();
|
||||
const languages = ['en', 'nl', 'de', 'fr'];
|
||||
|
||||
const paths = [];
|
||||
for (const lang of languages) {
|
||||
for (const post of posts) {
|
||||
if (typeof post.slug === 'string' && post.slug.trim() !== '') {
|
||||
paths.push({
|
||||
params: { lang, slug: post.slug },
|
||||
props: { post },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
const { post } = Astro.props;
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
const t = await useTranslations(lang);
|
||||
---
|
||||
|
||||
<BaseLayout title={`${post.title} | ${t('blog.title')}`} description={post.content.replace(/<[^>]+>/g, '').substring(0, 160)}>
|
||||
<Header />
|
||||
|
||||
<main class="flex-1">
|
||||
<!-- Hero Section -->
|
||||
<section class="bg-gradient-to-br from-blue-50 to-indigo-100 dark:from-gray-900 dark:to-gray-800 py-20">
|
||||
<div class="container-custom">
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<nav class="mb-6">
|
||||
<a href={`/${lang}/blog`} class="text-primary hover:underline flex items-center">
|
||||
← {t('blog.backToBlog')}
|
||||
</a>
|
||||
</nav>
|
||||
<header class="text-center">
|
||||
<h1 class="text-4xl md:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
{post.title}
|
||||
</h1>
|
||||
<p class="text-xl text-gray-600 dark:text-gray-300">
|
||||
{new Date(post.date_created).toLocaleDateString(lang === 'en' ? 'en-US' : lang === 'nl' ? 'nl-NL' : lang === 'de' ? 'de-DE' : 'fr-FR', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric'
|
||||
})}
|
||||
</p>
|
||||
</header>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Article Content -->
|
||||
<section class="py-16">
|
||||
<div class="container-custom">
|
||||
<article class="max-w-4xl mx-auto">
|
||||
<div class="prose prose-lg dark:prose-invert max-w-none prose-headings:text-gray-900 dark:prose-headings:text-white prose-p:text-gray-700 dark:prose-p:text-gray-300 prose-a:text-primary prose-a:no-underline hover:prose-a:underline prose-strong:text-gray-900 dark:prose-strong:text-white prose-code:text-primary prose-code:bg-gray-100 dark:prose-code:bg-gray-800 prose-code:px-1 prose-code:py-0.5 prose-code:rounded" set:html={post.content}></div>
|
||||
|
||||
<!-- Back to Blog Button -->
|
||||
<div class="mt-12 pt-8 border-t border-border text-center">
|
||||
<a href={`/${lang}/blog`} class="btn btn-primary">
|
||||
← {t('blog.backToBlog')}
|
||||
</a>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</BaseLayout>
|
107
src/pages/[lang]/blog/index.astro
Normal file
107
src/pages/[lang]/blog/index.astro
Normal file
@@ -0,0 +1,107 @@
|
||||
---
|
||||
import BaseLayout from '../../../layouts/BaseLayout.astro';
|
||||
import Header from '../../../components/Header.astro';
|
||||
import Footer from '../../../components/Footer.astro';
|
||||
import { getBlogPosts } from '../../../utils/directus';
|
||||
import { getLangFromUrl, useTranslations } from '../../../utils/i18n';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const languages = ['en', 'nl', 'de', 'fr'] as const;
|
||||
|
||||
return languages.map(lang => ({
|
||||
params: { lang },
|
||||
props: { lang }
|
||||
}));
|
||||
}
|
||||
|
||||
const { lang } = Astro.props;
|
||||
const t = await useTranslations(lang);
|
||||
|
||||
let posts = [];
|
||||
let error = null;
|
||||
|
||||
function stripHtml(html) {
|
||||
return html.replace(/<[^>]+>/g, '');
|
||||
}
|
||||
|
||||
try {
|
||||
posts = await getBlogPosts();
|
||||
} catch (e) {
|
||||
console.error('Error in blog page:', e);
|
||||
error = e.message;
|
||||
}
|
||||
---
|
||||
|
||||
<BaseLayout title={t('blog.title')} description={t('blog.description')}>
|
||||
<Header />
|
||||
|
||||
<main class="flex-1">
|
||||
<!-- Hero Section -->
|
||||
<section class="bg-gradient-to-br from-blue-50 to-indigo-100 dark:from-gray-900 dark:to-gray-800 py-20">
|
||||
<div class="container-custom">
|
||||
<div class="text-center max-w-3xl mx-auto">
|
||||
<h1 class="text-4xl md:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||
{t('blog.title')}
|
||||
</h1>
|
||||
<p class="text-xl text-gray-600 dark:text-gray-300">
|
||||
{t('blog.description')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Blog Posts Section -->
|
||||
<section class="py-16">
|
||||
<div class="container-custom">
|
||||
{error ? (
|
||||
<div class="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-6 mb-8">
|
||||
<p class="text-red-800 dark:text-red-200">
|
||||
{t('blog.error')}
|
||||
</p>
|
||||
{import.meta.env.DEV && (
|
||||
<pre class="mt-2 text-sm text-red-600 dark:text-red-400">{error}</pre>
|
||||
)}
|
||||
</div>
|
||||
) : posts.length === 0 ? (
|
||||
<div class="text-center py-12">
|
||||
<p class="text-gray-600 dark:text-gray-400 text-lg">
|
||||
{t('blog.noPosts')}
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{posts.map((post) => (
|
||||
<article class="card hover:shadow-lg transition-shadow duration-300 group">
|
||||
<div class="flex flex-col h-full">
|
||||
<div class="flex-1">
|
||||
<h2 class="text-xl font-bold mb-3 group-hover:text-primary transition-colors">
|
||||
<a href={`/${lang}/blog/${post.slug}`} class="hover:underline">
|
||||
{post.title}
|
||||
</a>
|
||||
</h2>
|
||||
<p class="text-muted-foreground text-sm mb-4">
|
||||
{new Date(post.date_created).toLocaleDateString(lang === 'en' ? 'en-US' : lang === 'nl' ? 'nl-NL' : lang === 'de' ? 'de-DE' : 'fr-FR')}
|
||||
</p>
|
||||
<div class="text-foreground text-sm mb-6 line-clamp-4">
|
||||
{stripHtml(post.content).substring(0, 200)}{stripHtml(post.content).length > 200 ? '...' : ''}
|
||||
</div>
|
||||
</div>
|
||||
<div class="pt-4 border-t border-border">
|
||||
<a
|
||||
href={`/${lang}/blog/${post.slug}`}
|
||||
class="inline-flex items-center text-primary font-medium hover:underline transition-colors"
|
||||
>
|
||||
{t('blog.readMore')} →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</BaseLayout>
|
46
src/pages/[lang]/contact.astro
Normal file
46
src/pages/[lang]/contact.astro
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import Header from '../../components/Header.astro';
|
||||
import ContactForm from '../../components/ContactForm.astro';
|
||||
import Footer from '../../components/Footer.astro';
|
||||
import { useTranslations, SUPPORTED_LOCALES } from '../../utils/i18n';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
return SUPPORTED_LOCALES.map(lang => ({ params: { lang } }));
|
||||
}
|
||||
|
||||
const { lang } = Astro.params;
|
||||
const t = await useTranslations(lang as any);
|
||||
|
||||
// Contact page structured data
|
||||
const contactStructuredData = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "ContactPage",
|
||||
"name": `${t("nav.contact")} - ${t("meta.title")}`,
|
||||
"description": t("contact.description"),
|
||||
"url": `https://tiber365.it/${lang === 'en' ? 'contact' : `${lang}/contact`}`,
|
||||
"inLanguage": lang,
|
||||
"mainEntity": {
|
||||
"@type": "Organization",
|
||||
"name": "Tiber365",
|
||||
"contactPoint": {
|
||||
"@type": "ContactPoint",
|
||||
"contactType": "customer service",
|
||||
"availableLanguage": ["English", "Dutch", "German", "French"],
|
||||
"email": "info@tiber365.it"
|
||||
}
|
||||
}
|
||||
};
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${t("nav.contact")} | ${t("meta.title")}`}
|
||||
description={t("contact.description")}
|
||||
>
|
||||
<script type="application/ld+json" set:html={JSON.stringify(contactStructuredData)} />
|
||||
<Header />
|
||||
<main>
|
||||
<ContactForm />
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
64
src/pages/[lang]/index.astro
Normal file
64
src/pages/[lang]/index.astro
Normal file
@@ -0,0 +1,64 @@
|
||||
---
|
||||
import BaseLayout from "../../layouts/BaseLayout.astro";
|
||||
import Header from "../../components/Header.astro";
|
||||
import Hero from "../../components/Hero.astro";
|
||||
import Services from "../../components/Services.astro";
|
||||
import Testimonials from "../../components/Testimonials.astro";
|
||||
import CTA from "../../components/CTA.astro";
|
||||
import Footer from "../../components/Footer.astro";
|
||||
import { getLangFromUrl, useTranslations, SUPPORTED_LOCALES } from '../../utils/i18n';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
return SUPPORTED_LOCALES.map(lang => ({ params: { lang } }));
|
||||
}
|
||||
|
||||
const { lang } = Astro.params;
|
||||
const t = await useTranslations(lang as any);
|
||||
|
||||
// Page-specific structured data
|
||||
const pageStructuredData = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "WebPage",
|
||||
"name": t("meta.title"),
|
||||
"description": t("meta.description"),
|
||||
"url": `https://tiber365.it/${lang === 'en' ? '' : lang}`,
|
||||
"inLanguage": lang,
|
||||
"isPartOf": {
|
||||
"@type": "WebSite",
|
||||
"name": "Tiber365",
|
||||
"url": "https://tiber365.it"
|
||||
},
|
||||
"mainEntity": {
|
||||
"@type": "Organization",
|
||||
"name": "Tiber365",
|
||||
"description": t("site.description"),
|
||||
"url": "https://tiber365.it",
|
||||
"logo": "https://tiber365.it/images/TIBER365.png",
|
||||
"contactPoint": {
|
||||
"@type": "ContactPoint",
|
||||
"contactType": "customer service",
|
||||
"availableLanguage": ["English", "Dutch", "German", "French"]
|
||||
},
|
||||
"serviceArea": {
|
||||
"@type": "Country",
|
||||
"name": "Italy"
|
||||
}
|
||||
}
|
||||
};
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={t("meta.title")}
|
||||
description={t("meta.description")}
|
||||
keywords={t("meta.keywords")}
|
||||
>
|
||||
<script type="application/ld+json" set:html={JSON.stringify(pageStructuredData)} />
|
||||
<Header />
|
||||
<main>
|
||||
<Hero />
|
||||
<Services />
|
||||
<Testimonials />
|
||||
<CTA />
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
33
src/pages/[lang]/privacy.astro
Normal file
33
src/pages/[lang]/privacy.astro
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import Header from '../../components/Header.astro';
|
||||
import Footer from '../../components/Footer.astro';
|
||||
import { useTranslations, SUPPORTED_LOCALES } from '../../utils/i18n';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
return SUPPORTED_LOCALES.map(lang => ({ params: { lang } }));
|
||||
}
|
||||
|
||||
const { lang } = Astro.params;
|
||||
const t = await useTranslations(lang as any);
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${t("privacy.title")} | ${t("meta.title")}`}
|
||||
description={t("privacy.description")}
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<section class="py-20">
|
||||
<div class="container-custom">
|
||||
<h1 class="text-4xl font-bold mb-8">{t("privacy.title")}</h1>
|
||||
<div class="prose prose-lg max-w-none">
|
||||
<p>{t("privacy.lastUpdated")}</p>
|
||||
<p>{t("privacy.introduction")}</p>
|
||||
<!-- Add more privacy content as needed -->
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
33
src/pages/[lang]/terms.astro
Normal file
33
src/pages/[lang]/terms.astro
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import Header from '../../components/Header.astro';
|
||||
import Footer from '../../components/Footer.astro';
|
||||
import { useTranslations, SUPPORTED_LOCALES } from '../../utils/i18n';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
return SUPPORTED_LOCALES.map(lang => ({ params: { lang } }));
|
||||
}
|
||||
|
||||
const { lang } = Astro.params;
|
||||
const t = await useTranslations(lang as any);
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${t("terms.title")} | ${t("meta.title")}`}
|
||||
description={t("terms.description")}
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<section class="py-20">
|
||||
<div class="container-custom">
|
||||
<h1 class="text-4xl font-bold mb-8">{t("terms.title")}</h1>
|
||||
<div class="prose prose-lg max-w-none">
|
||||
<p>{t("terms.lastUpdated")}</p>
|
||||
<p>{t("terms.introduction")}</p>
|
||||
<!-- Add more terms content as needed -->
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
@@ -1,4 +0,0 @@
|
||||
---
|
||||
// Redirect to English version
|
||||
return Astro.redirect('/en/about');
|
||||
---
|
@@ -1,31 +1,28 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import { getBlogPostBySlug, getBlogPosts } from '../../utils/directus';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
// Get all blog posts to create redirects
|
||||
const { getBlogPosts } = await import('../../utils/directus');
|
||||
const posts = await getBlogPosts();
|
||||
|
||||
return posts
|
||||
.filter((post) => typeof post.slug === 'string' && post.slug.trim() !== '')
|
||||
.map((post) => ({
|
||||
params: { slug: post.slug },
|
||||
props: { post },
|
||||
props: { slug: post.slug },
|
||||
}));
|
||||
}
|
||||
|
||||
const { post } = Astro.props;
|
||||
const { slug } = Astro.props;
|
||||
---
|
||||
|
||||
<BaseLayout title={`${post.title} | Tiber365 Blog`}>
|
||||
<main class="container mx-auto px-4 py-12">
|
||||
<article class="max-w-3xl mx-auto">
|
||||
<header class="mb-8">
|
||||
<h1 class="text-4xl font-bold mb-4">{post.title}</h1>
|
||||
<p class="text-gray-600 dark:text-gray-300">
|
||||
{new Date(post.date_created).toLocaleDateString()}
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<div class="prose dark:prose-invert max-w-none" set:html={post.content}></div>
|
||||
</article>
|
||||
</main>
|
||||
</BaseLayout>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Redirecting...</title>
|
||||
<meta http-equiv="refresh" content="0;url=/en/blog/{slug}">
|
||||
<link rel="canonical" href="/en/blog/{slug}">
|
||||
</head>
|
||||
<body>
|
||||
<p>Redirecting to <a href="/en/blog/{slug}">blog post</a>...</p>
|
||||
</body>
|
||||
</html>
|
@@ -1,63 +1,15 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import { getBlogPosts } from '../../utils/directus';
|
||||
|
||||
let posts = [];
|
||||
let error = null;
|
||||
|
||||
function stripHtml(html) {
|
||||
return html.replace(/<[^>]+>/g, '');
|
||||
}
|
||||
|
||||
try {
|
||||
posts = await getBlogPosts();
|
||||
} catch (e) {
|
||||
console.error('Error in blog page:', e);
|
||||
error = e.message;
|
||||
}
|
||||
// Static redirect to English blog
|
||||
---
|
||||
|
||||
<BaseLayout title="Blog | Tiber365">
|
||||
<main class="flex flex-col items-center min-h-screen bg-background py-16 px-4">
|
||||
<h1 class="text-5xl font-extrabold mb-12 text-center">Blog</h1>
|
||||
|
||||
{error ? (
|
||||
<div class="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 mb-8">
|
||||
<p class="text-red-800 dark:text-red-200">
|
||||
Sorry, we couldn't load the blog posts at this time. Please try again later.
|
||||
</p>
|
||||
{import.meta.env.DEV && (
|
||||
<pre class="mt-2 text-sm text-red-600 dark:text-red-400">{error}</pre>
|
||||
)}
|
||||
</div>
|
||||
) : posts.length === 0 ? (
|
||||
<p class="text-gray-600 dark:text-gray-400">No blog posts found.</p>
|
||||
) : (
|
||||
<div class="w-full max-w-4xl mx-auto grid grid-cols-1 md:grid-cols-2 gap-10">
|
||||
{posts.map((post) => (
|
||||
<article class="bg-white/90 dark:bg-gray-900/80 border border-gray-200 dark:border-gray-800 rounded-2xl shadow-lg hover:shadow-2xl transition-shadow duration-300 overflow-hidden flex flex-col h-full group">
|
||||
<div class="flex flex-col flex-1 p-8">
|
||||
<h2 class="text-2xl font-bold mb-3 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors">
|
||||
<a href={`/blog/${post.slug}`}>{post.title}</a>
|
||||
</h2>
|
||||
<p class="text-gray-500 dark:text-gray-400 text-sm mb-4">
|
||||
{new Date(post.date_created).toLocaleDateString()}
|
||||
</p>
|
||||
<div class="text-base text-gray-700 dark:text-gray-300 mb-6 line-clamp-4">
|
||||
{stripHtml(post.content).substring(0, 250)}{stripHtml(post.content).length > 250 ? '...' : ''}
|
||||
</div>
|
||||
<div class="mt-auto pt-2">
|
||||
<a
|
||||
href={`/blog/${post.slug}`}
|
||||
class="inline-block text-blue-600 dark:text-blue-400 font-medium hover:underline transition-colors"
|
||||
>
|
||||
Read more →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</main>
|
||||
</BaseLayout>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Redirecting...</title>
|
||||
<meta http-equiv="refresh" content="0;url=/en/blog">
|
||||
<link rel="canonical" href="/en/blog">
|
||||
</head>
|
||||
<body>
|
||||
<p>Redirecting to <a href="/en/blog">blog</a>...</p>
|
||||
</body>
|
||||
</html>
|
@@ -1,18 +0,0 @@
|
||||
---
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
import Header from '../components/Header.astro';
|
||||
import ContactForm from '../components/ContactForm.astro';
|
||||
import Footer from '../components/Footer.astro';
|
||||
import { t } from '../utils/i18n';
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${t('nav.contact')} | ${t('meta.title')}`}
|
||||
description="Contact Tiber365 for professional IT services. Get in touch for Microsoft 365 support, networking solutions, and custom IT projects."
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<ContactForm />
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
@@ -1,62 +0,0 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import Header from '../../components/Header.astro';
|
||||
import Footer from '../../components/Footer.astro';
|
||||
import { t } from '../../utils/i18n';
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${t('404.title', 'en')} | ${t('meta.title', 'en')}`}
|
||||
description={t('404.description', 'en')}
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<section class="min-h-screen flex items-center justify-center bg-gradient-to-br from-background via-background to-muted">
|
||||
<div class="container-custom">
|
||||
<div class="text-center max-w-2xl mx-auto animate-on-scroll">
|
||||
<!-- 404 Visual -->
|
||||
<div class="text-8xl sm:text-9xl font-bold text-primary/20 mb-8">404</div>
|
||||
<!-- Error message -->
|
||||
<h1 class="text-3xl sm:text-4xl lg:text-5xl font-display font-bold text-foreground mb-4">
|
||||
{t('404.title', 'en')}
|
||||
</h1>
|
||||
<p class="text-lg sm:text-xl text-muted-foreground mb-8">
|
||||
{t('404.description', 'en')}
|
||||
</p>
|
||||
<!-- Action buttons -->
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center items-center">
|
||||
<a
|
||||
href="/"
|
||||
class="btn-primary px-8 py-4 text-lg font-semibold rounded-xl shadow-lg hover:shadow-xl transition-all duration-300 hover:scale-105 inline-flex items-center group"
|
||||
>
|
||||
<svg class="h-5 w-5 mr-2 group-hover:-translate-x-1 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/>
|
||||
</svg>
|
||||
{t('404.button', 'en')}
|
||||
</a>
|
||||
<a
|
||||
href="/contact"
|
||||
class="btn-outline px-8 py-4 text-lg font-semibold rounded-xl transition-all duration-300 hover:scale-105"
|
||||
>
|
||||
Get Help
|
||||
</a>
|
||||
</div>
|
||||
<!-- Helpful links -->
|
||||
<div class="mt-12">
|
||||
<p class="text-muted-foreground mb-4">Or try one of these popular pages:</p>
|
||||
<div class="flex flex-wrap justify-center gap-4">
|
||||
<a href="/services" class="text-primary hover:text-primary/80 transition-colors">Services</a>
|
||||
<span class="text-muted-foreground">•</span>
|
||||
<a href="/about" class="text-primary hover:text-primary/80 transition-colors">About</a>
|
||||
<span class="text-muted-foreground">•</span>
|
||||
<a href="/contact" class="text-primary hover:text-primary/80 transition-colors">Contact</a>
|
||||
<span class="text-muted-foreground">•</span>
|
||||
<a href="https://blog.tiber365.it" target="_blank" rel="noopener noreferrer" class="text-primary hover:text-primary/80 transition-colors">Blog</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
@@ -1,55 +0,0 @@
|
||||
---
|
||||
import BaseLayout from "../../layouts/BaseLayout.astro";
|
||||
import Header from "../../components/Header.astro";
|
||||
import Footer from "../../components/Footer.astro";
|
||||
import CTA from "../../components/CTA.astro";
|
||||
import { t } from '../../utils/i18n';
|
||||
|
||||
const pageTitle = `${t('nav.about', 'en')} | ${t('meta.title', 'en')}`;
|
||||
const pageDescription = t('meta.description', 'en');
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={pageTitle}
|
||||
description={pageDescription}
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<!-- About Hero -->
|
||||
<section class="py-20 bg-gradient-to-br from-background via-background to-muted">
|
||||
<div class="container-custom">
|
||||
<div class="text-center max-w-4xl mx-auto animate-on-scroll">
|
||||
<h1 class="text-4xl sm:text-5xl lg:text-6xl font-display font-bold text-foreground mb-6">
|
||||
{t('about.title', 'en')}
|
||||
</h1>
|
||||
<p class="text-lg sm:text-xl text-muted-foreground leading-relaxed">
|
||||
{t('about.subtitle', 'en')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Company Story -->
|
||||
<section class="py-20 bg-background">
|
||||
<div class="container-custom">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Content -->
|
||||
<div class="animate-on-scroll">
|
||||
<h2 class="text-3xl sm:text-4xl font-display font-bold text-foreground mb-6">
|
||||
{t('about.story.title', 'en')}
|
||||
</h2>
|
||||
<p class="text-lg text-muted-foreground mb-6 leading-relaxed">
|
||||
{t('about.story.description', 'en')}
|
||||
</p>
|
||||
<p class="text-lg text-muted-foreground leading-relaxed">
|
||||
{t('about.story.mission', 'en')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<CTA />
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
@@ -1,18 +0,0 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import Header from '../../components/Header.astro';
|
||||
import ContactForm from '../../components/ContactForm.astro';
|
||||
import Footer from '../../components/Footer.astro';
|
||||
import { t } from '../../utils/i18n';
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${t('nav.contact', 'en')} | ${t('meta.title', 'en')}`}
|
||||
description="Contact Tiber365 for professional IT services. Get in touch for Microsoft 365 support, networking solutions, and custom IT projects."
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<ContactForm />
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
@@ -1,29 +0,0 @@
|
||||
---
|
||||
import BaseLayout from "../../layouts/BaseLayout.astro";
|
||||
import Header from "../../components/Header.astro";
|
||||
import Hero from "../../components/Hero.astro";
|
||||
import Services from "../../components/Services.astro";
|
||||
import Testimonials from "../../components/Testimonials.astro";
|
||||
import CTA from "../../components/CTA.astro";
|
||||
import Footer from "../../components/Footer.astro";
|
||||
import { t } from '../../utils/i18n';
|
||||
|
||||
const pageTitle = t('meta.title', 'en');
|
||||
const pageDescription = t('meta.description', 'en');
|
||||
const pageKeywords = t('meta.keywords', 'en');
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={pageTitle}
|
||||
description={pageDescription}
|
||||
keywords={pageKeywords}
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<Hero />
|
||||
<Services />
|
||||
<Testimonials />
|
||||
<CTA />
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
@@ -1,25 +1,4 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import Header from '../../components/Header.astro';
|
||||
import Footer from '../../components/Footer.astro';
|
||||
import { t } from '../../utils/i18n';
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${t('footer.links.privacy', 'en')} | ${t('meta.title', 'en')}`}
|
||||
description="Privacy Policy for Tiber365 - Learn how we collect, use, and protect your personal data in compliance with GDPR and Dutch privacy laws."
|
||||
>
|
||||
<Header />
|
||||
<main class="py-16 bg-background">
|
||||
<div class="container-custom">
|
||||
<article class="prose prose-lg dark:prose-invert max-w-4xl mx-auto">
|
||||
<h1 class="text-4xl font-display font-bold mb-8">{t('footer.links.privacy', 'en')}</h1>
|
||||
<div class="mb-8 text-sm text-muted-foreground">
|
||||
Last updated: {new Date().toLocaleDateString()}
|
||||
</div>
|
||||
<!-- Copy the rest of the original file, updating all t() calls to use 'en' as the locale -->
|
||||
</article>
|
||||
</div>
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
||||
// Redirect to main privacy page
|
||||
return Astro.redirect('/privacy');
|
||||
---
|
@@ -1,25 +0,0 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import Header from '../../components/Header.astro';
|
||||
import Footer from '../../components/Footer.astro';
|
||||
import { t } from '../../utils/i18n';
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${t('footer.links.terms', 'en')} | ${t('meta.title', 'en')}`}
|
||||
description="Terms of Service for Tiber365 - Understanding our service agreement and legal terms in compliance with European and Dutch laws."
|
||||
>
|
||||
<Header />
|
||||
<main class="py-16 bg-background">
|
||||
<div class="container-custom">
|
||||
<article class="prose prose-lg dark:prose-invert max-w-4xl mx-auto">
|
||||
<h1 class="text-4xl font-display font-bold mb-8">{t('footer.links.terms', 'en')}</h1>
|
||||
<div class="mb-8 text-sm text-muted-foreground">
|
||||
Last updated: {new Date().toLocaleDateString()}
|
||||
</div>
|
||||
<!-- Copy the rest of the original file, updating all t() calls to use 'en' as the locale -->
|
||||
</article>
|
||||
</div>
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
@@ -1,29 +1,4 @@
|
||||
---
|
||||
import BaseLayout from "../layouts/BaseLayout.astro";
|
||||
import Header from "../components/Header.astro";
|
||||
import Hero from "../components/Hero.astro";
|
||||
import Services from "../components/Services.astro";
|
||||
import Testimonials from "../components/Testimonials.astro";
|
||||
import CTA from "../components/CTA.astro";
|
||||
import Footer from "../components/Footer.astro";
|
||||
import { t } from '../utils/i18n';
|
||||
|
||||
const pageTitle = t('meta.title', 'en');
|
||||
const pageDescription = t('meta.description', 'en');
|
||||
const pageKeywords = t('meta.keywords', 'en');
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={pageTitle}
|
||||
description={pageDescription}
|
||||
keywords={pageKeywords}
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<Hero />
|
||||
<Services />
|
||||
<Testimonials />
|
||||
<CTA />
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
||||
// Redirect to English version
|
||||
return Astro.redirect('/en/');
|
||||
---
|
@@ -1,62 +0,0 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import Header from '../../components/Header.astro';
|
||||
import Footer from '../../components/Footer.astro';
|
||||
import { t } from '../../utils/i18n';
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${t('404.title', 'it')} | ${t('meta.title', 'it')}`}
|
||||
description={t('404.description', 'it')}
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<section class="min-h-screen flex items-center justify-center bg-gradient-to-br from-background via-background to-muted">
|
||||
<div class="container-custom">
|
||||
<div class="text-center max-w-2xl mx-auto animate-on-scroll">
|
||||
<!-- 404 Visual -->
|
||||
<div class="text-8xl sm:text-9xl font-bold text-primary/20 mb-8">404</div>
|
||||
<!-- Error message -->
|
||||
<h1 class="text-3xl sm:text-4xl lg:text-5xl font-display font-bold text-foreground mb-4">
|
||||
{t('404.title', 'it')}
|
||||
</h1>
|
||||
<p class="text-lg sm:text-xl text-muted-foreground mb-8">
|
||||
{t('404.description', 'it')}
|
||||
</p>
|
||||
<!-- Action buttons -->
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center items-center">
|
||||
<a
|
||||
href="/"
|
||||
class="btn-primary px-8 py-4 text-lg font-semibold rounded-xl shadow-lg hover:shadow-xl transition-all duration-300 hover:scale-105 inline-flex items-center group"
|
||||
>
|
||||
<svg class="h-5 w-5 mr-2 group-hover:-translate-x-1 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/>
|
||||
</svg>
|
||||
{t('404.button', 'it')}
|
||||
</a>
|
||||
<a
|
||||
href="/contact"
|
||||
class="btn-outline px-8 py-4 text-lg font-semibold rounded-xl transition-all duration-300 hover:scale-105"
|
||||
>
|
||||
Serve Aiuto
|
||||
</a>
|
||||
</div>
|
||||
<!-- Helpful links -->
|
||||
<div class="mt-12">
|
||||
<p class="text-muted-foreground mb-4">Oppure prova una di queste pagine popolari:</p>
|
||||
<div class="flex flex-wrap justify-center gap-4">
|
||||
<a href="/services" class="text-primary hover:text-primary/80 transition-colors">Servizi</a>
|
||||
<span class="text-muted-foreground">•</span>
|
||||
<a href="/about" class="text-primary hover:text-primary/80 transition-colors">Chi Siamo</a>
|
||||
<span class="text-muted-foreground">•</span>
|
||||
<a href="/contact" class="text-primary hover:text-primary/80 transition-colors">Contatti</a>
|
||||
<span class="text-muted-foreground">•</span>
|
||||
<a href="https://blog.tiber365.it" target="_blank" rel="noopener noreferrer" class="text-primary hover:text-primary/80 transition-colors">Blog</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
@@ -1,32 +0,0 @@
|
||||
---
|
||||
import BaseLayout from "../../layouts/BaseLayout.astro";
|
||||
import Header from "../../components/Header.astro";
|
||||
import Footer from "../../components/Footer.astro";
|
||||
import CTA from "../../components/CTA.astro";
|
||||
import { Trans } from "astro-i18next/components";
|
||||
import i18next from "i18next";
|
||||
|
||||
// Initialize i18next for this page
|
||||
await i18next.changeLanguage("it");
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${i18next.t("nav.about")} | ${i18next.t("meta.title")}`}
|
||||
description={i18next.t("meta.description")}
|
||||
keywords={i18next.t("meta.keywords")}
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<section class="py-20">
|
||||
<div class="container-custom">
|
||||
<h1 class="text-4xl font-bold mb-8">{i18next.t("about.title")}</h1>
|
||||
<div class="prose prose-lg">
|
||||
<p>{i18next.t("about.description")}</p>
|
||||
<p>{i18next.t("about.mission")}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<CTA />
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
@@ -1,18 +0,0 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import Header from '../../components/Header.astro';
|
||||
import ContactForm from '../../components/ContactForm.astro';
|
||||
import Footer from '../../components/Footer.astro';
|
||||
import { t } from '../../utils/i18n';
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${t('nav.contact', 'it')} | ${t('meta.title', 'it')}`}
|
||||
description="Contatta Tiber365 per servizi IT professionali. Contattaci per supporto Microsoft 365, soluzioni di rete e progetti IT personalizzati."
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<ContactForm />
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
@@ -1,29 +0,0 @@
|
||||
---
|
||||
import BaseLayout from "../../layouts/BaseLayout.astro";
|
||||
import Header from "../../components/Header.astro";
|
||||
import Hero from "../../components/Hero.astro";
|
||||
import Services from "../../components/Services.astro";
|
||||
import Testimonials from "../../components/Testimonials.astro";
|
||||
import CTA from "../../components/CTA.astro";
|
||||
import Footer from "../../components/Footer.astro";
|
||||
import { Trans } from "astro-i18next/components";
|
||||
import i18next from "i18next";
|
||||
|
||||
// Initialize i18next for this page
|
||||
await i18next.changeLanguage("it");
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={i18next.t("meta.title")}
|
||||
description={i18next.t("meta.description")}
|
||||
keywords={i18next.t("meta.keywords")}
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<Hero />
|
||||
<Services />
|
||||
<Testimonials />
|
||||
<CTA />
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
@@ -1,25 +0,0 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import Header from '../../components/Header.astro';
|
||||
import Footer from '../../components/Footer.astro';
|
||||
import { t } from '../../utils/i18n';
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${t('footer.links.privacy', 'it')} | ${t('meta.title', 'it')}`}
|
||||
description="Informativa sulla privacy per Tiber365 - Scopri come raccogliamo, utilizziamo e proteggiamo i tuoi dati personali in conformità con il GDPR e le leggi italiane sulla privacy."
|
||||
>
|
||||
<Header />
|
||||
<main class="py-16 bg-background">
|
||||
<div class="container-custom">
|
||||
<article class="prose prose-lg dark:prose-invert max-w-4xl mx-auto">
|
||||
<h1 class="text-4xl font-display font-bold mb-8">{t('footer.links.privacy', 'it')}</h1>
|
||||
<div class="mb-8 text-sm text-muted-foreground">
|
||||
Ultimo aggiornamento: {new Date().toLocaleDateString()}
|
||||
</div>
|
||||
<!-- Copy the rest of the original file, updating all t() calls to use 'it' as the locale -->
|
||||
</article>
|
||||
</div>
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
@@ -1,25 +0,0 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import Header from '../../components/Header.astro';
|
||||
import Footer from '../../components/Footer.astro';
|
||||
import { t } from '../../utils/i18n';
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${t('footer.links.terms', 'it')} | ${t('meta.title', 'it')}`}
|
||||
description="Termini di servizio per Tiber365 - Comprendere il nostro accordo di servizio e i termini legali in conformità con le leggi europee e italiane."
|
||||
>
|
||||
<Header />
|
||||
<main class="py-16 bg-background">
|
||||
<div class="container-custom">
|
||||
<article class="prose prose-lg dark:prose-invert max-w-4xl mx-auto">
|
||||
<h1 class="text-4xl font-display font-bold mb-8">{t('footer.links.terms', 'it')}</h1>
|
||||
<div class="mb-8 text-sm text-muted-foreground">
|
||||
Ultimo aggiornamento: {new Date().toLocaleDateString()}
|
||||
</div>
|
||||
<!-- Copy the rest of the original file, updating all t() calls to use 'it' as the locale -->
|
||||
</article>
|
||||
</div>
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
@@ -1,62 +0,0 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import Header from '../../components/Header.astro';
|
||||
import Footer from '../../components/Footer.astro';
|
||||
import { t } from '../../utils/i18n';
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${t('404.title', 'nl')} | ${t('meta.title', 'nl')}`}
|
||||
description={t('404.description', 'nl')}
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<section class="min-h-screen flex items-center justify-center bg-gradient-to-br from-background via-background to-muted">
|
||||
<div class="container-custom">
|
||||
<div class="text-center max-w-2xl mx-auto animate-on-scroll">
|
||||
<!-- 404 Visual -->
|
||||
<div class="text-8xl sm:text-9xl font-bold text-primary/20 mb-8">404</div>
|
||||
<!-- Error message -->
|
||||
<h1 class="text-3xl sm:text-4xl lg:text-5xl font-display font-bold text-foreground mb-4">
|
||||
{t('404.title', 'nl')}
|
||||
</h1>
|
||||
<p class="text-lg sm:text-xl text-muted-foreground mb-8">
|
||||
{t('404.description', 'nl')}
|
||||
</p>
|
||||
<!-- Action buttons -->
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center items-center">
|
||||
<a
|
||||
href="/"
|
||||
class="btn-primary px-8 py-4 text-lg font-semibold rounded-xl shadow-lg hover:shadow-xl transition-all duration-300 hover:scale-105 inline-flex items-center group"
|
||||
>
|
||||
<svg class="h-5 w-5 mr-2 group-hover:-translate-x-1 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/>
|
||||
</svg>
|
||||
{t('404.button', 'nl')}
|
||||
</a>
|
||||
<a
|
||||
href="/contact"
|
||||
class="btn-outline px-8 py-4 text-lg font-semibold rounded-xl transition-all duration-300 hover:scale-105"
|
||||
>
|
||||
Hulp Nodig
|
||||
</a>
|
||||
</div>
|
||||
<!-- Helpful links -->
|
||||
<div class="mt-12">
|
||||
<p class="text-muted-foreground mb-4">Of probeer een van deze populaire pagina's:</p>
|
||||
<div class="flex flex-wrap justify-center gap-4">
|
||||
<a href="/services" class="text-primary hover:text-primary/80 transition-colors">Diensten</a>
|
||||
<span class="text-muted-foreground">•</span>
|
||||
<a href="/about" class="text-primary hover:text-primary/80 transition-colors">Over Ons</a>
|
||||
<span class="text-muted-foreground">•</span>
|
||||
<a href="/contact" class="text-primary hover:text-primary/80 transition-colors">Contact</a>
|
||||
<span class="text-muted-foreground">•</span>
|
||||
<a href="https://blog.tiber365.it" target="_blank" rel="noopener noreferrer" class="text-primary hover:text-primary/80 transition-colors">Blog</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
@@ -1,32 +0,0 @@
|
||||
---
|
||||
import BaseLayout from "../../layouts/BaseLayout.astro";
|
||||
import Header from "../../components/Header.astro";
|
||||
import Footer from "../../components/Footer.astro";
|
||||
import CTA from "../../components/CTA.astro";
|
||||
import { Trans } from "astro-i18next/components";
|
||||
import i18next from "i18next";
|
||||
|
||||
// Initialize i18next for this page
|
||||
await i18next.changeLanguage("nl");
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${i18next.t("nav.about")} | ${i18next.t("meta.title")}`}
|
||||
description={i18next.t("meta.description")}
|
||||
keywords={i18next.t("meta.keywords")}
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<section class="py-20">
|
||||
<div class="container-custom">
|
||||
<h1 class="text-4xl font-bold mb-8">{i18next.t("about.title")}</h1>
|
||||
<div class="prose prose-lg">
|
||||
<p>{i18next.t("about.description")}</p>
|
||||
<p>{i18next.t("about.mission")}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<CTA />
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
@@ -1 +0,0 @@
|
||||
|
@@ -1,29 +0,0 @@
|
||||
---
|
||||
import BaseLayout from "../../layouts/BaseLayout.astro";
|
||||
import Header from "../../components/Header.astro";
|
||||
import Hero from "../../components/Hero.astro";
|
||||
import Services from "../../components/Services.astro";
|
||||
import Testimonials from "../../components/Testimonials.astro";
|
||||
import CTA from "../../components/CTA.astro";
|
||||
import Footer from "../../components/Footer.astro";
|
||||
import { Trans } from "astro-i18next/components";
|
||||
import i18next from "i18next";
|
||||
|
||||
// Initialize i18next for this page
|
||||
await i18next.changeLanguage("nl");
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={i18next.t("meta.title")}
|
||||
description={i18next.t("meta.description")}
|
||||
keywords={i18next.t("meta.keywords")}
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<Hero />
|
||||
<Services />
|
||||
<Testimonials />
|
||||
<CTA />
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
@@ -1 +1,29 @@
|
||||
|
||||
---
|
||||
import BaseLayout from "../../layouts/BaseLayout.astro";
|
||||
import Header from "../../components/Header.astro";
|
||||
import Footer from "../../components/Footer.astro";
|
||||
import { getLangFromUrl, useTranslations } from '../../utils/i18n';
|
||||
|
||||
const lang = getLangFromUrl(Astro.url);
|
||||
const t = await useTranslations(lang);
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${t("privacy.title")} | ${t("meta.title")}`}
|
||||
description={t("privacy.description")}
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<section class="py-20">
|
||||
<div class="container-custom">
|
||||
<h1 class="text-4xl font-bold mb-8">{t("privacy.title")}</h1>
|
||||
<div class="prose prose-lg max-w-none">
|
||||
<p>{t("privacy.lastUpdated")}</p>
|
||||
<p>{t("privacy.introduction")}</p>
|
||||
<!-- Add more privacy content as needed -->
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
@@ -1 +0,0 @@
|
||||
|
@@ -1,154 +0,0 @@
|
||||
---
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
import Header from '../components/Header.astro';
|
||||
import Footer from '../components/Footer.astro';
|
||||
import { t } from '../utils/i18n';
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${t('footer.links.privacy')} | ${t('meta.title')}`}
|
||||
description="Privacy Policy for Tiber365 - Learn how we collect, use, and protect your personal data in compliance with GDPR and Dutch privacy laws."
|
||||
>
|
||||
<Header />
|
||||
<main class="py-16 bg-background">
|
||||
<div class="container-custom">
|
||||
<article class="prose prose-lg dark:prose-invert max-w-4xl mx-auto">
|
||||
<h1 class="text-4xl font-display font-bold mb-8">{t('footer.links.privacy')}</h1>
|
||||
|
||||
<div class="mb-8 text-sm text-muted-foreground">
|
||||
Last updated: {new Date().toLocaleDateString()}
|
||||
</div>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>1. Introduction</h2>
|
||||
<p>
|
||||
Tiber365 ("we", "our", or "us") is committed to protecting your privacy and personal data. This Privacy Policy explains how we collect, use, and protect your personal information in accordance with the General Data Protection Regulation (GDPR) and Dutch privacy laws.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>2. Data Controller</h2>
|
||||
<p>
|
||||
Tiber365<br />
|
||||
Italy<br />
|
||||
Email: info@tiber365.it
|
||||
</p>
|
||||
<p>
|
||||
For privacy-related inquiries, you can contact our Data Protection Officer at privacy@tiber365.it.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>3. Personal Data We Collect</h2>
|
||||
<p>We collect and process the following types of personal data:</p>
|
||||
<ul>
|
||||
<li>Contact information (name, email, phone number, company name)</li>
|
||||
<li>Technical data (IP address, browser type, device information)</li>
|
||||
<li>Usage data (how you interact with our website and services)</li>
|
||||
<li>Communication data (messages you send us through our contact form)</li>
|
||||
<li>Service data (information related to the IT services we provide)</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>4. Legal Basis for Processing</h2>
|
||||
<p>We process your personal data based on the following legal grounds:</p>
|
||||
<ul>
|
||||
<li>Contract performance (when providing our IT services)</li>
|
||||
<li>Legal obligations (compliance with Dutch and EU laws)</li>
|
||||
<li>Legitimate interests (improving our services and communication)</li>
|
||||
<li>Consent (for marketing communications and cookies)</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>5. How We Use Your Data</h2>
|
||||
<p>We use your personal data for:</p>
|
||||
<ul>
|
||||
<li>Providing and managing our IT services</li>
|
||||
<li>Communicating with you about our services</li>
|
||||
<li>Improving our website and services</li>
|
||||
<li>Complying with legal obligations</li>
|
||||
<li>Sending you marketing communications (with your consent)</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>6. Data Sharing and Transfers</h2>
|
||||
<p>
|
||||
We may share your data with:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Service providers (hosting, email, analytics)</li>
|
||||
<li>Professional advisers (lawyers, accountants)</li>
|
||||
<li>Authorities (when legally required)</li>
|
||||
</ul>
|
||||
<p>
|
||||
Data transfers outside the EU/EEA are protected by appropriate safeguards (Standard Contractual Clauses).
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>7. Data Retention</h2>
|
||||
<p>
|
||||
We retain your personal data only for as long as necessary to fulfill the purposes for which it was collected, including legal requirements and accounting purposes.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>8. Your Rights</h2>
|
||||
<p>Under GDPR and Dutch privacy laws, you have the right to:</p>
|
||||
<ul>
|
||||
<li>Access your personal data</li>
|
||||
<li>Correct inaccurate data</li>
|
||||
<li>Request deletion of your data</li>
|
||||
<li>Object to processing</li>
|
||||
<li>Data portability</li>
|
||||
<li>Withdraw consent</li>
|
||||
</ul>
|
||||
<p>
|
||||
To exercise these rights, contact us at privacy@tiber365.it. We'll respond within 30 days.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>9. Cookies and Tracking</h2>
|
||||
<p>
|
||||
We use cookies and similar technologies to improve your browsing experience. You can manage cookie preferences through your browser settings.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>10. Security</h2>
|
||||
<p>
|
||||
We implement appropriate technical and organizational measures to protect your personal data against unauthorized access, alteration, disclosure, or destruction.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>11. Changes to This Policy</h2>
|
||||
<p>
|
||||
We may update this Privacy Policy periodically. We will notify you of any material changes by posting the new policy on this page.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>12. Complaints</h2>
|
||||
<p>
|
||||
If you have concerns about how we process your personal data, please contact us first. You also have the right to file a complaint with the Dutch Data Protection Authority (Autoriteit Persoonsgegevens).
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>13. Contact Us</h2>
|
||||
<p>
|
||||
For any privacy-related questions or requests, please contact us at:<br />
|
||||
Email: privacy@tiber365.it<br />
|
||||
Phone: +39 123 456 7890
|
||||
</p>
|
||||
</section>
|
||||
</article>
|
||||
</div>
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
81
src/pages/sitemap.xml.ts
Normal file
81
src/pages/sitemap.xml.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import type { APIRoute } from 'astro';
|
||||
import { SITE } from '../site.config';
|
||||
import { getBlogPosts } from '../utils/directus';
|
||||
|
||||
const pages = [
|
||||
'',
|
||||
'/about',
|
||||
'/contact',
|
||||
'/services',
|
||||
'/blog',
|
||||
'/privacy',
|
||||
'/terms'
|
||||
];
|
||||
|
||||
const locales = ['en', 'nl', 'de', 'fr'];
|
||||
|
||||
export const GET: APIRoute = async () => {
|
||||
// Get blog posts for sitemap
|
||||
let blogPosts = [];
|
||||
try {
|
||||
blogPosts = await getBlogPosts();
|
||||
} catch (error) {
|
||||
console.error('Error fetching blog posts for sitemap:', error);
|
||||
}
|
||||
|
||||
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
||||
xmlns:xhtml="http://www.w3.org/1999/xhtml">
|
||||
${pages.map(page => {
|
||||
const urls = locales.map(locale => {
|
||||
const url = locale === 'en' ? page : `/${locale}${page}`;
|
||||
const fullUrl = `${SITE.url}${url}`;
|
||||
const lastmod = new Date().toISOString().split('T')[0];
|
||||
const priority = page === '' ? '1.0' : '0.8';
|
||||
const changefreq = page === '' ? 'weekly' : 'monthly';
|
||||
|
||||
return ` <url>
|
||||
<loc>${fullUrl}</loc>
|
||||
<lastmod>${lastmod}</lastmod>
|
||||
<changefreq>${changefreq}</changefreq>
|
||||
<priority>${priority}</priority>
|
||||
<xhtml:link rel="alternate" hreflang="${locale}" href="${fullUrl}" />
|
||||
${locales.map(altLocale => {
|
||||
const altUrl = altLocale === 'en' ? page : `/${altLocale}${page}`;
|
||||
const altFullUrl = `${SITE.url}${altUrl}`;
|
||||
return ` <xhtml:link rel="alternate" hreflang="${altLocale}" href="${altFullUrl}" />`;
|
||||
}).join('\n')}
|
||||
</url>`;
|
||||
});
|
||||
return urls.join('\n');
|
||||
}).join('\n')}
|
||||
${blogPosts.map(post => {
|
||||
const urls = locales.map(locale => {
|
||||
const url = `/${locale}/blog/${post.slug}`;
|
||||
const fullUrl = `${SITE.url}${url}`;
|
||||
const lastmod = new Date(post.date_updated || post.date_created).toISOString().split('T')[0];
|
||||
|
||||
return ` <url>
|
||||
<loc>${fullUrl}</loc>
|
||||
<lastmod>${lastmod}</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.6</priority>
|
||||
<xhtml:link rel="alternate" hreflang="${locale}" href="${fullUrl}" />
|
||||
${locales.map(altLocale => {
|
||||
const altUrl = `/${altLocale}/blog/${post.slug}`;
|
||||
const altFullUrl = `${SITE.url}${altUrl}`;
|
||||
return ` <xhtml:link rel="alternate" hreflang="${altLocale}" href="${altFullUrl}" />`;
|
||||
}).join('\n')}
|
||||
</url>`;
|
||||
});
|
||||
return urls.join('\n');
|
||||
}).join('\n')}
|
||||
</urlset>`;
|
||||
|
||||
return new Response(sitemap, {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/xml'
|
||||
}
|
||||
});
|
||||
};
|
@@ -1,165 +0,0 @@
|
||||
---
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
import Header from '../components/Header.astro';
|
||||
import Footer from '../components/Footer.astro';
|
||||
import { t } from '../utils/i18n';
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${t('footer.links.terms')} | ${t('meta.title')}`}
|
||||
description="Terms of Service for Tiber365 - Understanding our service agreement and legal terms in compliance with European and Dutch laws."
|
||||
>
|
||||
<Header />
|
||||
<main class="py-16 bg-background">
|
||||
<div class="container-custom">
|
||||
<article class="prose prose-lg dark:prose-invert max-w-4xl mx-auto">
|
||||
<h1 class="text-4xl font-display font-bold mb-8">{t('footer.links.terms')}</h1>
|
||||
|
||||
<div class="mb-8 text-sm text-muted-foreground">
|
||||
Last updated: {new Date().toLocaleDateString()}
|
||||
</div>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>1. Introduction</h2>
|
||||
<p>
|
||||
These Terms of Service ("Terms") govern your use of Tiber365's website and services. By accessing our website or using our services, you agree to be bound by these Terms. If you disagree with any part of these terms, please do not use our services.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>2. Company Information</h2>
|
||||
<p>
|
||||
Tiber365<br />
|
||||
Registered in Italy<br />
|
||||
Email: info@tiber365.it<br />
|
||||
Phone: +39 123 456 7890
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>3. Services</h2>
|
||||
<p>
|
||||
We provide IT services including:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Microsoft 365 support and management</li>
|
||||
<li>Networking and infrastructure solutions</li>
|
||||
<li>Web hosting and management</li>
|
||||
<li>Custom IT projects</li>
|
||||
</ul>
|
||||
<p>
|
||||
Service specifics will be detailed in individual service agreements.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>4. Service Agreement</h2>
|
||||
<p>
|
||||
Upon engaging our services:
|
||||
</p>
|
||||
<ul>
|
||||
<li>We will provide services as specified in the service agreement</li>
|
||||
<li>You agree to provide necessary information and access for service delivery</li>
|
||||
<li>You will maintain the confidentiality of any access credentials provided</li>
|
||||
<li>You will use the services in compliance with applicable laws</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>5. Intellectual Property</h2>
|
||||
<p>
|
||||
All content on our website and services, including but not limited to text, graphics, logos, and software, is our property or that of our licensors and is protected by intellectual property laws.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>6. User Obligations</h2>
|
||||
<p>You agree to:</p>
|
||||
<ul>
|
||||
<li>Provide accurate and complete information</li>
|
||||
<li>Maintain the security of your account</li>
|
||||
<li>Not use our services for illegal purposes</li>
|
||||
<li>Not interfere with the proper functioning of our services</li>
|
||||
<li>Comply with all applicable laws and regulations</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>7. Payment Terms</h2>
|
||||
<p>
|
||||
Payment terms, including fees, billing cycles, and payment methods, will be specified in your service agreement. Late payments may result in service suspension.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>8. Liability</h2>
|
||||
<p>
|
||||
To the extent permitted by law:
|
||||
</p>
|
||||
<ul>
|
||||
<li>We provide services "as is" without warranties</li>
|
||||
<li>We are not liable for indirect, consequential, or incidental damages</li>
|
||||
<li>Our liability is limited to the amount paid for services in the previous 12 months</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>9. Data Protection</h2>
|
||||
<p>
|
||||
We process personal data in accordance with our Privacy Policy and applicable data protection laws (GDPR and Dutch privacy laws).
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>10. Service Availability</h2>
|
||||
<p>
|
||||
While we strive for high availability, we do not guarantee uninterrupted service. We will provide notice of scheduled maintenance when possible.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>11. Termination</h2>
|
||||
<p>
|
||||
Either party may terminate services according to the terms in the service agreement. Upon termination:
|
||||
</p>
|
||||
<ul>
|
||||
<li>All access to services will cease</li>
|
||||
<li>You remain liable for any outstanding payments</li>
|
||||
<li>We will assist with data transition as specified in the service agreement</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>12. Changes to Terms</h2>
|
||||
<p>
|
||||
We may modify these Terms at any time. Continued use of our services after changes constitutes acceptance of the modified Terms.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>13. Governing Law</h2>
|
||||
<p>
|
||||
These Terms are governed by Dutch law. Any disputes will be subject to the exclusive jurisdiction of the Dutch courts.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>14. Severability</h2>
|
||||
<p>
|
||||
If any provision of these Terms is found to be unenforceable, the remaining provisions will remain in effect.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mb-12">
|
||||
<h2>15. Contact</h2>
|
||||
<p>
|
||||
For questions about these Terms, please contact us at:<br />
|
||||
Email: legal@tiber365.it<br />
|
||||
Phone: +39 123 456 7890
|
||||
</p>
|
||||
</section>
|
||||
</article>
|
||||
</div>
|
||||
</main>
|
||||
<Footer />
|
||||
</BaseLayout>
|
Reference in New Issue
Block a user