Skip to content

Commit a74b079

Browse files
feat: add site manifest route and SEO schema component
- Implemented a new route for serving the web app manifest. - Created a new component for generating structured SEO schema data. - Added capabilities content for various technical skills and services. - Developed bilingual "About" and "Contact" pages in English and Turkish. - Introduced a custom hook for internationalization (i18n) support. - Added translations for navigation, sections, and UI elements in both languages. - Enhanced SEO functionalities with utility functions for metadata generation.
1 parent a084890 commit a74b079

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+9544
-1891
lines changed

.hintrc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"extends": [
3+
"development"
4+
],
5+
"hints": {
6+
"axe/aria": [
7+
"default",
8+
{
9+
"aria-valid-attr-value": "off"
10+
}
11+
]
12+
}
13+
}

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,39 @@ Validate content:
4040
npm run validate-content
4141
```
4242

43+
## Languages (TR / EN)
44+
45+
Translations live here:
46+
47+
```
48+
src/i18n/translations.ts
49+
```
50+
51+
Markdown pages are per-language:
52+
53+
```
54+
src/content/pages/about.tr.md
55+
src/content/pages/about.en.md
56+
src/content/pages/contact.tr.md
57+
src/content/pages/contact.en.md
58+
src/content/pages/title.tr.md
59+
src/content/pages/title.en.md
60+
```
61+
62+
Projects and profile content are localized inside:
63+
64+
```
65+
src/content/profile.ts
66+
src/content/projects.ts
67+
```
68+
69+
To add a new language:
70+
1) Extend `Language` in `src/lib/i18n.ts`.
71+
2) Add translations in `src/i18n/translations.ts`.
72+
3) Add `*.md` pages for the new language.
73+
74+
Language toggle writes to localStorage + cookie and also updates `?lang=tr|en`.
75+
4376
## 3D Model (GLB)
4477

4578
Place the model here:
@@ -115,3 +148,12 @@ firebase emulators:start
115148
```
116149

117150
Note: `max-instances` caps cost.
151+
152+
## SEO Checklist
153+
154+
- Verify domain in Google Search Console (DNS).
155+
- Submit the sitemap (`/sitemap.xml`).
156+
- Check indexing with `site:your-domain`.
157+
- Validate canonical + hreflang tags.
158+
- Test structured data with Google Rich Results / Schema validator.
159+
- For preview/staging set `NEXT_PUBLIC_NO_INDEX=1` to prevent indexing.

eslint.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const eslintConfig = defineConfig([
1212
"out/**",
1313
"build/**",
1414
"next-env.d.ts",
15+
".history/**",
1516
]),
1617
]);
1718

middleware.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import type { NextRequest } from "next/server";
2+
import { NextResponse } from "next/server";
3+
4+
const SUPPORTED = ["tr", "en"] as const;
5+
6+
export function middleware(request: NextRequest) {
7+
const { pathname } = request.nextUrl;
8+
9+
if (pathname.startsWith("/_next") || pathname.startsWith("/api")) {
10+
return NextResponse.next();
11+
}
12+
13+
const match = pathname.match(/^\/(tr|en)(\/.*)?$/);
14+
if (match) {
15+
const lang = match[1];
16+
const rest = match[2] ?? "/";
17+
const url = request.nextUrl.clone();
18+
url.pathname = rest === "" ? "/" : rest;
19+
url.searchParams.set("lang", lang);
20+
const response = NextResponse.rewrite(url);
21+
response.cookies.set("lang", lang, {
22+
path: "/",
23+
maxAge: 60 * 60 * 24 * 365,
24+
sameSite: "lax",
25+
});
26+
return response;
27+
}
28+
29+
const langCookie = request.cookies.get("lang")?.value;
30+
if (!langCookie || !SUPPORTED.includes(langCookie as typeof SUPPORTED[number])) {
31+
const response = NextResponse.next();
32+
response.cookies.set("lang", "en", {
33+
path: "/",
34+
maxAge: 60 * 60 * 24 * 365,
35+
sameSite: "lax",
36+
});
37+
return response;
38+
}
39+
40+
return NextResponse.next();
41+
}
42+
43+
export const config = {
44+
matcher: [
45+
"/((?!_next|api|favicon.ico|robots.txt|sitemap.xml|site.webmanifest|icon-192.png|icon-512.png|apple-icon.png|icon.png|og.png|og.svg).*)",
46+
],
47+
};

package-lock.json

Lines changed: 43 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"dependencies": {
1414
"@react-three/drei": "^10.7.7",
1515
"@react-three/fiber": "^9.5.0",
16+
"framer-motion": "^11.0.0",
1617
"next": "16.1.5",
1718
"react": "19.2.3",
1819
"react-dom": "19.2.3",

public/icon-192.png

7.25 KB
Loading

public/icon-512.png

11.9 KB
Loading

public/models/computer.glb

7.44 MB
Binary file not shown.

public/og.png

-24.2 KB
Loading

0 commit comments

Comments
 (0)