diff --git a/content/projects/cs2-arbitrage-monitor.mdx b/content/projects/cs2-arbitrage-monitor.mdx
new file mode 100644
index 0000000..365a2a1
--- /dev/null
+++ b/content/projects/cs2-arbitrage-monitor.mdx
@@ -0,0 +1,44 @@
+---
+title: 'CS2 Arbitrage Monitor'
+description: 'A Python data pipeline that tracks completed-sale prices for CS2 skins across marketplaces and alerts on profitable spreads.'
+date: '2026-05-20'
+tags: ['python', 'data-pipeline', 'scraping', 'automation']
+featured: false
+category: Tools
+role: 'Solo project'
+cover: '/projects/cs2-arbitrage-monitor.svg'
+---
+
+Skin prices for the same CS2 item can differ noticeably between Steam and other
+skin marketplaces, but spotting the gap by hand means watching several tabs at
+once. I built a data pipeline that watches for me and pings a Discord channel
+when a real arbitrage window opens.
+
+The system runs in four stages. **Connectors** pull data per marketplace — a mix
+of scrapers and official API feeds. A **sales price engine** normalizes item
+names, deduplicates records, and stores historical prices. A **matcher** applies
+configurable spread rules to find items priced apart across venues. **Alerts**
+post an embed card to Discord with the item, per-marketplace sale prices and
+timestamps, the absolute and percentage spread, and links to each listing.
+
+## Stack
+
+- **Python** — connectors, the price engine, and the matcher
+- **Per-marketplace connectors** — scraping for some venues, official APIs for others
+- **Storage layer with migrations** — historical completed-sale prices
+- **Declarative rule files** in `src/rules/` — minimum spread, item filters, cooldowns
+- **Discord webhook** — embed-card alerts to a single channel
+
+## Interesting decisions
+
+I track **completed-sale prices** — realized transactions — rather than
+listing or asking prices. What a seller hopes to get is not what an item is
+worth; only closed sales give an honest arbitrage signal.
+
+Detection logic lives in **declarative rule files**, not code. Spread
+thresholds, item filters, and cooldowns are all config, so I can tune what
+counts as an opportunity without editing the pipeline.
+
+The whole thing is compliance-first: it respects each platform's terms of
+service, robots.txt, and rate limits, collects only public completed-sale data,
+and performs no automated purchasing or trading.
diff --git a/content/projects/esmer-market-accounting.mdx b/content/projects/esmer-market-accounting.mdx
new file mode 100644
index 0000000..45d35e6
--- /dev/null
+++ b/content/projects/esmer-market-accounting.mdx
@@ -0,0 +1,39 @@
+---
+title: 'Esmer Market Accounting'
+description: 'A unified inventory, invoicing, and accounting system for a family Turkish grocery, shipped as both a web app and a Windows desktop app.'
+date: '2026-05-15'
+tags: ['react', 'node', 'electron', 'sql-server']
+featured: false
+category: Desktop
+role: 'Solo project'
+cover: '/projects/esmer-market-accounting.svg'
+---
+
+Our family grocery kept stock counts, invoices, and the books in separate
+places that never reconciled on their own. Esmer Market Accounting folds all of
+it into one Turkish-language system a non-technical shop can run at the counter.
+
+Four modules. Inventory tracks products, SKUs, categories, suppliers, and stock
+transactions. Invoicing takes manual entry plus PDF and image uploads, running
+OCR extraction into a status-tracked document archive. Accounting
+does multi-currency bookkeeping (TRY/USD/EUR with exchange rates), VAT
+reporting, P&L, balance sheet, and cash flow. Analytics rolls it up into
+dashboard KPIs and revenue and profit trends. Access is split across admin,
+accountant, and cashier roles.
+
+## Stack
+
+- **React 18 + React Router** — Tailwind, Bootstrap, React Query, i18next (Turkish)
+- **Node.js + Express** — JWT auth, Joi validation, Winston logging, Multer uploads
+- **Microsoft SQL Server** — raw `mssql` driver over a Turkish schema (STOK, FIS, CARI)
+- **Electron + electron-builder** — packaged as an NSIS installer and portable build
+
+## Interesting decisions
+
+- I dropped the ORM and wrote raw SQL over the `mssql` driver. The schema is
+ Turkish-named (STOK for products, FIS/FIS_DETAY for invoices, CARI for
+ customers), and direct queries kept full control over how SQL Server was hit.
+- One React/Express codebase ships two ways: a web app, and a packaged Windows
+ desktop app so the shop can install and run it locally on the counter machine.
+- Multi-currency accounting with exchange rates, plus OCR on uploaded
+ invoices so paper documents land straight in the archive.
diff --git a/content/projects/esmer-market-website.mdx b/content/projects/esmer-market-website.mdx
new file mode 100644
index 0000000..61968c8
--- /dev/null
+++ b/content/projects/esmer-market-website.mdx
@@ -0,0 +1,35 @@
+---
+title: 'Esmer Market'
+description: 'The official site for my family grocery store in Northern Cyprus — Turkish-first, statically exported, with client-side Firebase for reviews and campaigns.'
+date: '2026-06-10'
+tags: ['nextjs', 'react', 'typescript', 'firebase', 'i18n']
+featured: false
+category: Web
+role: 'Solo project'
+cover: '/projects/esmer-market-website.svg'
+---
+
+Esmer Market is my family's local grocery store in Yeni Boğaziçi, Gazimağusa,
+Northern Cyprus. I built the store its own website so regulars can check
+campaigns, leave reviews, and find us without going through a social feed.
+
+The site covers the essentials: home, about, contact, a gallery, a store map
+for the location, customer reviews, and the usual privacy and terms pages, plus
+an admin login for managing content. It reads Turkish-first, with English as the
+secondary language.
+
+## Stack
+
+- **Next.js 15 (App Router, `output: 'export'`)** + **React 19** + **TypeScript**
+- **Tailwind CSS v4** with **shadcn/ui** (new-york style)
+- **Firebase** — Firestore + Auth, client-side only, for reviews and campaigns
+- **i18next / react-i18next** — Turkish default, English secondary
+- **Framer Motion** for transitions; deployed static on **Netlify**
+
+## Interesting decisions
+
+The whole site ships as a static export, yet it's still dynamic where it counts:
+Firebase runs entirely client-side, so reviews and campaigns update live without
+any server to host. The one non-static piece is the contact form — a Netlify
+serverless function using nodemailer and reCAPTCHA v3, which keeps spam out and
+email credentials off the client without standing up a backend.
diff --git a/content/projects/event-management-system.mdx b/content/projects/event-management-system.mdx
new file mode 100644
index 0000000..f6ff2b5
--- /dev/null
+++ b/content/projects/event-management-system.mdx
@@ -0,0 +1,38 @@
+---
+title: 'Event Management System'
+description: 'A multi-tenant app for hotel staff to schedule and track events across rooms and venues, backed by one PostgreSQL database.'
+date: '2026-06-15'
+tags: ['react', 'node', 'postgres', 'prisma', 'auth0']
+featured: false
+category: Web
+role: 'Solo project'
+cover: '/projects/event-management-system.svg'
+---
+
+Hotel staff were juggling weddings, conferences, and private parties across
+rooms and venues, with double-bookings a constant risk. I built a single app
+that puts every event on one shared calendar and keeps one hotel's data walled
+off from the next.
+
+The frontend is a React calendar with month, week, and day views, color-coded by
+category, plus revenue, occupancy, and peak-time charts. Behind it, an Express
+API talks to PostgreSQL through Prisma, with Auth0 handling sign-in and Winston
+recording what happened.
+
+## Stack
+
+- **React 18 + React Router** — SPA with React Big Calendar and Recharts
+- **Node.js / Express + Prisma** — REST API over one PostgreSQL database
+- **Auth0** — authentication with JWT validation on every request
+- **Helmet, CORS, rate limiting, input sanitization** — baseline hardening
+- **Electron + PM2 / Nginx** — desktop wrapper and production process management
+
+## Interesting decisions
+
+**Multi-tenant with three-tier RBAC.** Every row is scoped to a hotel, and roles
+run Super Admin, Hotel Admin, and User. A hotel admin only ever queries their own
+hotel's events — isolation lives in the data layer, not the UI.
+
+**Soft-delete over hard-delete.** Cancelled events are flagged, never dropped, so
+there is always an audit trail. The same booking data feeds automatic conflict
+detection, which flags two events fighting over the same room before they save.
diff --git a/public/projects/cs2-arbitrage-monitor.svg b/public/projects/cs2-arbitrage-monitor.svg
new file mode 100644
index 0000000..7709043
--- /dev/null
+++ b/public/projects/cs2-arbitrage-monitor.svg
@@ -0,0 +1,103 @@
+
diff --git a/public/projects/esmer-market-accounting.svg b/public/projects/esmer-market-accounting.svg
new file mode 100644
index 0000000..8b0c020
--- /dev/null
+++ b/public/projects/esmer-market-accounting.svg
@@ -0,0 +1,119 @@
+
diff --git a/public/projects/esmer-market-website.svg b/public/projects/esmer-market-website.svg
new file mode 100644
index 0000000..ad7c9ac
--- /dev/null
+++ b/public/projects/esmer-market-website.svg
@@ -0,0 +1,91 @@
+
diff --git a/public/projects/event-management-system.svg b/public/projects/event-management-system.svg
new file mode 100644
index 0000000..35df11d
--- /dev/null
+++ b/public/projects/event-management-system.svg
@@ -0,0 +1,116 @@
+
diff --git a/src/app/apple-icon.png b/src/app/apple-icon.png
new file mode 100644
index 0000000..a5d42b7
Binary files /dev/null and b/src/app/apple-icon.png differ
diff --git a/src/app/icon.svg b/src/app/icon.svg
new file mode 100644
index 0000000..db52568
--- /dev/null
+++ b/src/app/icon.svg
@@ -0,0 +1,8 @@
+