feat(technologies): add full stack directory and home preview

This commit is contained in:
poyrazavsever
2026-08-31 20:19:42 +03:00
parent ddeab06b45
commit a2538e53c0
10 changed files with 228 additions and 46 deletions
+20
View File
@@ -0,0 +1,20 @@
import { TechnologiesContent } from "@/components/technologies-content";
import { getStaticPageMetadata } from "@/lib/seo";
export async function generateMetadata({
params,
}: {
params: Promise<{ locale: string }>;
}) {
const { locale } = await params;
return getStaticPageMetadata({
locale,
page: "technologies",
path: "/technologies",
});
}
export default function TechnologiesPage() {
return <TechnologiesContent />;
}
+1
View File
@@ -25,6 +25,7 @@ const STATIC_ROUTES = [
{ path: "/projects", changeFrequency: "monthly", priority: 0.8 }, { path: "/projects", changeFrequency: "monthly", priority: 0.8 },
{ path: "/content", changeFrequency: "weekly", priority: 0.7 }, { path: "/content", changeFrequency: "weekly", priority: 0.7 },
{ path: "/gallery", changeFrequency: "monthly", priority: 0.6 }, { path: "/gallery", changeFrequency: "monthly", priority: 0.6 },
{ path: "/technologies", changeFrequency: "monthly", priority: 0.7 },
{ path: "/contact", changeFrequency: "yearly", priority: 0.5 }, { path: "/contact", changeFrequency: "yearly", priority: 0.5 },
{ path: "/media-kit", changeFrequency: "monthly", priority: 0.6 }, { path: "/media-kit", changeFrequency: "monthly", priority: 0.6 },
{ path: "/links", changeFrequency: "monthly", priority: 0.4 }, { path: "/links", changeFrequency: "monthly", priority: 0.4 },
+34 -33
View File
@@ -1,20 +1,27 @@
"use client"; "use client";
import { Icon } from "@iconify/react"; import { Icon } from "@iconify/react";
import { useLocale, useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { Badge, Typography } from "poyraz-ui/atoms"; import {
Button,
ButtonIcon,
ButtonLabel,
Typography,
} from "poyraz-ui/atoms";
import { TECHNOLOGY_STACK } from "@/data/technology-stack"; import { TECHNOLOGY_STACK } from "@/data/technology-stack";
import { getLocalizedValue } from "@/lib/locale"; import { Link } from "@/i18n/routing";
import { TechnologyBadge } from "@/components/technology-badge";
export function HomeTechnologyStack() { export function HomeTechnologyStack() {
const t = useTranslations("Home"); const t = useTranslations("Home");
const locale = useLocale(); const technologies = TECHNOLOGY_STACK.flatMap((group) => group.items);
return ( return (
<section <section
className="space-y-4 pb-4 pt-12 md:pt-14" className="space-y-4 pt-12 md:pt-14"
aria-labelledby="home-technology-stack-title" aria-labelledby="home-technology-stack-title"
> >
<div className="flex flex-wrap items-center justify-between gap-3">
<Typography <Typography
id="home-technology-stack-title" id="home-technology-stack-title"
variant="h3" variant="h3"
@@ -24,38 +31,32 @@ export function HomeTechnologyStack() {
{t("technologiesTitle")} {t("technologiesTitle")}
</Typography> </Typography>
<div className="grid gap-x-8 gap-y-6 md:grid-cols-2"> <Button
{TECHNOLOGY_STACK.map((group) => ( asChild
<div key={group.id} className="space-y-2.5 border-t border-border pt-3"> size="sm"
<Typography
variant="small"
component="h3"
className="text-xs font-medium uppercase tracking-[0.08em] text-muted-foreground"
>
{t(`technologyCategories.${group.id}`)}
</Typography>
<div className="flex flex-wrap gap-2">
{group.items.map((technology) => (
<Badge
key={technology.id}
variant="secondary"
radius="sm" radius="sm"
className="gap-1.5 px-2.5 py-1 text-xs font-medium text-foreground" effect="swap"
swapTarget="both"
> >
<Icon <Link href="/technologies">
icon={technology.icon} <ButtonLabel>{t("allTechnologies")}</ButtonLabel>
width={14} <ButtonIcon>
height={14} <Icon icon="mdi:arrow-right" width={15} height={15} />
</ButtonIcon>
</Link>
</Button>
</div>
<div className="relative max-h-14 overflow-hidden border-t border-border pt-3">
<div className="flex flex-wrap gap-2" aria-label={t("technologiesTitle")}>
{technologies.map((technology) => (
<TechnologyBadge key={technology.id} technology={technology} />
))}
</div>
<div
aria-hidden="true" aria-hidden="true"
className="shrink-0" className="pointer-events-none absolute inset-x-0 bottom-0 h-6 bg-gradient-to-t from-background via-background/85 to-transparent backdrop-blur-[2px]"
/> />
<span>{getLocalizedValue(technology.label, locale)}</span>
</Badge>
))}
</div>
</div>
))}
</div> </div>
</section> </section>
); );
+59
View File
@@ -0,0 +1,59 @@
"use client";
import { useTranslations } from "next-intl";
import { Card, Typography } from "poyraz-ui/atoms";
import { TechnologyBadge } from "@/components/technology-badge";
import { TECHNOLOGY_STACK } from "@/data/technology-stack";
export function TechnologiesContent() {
const t = useTranslations("Technologies");
return (
<section className="flex h-full flex-col gap-10">
<header className="border-b border-border py-4 sm:py-5">
<Typography
variant="h2"
component="h1"
className="font-secondary text-2xl font-semibold leading-none tracking-[-0.045em] text-foreground"
>
{t("title")}
</Typography>
<Typography
variant="small"
className="mt-2 max-w-2xl text-xs leading-5 text-muted-foreground sm:text-sm"
>
{t("description")}
</Typography>
</header>
<div className="grid gap-3 md:grid-cols-2">
{TECHNOLOGY_STACK.map((group) => (
<Card
key={group.id}
role="region"
className="rounded-sm border-border p-4"
aria-labelledby={`technology-group-${group.id}`}
>
<Typography
id={`technology-group-${group.id}`}
variant="large"
component="h2"
className="text-sm font-semibold tracking-[-0.02em]"
>
{t(`categories.${group.id}`)}
</Typography>
<div className="mt-3 flex flex-wrap gap-2">
{group.items.map((technology) => (
<TechnologyBadge
key={technology.id}
technology={technology}
/>
))}
</div>
</Card>
))}
</div>
</section>
);
}
+32
View File
@@ -0,0 +1,32 @@
"use client";
import { Icon } from "@iconify/react";
import { useLocale } from "next-intl";
import { Badge } from "poyraz-ui/atoms";
import type { TechnologyStackItem } from "@/data/technology-stack";
import { getLocalizedValue } from "@/lib/locale";
export function TechnologyBadge({
technology,
}: {
technology: TechnologyStackItem;
}) {
const locale = useLocale();
return (
<Badge
variant="secondary"
radius="sm"
className="shrink-0 gap-1.5 px-2.5 py-1 text-xs font-medium text-foreground"
>
<Icon
icon={technology.icon}
width={14}
height={14}
aria-hidden="true"
className="shrink-0"
/>
<span>{getLocalizedValue(technology.label, locale)}</span>
</Badge>
);
}
+19 -2
View File
@@ -7,7 +7,7 @@ export type TechnologyStackItem = {
}; };
export type TechnologyStackGroup = { export type TechnologyStackGroup = {
id: "frontend" | "backend" | "languages" | "designTools"; id: "frontend" | "backend" | "databases" | "languages" | "designTools";
items: readonly TechnologyStackItem[]; items: readonly TechnologyStackItem[];
}; };
@@ -56,7 +56,6 @@ export const TECHNOLOGY_STACK: readonly TechnologyStackGroup[] = [
icon: "simple-icons:jsonwebtokens", icon: "simple-icons:jsonwebtokens",
}, },
{ id: "prisma", label: "Prisma", icon: "simple-icons:prisma" }, { id: "prisma", label: "Prisma", icon: "simple-icons:prisma" },
{ id: "mongoose", label: "Mongoose", icon: "simple-icons:mongoose" },
{ {
id: "socket-io", id: "socket-io",
label: "Socket.io", label: "Socket.io",
@@ -64,6 +63,24 @@ export const TECHNOLOGY_STACK: readonly TechnologyStackGroup[] = [
}, },
], ],
}, },
{
id: "databases",
items: [
{ id: "mongodb", label: "MongoDB", icon: "simple-icons:mongodb" },
{ id: "mongoose", label: "Mongoose", icon: "simple-icons:mongoose" },
{
id: "postgresql",
label: "PostgreSQL",
icon: "simple-icons:postgresql",
},
{ id: "mysql", label: "MySQL", icon: "simple-icons:mysql" },
{
id: "mssql",
label: "Microsoft SQL Server",
icon: "simple-icons:microsoftsqlserver",
},
],
},
{ {
id: "languages", id: "languages",
items: [ items: [
+15
View File
@@ -87,6 +87,21 @@ export const NAV_DROPDOWN_GROUPS = [
external: false, external: false,
keywords: ["animasyon", "animation", "kaynak", "resource", "motion"], keywords: ["animasyon", "animation", "kaynak", "resource", "motion"],
}, },
{
id: "technologies",
label: "Teknolojiler",
href: "/technologies",
icon: "mdi:layers-triple-outline",
external: false,
keywords: [
"teknolojiler",
"technologies",
"tech stack",
"araçlar",
"tools",
"skills",
],
},
], ],
}, },
] as const; ] as const;
+1
View File
@@ -30,6 +30,7 @@ type StaticSeoPage =
| "projects" | "projects"
| "content" | "content"
| "gallery" | "gallery"
| "technologies"
| "links" | "links"
| "contact"; | "contact";
+18
View File
@@ -13,6 +13,7 @@
"socialLinks": "Social Links", "socialLinks": "Social Links",
"others": "Others", "others": "Others",
"animationResources": "Animation Resources", "animationResources": "Animation Resources",
"technologies": "Technologies",
"links": "Links", "links": "Links",
"mediaKit": "Media Kit", "mediaKit": "Media Kit",
"references": "References", "references": "References",
@@ -34,9 +35,11 @@
"reviewsAndReferences": "Reviews & References", "reviewsAndReferences": "Reviews & References",
"allReferences": "All references", "allReferences": "All references",
"technologiesTitle": "Technologies I use", "technologiesTitle": "Technologies I use",
"allTechnologies": "Explore all technologies",
"technologyCategories": { "technologyCategories": {
"frontend": "Front End", "frontend": "Front End",
"backend": "Back End", "backend": "Back End",
"databases": "Databases",
"languages": "Programming Languages", "languages": "Programming Languages",
"designTools": "Design & Tools" "designTools": "Design & Tools"
}, },
@@ -216,6 +219,17 @@
"resources": "Resources" "resources": "Resources"
} }
}, },
"Technologies": {
"title": "Technologies I Use",
"description": "The front-end, back-end, database, programming language, design, and development tools I use to build products.",
"categories": {
"frontend": "Front End",
"backend": "Back End",
"databases": "Databases",
"languages": "Programming Languages",
"designTools": "Design & Tools"
}
},
"Gallery": { "Gallery": {
"empty": "No images added to the gallery yet.", "empty": "No images added to the gallery yet.",
"close": "Close", "close": "Close",
@@ -255,6 +269,10 @@
"title": "Gallery", "title": "Gallery",
"description": "Selected images from Poyraz Avsever's events, presentations, projects, and community work." "description": "Selected images from Poyraz Avsever's events, presentations, projects, and community work."
}, },
"technologies": {
"title": "Technologies I Use",
"description": "Explore the front-end, back-end, database, programming language, and development tools Poyraz Avsever uses to build products."
},
"links": { "links": {
"title": "Links", "title": "Links",
"description": "Access Poyraz Avsever's social profiles, projects, content, and essential links from one page." "description": "Access Poyraz Avsever's social profiles, projects, content, and essential links from one page."
+18
View File
@@ -13,6 +13,7 @@
"socialLinks": "Sosyal Bağlantılar", "socialLinks": "Sosyal Bağlantılar",
"others": "Diğerleri", "others": "Diğerleri",
"animationResources": "Animasyon Kaynakları", "animationResources": "Animasyon Kaynakları",
"technologies": "Teknolojiler",
"links": "Bağlantılar", "links": "Bağlantılar",
"mediaKit": "Medya Kiti", "mediaKit": "Medya Kiti",
"references": "Referanslar", "references": "Referanslar",
@@ -34,9 +35,11 @@
"reviewsAndReferences": "Yorumlar & Referanslar", "reviewsAndReferences": "Yorumlar & Referanslar",
"allReferences": "Tüm referanslar", "allReferences": "Tüm referanslar",
"technologiesTitle": "Ben bu teknolojileri kullanıyorum", "technologiesTitle": "Ben bu teknolojileri kullanıyorum",
"allTechnologies": "Tüm teknolojileri incele",
"technologyCategories": { "technologyCategories": {
"frontend": "Ön Yüz", "frontend": "Ön Yüz",
"backend": "Arka Yüz", "backend": "Arka Yüz",
"databases": "Veritabanları",
"languages": "Programlama Dilleri", "languages": "Programlama Dilleri",
"designTools": "Tasarım ve Araçlar" "designTools": "Tasarım ve Araçlar"
}, },
@@ -216,6 +219,17 @@
"resources": "Kaynaklar" "resources": "Kaynaklar"
} }
}, },
"Technologies": {
"title": "Kullandığım Teknolojiler",
"description": "Ürün geliştirirken kullandığım ön yüz, arka yüz, veritabanı, programlama dili, tasarım ve geliştirme araçları.",
"categories": {
"frontend": "Ön Yüz",
"backend": "Arka Yüz",
"databases": "Veritabanları",
"languages": "Programlama Dilleri",
"designTools": "Tasarım ve Araçlar"
}
},
"Gallery": { "Gallery": {
"empty": "Henüz galeriye görsel eklenmemiş.", "empty": "Henüz galeriye görsel eklenmemiş.",
"close": "Kapat", "close": "Kapat",
@@ -255,6 +269,10 @@
"title": "Galeri", "title": "Galeri",
"description": "Poyraz Avsever'in etkinlik, sunum, proje ve topluluk çalışmalarından seçilmiş görseller." "description": "Poyraz Avsever'in etkinlik, sunum, proje ve topluluk çalışmalarından seçilmiş görseller."
}, },
"technologies": {
"title": "Kullandığım Teknolojiler",
"description": "Poyraz Avsever'in ürün geliştirirken kullandığı ön yüz, arka yüz, veritabanı, programlama dili ve geliştirme araçlarını inceleyin."
},
"links": { "links": {
"title": "Bağlantılar", "title": "Bağlantılar",
"description": "Poyraz Avsever'in sosyal medya hesaplarına, projelerine, içeriklerine ve hızlı erişim bağlantılarına tek sayfadan ulaşın." "description": "Poyraz Avsever'in sosyal medya hesaplarına, projelerine, içeriklerine ve hızlı erişim bağlantılarına tek sayfadan ulaşın."