diff --git a/app/@breadcrumbs/about/page.tsx b/app/@breadcrumbs/about/page.tsx
new file mode 100644
index 0000000..ed78d5e
--- /dev/null
+++ b/app/@breadcrumbs/about/page.tsx
@@ -0,0 +1,15 @@
+import { Breadcrumbs } from '@/components/layout/Breadcrumbs';
+
+export default function AboutBreadcrumb() {
+ return (
+
+ );
+}
diff --git a/app/@breadcrumbs/blog/[...slug]/page.tsx b/app/@breadcrumbs/blog/[...slug]/page.tsx
new file mode 100644
index 0000000..a2dc242
--- /dev/null
+++ b/app/@breadcrumbs/blog/[...slug]/page.tsx
@@ -0,0 +1,53 @@
+import { Breadcrumbs } from '@/components/layout/Breadcrumbs';
+import { getPostBySlug } from '@/lib/markdown';
+
+interface BreadcrumbItem {
+ label: string;
+ href: string;
+ current?: boolean;
+}
+
+function formatDirectoryName(name: string): string {
+ const directoryNames: { [key: string]: string } = {
+ tech: 'Tehnologie',
+ design: 'Design',
+ tutorial: 'Tutoriale',
+ };
+
+ return directoryNames[name] || name.charAt(0).toUpperCase() + name.slice(1);
+}
+
+export default async function BlogPostBreadcrumb({
+ params,
+}: {
+ params: Promise<{ slug: string[] }>;
+}) {
+ const { slug } = await params;
+ const slugPath = slug.join('/');
+ const post = getPostBySlug(slugPath);
+
+ const items: BreadcrumbItem[] = [
+ {
+ label: 'Blog',
+ href: '/blog',
+ },
+ ];
+
+ if (slug.length > 1) {
+ for (let i = 0; i < slug.length - 1; i++) {
+ const segmentPath = slug.slice(0, i + 1).join('/');
+ items.push({
+ label: formatDirectoryName(slug[i]),
+ href: `/blog/${segmentPath}`,
+ });
+ }
+ }
+
+ items.push({
+ label: post ? post.frontmatter.title : slug[slug.length - 1],
+ href: `/blog/${slugPath}`,
+ current: true,
+ });
+
+ return ;
+}
diff --git a/app/@breadcrumbs/blog/page.tsx b/app/@breadcrumbs/blog/page.tsx
new file mode 100644
index 0000000..6abd4ba
--- /dev/null
+++ b/app/@breadcrumbs/blog/page.tsx
@@ -0,0 +1,15 @@
+import { Breadcrumbs } from '@/components/layout/Breadcrumbs';
+
+export default function BlogBreadcrumb() {
+ return (
+
+ );
+}
diff --git a/app/@breadcrumbs/default.tsx b/app/@breadcrumbs/default.tsx
new file mode 100644
index 0000000..8f1d385
--- /dev/null
+++ b/app/@breadcrumbs/default.tsx
@@ -0,0 +1,7 @@
+'use client';
+
+import { Breadcrumbs } from '@/components/layout/Breadcrumbs';
+
+export default function DefaultBreadcrumb() {
+ return ;
+}
diff --git a/app/@breadcrumbs/tags/[tag]/page.tsx b/app/@breadcrumbs/tags/[tag]/page.tsx
new file mode 100644
index 0000000..9451e8d
--- /dev/null
+++ b/app/@breadcrumbs/tags/[tag]/page.tsx
@@ -0,0 +1,29 @@
+import { Breadcrumbs } from '@/components/layout/Breadcrumbs';
+
+export default async function TagBreadcrumb({
+ params,
+}: {
+ params: Promise<{ tag: string }>;
+}) {
+ const { tag } = await params;
+ const tagName = tag
+ .split('-')
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1))
+ .join(' ');
+
+ return (
+
+ );
+}
diff --git a/app/@breadcrumbs/tags/page.tsx b/app/@breadcrumbs/tags/page.tsx
new file mode 100644
index 0000000..8d74cd3
--- /dev/null
+++ b/app/@breadcrumbs/tags/page.tsx
@@ -0,0 +1,15 @@
+import { Breadcrumbs } from '@/components/layout/Breadcrumbs';
+
+export default function TagsBreadcrumb() {
+ return (
+
+ );
+}
diff --git a/app/globals.css b/app/globals.css
index f1d8c73..d5487a6 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -1 +1,11 @@
@import "tailwindcss";
+
+@layer utilities {
+ .scrollbar-hide {
+ -ms-overflow-style: none;
+ scrollbar-width: none;
+ }
+ .scrollbar-hide::-webkit-scrollbar {
+ display: none;
+ }
+}
diff --git a/app/layout.tsx b/app/layout.tsx
index da72438..56b8ff5 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -27,8 +27,10 @@ export const metadata: Metadata = {
export default function RootLayout({
children,
+ breadcrumbs,
}: {
children: React.ReactNode
+ breadcrumbs: React.ReactNode
}) {
return (
@@ -48,6 +50,7 @@ export default function RootLayout({
+ {breadcrumbs}
{children}
diff --git a/components/layout/Breadcrumbs.tsx b/components/layout/Breadcrumbs.tsx
new file mode 100644
index 0000000..1dfd000
--- /dev/null
+++ b/components/layout/Breadcrumbs.tsx
@@ -0,0 +1,145 @@
+'use client';
+
+import Link from 'next/link';
+import { usePathname } from 'next/navigation';
+import { Fragment } from 'react';
+import { BreadcrumbsSchema } from './BreadcrumbsSchema';
+
+interface BreadcrumbItem {
+ label: string;
+ href: string;
+ current?: boolean;
+}
+
+function HomeIcon({ className }: { className?: string }) {
+ return (
+
+ );
+}
+
+function ChevronIcon({ className }: { className?: string }) {
+ return (
+
+ );
+}
+
+function formatSegmentLabel(segment: string): string {
+ const specialCases: { [key: string]: string } = {
+ blog: 'Blog',
+ tags: 'Tag-uri',
+ about: 'Despre',
+ };
+
+ if (specialCases[segment]) {
+ return specialCases[segment];
+ }
+
+ return segment
+ .split('-')
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1))
+ .join(' ');
+}
+
+export function Breadcrumbs({ items }: { items?: BreadcrumbItem[] }) {
+ const pathname = usePathname();
+
+ let breadcrumbs: BreadcrumbItem[] = items || [];
+
+ if (!items) {
+ const segments = pathname.split('/').filter(Boolean);
+ breadcrumbs = segments.map((segment, index) => {
+ const href = '/' + segments.slice(0, index + 1).join('/');
+ const label = formatSegmentLabel(segment);
+ const current = index === segments.length - 1;
+
+ return { label, href, current };
+ });
+ }
+
+ if (pathname === '/') {
+ return null;
+ }
+
+ const schemaItems = [
+ { position: 1, name: 'Acasă', item: '/' },
+ ...breadcrumbs.map((item, index) => ({
+ position: index + 2,
+ name: item.label,
+ item: item.href,
+ })),
+ ];
+
+ return (
+ <>
+
+
+ >
+ );
+}
diff --git a/components/layout/BreadcrumbsSchema.tsx b/components/layout/BreadcrumbsSchema.tsx
new file mode 100644
index 0000000..18c1467
--- /dev/null
+++ b/components/layout/BreadcrumbsSchema.tsx
@@ -0,0 +1,25 @@
+interface BreadcrumbSchemaItem {
+ position: number;
+ name: string;
+ item: string;
+}
+
+export function BreadcrumbsSchema({ items }: { items: BreadcrumbSchemaItem[] }) {
+ const structuredData = {
+ '@context': 'https://schema.org',
+ '@type': 'BreadcrumbList',
+ itemListElement: items.map((item) => ({
+ '@type': 'ListItem',
+ position: item.position,
+ name: item.name,
+ item: `http://localhost:3000${item.item}`,
+ })),
+ };
+
+ return (
+
+ );
+}
diff --git a/next-env.d.ts b/next-env.d.ts
index 9edff1c..c4b7818 100644
--- a/next-env.d.ts
+++ b/next-env.d.ts
@@ -1,6 +1,6 @@
///
///
-import "./.next/types/routes.d.ts";
+import "./.next/dev/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
diff --git a/package.json b/package.json
index 864a40d..5127e98 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
"description": "",
"main": "index.js",
"scripts": {
- "dev": "next dev",
+ "dev": "next dev -p 3030",
"build": "next build",
"start": "next start",
"lint": "next lint",