feat: update dependencies and enhance privacy policy
Replace "@vercel/analytics" with "@tryghost/content-api" and add "node-fetch" to dependencies. Remove "@vercel/speed-insights" to streamline the package. Update robots.txt to dis access to "/legal-notice" and "/privacy-policy". Change <p> tags to <div> in the Privacy Policy for better structure. Update the last modified date in the Legal Notice. Add a new API route for fetching images with error handling for missing URL parameters.
This commit is contained in:
@@ -1,28 +1,36 @@
|
||||
// app/Projects/[slug]/page.tsx
|
||||
"use client";
|
||||
|
||||
import {useParams, useRouter} from "next/navigation";
|
||||
import {
|
||||
useRouter,
|
||||
useSearchParams,
|
||||
useParams,
|
||||
usePathname,
|
||||
} from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
import Header from "../../components/Header";
|
||||
import Footer_Back from "../../components/Footer_Back";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import rehypeRaw from "rehype-raw";
|
||||
import matter from "gray-matter";
|
||||
|
||||
import Footer_Back from "@/app/components/Footer_Back";
|
||||
import Header from "@/app/components/Header";
|
||||
import Image from "next/image";
|
||||
import "@/app/styles/ghostContent.css"; // Import the global styles
|
||||
|
||||
interface Project {
|
||||
slug: string;
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
text: string;
|
||||
slug: string;
|
||||
image: string;
|
||||
feature_image: string;
|
||||
visibility: string;
|
||||
published_at: string;
|
||||
updated_at: string;
|
||||
html: string;
|
||||
reading_time: number;
|
||||
meta_description: string;
|
||||
}
|
||||
|
||||
export default function ProjectDetail() {
|
||||
const params = useParams();
|
||||
const ProjectDetails = () => {
|
||||
const router = useRouter();
|
||||
const {slug} = params as { slug: string };
|
||||
const searchParams = useSearchParams();
|
||||
const params = useParams();
|
||||
const pathname = usePathname();
|
||||
const [project, setProject] = useState<Project | null>(null);
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
|
||||
@@ -33,57 +41,87 @@ export default function ProjectDetail() {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (slug) {
|
||||
fetch(`/projects/${slug}.md`)
|
||||
.then((res) => res.text())
|
||||
.then((content) => {
|
||||
const {data, content: markdownContent} = matter(content);
|
||||
setProject({
|
||||
id: data.id,
|
||||
title: data.title,
|
||||
description: data.description,
|
||||
text: markdownContent,
|
||||
slug: slug,
|
||||
image: data.image,
|
||||
});
|
||||
|
||||
// Log the project view
|
||||
fetch("/api/stats", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
type: "project_view",
|
||||
projectId: data.id,
|
||||
}),
|
||||
}).catch((err) => console.error("Failed to log project view", err));
|
||||
})
|
||||
.catch(() => {
|
||||
// Redirect to 404 if project not found
|
||||
router.replace("/not-found");
|
||||
});
|
||||
const projectData = searchParams.get("project");
|
||||
if (projectData) {
|
||||
setProject(JSON.parse(projectData));
|
||||
// Remove the project data from the URL without reloading the page
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.delete("project");
|
||||
window.history.replaceState({}, "", url.toString());
|
||||
} else {
|
||||
// Fetch project data based on slug from URL
|
||||
const slug = params.slug as string;
|
||||
fetchProjectData(slug);
|
||||
}
|
||||
}, [slug, router]);
|
||||
}, [searchParams, router, params, pathname]);
|
||||
|
||||
const fetchProjectData = async (slug: string) => {
|
||||
try {
|
||||
const response = await fetch(`/api/fetchProject?slug=${slug}`);
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch project data");
|
||||
}
|
||||
const projectData = await response.json();
|
||||
setProject(projectData.posts[0]); // Assuming the API returns an array of posts
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch project data:", error);
|
||||
}
|
||||
};
|
||||
|
||||
if (!project) {
|
||||
return <div className="p-10 text-center">Loading...</div>;
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-radiant">
|
||||
<Header />
|
||||
<div className="flex-grow flex items-center justify-center">
|
||||
<div className="loader ease-linear rounded-full border-8 border-t-8 border-gray-200 h-32 w-32"></div>
|
||||
</div>
|
||||
<Footer_Back />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const featureImageUrl = `/api/fetchImage?url=${encodeURIComponent(project.feature_image)}`;
|
||||
|
||||
return (
|
||||
<div className={`min-h-screen flex flex-col bg-radiant ${isVisible ? 'animate-fly-in' : 'opacity-0'}`}>
|
||||
<Header/>
|
||||
<div className="flex-grow p-10 pt-24">
|
||||
<div
|
||||
className="flex flex-col p-8 bg-gradient-to-br from-white/60 to-white/30 backdrop-blur-lg rounded-2xl shadow-xl">
|
||||
<div className="mt-4 text-gray-600 dark:text-gray-300 markdown">
|
||||
<ReactMarkdown remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]}>
|
||||
{project.text}
|
||||
</ReactMarkdown>
|
||||
className={`min-h-screen flex flex-col bg-radiant ${isVisible ? "animate-fly-in" : "opacity-0"}`}
|
||||
>
|
||||
<Header />
|
||||
<div className="flex-grow">
|
||||
{/* Hero Section */}
|
||||
<div className="flex justify-center md:mt-28 px-4 md:px-0">
|
||||
<div className="relative w-full max-w-4xl h-0 pb-[56.25%] rounded-2xl overflow-hidden">
|
||||
{" "}
|
||||
{/* 16:9 Aspect Ratio */}
|
||||
<Image
|
||||
src={featureImageUrl}
|
||||
alt={project.title}
|
||||
fill
|
||||
style={{ objectFit: "cover" }}
|
||||
className="rounded-2xl"
|
||||
priority={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-center mt-4">
|
||||
<h1 className="text-4xl md:text-6xl font-bold text-white">
|
||||
{project.title}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
{/* Project Content */}
|
||||
<div className="p-10 pt-12">
|
||||
<div className="flex flex-col p-8 bg-gradient-to-br from-white/60 to-white/30 backdrop-blur-lg rounded-2xl shadow-xl">
|
||||
<div
|
||||
className="content mt-4 text-gray-600 text-lg leading-relaxed"
|
||||
dangerouslySetInnerHTML={{ __html: project.html }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Footer_Back />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default ProjectDetails;
|
||||
|
||||
25
app/api/fetchAllProjects/route.tsx
Normal file
25
app/api/fetchAllProjects/route.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
export const runtime = "nodejs"; // Force Node runtime
|
||||
|
||||
const GHOST_API_URL = "http://192.168.179.31:2368";
|
||||
const GHOST_API_KEY = "067b8434f2e7f2a771dfcc45a7"; // Replace with your actual key
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${GHOST_API_URL}/ghost/api/content/posts/?key=${GHOST_API_KEY}&limit=all`,
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch posts: ${response.statusText}`);
|
||||
}
|
||||
const posts = await response.json();
|
||||
return NextResponse.json(posts);
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch posts from Ghost:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Failed to fetch projects" },
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
}
|
||||
35
app/api/fetchImage/route.tsx
Normal file
35
app/api/fetchImage/route.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const { searchParams } = new URL(req.url);
|
||||
const url = searchParams.get("url");
|
||||
|
||||
if (!url) {
|
||||
return NextResponse.json(
|
||||
{ error: "Missing URL parameter" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch image: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const contentType = response.headers.get("content-type");
|
||||
const buffer = await response.arrayBuffer();
|
||||
|
||||
return new NextResponse(buffer, {
|
||||
headers: {
|
||||
"Content-Type": contentType || "application/octet-stream",
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch image:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Failed to fetch image" },
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
}
|
||||
32
app/api/fetchProject/route.tsx
Normal file
32
app/api/fetchProject/route.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
export const runtime = "nodejs"; // Force Node runtime
|
||||
|
||||
const GHOST_API_URL = "http://192.168.179.31:2368";
|
||||
const GHOST_API_KEY = "067b8434f2e7f2a771dfcc45a7"; // Replace with your actual key
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const slug = searchParams.get("slug");
|
||||
|
||||
if (!slug) {
|
||||
return NextResponse.json({ error: "Slug is required" }, { status: 400 });
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${GHOST_API_URL}/ghost/api/content/posts/slug/${slug}/?key=${GHOST_API_KEY}`,
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch post: ${response.statusText}`);
|
||||
}
|
||||
const post = await response.json();
|
||||
return NextResponse.json(post);
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch post from Ghost:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Failed to fetch project" },
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -12,10 +12,11 @@ export default function Hero() {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div id="about"
|
||||
className={`flex flex-col md:flex-row items-center justify-center pt-16 pb-16 px-6 text-gray-700 ${isVisible ? 'animate-fly-in' : 'opacity-0'}`}>
|
||||
<div
|
||||
className="flex flex-col items-center p-8 bg-gradient-to-br from-white/60 to-white/30 backdrop-blur-lg rounded-2xl shadow-xl max-w-lg text-center">
|
||||
id="about"
|
||||
className={`flex flex-col md:flex-row items-center justify-center pt-16 pb-16 px-6 text-gray-700 ${isVisible ? "animate-fly-in" : "opacity-0"}`}
|
||||
>
|
||||
<div className="flex flex-col items-center p-8 bg-gradient-to-br from-white/60 to-white/30 backdrop-blur-lg rounded-2xl shadow-xl max-w-lg text-center">
|
||||
<h1 className="text-4xl md:text-5xl font-extrabold text-gray-900">
|
||||
Hi, I’m Dennis
|
||||
</h1>
|
||||
@@ -27,11 +28,12 @@ export default function Hero() {
|
||||
</h3>
|
||||
<p className="mt-6 text-gray-800 text-lg leading-relaxed">
|
||||
Passionate about technology, coding, and solving real-world problems.
|
||||
I enjoy building innovative solutions and continuously expanding my knowledge.
|
||||
I enjoy building innovative solutions and continuously expanding my
|
||||
knowledge.
|
||||
</p>
|
||||
<p className="mt-4 text-gray-700 text-base">
|
||||
Currently working on exciting projects that merge creativity with functionality.
|
||||
Always eager to learn and collaborate!
|
||||
Currently working on exciting projects that merge creativity with
|
||||
functionality. Always eager to learn and collaborate!
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex mt-8 md:mt-0 md:ml-12">
|
||||
@@ -41,6 +43,8 @@ export default function Hero() {
|
||||
width={400}
|
||||
height={400}
|
||||
className="rounded-2xl shadow-lg shadow-gray-700 object-cover"
|
||||
priority={true}
|
||||
style={{ width: "auto", height: "400px" }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,10 +2,16 @@ import React, {useEffect, useState} from "react";
|
||||
import Link from "next/link";
|
||||
|
||||
interface Project {
|
||||
slug: string;
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
slug: string;
|
||||
feature_image: string;
|
||||
visibility: string;
|
||||
published_at: string;
|
||||
updated_at: string;
|
||||
html: string;
|
||||
reading_time: number;
|
||||
meta_description: string;
|
||||
}
|
||||
|
||||
export default function Projects() {
|
||||
@@ -15,16 +21,13 @@ export default function Projects() {
|
||||
useEffect(() => {
|
||||
const fetchProjects = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/projects');
|
||||
try {
|
||||
const response = await fetch("/api/fetchAllProjects");
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch projects");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch projects:", error);
|
||||
throw new Error("Failed to fetch projects from Ghost");
|
||||
}
|
||||
const projectsData = await response.json();
|
||||
setProjects(projectsData);
|
||||
setProjects(projectsData.posts);
|
||||
|
||||
setTimeout(() => {
|
||||
setIsVisible(true);
|
||||
}, 250); // Delay to start the animation after Hero
|
||||
@@ -32,37 +35,45 @@ export default function Projects() {
|
||||
console.error("Failed to fetch projects:", error);
|
||||
}
|
||||
};
|
||||
fetchProjects().then(r => r);
|
||||
fetchProjects();
|
||||
}, []);
|
||||
const numberOfProjects = projects.length;
|
||||
|
||||
console.log(projects.at(0)?.feature_image);
|
||||
|
||||
const numberOfProjects = projects.length;
|
||||
return (
|
||||
<section id="projects" className={`p-10 ${isVisible ? 'animate-fly-in' : 'opacity-0'}`}>
|
||||
<h2 className="text-3xl font-bold text-center text-gray-800">
|
||||
Projects
|
||||
</h2>
|
||||
<section
|
||||
id="projects"
|
||||
className={`p-10 ${isVisible ? "animate-fly-in" : "opacity-0"}`}
|
||||
>
|
||||
<h2 className="text-3xl font-bold text-center text-gray-800">Projects</h2>
|
||||
<div className="mt-6 grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{projects.map((project, index) => (
|
||||
<Link key={project.id} href={`/Projects/${project.slug}`} className="cursor-pointer">
|
||||
<div className={`p-4 border shadow-lg bg-white/45 rounded-2xl animate-fly-in`}
|
||||
style={{animationDelay: `${index * 0.1}s`}}>
|
||||
<Link
|
||||
key={project.id}
|
||||
href={{
|
||||
pathname: `/Projects/${project.slug}`,
|
||||
query: { project: JSON.stringify(project) },
|
||||
}}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<div
|
||||
className={`p-4 border shadow-lg bg-white/45 rounded-2xl animate-fly-in`}
|
||||
style={{ animationDelay: `${index * 0.1}s` }}
|
||||
>
|
||||
<h3 className="text-2xl font-bold text-gray-800">
|
||||
{project.title}
|
||||
</h3>
|
||||
<p className="mt-2 text-gray-500">
|
||||
{project.description}
|
||||
</p>
|
||||
<p className="mt-2 text-gray-500">{project.meta_description}</p>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
<div className={`p-4 border shadow-lg bg-white/45 rounded-2xl animate-fly-in`}
|
||||
style={{animationDelay: `${(numberOfProjects + 1) * 0.1}s`}}>
|
||||
<h3 className="text-2xl font-bold text-gray-800">
|
||||
More to come
|
||||
</h3>
|
||||
<p className="mt-2 text-gray-500">
|
||||
...
|
||||
</p>
|
||||
<div
|
||||
className={`p-4 border shadow-lg bg-white/45 rounded-2xl animate-fly-in`}
|
||||
style={{ animationDelay: `${(numberOfProjects + 1) * 0.1}s` }}
|
||||
>
|
||||
<h3 className="text-2xl font-bold text-gray-800">More to come</h3>
|
||||
<p className="mt-2 text-gray-500">...</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -4,15 +4,14 @@
|
||||
|
||||
import "./globals.css";
|
||||
|
||||
import {Roboto} from 'next/font/google';
|
||||
import { Roboto } from "next/font/google";
|
||||
import React from "react";
|
||||
//import ClientCookieConsentBanner from "./components/ClientCookieConsentBanner";
|
||||
|
||||
|
||||
const roboto = Roboto({
|
||||
variable: '--font-roboto',
|
||||
weight: '400',
|
||||
subsets: ['latin'],
|
||||
variable: "--font-roboto",
|
||||
weight: "400",
|
||||
subsets: ["latin"],
|
||||
});
|
||||
|
||||
export default function RootLayout({
|
||||
@@ -20,13 +19,17 @@ export default function RootLayout({
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
|
||||
return (
|
||||
<html lang="en">
|
||||
<script defer src="https://umami.denshooter.de/script.js" data-website-id="1f213877-deef-4238-8df1-71a5a3bcd142"></script>
|
||||
<body className={roboto.variable}>
|
||||
{children}
|
||||
</body>
|
||||
<head>
|
||||
<script
|
||||
defer
|
||||
src="https://umami.denshooter.de/script.js"
|
||||
data-website-id="1f213877-deef-4238-8df1-71a5a3bcd142"
|
||||
></script>
|
||||
<meta charSet="utf-8" />
|
||||
</head>
|
||||
<body className={roboto.variable}>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -27,11 +27,6 @@ export default function LegalNotice() {
|
||||
info@dki.one
|
||||
</Link>{" "}
|
||||
<br />
|
||||
<strong>Telefon:</strong>{" "}
|
||||
<Link href={"tel:+4917612669990"} className="transition-underline">
|
||||
+49 176 12669990
|
||||
</Link>
|
||||
<br />
|
||||
<strong>Website:</strong>{" "}
|
||||
<Link href={"https://www.dki.one"} className="transition-underline">
|
||||
{" "}
|
||||
@@ -44,7 +39,10 @@ export default function LegalNotice() {
|
||||
Meine Website enthält Links auf externe Websites. Ich habe keinen
|
||||
Einfluss auf die Inhalte dieser Websites und kann daher keine Gewähr
|
||||
übernehmen. Für die Inhalte der verlinkten Seiten ist stets der
|
||||
Betreiber oder Anbieter der Seiten verantwortlich.
|
||||
Betreiber oder Anbieter der Seiten verantwortlich. Jedoch überprüfe
|
||||
ich die verlinkten Seiten zum Zeitpunkt der Verlinkung auf mögliche
|
||||
Rechtsverstöße. Bei Bekanntwerden von Rechtsverletzungen werde ich
|
||||
derartige Links umgehend entfernen.
|
||||
</p>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-6">Urheberrecht</h2>
|
||||
@@ -60,7 +58,7 @@ export default function LegalNotice() {
|
||||
Diensteanbieter kann ich keine Gewähr übernehmen für Schäden, die
|
||||
entstehen können, durch den Zugriff oder die Nutzung dieser Website.
|
||||
</p>
|
||||
<p className="font-semibold mt-6">Letzte Aktualisierung: 11.02.2025</p>
|
||||
<p className="font-semibold mt-6">Letzte Aktualisierung: 12.02.2025</p>
|
||||
</main>
|
||||
<Footer_Back />
|
||||
</div>
|
||||
|
||||
15
app/page.tsx
15
app/page.tsx
@@ -10,7 +10,6 @@ import Script from "next/script";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
|
||||
<div className="min-h-screen flex flex-col bg-radiant-animated">
|
||||
<Script
|
||||
id={"structured-data"}
|
||||
@@ -19,15 +18,15 @@ export default function Home() {
|
||||
__html: JSON.stringify({
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Person",
|
||||
"name": "Dennis Konkol",
|
||||
"url": "https://dki.one",
|
||||
"jobTitle": "Software Engineer",
|
||||
"address": {
|
||||
name: "Dennis Konkol",
|
||||
url: "https://dki.one",
|
||||
jobTitle: "Software Engineer",
|
||||
address: {
|
||||
"@type": "PostalAddress",
|
||||
"addressLocality": "Osnabrück",
|
||||
"addressCountry": "Germany",
|
||||
addressLocality: "Osnabrück",
|
||||
addressCountry: "Germany",
|
||||
},
|
||||
"sameAs": [
|
||||
sameAs: [
|
||||
"https://github.com/Denshooter",
|
||||
"https://linkedin.com/in/dkonkol",
|
||||
],
|
||||
|
||||
@@ -39,11 +39,6 @@ export default function PrivacyPolicy() {
|
||||
info@dki.one
|
||||
</Link>{" "}
|
||||
<br />
|
||||
<strong>Telefon:</strong>{" "}
|
||||
<Link className="transition-underline" href={"tel:+4917612669990"}>
|
||||
+49 176 12669990
|
||||
</Link>
|
||||
<br />
|
||||
<strong>Website:</strong>{" "}
|
||||
<Link className="transition-underline" href={"https://www.dki.one"}>
|
||||
{" "}
|
||||
@@ -57,7 +52,7 @@ export default function PrivacyPolicy() {
|
||||
<h2 className="text-2xl font-semibold mt-6">
|
||||
Erfassung allgemeiner Informationen beim Besuch meiner Website
|
||||
</h2>
|
||||
<p className="mt-2">
|
||||
<div className="mt-2">
|
||||
Beim Zugriff auf meiner Website werden automatisch Informationen
|
||||
allgemeiner Natur erfasst. Diese beinhalten unter anderem:
|
||||
<ul className="list-disc list-inside mt-2">
|
||||
@@ -76,7 +71,7 @@ export default function PrivacyPolicy() {
|
||||
<li>die Inhalte meiner Website zu optimieren,</li>
|
||||
<li>die Systemsicherheit und -stabilität zu analysiern.</li>
|
||||
</ul>
|
||||
</p>
|
||||
</div>
|
||||
<h2 className="text-2xl font-semibold mt-6">Cookies</h2>
|
||||
<p className="mt-2">
|
||||
Meine Website verwendet keine Cookies. Daher ist kein
|
||||
@@ -129,7 +124,7 @@ export default function PrivacyPolicy() {
|
||||
jeweiligen Anbieter.
|
||||
</p>
|
||||
<h2 className="text-2xl font-semibold mt-6">Weitergabe von Daten</h2>
|
||||
<p className="mt-2">
|
||||
<div className="mt-2">
|
||||
Eine Weitergabe Ihrer personenbezogenen Daten erfolgt nur, wenn:
|
||||
<ul className="list-disc list-inside mt-2">
|
||||
<li>
|
||||
@@ -149,7 +144,7 @@ export default function PrivacyPolicy() {
|
||||
berechtigter Interessen erforderlich ist.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
</div>
|
||||
<h2 className="text-2xl font-semibold mt-6">
|
||||
Speicherdauer und Löschung
|
||||
</h2>
|
||||
@@ -159,7 +154,7 @@ export default function PrivacyPolicy() {
|
||||
werden Ihre Daten gelöscht.
|
||||
</p>
|
||||
<h2 className="text-2xl font-semibold mt-6">Ihre Rechte</h2>
|
||||
<p className="mt-2">
|
||||
<div className="mt-2">
|
||||
Sie haben gemäß DSGVO folgende Rechte:
|
||||
<ul className="list-disc list-inside mt-2">
|
||||
<li>
|
||||
@@ -198,7 +193,7 @@ export default function PrivacyPolicy() {
|
||||
>
|
||||
https://www.bfdi.bund.de/
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
<h2 className="text-2xl font-semibold mt-6">Datensicherheit</h2>
|
||||
<p className="mt-2">
|
||||
Ich setze technische und organisatorische Maßnahmen ein, um Ihre Daten
|
||||
@@ -226,7 +221,7 @@ export default function PrivacyPolicy() {
|
||||
berücksichtigen. Die jeweils aktuelle Datenschutzerklärung finden Sie
|
||||
auf meiner Website.
|
||||
</p>
|
||||
<p className="mt-6 font-bold">Letzte Aktualisierung: 11.02.2025</p>
|
||||
<p className="mt-6 font-bold">Letzte Aktualisierung: 12.02.2025</p>
|
||||
</main>
|
||||
<Footer_Back />
|
||||
</div>
|
||||
|
||||
70
app/styles/ghostContent.css
Normal file
70
app/styles/ghostContent.css
Normal file
@@ -0,0 +1,70 @@
|
||||
/* ghostContent.css */
|
||||
|
||||
.content {
|
||||
font-family: "Arial", sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.content h1,
|
||||
.content h2,
|
||||
.content h3,
|
||||
.content h4,
|
||||
.content h5,
|
||||
.content h6 {
|
||||
color: #222;
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.content p {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.content img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.content ul,
|
||||
.content ol {
|
||||
margin: 1em 0;
|
||||
padding-left: 1.5em;
|
||||
}
|
||||
|
||||
.content a {
|
||||
color: #0070f3;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.content a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.content blockquote {
|
||||
border-left: 4px solid #ddd;
|
||||
padding-left: 1em;
|
||||
color: #666;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.content pre {
|
||||
background: #f5f5f5;
|
||||
padding: 1em;
|
||||
border-radius: 8px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.loader {
|
||||
border-top-color: #3498db;
|
||||
animation: spin 1s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
275
package-lock.json
generated
275
package-lock.json
generated
@@ -9,12 +9,12 @@
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@prisma/client": "^6.1.0",
|
||||
"@vercel/analytics": "^1.4.1",
|
||||
"@tryghost/content-api": "^1.11.21",
|
||||
"@vercel/og": "^0.6.5",
|
||||
"@vercel/speed-insights": "^1.1.0",
|
||||
"dotenv": "^16.4.7",
|
||||
"gray-matter": "^4.0.3",
|
||||
"next": "15.1.3",
|
||||
"node-fetch": "^3.3.2",
|
||||
"nodemailer": "^6.10.0",
|
||||
"prisma": "^6.1.0",
|
||||
"react": "^19.0.0",
|
||||
@@ -1010,6 +1010,15 @@
|
||||
"tslib": "^2.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tryghost/content-api": {
|
||||
"version": "1.11.21",
|
||||
"resolved": "https://registry.npmjs.org/@tryghost/content-api/-/content-api-1.11.21.tgz",
|
||||
"integrity": "sha512-ozJqEMHDUO7D0SGxPbUnG+RvwBbzC3zmdGOW8cFvkcKzrhe7uOAmVKyq7/J3kRAM2QthTlmiDpqp7NEo9ZLlKg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"axios": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/debug": {
|
||||
"version": "4.1.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
|
||||
@@ -1359,44 +1368,6 @@
|
||||
"integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/@vercel/analytics": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.4.1.tgz",
|
||||
"integrity": "sha512-ekpL4ReX2TH3LnrRZTUKjHHNpNy9S1I7QmS+g/RQXoSUQ8ienzosuX7T9djZ/s8zPhBx1mpHP/Rw5875N+zQIQ==",
|
||||
"license": "MPL-2.0",
|
||||
"peerDependencies": {
|
||||
"@remix-run/react": "^2",
|
||||
"@sveltejs/kit": "^1 || ^2",
|
||||
"next": ">= 13",
|
||||
"react": "^18 || ^19 || ^19.0.0-rc",
|
||||
"svelte": ">= 4",
|
||||
"vue": "^3",
|
||||
"vue-router": "^4"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@remix-run/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@sveltejs/kit": {
|
||||
"optional": true
|
||||
},
|
||||
"next": {
|
||||
"optional": true
|
||||
},
|
||||
"react": {
|
||||
"optional": true
|
||||
},
|
||||
"svelte": {
|
||||
"optional": true
|
||||
},
|
||||
"vue": {
|
||||
"optional": true
|
||||
},
|
||||
"vue-router": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@vercel/og": {
|
||||
"version": "0.6.5",
|
||||
"resolved": "https://registry.npmjs.org/@vercel/og/-/og-0.6.5.tgz",
|
||||
@@ -1411,41 +1382,6 @@
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@vercel/speed-insights": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@vercel/speed-insights/-/speed-insights-1.1.0.tgz",
|
||||
"integrity": "sha512-rAXxuhhO4mlRGC9noa5F7HLMtGg8YF1zAN6Pjd1Ny4pII4cerhtwSG4vympbCl+pWkH7nBS9kVXRD4FAn54dlg==",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"peerDependencies": {
|
||||
"@sveltejs/kit": "^1 || ^2",
|
||||
"next": ">= 13",
|
||||
"react": "^18 || ^19 || ^19.0.0-rc",
|
||||
"svelte": ">= 4",
|
||||
"vue": "^3",
|
||||
"vue-router": "^4"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@sveltejs/kit": {
|
||||
"optional": true
|
||||
},
|
||||
"next": {
|
||||
"optional": true
|
||||
},
|
||||
"react": {
|
||||
"optional": true
|
||||
},
|
||||
"svelte": {
|
||||
"optional": true
|
||||
},
|
||||
"vue": {
|
||||
"optional": true
|
||||
},
|
||||
"vue-router": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.14.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
||||
@@ -1734,6 +1670,12 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/available-typed-arrays": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
|
||||
@@ -1760,6 +1702,17 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.7.9",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz",
|
||||
"integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/axobject-query": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
||||
@@ -2098,6 +2051,18 @@
|
||||
"simple-swizzle": "^0.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/comma-separated-tokens": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
|
||||
@@ -2207,6 +2172,15 @@
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/data-uri-to-buffer": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
|
||||
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/data-view-buffer": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
|
||||
@@ -2334,6 +2308,15 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dequal": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
|
||||
@@ -3208,6 +3191,29 @@
|
||||
"reusify": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/fetch-blob": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
||||
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/jimmywarting"
|
||||
},
|
||||
{
|
||||
"type": "paypal",
|
||||
"url": "https://paypal.me/jimmywarting"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"node-domexception": "^1.0.0",
|
||||
"web-streams-polyfill": "^3.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20 || >= 14.13"
|
||||
}
|
||||
},
|
||||
"node_modules/fflate": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.4.tgz",
|
||||
@@ -3278,6 +3284,26 @@
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.9",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
||||
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/for-each": {
|
||||
"version": "0.3.4",
|
||||
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.4.tgz",
|
||||
@@ -3311,6 +3337,32 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
|
||||
"integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/formdata-polyfill": {
|
||||
"version": "4.0.10",
|
||||
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
||||
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fetch-blob": "^3.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
@@ -5550,6 +5602,27 @@
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
@@ -5708,6 +5781,43 @@
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/node-domexception": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/jimmywarting"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://paypal.me/jimmywarting"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
|
||||
"integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"data-uri-to-buffer": "^4.0.0",
|
||||
"fetch-blob": "^3.1.4",
|
||||
"formdata-polyfill": "^4.0.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/node-fetch"
|
||||
}
|
||||
},
|
||||
"node_modules/nodemailer": {
|
||||
"version": "6.10.0",
|
||||
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.10.0.tgz",
|
||||
@@ -6301,6 +6411,12 @@
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
@@ -7817,6 +7933,15 @@
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/web-streams-polyfill": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
|
||||
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "^6.1.0",
|
||||
"@vercel/analytics": "^1.4.1",
|
||||
"@tryghost/content-api": "^1.11.21",
|
||||
"@vercel/og": "^0.6.5",
|
||||
"@vercel/speed-insights": "^1.1.0",
|
||||
"dotenv": "^16.4.7",
|
||||
"gray-matter": "^4.0.3",
|
||||
"next": "15.1.3",
|
||||
"node-fetch": "^3.3.2",
|
||||
"nodemailer": "^6.10.0",
|
||||
"prisma": "^6.1.0",
|
||||
"react": "^19.0.0",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
User-agent: *
|
||||
Allow: /
|
||||
Disallow: ['/legal-notice', '/privacy-policy']
|
||||
Sitemap: https://dki.one/sitemap.xml
|
||||
|
||||
Reference in New Issue
Block a user