Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b75fcc9bea | ||
|
|
8bd15d9d03 | ||
|
|
87261c6b92 | ||
|
|
b1e89b64c5 |
@@ -0,0 +1,93 @@
|
|||||||
|
'use server';
|
||||||
|
|
||||||
|
import { validateCsrfToken } from '@/lib/csrf/server';
|
||||||
|
|
||||||
|
interface ContactFormData {
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ContactFormResult {
|
||||||
|
success: boolean;
|
||||||
|
error?: string;
|
||||||
|
errors?: Partial<Record<keyof ContactFormData, string>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server action to handle contact form submissions
|
||||||
|
* Validates CSRF token and form data before processing
|
||||||
|
*/
|
||||||
|
export async function submitContactForm(
|
||||||
|
formData: FormData
|
||||||
|
): Promise<ContactFormResult> {
|
||||||
|
// Extract CSRF token from form data
|
||||||
|
const csrfToken = formData.get('csrfToken');
|
||||||
|
|
||||||
|
// Validate CSRF token
|
||||||
|
if (!csrfToken || typeof csrfToken !== 'string') {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: 'CSRF token is missing',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const isValidToken = await validateCsrfToken(csrfToken);
|
||||||
|
if (!isValidToken) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: 'Invalid CSRF token',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract and validate form fields
|
||||||
|
const name = formData.get('name')?.toString() || '';
|
||||||
|
const email = formData.get('email')?.toString() || '';
|
||||||
|
const message = formData.get('message')?.toString() || '';
|
||||||
|
|
||||||
|
// Validation
|
||||||
|
const errors: Partial<Record<keyof ContactFormData, string>> = {};
|
||||||
|
|
||||||
|
if (!name.trim()) {
|
||||||
|
errors.name = 'Name is required';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!email.trim()) {
|
||||||
|
errors.email = 'Email is required';
|
||||||
|
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
||||||
|
errors.email = 'Invalid email format';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!message.trim()) {
|
||||||
|
errors.message = 'Message is required';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(errors).length > 0) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// TODO: Implement actual email sending logic here
|
||||||
|
// For now, we'll simulate successful submission
|
||||||
|
// In production, this would integrate with an email service like:
|
||||||
|
// - Supabase Edge Functions
|
||||||
|
// - SendGrid
|
||||||
|
// - AWS SES
|
||||||
|
// - Resend
|
||||||
|
|
||||||
|
// Simulate processing delay
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 500));
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: error instanceof Error ? error.message : 'Failed to send message',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,6 @@ import Link from 'next/link';
|
|||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import { getAllBlogPosts, BlogPost } from '@/lib/blog';
|
import { getAllBlogPosts, BlogPost } from '@/lib/blog';
|
||||||
import { legacyBlogPosts } from '@/data/legacyBlogPosts';
|
|
||||||
|
|
||||||
const POSTS_PER_PAGE = 12;
|
const POSTS_PER_PAGE = 12;
|
||||||
|
|
||||||
@@ -14,6 +13,232 @@ type Props = {
|
|||||||
searchParams: Promise<{ page?: string }>;
|
searchParams: Promise<{ page?: string }>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Legacy blog posts with translations (these have manual translations)
|
||||||
|
const legacyBlogPosts: Record<string, BlogPost[]> = {
|
||||||
|
de: [
|
||||||
|
{
|
||||||
|
slug: 'n8n-automatisierung-tutorial',
|
||||||
|
title: 'n8n Tutorial: Workflows automatisieren ohne Code - Schritt für Schritt',
|
||||||
|
date: '2026-01-18',
|
||||||
|
excerpt: 'Lernen Sie, wie Sie mit n8n leistungsstarke Automatisierungen erstellen. Von der Installation bis zum ersten produktiven Workflow - inklusive Best Practices.',
|
||||||
|
category: 'Automatisierung',
|
||||||
|
tags: ['n8n', 'Tutorial', 'Automatisierung', 'Workflow', 'No-Code', 'Self-Hosted'],
|
||||||
|
coverImage: '/images/posts/n8n-automatisierung-tutorial/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'geo-generative-engine-optimization',
|
||||||
|
title: 'GEO: Generative Engine Optimization - SEO für die KI-Ära',
|
||||||
|
date: '2026-01-17',
|
||||||
|
excerpt: 'Wie Sie Ihre Inhalte für ChatGPT, Perplexity und andere KI-Suchmaschinen optimieren. Der neue Standard nach klassischem SEO.',
|
||||||
|
category: 'Marketing',
|
||||||
|
tags: ['GEO', 'SEO', 'KI', 'ChatGPT', 'Perplexity', 'Content Marketing', 'AEO'],
|
||||||
|
coverImage: '/images/posts/geo-generative-engine-optimization/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'gpt-api-integration-praxisguide',
|
||||||
|
title: 'GPT API Integration: Vom API-Key zur produktionsreifen Anwendung',
|
||||||
|
date: '2026-01-16',
|
||||||
|
excerpt: 'Praktische Anleitung zur Integration von OpenAI GPT-4 in Ihre Anwendungen. Token-Optimierung, Fehlerbehandlung und Best Practices.',
|
||||||
|
category: 'KI-Entwicklung',
|
||||||
|
tags: ['GPT-4', 'OpenAI', 'API', 'Integration', 'Python', 'LLM', 'Prompt Engineering'],
|
||||||
|
coverImage: '/images/posts/gpt-api-integration-praxisguide/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'ki-agenten-unternehmen-guide',
|
||||||
|
title: 'KI-Agenten für Unternehmen: Der ultimative Praxisguide 2026',
|
||||||
|
date: '2026-01-15',
|
||||||
|
excerpt: 'Wie Unternehmen KI-Agenten einsetzen können, um Prozesse zu automatisieren, Kosten zu senken und Wettbewerbsvorteile zu gewinnen.',
|
||||||
|
category: 'KI-Entwicklung',
|
||||||
|
tags: ['KI-Agenten', 'Automatisierung', 'GPT-4', 'Claude', 'LLM', 'Unternehmen'],
|
||||||
|
coverImage: '/images/posts/ki-agenten-unternehmen-guide/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'n8n-make-zapier-vergleich',
|
||||||
|
title: 'n8n vs Make vs Zapier: Welches Automatisierungstool passt zu Ihnen?',
|
||||||
|
date: '2026-01-10',
|
||||||
|
excerpt: 'Ein detaillierter Vergleich der führenden Workflow-Automatisierungstools mit Vor- und Nachteilen für verschiedene Anwendungsfälle.',
|
||||||
|
category: 'Automatisierung',
|
||||||
|
tags: ['n8n', 'Make', 'Zapier', 'Workflow', 'Automatisierung', 'No-Code'],
|
||||||
|
coverImage: '/images/posts/n8n-make-zapier-vergleich/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'voice-ai-kundenservice-trends',
|
||||||
|
title: 'Voice AI im Kundenservice: Trends und Best Practices 2026',
|
||||||
|
date: '2026-01-05',
|
||||||
|
excerpt: 'Wie Voice AI den Kundenservice revolutioniert und welche Technologien Sie für Ihr Unternehmen evaluieren sollten.',
|
||||||
|
category: 'Voice AI',
|
||||||
|
tags: ['Voice AI', 'Sprachassistent', 'Kundenservice', 'NLP', 'Chatbot', 'Vapi'],
|
||||||
|
coverImage: '/images/posts/voice-ai-kundenservice-trends/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'saas-mvp-entwicklung-4-wochen',
|
||||||
|
title: 'SaaS MVP in 4 Wochen: Von der Idee zum Launch',
|
||||||
|
date: '2025-12-20',
|
||||||
|
excerpt: 'Schritt-für-Schritt Anleitung zur schnellen Entwicklung eines SaaS MVP mit Next.js, Prisma und modernen Cloud-Diensten.',
|
||||||
|
category: 'SaaS-Entwicklung',
|
||||||
|
tags: ['SaaS', 'MVP', 'Next.js', 'Startup', 'Produktentwicklung', 'React'],
|
||||||
|
coverImage: '/images/posts/saas-mvp-entwicklung-4-wochen/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'erp-integration-breuninger',
|
||||||
|
title: 'ApparelMagic und TradeByte: Analyse komplexer Integrationen',
|
||||||
|
date: '2024-02-09',
|
||||||
|
excerpt: 'Detaillierte Analyse einer E-Commerce-Integration zwischen Apparel Magic und Breuninger via TradeByte',
|
||||||
|
category: 'System Integration',
|
||||||
|
tags: ['ERP', 'Apparel Magic', 'TradeByte', 'API Integration', 'Python', 'MariaDB'],
|
||||||
|
coverImage: '/images/posts/erp-integration-breuninger/cover.jpg',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
en: [
|
||||||
|
{
|
||||||
|
slug: 'n8n-automatisierung-tutorial',
|
||||||
|
title: 'n8n Tutorial: Automate Workflows Without Code - Step by Step',
|
||||||
|
date: '2026-01-18',
|
||||||
|
excerpt: 'Learn how to create powerful automations with n8n. From installation to your first production workflow - including best practices.',
|
||||||
|
category: 'Automation',
|
||||||
|
tags: ['n8n', 'Tutorial', 'Automation', 'Workflow', 'No-Code', 'Self-Hosted'],
|
||||||
|
coverImage: '/images/posts/n8n-automatisierung-tutorial/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'geo-generative-engine-optimization',
|
||||||
|
title: 'GEO: Generative Engine Optimization - SEO for the AI Era',
|
||||||
|
date: '2026-01-17',
|
||||||
|
excerpt: 'How to optimize your content for ChatGPT, Perplexity and other AI search engines. The new standard after traditional SEO.',
|
||||||
|
category: 'Marketing',
|
||||||
|
tags: ['GEO', 'SEO', 'AI', 'ChatGPT', 'Perplexity', 'Content Marketing', 'AEO'],
|
||||||
|
coverImage: '/images/posts/geo-generative-engine-optimization/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'gpt-api-integration-praxisguide',
|
||||||
|
title: 'GPT API Integration: From API Key to Production-Ready Application',
|
||||||
|
date: '2026-01-16',
|
||||||
|
excerpt: 'Practical guide to integrating OpenAI GPT-4 into your applications. Token optimization, error handling and best practices.',
|
||||||
|
category: 'AI Development',
|
||||||
|
tags: ['GPT-4', 'OpenAI', 'API', 'Integration', 'Python', 'LLM', 'Prompt Engineering'],
|
||||||
|
coverImage: '/images/posts/gpt-api-integration-praxisguide/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'ki-agenten-unternehmen-guide',
|
||||||
|
title: 'AI Agents for Business: The Ultimate Practical Guide 2026',
|
||||||
|
date: '2026-01-15',
|
||||||
|
excerpt: 'How companies can use AI agents to automate processes, reduce costs and gain competitive advantages.',
|
||||||
|
category: 'AI Development',
|
||||||
|
tags: ['AI Agents', 'Automation', 'GPT-4', 'Claude', 'LLM', 'Enterprise'],
|
||||||
|
coverImage: '/images/posts/ki-agenten-unternehmen-guide/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'n8n-make-zapier-vergleich',
|
||||||
|
title: 'n8n vs Make vs Zapier: Which Automation Tool is Right for You?',
|
||||||
|
date: '2026-01-10',
|
||||||
|
excerpt: 'A detailed comparison of leading workflow automation tools with pros and cons for different use cases.',
|
||||||
|
category: 'Automation',
|
||||||
|
tags: ['n8n', 'Make', 'Zapier', 'Workflow', 'Automation', 'No-Code'],
|
||||||
|
coverImage: '/images/posts/n8n-make-zapier-vergleich/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'voice-ai-kundenservice-trends',
|
||||||
|
title: 'Voice AI in Customer Service: Trends and Best Practices 2026',
|
||||||
|
date: '2026-01-05',
|
||||||
|
excerpt: 'How Voice AI is revolutionizing customer service and which technologies you should evaluate for your business.',
|
||||||
|
category: 'Voice AI',
|
||||||
|
tags: ['Voice AI', 'Voice Assistant', 'Customer Service', 'NLP', 'Chatbot', 'Vapi'],
|
||||||
|
coverImage: '/images/posts/voice-ai-kundenservice-trends/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'saas-mvp-entwicklung-4-wochen',
|
||||||
|
title: 'SaaS MVP in 4 Weeks: From Idea to Launch',
|
||||||
|
date: '2025-12-20',
|
||||||
|
excerpt: 'Step-by-step guide to quickly developing a SaaS MVP with Next.js, Prisma and modern cloud services.',
|
||||||
|
category: 'SaaS Development',
|
||||||
|
tags: ['SaaS', 'MVP', 'Next.js', 'Startup', 'Product Development', 'React'],
|
||||||
|
coverImage: '/images/posts/saas-mvp-entwicklung-4-wochen/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'erp-integration-breuninger',
|
||||||
|
title: 'ApparelMagic and TradeByte: Complex Integration Analysis',
|
||||||
|
date: '2024-02-09',
|
||||||
|
excerpt: 'Detailed analysis of an e-commerce integration between Apparel Magic and Breuninger via TradeByte',
|
||||||
|
category: 'System Integration',
|
||||||
|
tags: ['ERP', 'Apparel Magic', 'TradeByte', 'API Integration', 'Python', 'MariaDB'],
|
||||||
|
coverImage: '/images/posts/erp-integration-breuninger/cover.jpg',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sr: [
|
||||||
|
{
|
||||||
|
slug: 'n8n-automatisierung-tutorial',
|
||||||
|
title: 'n8n Tutorial: Automatizujte Radne Tokove Bez Koda - Korak po Korak',
|
||||||
|
date: '2026-01-18',
|
||||||
|
excerpt: 'Naučite kako da kreirate moćne automatizacije sa n8n. Od instalacije do prvog produktivnog radnog toka - uključujući najbolje prakse.',
|
||||||
|
category: 'Automatizacija',
|
||||||
|
tags: ['n8n', 'Tutorial', 'Automatizacija', 'Workflow', 'No-Code', 'Self-Hosted'],
|
||||||
|
coverImage: '/images/posts/n8n-automatisierung-tutorial/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'geo-generative-engine-optimization',
|
||||||
|
title: 'GEO: Generative Engine Optimization - SEO za AI Eru',
|
||||||
|
date: '2026-01-17',
|
||||||
|
excerpt: 'Kako da optimizujete sadržaj za ChatGPT, Perplexity i druge AI pretraživače. Novi standard posle klasičnog SEO-a.',
|
||||||
|
category: 'Marketing',
|
||||||
|
tags: ['GEO', 'SEO', 'AI', 'ChatGPT', 'Perplexity', 'Content Marketing', 'AEO'],
|
||||||
|
coverImage: '/images/posts/geo-generative-engine-optimization/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'gpt-api-integration-praxisguide',
|
||||||
|
title: 'GPT API Integracija: Od API Ključa do Produkcione Aplikacije',
|
||||||
|
date: '2026-01-16',
|
||||||
|
excerpt: 'Praktični vodič za integraciju OpenAI GPT-4 u vaše aplikacije. Optimizacija tokena, rukovanje greškama i najbolje prakse.',
|
||||||
|
category: 'AI Razvoj',
|
||||||
|
tags: ['GPT-4', 'OpenAI', 'API', 'Integracija', 'Python', 'LLM', 'Prompt Engineering'],
|
||||||
|
coverImage: '/images/posts/gpt-api-integration-praxisguide/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'ki-agenten-unternehmen-guide',
|
||||||
|
title: 'AI Agenti za Preduzeća: Ultimativni Praktični Vodič 2026',
|
||||||
|
date: '2026-01-15',
|
||||||
|
excerpt: 'Kako kompanije mogu koristiti AI agente za automatizaciju procesa, smanjenje troškova i sticanje konkurentskih prednosti.',
|
||||||
|
category: 'AI Razvoj',
|
||||||
|
tags: ['AI Agenti', 'Automatizacija', 'GPT-4', 'Claude', 'LLM', 'Preduzeća'],
|
||||||
|
coverImage: '/images/posts/ki-agenten-unternehmen-guide/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'n8n-make-zapier-vergleich',
|
||||||
|
title: 'n8n vs Make vs Zapier: Koji Alat za Automatizaciju je Pravi za Vas?',
|
||||||
|
date: '2026-01-10',
|
||||||
|
excerpt: 'Detaljna uporedna analiza vodećih alata za automatizaciju radnih tokova sa prednostima i manama za različite slučajeve upotrebe.',
|
||||||
|
category: 'Automatizacija',
|
||||||
|
tags: ['n8n', 'Make', 'Zapier', 'Workflow', 'Automatizacija', 'No-Code'],
|
||||||
|
coverImage: '/images/posts/n8n-make-zapier-vergleich/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'voice-ai-kundenservice-trends',
|
||||||
|
title: 'Voice AI u Korisničkoj Službi: Trendovi i Najbolje Prakse 2026',
|
||||||
|
date: '2026-01-05',
|
||||||
|
excerpt: 'Kako Voice AI revolucioniše korisničku službu i koje tehnologije treba da evaluirate za vaš posao.',
|
||||||
|
category: 'Voice AI',
|
||||||
|
tags: ['Voice AI', 'Glasovni Asistent', 'Korisnička Služba', 'NLP', 'Chatbot', 'Vapi'],
|
||||||
|
coverImage: '/images/posts/voice-ai-kundenservice-trends/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'saas-mvp-entwicklung-4-wochen',
|
||||||
|
title: 'SaaS MVP za 4 Nedelje: Od Ideje do Lansiranja',
|
||||||
|
date: '2025-12-20',
|
||||||
|
excerpt: 'Korak-po-korak vodič za brz razvoj SaaS MVP-a sa Next.js, Prisma i modernim cloud servisima.',
|
||||||
|
category: 'SaaS Razvoj',
|
||||||
|
tags: ['SaaS', 'MVP', 'Next.js', 'Startup', 'Razvoj Proizvoda', 'React'],
|
||||||
|
coverImage: '/images/posts/saas-mvp-entwicklung-4-wochen/cover.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'erp-integration-breuninger',
|
||||||
|
title: 'ApparelMagic i TradeByte: Analiza kompleksnih integracija',
|
||||||
|
date: '2024-02-09',
|
||||||
|
excerpt: 'Detaljna analiza e-commerce integracije izmedu Apparel Magic i Breuninger putem TradeByte',
|
||||||
|
category: 'Sistemska Integracija',
|
||||||
|
tags: ['ERP', 'Apparel Magic', 'TradeByte', 'API Integracija', 'Python', 'MariaDB'],
|
||||||
|
coverImage: '/images/posts/erp-integration-breuninger/cover.jpg',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
const BASE_URL = process.env.NEXT_PUBLIC_SITE_URL || 'https://damjan-savic.com';
|
const BASE_URL = process.env.NEXT_PUBLIC_SITE_URL || 'https://damjan-savic.com';
|
||||||
|
|
||||||
export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
||||||
|
|||||||
@@ -1,228 +0,0 @@
|
|||||||
import type { BlogPost } from '@/lib/blog';
|
|
||||||
|
|
||||||
export type LegacyBlogPostsData = Record<string, BlogPost[]>;
|
|
||||||
|
|
||||||
export const legacyBlogPosts: LegacyBlogPostsData = {
|
|
||||||
de: [
|
|
||||||
{
|
|
||||||
slug: 'n8n-automatisierung-tutorial',
|
|
||||||
title: 'n8n Tutorial: Workflows automatisieren ohne Code - Schritt für Schritt',
|
|
||||||
date: '2026-01-18',
|
|
||||||
excerpt: 'Lernen Sie, wie Sie mit n8n leistungsstarke Automatisierungen erstellen. Von der Installation bis zum ersten produktiven Workflow - inklusive Best Practices.',
|
|
||||||
category: 'Automatisierung',
|
|
||||||
tags: ['n8n', 'Tutorial', 'Automatisierung', 'Workflow', 'No-Code', 'Self-Hosted'],
|
|
||||||
coverImage: '/images/posts/n8n-automatisierung-tutorial/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'geo-generative-engine-optimization',
|
|
||||||
title: 'GEO: Generative Engine Optimization - SEO für die KI-Ära',
|
|
||||||
date: '2026-01-17',
|
|
||||||
excerpt: 'Wie Sie Ihre Inhalte für ChatGPT, Perplexity und andere KI-Suchmaschinen optimieren. Der neue Standard nach klassischem SEO.',
|
|
||||||
category: 'Marketing',
|
|
||||||
tags: ['GEO', 'SEO', 'KI', 'ChatGPT', 'Perplexity', 'Content Marketing', 'AEO'],
|
|
||||||
coverImage: '/images/posts/geo-generative-engine-optimization/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'gpt-api-integration-praxisguide',
|
|
||||||
title: 'GPT API Integration: Vom API-Key zur produktionsreifen Anwendung',
|
|
||||||
date: '2026-01-16',
|
|
||||||
excerpt: 'Praktische Anleitung zur Integration von OpenAI GPT-4 in Ihre Anwendungen. Token-Optimierung, Fehlerbehandlung und Best Practices.',
|
|
||||||
category: 'KI-Entwicklung',
|
|
||||||
tags: ['GPT-4', 'OpenAI', 'API', 'Integration', 'Python', 'LLM', 'Prompt Engineering'],
|
|
||||||
coverImage: '/images/posts/gpt-api-integration-praxisguide/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'ki-agenten-unternehmen-guide',
|
|
||||||
title: 'KI-Agenten für Unternehmen: Der ultimative Praxisguide 2026',
|
|
||||||
date: '2026-01-15',
|
|
||||||
excerpt: 'Wie Unternehmen KI-Agenten einsetzen können, um Prozesse zu automatisieren, Kosten zu senken und Wettbewerbsvorteile zu gewinnen.',
|
|
||||||
category: 'KI-Entwicklung',
|
|
||||||
tags: ['KI-Agenten', 'Automatisierung', 'GPT-4', 'Claude', 'LLM', 'Unternehmen'],
|
|
||||||
coverImage: '/images/posts/ki-agenten-unternehmen-guide/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'n8n-make-zapier-vergleich',
|
|
||||||
title: 'n8n vs Make vs Zapier: Welches Automatisierungstool passt zu Ihnen?',
|
|
||||||
date: '2026-01-10',
|
|
||||||
excerpt: 'Ein detaillierter Vergleich der führenden Workflow-Automatisierungstools mit Vor- und Nachteilen für verschiedene Anwendungsfälle.',
|
|
||||||
category: 'Automatisierung',
|
|
||||||
tags: ['n8n', 'Make', 'Zapier', 'Workflow', 'Automatisierung', 'No-Code'],
|
|
||||||
coverImage: '/images/posts/n8n-make-zapier-vergleich/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'voice-ai-kundenservice-trends',
|
|
||||||
title: 'Voice AI im Kundenservice: Trends und Best Practices 2026',
|
|
||||||
date: '2026-01-05',
|
|
||||||
excerpt: 'Wie Voice AI den Kundenservice revolutioniert und welche Technologien Sie für Ihr Unternehmen evaluieren sollten.',
|
|
||||||
category: 'Voice AI',
|
|
||||||
tags: ['Voice AI', 'Sprachassistent', 'Kundenservice', 'NLP', 'Chatbot', 'Vapi'],
|
|
||||||
coverImage: '/images/posts/voice-ai-kundenservice-trends/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'saas-mvp-entwicklung-4-wochen',
|
|
||||||
title: 'SaaS MVP in 4 Wochen: Von der Idee zum Launch',
|
|
||||||
date: '2025-12-20',
|
|
||||||
excerpt: 'Schritt-für-Schritt Anleitung zur schnellen Entwicklung eines SaaS MVP mit Next.js, Prisma und modernen Cloud-Diensten.',
|
|
||||||
category: 'SaaS-Entwicklung',
|
|
||||||
tags: ['SaaS', 'MVP', 'Next.js', 'Startup', 'Produktentwicklung', 'React'],
|
|
||||||
coverImage: '/images/posts/saas-mvp-entwicklung-4-wochen/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'erp-integration-breuninger',
|
|
||||||
title: 'ApparelMagic und TradeByte: Analyse komplexer Integrationen',
|
|
||||||
date: '2024-02-09',
|
|
||||||
excerpt: 'Detaillierte Analyse einer E-Commerce-Integration zwischen Apparel Magic und Breuninger via TradeByte',
|
|
||||||
category: 'System Integration',
|
|
||||||
tags: ['ERP', 'Apparel Magic', 'TradeByte', 'API Integration', 'Python', 'MariaDB'],
|
|
||||||
coverImage: '/images/posts/erp-integration-breuninger/cover.jpg',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
en: [
|
|
||||||
{
|
|
||||||
slug: 'n8n-automatisierung-tutorial',
|
|
||||||
title: 'n8n Tutorial: Automate Workflows Without Code - Step by Step',
|
|
||||||
date: '2026-01-18',
|
|
||||||
excerpt: 'Learn how to create powerful automations with n8n. From installation to your first production workflow - including best practices.',
|
|
||||||
category: 'Automation',
|
|
||||||
tags: ['n8n', 'Tutorial', 'Automation', 'Workflow', 'No-Code', 'Self-Hosted'],
|
|
||||||
coverImage: '/images/posts/n8n-automatisierung-tutorial/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'geo-generative-engine-optimization',
|
|
||||||
title: 'GEO: Generative Engine Optimization - SEO for the AI Era',
|
|
||||||
date: '2026-01-17',
|
|
||||||
excerpt: 'How to optimize your content for ChatGPT, Perplexity and other AI search engines. The new standard after traditional SEO.',
|
|
||||||
category: 'Marketing',
|
|
||||||
tags: ['GEO', 'SEO', 'AI', 'ChatGPT', 'Perplexity', 'Content Marketing', 'AEO'],
|
|
||||||
coverImage: '/images/posts/geo-generative-engine-optimization/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'gpt-api-integration-praxisguide',
|
|
||||||
title: 'GPT API Integration: From API Key to Production-Ready Application',
|
|
||||||
date: '2026-01-16',
|
|
||||||
excerpt: 'Practical guide to integrating OpenAI GPT-4 into your applications. Token optimization, error handling and best practices.',
|
|
||||||
category: 'AI Development',
|
|
||||||
tags: ['GPT-4', 'OpenAI', 'API', 'Integration', 'Python', 'LLM', 'Prompt Engineering'],
|
|
||||||
coverImage: '/images/posts/gpt-api-integration-praxisguide/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'ki-agenten-unternehmen-guide',
|
|
||||||
title: 'AI Agents for Business: The Ultimate Practical Guide 2026',
|
|
||||||
date: '2026-01-15',
|
|
||||||
excerpt: 'How companies can use AI agents to automate processes, reduce costs and gain competitive advantages.',
|
|
||||||
category: 'AI Development',
|
|
||||||
tags: ['AI Agents', 'Automation', 'GPT-4', 'Claude', 'LLM', 'Enterprise'],
|
|
||||||
coverImage: '/images/posts/ki-agenten-unternehmen-guide/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'n8n-make-zapier-vergleich',
|
|
||||||
title: 'n8n vs Make vs Zapier: Which Automation Tool is Right for You?',
|
|
||||||
date: '2026-01-10',
|
|
||||||
excerpt: 'A detailed comparison of leading workflow automation tools with pros and cons for different use cases.',
|
|
||||||
category: 'Automation',
|
|
||||||
tags: ['n8n', 'Make', 'Zapier', 'Workflow', 'Automation', 'No-Code'],
|
|
||||||
coverImage: '/images/posts/n8n-make-zapier-vergleich/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'voice-ai-kundenservice-trends',
|
|
||||||
title: 'Voice AI in Customer Service: Trends and Best Practices 2026',
|
|
||||||
date: '2026-01-05',
|
|
||||||
excerpt: 'How Voice AI is revolutionizing customer service and which technologies you should evaluate for your business.',
|
|
||||||
category: 'Voice AI',
|
|
||||||
tags: ['Voice AI', 'Voice Assistant', 'Customer Service', 'NLP', 'Chatbot', 'Vapi'],
|
|
||||||
coverImage: '/images/posts/voice-ai-kundenservice-trends/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'saas-mvp-entwicklung-4-wochen',
|
|
||||||
title: 'SaaS MVP in 4 Weeks: From Idea to Launch',
|
|
||||||
date: '2025-12-20',
|
|
||||||
excerpt: 'Step-by-step guide to quickly developing a SaaS MVP with Next.js, Prisma and modern cloud services.',
|
|
||||||
category: 'SaaS Development',
|
|
||||||
tags: ['SaaS', 'MVP', 'Next.js', 'Startup', 'Product Development', 'React'],
|
|
||||||
coverImage: '/images/posts/saas-mvp-entwicklung-4-wochen/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'erp-integration-breuninger',
|
|
||||||
title: 'ApparelMagic and TradeByte: Complex Integration Analysis',
|
|
||||||
date: '2024-02-09',
|
|
||||||
excerpt: 'Detailed analysis of an e-commerce integration between Apparel Magic and Breuninger via TradeByte',
|
|
||||||
category: 'System Integration',
|
|
||||||
tags: ['ERP', 'Apparel Magic', 'TradeByte', 'API Integration', 'Python', 'MariaDB'],
|
|
||||||
coverImage: '/images/posts/erp-integration-breuninger/cover.jpg',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sr: [
|
|
||||||
{
|
|
||||||
slug: 'n8n-automatisierung-tutorial',
|
|
||||||
title: 'n8n Tutorial: Automatizujte Radne Tokove Bez Koda - Korak po Korak',
|
|
||||||
date: '2026-01-18',
|
|
||||||
excerpt: 'Naučite kako da kreirate moćne automatizacije sa n8n. Od instalacije do prvog produktivnog radnog toka - uključujući najbolje prakse.',
|
|
||||||
category: 'Automatizacija',
|
|
||||||
tags: ['n8n', 'Tutorial', 'Automatizacija', 'Workflow', 'No-Code', 'Self-Hosted'],
|
|
||||||
coverImage: '/images/posts/n8n-automatisierung-tutorial/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'geo-generative-engine-optimization',
|
|
||||||
title: 'GEO: Generative Engine Optimization - SEO za AI Eru',
|
|
||||||
date: '2026-01-17',
|
|
||||||
excerpt: 'Kako da optimizujete sadržaj za ChatGPT, Perplexity i druge AI pretraživače. Novi standard posle klasičnog SEO-a.',
|
|
||||||
category: 'Marketing',
|
|
||||||
tags: ['GEO', 'SEO', 'AI', 'ChatGPT', 'Perplexity', 'Content Marketing', 'AEO'],
|
|
||||||
coverImage: '/images/posts/geo-generative-engine-optimization/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'gpt-api-integration-praxisguide',
|
|
||||||
title: 'GPT API Integracija: Od API Ključa do Produkcione Aplikacije',
|
|
||||||
date: '2026-01-16',
|
|
||||||
excerpt: 'Praktični vodič za integraciju OpenAI GPT-4 u vaše aplikacije. Optimizacija tokena, rukovanje greškama i najbolje prakse.',
|
|
||||||
category: 'AI Razvoj',
|
|
||||||
tags: ['GPT-4', 'OpenAI', 'API', 'Integracija', 'Python', 'LLM', 'Prompt Engineering'],
|
|
||||||
coverImage: '/images/posts/gpt-api-integration-praxisguide/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'ki-agenten-unternehmen-guide',
|
|
||||||
title: 'AI Agenti za Preduzeća: Ultimativni Praktični Vodič 2026',
|
|
||||||
date: '2026-01-15',
|
|
||||||
excerpt: 'Kako kompanije mogu koristiti AI agente za automatizaciju procesa, smanjenje troškova i sticanje konkurentskih prednosti.',
|
|
||||||
category: 'AI Razvoj',
|
|
||||||
tags: ['AI Agenti', 'Automatizacija', 'GPT-4', 'Claude', 'LLM', 'Preduzeća'],
|
|
||||||
coverImage: '/images/posts/ki-agenten-unternehmen-guide/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'n8n-make-zapier-vergleich',
|
|
||||||
title: 'n8n vs Make vs Zapier: Koji Alat za Automatizaciju je Pravi za Vas?',
|
|
||||||
date: '2026-01-10',
|
|
||||||
excerpt: 'Detaljna uporedna analiza vodećih alata za automatizaciju radnih tokova sa prednostima i manama za različite slučajeve upotrebe.',
|
|
||||||
category: 'Automatizacija',
|
|
||||||
tags: ['n8n', 'Make', 'Zapier', 'Workflow', 'Automatizacija', 'No-Code'],
|
|
||||||
coverImage: '/images/posts/n8n-make-zapier-vergleich/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'voice-ai-kundenservice-trends',
|
|
||||||
title: 'Voice AI u Korisničkoj Službi: Trendovi i Najbolje Prakse 2026',
|
|
||||||
date: '2026-01-05',
|
|
||||||
excerpt: 'Kako Voice AI revolucioniše korisničku službu i koje tehnologije treba da evaluirate za vaš posao.',
|
|
||||||
category: 'Voice AI',
|
|
||||||
tags: ['Voice AI', 'Glasovni Asistent', 'Korisnička Služba', 'NLP', 'Chatbot', 'Vapi'],
|
|
||||||
coverImage: '/images/posts/voice-ai-kundenservice-trends/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'saas-mvp-entwicklung-4-wochen',
|
|
||||||
title: 'SaaS MVP za 4 Nedelje: Od Ideje do Lansiranja',
|
|
||||||
date: '2025-12-20',
|
|
||||||
excerpt: 'Korak-po-korak vodič za brz razvoj SaaS MVP-a sa Next.js, Prisma i modernim cloud servisima.',
|
|
||||||
category: 'SaaS Razvoj',
|
|
||||||
tags: ['SaaS', 'MVP', 'Next.js', 'Startup', 'Razvoj Proizvoda', 'React'],
|
|
||||||
coverImage: '/images/posts/saas-mvp-entwicklung-4-wochen/cover.jpg',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: 'erp-integration-breuninger',
|
|
||||||
title: 'ApparelMagic i TradeByte: Analiza kompleksnih integracija',
|
|
||||||
date: '2024-02-09',
|
|
||||||
excerpt: 'Detaljna analiza e-commerce integracije izmedu Apparel Magic i Breuninger putem TradeByte',
|
|
||||||
category: 'Sistemska Integracija',
|
|
||||||
tags: ['ERP', 'Apparel Magic', 'TradeByte', 'API Integracija', 'Python', 'MariaDB'],
|
|
||||||
coverImage: '/images/posts/erp-integration-breuninger/cover.jpg',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
+1
-15
@@ -1,6 +1,5 @@
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { cache } from '@/utils/cache';
|
|
||||||
|
|
||||||
export interface BlogPost {
|
export interface BlogPost {
|
||||||
slug: string;
|
slug: string;
|
||||||
@@ -131,14 +130,6 @@ function parseMarkdownPost(filename: string, content: string): BlogPost | null {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getAllBlogPosts(): BlogPost[] {
|
export function getAllBlogPosts(): BlogPost[] {
|
||||||
const cacheKey = 'blog:all-posts';
|
|
||||||
|
|
||||||
// Check cache first
|
|
||||||
const cachedPosts = cache.get<BlogPost[]>(cacheKey);
|
|
||||||
if (cachedPosts) {
|
|
||||||
return cachedPosts;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fs.existsSync(BLOG_POSTS_DIR)) {
|
if (!fs.existsSync(BLOG_POSTS_DIR)) {
|
||||||
console.warn('Blog posts directory not found:', BLOG_POSTS_DIR);
|
console.warn('Blog posts directory not found:', BLOG_POSTS_DIR);
|
||||||
return [];
|
return [];
|
||||||
@@ -160,12 +151,7 @@ export function getAllBlogPosts(): BlogPost[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sort by date descending (newest first)
|
// Sort by date descending (newest first)
|
||||||
const sortedPosts = posts.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
|
return posts.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
|
||||||
|
|
||||||
// Cache the results
|
|
||||||
cache.set(cacheKey, sortedPosts);
|
|
||||||
|
|
||||||
return sortedPosts;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBlogPostBySlug(slug: string): BlogPost | null {
|
export function getBlogPostBySlug(slug: string): BlogPost | null {
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
const CSRF_META_TAG_NAME = 'csrf-token';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the CSRF token from the meta tag in the document head
|
||||||
|
* The server should render: <meta name="csrf-token" content="..." />
|
||||||
|
*/
|
||||||
|
export function getCsrfToken(): string | null {
|
||||||
|
if (typeof document === 'undefined') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const metaTag = document.querySelector<HTMLMetaElement>(
|
||||||
|
`meta[name="${CSRF_META_TAG_NAME}"]`
|
||||||
|
);
|
||||||
|
|
||||||
|
return metaTag?.content || null;
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
import { cookies } from 'next/headers';
|
||||||
|
import { randomBytes } from 'crypto';
|
||||||
|
|
||||||
|
const CSRF_TOKEN_COOKIE_NAME = 'csrf_token';
|
||||||
|
const CSRF_TOKEN_LENGTH = 32;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a cryptographically secure CSRF token
|
||||||
|
*/
|
||||||
|
export function generateCsrfToken(): string {
|
||||||
|
return randomBytes(CSRF_TOKEN_LENGTH).toString('base64url');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current CSRF token from cookies or generate a new one
|
||||||
|
*/
|
||||||
|
export async function getCsrfToken(): Promise<string> {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
const existingToken = cookieStore.get(CSRF_TOKEN_COOKIE_NAME);
|
||||||
|
|
||||||
|
if (existingToken?.value) {
|
||||||
|
return existingToken.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newToken = generateCsrfToken();
|
||||||
|
await setCsrfToken(newToken);
|
||||||
|
return newToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the CSRF token in an httpOnly cookie
|
||||||
|
*/
|
||||||
|
export async function setCsrfToken(token: string): Promise<void> {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
|
||||||
|
try {
|
||||||
|
cookieStore.set(CSRF_TOKEN_COOKIE_NAME, token, {
|
||||||
|
httpOnly: true,
|
||||||
|
secure: process.env.NODE_ENV === 'production',
|
||||||
|
sameSite: 'strict',
|
||||||
|
maxAge: 60 * 60 * 24, // 24 hours
|
||||||
|
path: '/',
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
// Handle server component context where cookies can't be set
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate a CSRF token against the stored token in cookies
|
||||||
|
*/
|
||||||
|
export async function validateCsrfToken(token: string): Promise<boolean> {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
const storedToken = cookieStore.get(CSRF_TOKEN_COOKIE_NAME);
|
||||||
|
|
||||||
|
if (!storedToken?.value || !token) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constant-time comparison to prevent timing attacks
|
||||||
|
return timingSafeEqual(
|
||||||
|
Buffer.from(storedToken.value),
|
||||||
|
Buffer.from(token)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timing-safe string comparison to prevent timing attacks
|
||||||
|
*/
|
||||||
|
function timingSafeEqual(a: Buffer, b: Buffer): boolean {
|
||||||
|
if (a.length !== b.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = 0;
|
||||||
|
for (let i = 0; i < a.length; i++) {
|
||||||
|
result |= a[i] ^ b[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete the CSRF token cookie
|
||||||
|
*/
|
||||||
|
export async function deleteCsrfToken(): Promise<void> {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
|
||||||
|
try {
|
||||||
|
cookieStore.delete(CSRF_TOKEN_COOKIE_NAME);
|
||||||
|
} catch {
|
||||||
|
// Handle server component context
|
||||||
|
}
|
||||||
|
}
|
||||||
+34
-1
@@ -1,12 +1,45 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
import createMiddleware from 'next-intl/middleware';
|
import createMiddleware from 'next-intl/middleware';
|
||||||
import { locales, defaultLocale } from './i18n/config';
|
import { locales, defaultLocale } from './i18n/config';
|
||||||
|
import { randomBytes } from 'crypto';
|
||||||
|
|
||||||
export default createMiddleware({
|
const CSRF_TOKEN_COOKIE_NAME = 'csrf_token';
|
||||||
|
const CSRF_TOKEN_LENGTH = 32;
|
||||||
|
|
||||||
|
const intlMiddleware = createMiddleware({
|
||||||
locales,
|
locales,
|
||||||
defaultLocale,
|
defaultLocale,
|
||||||
localePrefix: 'always',
|
localePrefix: 'always',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default function middleware(request: NextRequest) {
|
||||||
|
// Run the i18n middleware first
|
||||||
|
const response = intlMiddleware(request);
|
||||||
|
|
||||||
|
// Check if CSRF token exists in cookies
|
||||||
|
const existingToken = request.cookies.get(CSRF_TOKEN_COOKIE_NAME);
|
||||||
|
|
||||||
|
// Generate and set CSRF token if it doesn't exist
|
||||||
|
if (!existingToken) {
|
||||||
|
const newToken = randomBytes(CSRF_TOKEN_LENGTH).toString('base64url');
|
||||||
|
|
||||||
|
// Create a new response or clone the existing one
|
||||||
|
const finalResponse = response || NextResponse.next();
|
||||||
|
|
||||||
|
finalResponse.cookies.set(CSRF_TOKEN_COOKIE_NAME, newToken, {
|
||||||
|
httpOnly: true,
|
||||||
|
secure: process.env.NODE_ENV === 'production',
|
||||||
|
sameSite: 'strict',
|
||||||
|
maxAge: 60 * 60 * 24, // 24 hours
|
||||||
|
path: '/',
|
||||||
|
});
|
||||||
|
|
||||||
|
return finalResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
matcher: [
|
matcher: [
|
||||||
'/',
|
'/',
|
||||||
|
|||||||
Reference in New Issue
Block a user