Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# CODEOWNERS

# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners

#

# Each line is a file pattern followed by one or more owners.

# The last matching pattern takes precedence.

# Default owner for everything in the repo

- @ColdByDefault

# Core configuration

package.json @ColdByDefault
next.config.ts @ColdByDefault
tsconfig.json @ColdByDefault
prisma/schema.prisma @ColdByDefault

# Security-sensitive paths

lib/security.ts @ColdByDefault
app/api/** @ColdByDefault
prisma/** @ColdByDefault
.github/\*\* @ColdByDefault
37 changes: 37 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Code of Conduct

## Our Pledge

This is the personal portfolio of **Yazan Abo-Ayash (ColdByDefault©)**. While contributions, issues, and discussions are welcome, all participants are expected to interact respectfully and professionally.

## Standards

**Acceptable behavior:**

- Constructive feedback and suggestions
- Respectful and professional communication
- Focusing on what benefits the project

**Unacceptable behavior:**

- Harassment, insults, or personal attacks
- Publishing private information without consent
- Spam, off-topic promotion, or disruptive conduct

## Scope

This Code of Conduct applies in all project spaces — GitHub Issues, Pull Requests, Discussions, and any related communication channels.

## Enforcement

Violations may result in comments being removed, issues being closed, or the offending account being blocked from the repository.

To report an issue, contact: **contact@coldbydefault.com**

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1.

---

_Copyright © 2026 ColdByDefault. All Rights Reserved._
7 changes: 3 additions & 4 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,10 @@ export default async function RootLayout({
href="https://generativelanguage.googleapis.com"
/>

{/* Structured Data */}
{/* Structured Data - JSON-LD for SEO rich snippets */}
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(structuredData),
}}
dangerouslySetInnerHTML={{ __html: JSON.stringify(structuredData) }}
/>
</head>
<body className={`${urbanist.variable} flex flex-col min-h-screen`}>
Expand All @@ -199,6 +197,7 @@ export default async function RootLayout({
defaultTheme="dark"
enableSystem
disableTransitionOnChange
scriptProps={{ type: "application/json" }}
>
<Navbar />
<main className="flex-1" id="main-content">
Expand Down
81 changes: 29 additions & 52 deletions components/cer/CertificationShowcaseDesktop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@
* @copyright 2026 ColdByDefault. All Rights Reserved.
*/

import React from "react";
import Image from "next/image";
import { Card, CardTitle } from "@/components/ui/card";
import { useTranslations } from "next-intl";
import { ImageZoomDialog } from "@/components/visuals";
import type { CertificationShowcaseLogic } from "@/components/cer/CertificationShowcase.logic";

interface Certification {
Expand Down Expand Up @@ -35,56 +31,37 @@ export function CertificationShowcaseDesktop({
const tDescriptions = useTranslations("Certifications.descriptions");
const tIssuers = useTranslations("Certifications.issuers");

const renderDesktopCard = (cert: Certification) => {
return (
<Card
key={cert.id}
className="px-3 py-4 h-full flex flex-col bg-background/80 backdrop-blur-sm border-border/50 shadow-lg hover:shadow-xl transition-all duration-300"
>
<CardTitle className="mb-3">
<h3 className="text-lg font-semibold text-center min-h-12 flex items-center justify-center">
{cert.title}
</h3>
</CardTitle>
<div className="flex w-full justify-center items-center pt-2 mb-4">
<ImageZoomDialog src={cert.image} alt={cert.title} title={cert.title}>
<Image
src={cert.image}
alt={cert.title}
width={400}
height={280}
className="object-cover rounded-md w-full max-w-100 h-70"
style={{ width: "100%", maxWidth: "400px", height: "280px" }}
priority={cert.id <= 4}
/>
</ImageZoomDialog>
</div>
<div className="flex-1 space-y-2">
<p className="text-sm">
{t("issuedBy")}{" "}
{cert.issuerKey ? tIssuers(cert.issuerKey) : cert.issuer}
</p>
<p className="text-sm text-gray-600 dark:text-gray-400">
{t("date")} {cert.date}
</p>
<p className="text-sm text-gray-700 dark:text-gray-300 leading-relaxed">
{tDescriptions(cert.descriptionKey)}
</p>
</div>
</Card>
);
};

return (
<section className={className} id="cert">
<Card className="max-w-7xl mx-auto bg-transparent dark:bg-transparent shadow-none border-0!">
<CardTitle className="text-3xl font-light sm:text-4xl text-center mb-8 text-black dark:text-white">
{t("title")}
</CardTitle>
<div className="z-40 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 items-start">
{certifications.map((cert) => renderDesktopCard(cert))}
</div>
</Card>
<h2 className="text-3xl font-light sm:text-4xl text-center mb-12 text-black dark:text-white">
{t("title")}
</h2>
<div className="max-w-6xl mx-auto grid grid-cols-2 gap-x-16 gap-y-12">
{certifications.map((cert, index) => (
<div
key={cert.id}
className="bg-background/80 backdrop-blur-sm rounded-xl border border-border/50 shadow-lg hover:shadow-xl hover:border-muted-foreground/30 transition-all duration-300 overflow-hidden group"
>
<div className="pl-5 border-l-2 border-foreground/20 group-hover:border-foreground/60 transition-colors duration-300 p-6">
<span className="text-5xl font-bold text-foreground/8 select-none leading-none block mb-3">
{String(index + 1).padStart(2, "0")}
</span>
<h3 className="text-xl font-semibold mb-1 text-foreground">
{cert.title}
</h3>
<p className="text-sm text-muted-foreground mb-1">
{cert.issuerKey ? tIssuers(cert.issuerKey) : cert.issuer}
</p>
<p className="text-xs text-muted-foreground/60 mb-3 font-mono">
{cert.date}
</p>
<p className="text-sm text-foreground/75 leading-relaxed">
{tDescriptions(cert.descriptionKey)}
</p>
</div>
</div>
))}
</div>
</section>
);
}
Loading
Loading