Skip to content
Open
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
39 changes: 39 additions & 0 deletions assets/css/tailwind.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

/* Preflight is disabled in tailwind.config.ts so existing SCSS pages keep
their styling. The new (Tailwind) routes opt into a clean baseline via the
`.tw` wrapper applied at the page root. */
.tw *,
.tw *::before,
.tw *::after {
box-sizing: border-box;
}

.tw {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

.tw h1,
.tw h2,
.tw h3,
.tw h4,
.tw p,
.tw ul,
.tw ol,
.tw figure {
margin: 0;
padding: 0;
}

.tw ul,
.tw ol {
list-style: none;
}

.tw a {
text-decoration: none;
color: inherit;
}
1 change: 1 addition & 0 deletions components/AppFooter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<NuxtLink to="/">Overview</NuxtLink>
<NuxtLink to="/experience/">Experience</NuxtLink>
<NuxtLink to="/projects">Projects</NuxtLink>
<NuxtLink to="/freelance">Freelance</NuxtLink>
<NuxtLink to="/contact">Contact</NuxtLink>
</div>
<span>Designed & Built with <MdiIcon icon="mdiHeart" /> by <a href="https://linkedin.com/in/deveci96">Mehmet Deveci</a></span>
Expand Down
1 change: 1 addition & 0 deletions components/AppHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<NuxtLink to="/" exact>Overview</NuxtLink>
<NuxtLink to="/experience" :class="{ 'router-link-active': route.path.startsWith('/experience') }">Experience</NuxtLink>
<NuxtLink to="/projects" :class="{ 'router-link-active': route.path.startsWith('/projects') }">Projects</NuxtLink>
<NuxtLink to="/freelance" :class="{ 'router-link-active': route.path.startsWith('/freelance') }">Freelance</NuxtLink>
<!-- <NuxtLink to="/blog">Blog</NuxtLink> -->
<NuxtLink to="/contact" exact>Contact</NuxtLink>
<!-- Add loading="lazy" and optimize rendering priority -->
Expand Down
49 changes: 49 additions & 0 deletions components/freelance/FreelanceCta.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<template>
<section class="relative px-5 pb-28 pt-10">
<div class="mx-auto max-w-5xl">
<div class="relative overflow-hidden rounded-3xl border border-brand/30 bg-navy-soft px-6 py-16 text-center sm:px-12">
<div class="pointer-events-none absolute inset-0 -z-10">
<div class="absolute left-1/2 top-0 h-72 w-[560px] max-w-full -translate-x-1/2 rounded-full bg-brand/20 blur-[120px]" />
<div class="absolute inset-0 bg-[linear-gradient(to_right,#1a1f3c_1px,transparent_1px),linear-gradient(to_bottom,#1a1f3c_1px,transparent_1px)] bg-[size:48px_48px] opacity-20" />
</div>

<h2 class="mx-auto max-w-2xl font-display text-4xl font-black tracking-tight sm:text-5xl">
Have a project in mind?
</h2>
<p class="mx-auto mt-4 max-w-xl text-lg text-cloud">
Tell me what you're building. I'll reply with how I can help, an honest estimate, and how reporting will work — usually
within a day.
</p>

<div class="mt-9 flex flex-wrap items-center justify-center gap-4">
<NuxtLink
to="/contact?intent=freelance"
class="group inline-flex items-center gap-2 rounded-md bg-brand px-7 py-3.5 font-display text-lg font-bold text-navy shadow-brand transition-all hover:-translate-x-0.5 hover:-translate-y-0.5 hover:bg-brand-hover hover:shadow-brand-lg"
>
Start a conversation
<MdiIcon icon="mdiArrowRight" class="h-5 w-5 transition-transform group-hover:translate-x-1" />
</NuxtLink>
<a
href="mailto:deveci2024@gmail.com?subject=Freelance%20project%20inquiry"
class="inline-flex items-center gap-2 rounded-md border border-hair bg-white/5 px-7 py-3.5 font-display text-lg font-bold text-white transition-colors hover:border-brand/60 hover:text-brand"
>
<MdiIcon icon="mdiEmailOutline" class="h-5 w-5" />
deveci2024@gmail.com
</a>
</div>

<div class="mt-8 flex items-center justify-center gap-5 text-2xl text-slatey">
<a rel="noopener noreferrer" target="_blank" href="https://www.linkedin.com/in/deveci96/" aria-label="LinkedIn" class="transition-colors hover:text-brand">
<MdiIcon icon="mdiLinkedin" />
</a>
<a rel="noopener noreferrer" target="_blank" href="https://x.com/volcanioo" aria-label="X" class="transition-colors hover:text-brand">
<MdiIcon icon="mdiTwitter" />
</a>
<a rel="noopener noreferrer" target="_blank" href="https://github.com/volcanioo" aria-label="GitHub" class="transition-colors hover:text-brand">
<MdiIcon icon="mdiGithub" />
</a>
</div>
</div>
</div>
</section>
</template>
71 changes: 71 additions & 0 deletions components/freelance/FreelanceEngagement.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<template>
<section id="engagement" class="relative px-5 py-24">
<div class="absolute inset-x-0 top-0 -z-10 h-px bg-gradient-to-r from-transparent via-hair to-transparent" />
<div class="mx-auto max-w-6xl">
<header class="max-w-2xl">
<p class="font-display text-sm font-bold uppercase tracking-[0.2em] text-brand">How we work together</p>
<h2 class="mt-3 font-display text-4xl font-black tracking-tight sm:text-5xl">Engagement models</h2>
<p class="mt-4 text-lg text-cloud">
Flexible ways to collaborate — every model comes with the same transparent, Toggl-based time reporting.
</p>
</header>

<div class="mt-12 grid grid-cols-1 gap-5 md:grid-cols-3">
<article
v-for="model in models"
:key="model.name"
class="relative flex flex-col rounded-2xl border p-7 transition-all duration-300"
:class="model.featured ? 'border-brand/60 bg-navy-soft shadow-glow' : 'border-hair bg-navy-soft/50 hover:border-brand/40'"
>
<span
v-if="model.featured"
class="absolute right-6 top-6 rounded-full bg-brand px-3 py-1 text-xs font-bold text-navy"
>
Most popular
</span>
<span class="inline-flex h-11 w-11 items-center justify-center rounded-xl bg-brand/15 text-brand ring-1 ring-brand/30">
<MdiIcon :icon="model.icon" class="h-6 w-6" />
</span>
<h3 class="mt-5 font-display text-2xl font-bold text-white">{{ model.name }}</h3>
<p class="mt-2 text-[15px] leading-relaxed text-cloud">{{ model.desc }}</p>
<p class="mt-5 font-display text-sm font-semibold text-brand">{{ model.best }}</p>
<ul class="mt-4 space-y-2.5 border-t border-hair pt-5">
<li v-for="point in model.points" :key="point" class="flex items-start gap-2.5 text-[15px] text-cloud">
<MdiIcon icon="mdiCheckCircle" class="mt-0.5 h-5 w-5 shrink-0 text-brand" />
<span>{{ point }}</span>
</li>
</ul>
</article>
</div>
</div>
</section>
</template>

<script setup lang="ts">
const models = [
{
name: 'Hourly',
icon: 'mdiClockOutline',
desc: 'Pay for exactly the time you use, tracked to the minute in Toggl.',
best: 'Best for: ongoing support & small fixes',
points: ['Detailed daily time entries', 'No minimum commitment', 'Weekly summary report'],
featured: false
},
{
name: 'Project-based',
icon: 'mdiRocketLaunchOutline',
desc: 'A fixed scope with a clear deliverable, milestones, and a transparent estimate.',
best: 'Best for: defined features & MVPs',
points: ['Milestone-based delivery', 'Scoped estimate up front', 'Hours still reported in full'],
featured: true
},
{
name: 'Retainer',
icon: 'mdiCalendarCheckOutline',
desc: 'A reserved block of hours each month so I can act as your embedded engineer.',
best: 'Best for: long-term partnerships',
points: ['Priority availability', 'Monthly Toggl breakdown', 'Discounted blended rate'],
featured: false
}
];
</script>
65 changes: 65 additions & 0 deletions components/freelance/FreelanceHero.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<template>
<section class="relative isolate min-h-[92vh] flex items-center px-5 pt-28 pb-20">
<!-- Background grid + glow -->
<div class="pointer-events-none absolute inset-0 -z-10">
<div class="absolute inset-0 bg-[linear-gradient(to_right,#1a1f3c_1px,transparent_1px),linear-gradient(to_bottom,#1a1f3c_1px,transparent_1px)] bg-[size:64px_64px] opacity-40" />
<div class="absolute inset-0 bg-grid-fade" />
<div class="absolute left-1/2 top-24 h-[420px] w-[680px] max-w-[90vw] -translate-x-1/2 rounded-full bg-brand/20 blur-[120px]" />
</div>

<div class="mx-auto w-full max-w-6xl">
<span class="inline-flex items-center gap-2 rounded-full border border-brand/40 bg-brand/10 px-4 py-1.5 text-sm font-medium text-brand animate-fade-up">
<span class="relative flex h-2.5 w-2.5">
<span class="absolute inline-flex h-full w-full animate-ping rounded-full bg-brand opacity-75" />
<span class="relative inline-flex h-2.5 w-2.5 rounded-full bg-brand" />
</span>
Available for freelance &amp; contract work
</span>

<h1 class="mt-7 max-w-4xl font-display text-5xl font-black leading-[1.05] tracking-tight sm:text-6xl lg:text-7xl animate-fade-up" style="animation-delay: 0.08s">
Ship faster with a
<span class="bg-brand-gradient bg-clip-text text-transparent">senior product engineer</span>
who reports every hour.
</h1>

<p class="mt-6 max-w-2xl text-lg leading-relaxed text-cloud animate-fade-up sm:text-xl" style="animation-delay: 0.16s">
I'm Mehmet — 10+ years building web products end to end, from frontend architecture to backend microservices and AI.
I take on freelance projects and contracts with <span class="text-white">radical transparency</span>:
you see exactly what I work on, when, and for how long.
</p>

<div class="mt-9 flex flex-wrap items-center gap-4 animate-fade-up" style="animation-delay: 0.24s">
<NuxtLink
to="/contact?intent=freelance"
class="group inline-flex items-center gap-2 rounded-md bg-brand px-6 py-3 font-display text-lg font-bold text-navy shadow-brand transition-all hover:-translate-x-0.5 hover:-translate-y-0.5 hover:bg-brand-hover hover:shadow-brand-lg"
>
Start a project
<MdiIcon icon="mdiArrowRight" class="h-5 w-5 transition-transform group-hover:translate-x-1" />
</NuxtLink>
<a
href="#reporting"
class="inline-flex items-center gap-2 rounded-md border border-hair bg-white/5 px-6 py-3 font-display text-lg font-bold text-white transition-colors hover:border-brand/60 hover:text-brand"
>
See how I report time
</a>
</div>

<!-- Trust stats -->
<dl class="mt-14 grid max-w-2xl grid-cols-2 gap-6 sm:grid-cols-4 animate-fade-up" style="animation-delay: 0.32s">
<div v-for="stat in stats" :key="stat.label">
<dt class="font-display text-3xl font-black text-white sm:text-4xl">{{ stat.value }}</dt>
<dd class="mt-1 text-sm text-slatey">{{ stat.label }}</dd>
</div>
</dl>
</div>
</section>
</template>

<script setup lang="ts">
const stats = [
{ value: '10+', label: 'Years of experience' },
{ value: '6', label: 'Industries shipped in' },
{ value: '150+', label: 'Collaborators worldwide' },
{ value: '100%', label: 'Transparent hours' }
];
</script>
37 changes: 37 additions & 0 deletions components/freelance/FreelanceProcess.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<template>
<section id="process" class="relative px-5 py-24">
<div class="mx-auto max-w-6xl">
<header class="max-w-2xl">
<p class="font-display text-sm font-bold uppercase tracking-[0.2em] text-brand">The process</p>
<h2 class="mt-3 font-display text-4xl font-black tracking-tight sm:text-5xl">How an engagement runs</h2>
<p class="mt-4 text-lg text-cloud">A simple, predictable path from first message to shipped work.</p>
</header>

<ol class="mt-14 grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4">
<li
v-for="(step, i) in steps"
:key="step.title"
class="relative rounded-2xl border border-hair bg-navy-soft/50 p-6 transition-colors hover:border-brand/40"
>
<span class="font-display text-5xl font-black text-brand/25">0{{ i + 1 }}</span>
<h3 class="mt-3 font-display text-lg font-bold text-white">{{ step.title }}</h3>
<p class="mt-2 text-[15px] leading-relaxed text-cloud">{{ step.desc }}</p>
<MdiIcon
v-if="i < steps.length - 1"
icon="mdiArrowRight"
class="absolute -right-3 top-1/2 hidden h-6 w-6 -translate-y-1/2 text-hair lg:block"
/>
</li>
</ol>
</div>
</section>
</template>

<script setup lang="ts">
const steps = [
{ title: 'Discovery call', desc: 'A free call to understand your goals, scope, timeline, and constraints.' },
{ title: 'Proposal & estimate', desc: 'A clear plan with an engagement model, milestones, and a transparent time estimate.' },
{ title: 'Build with reports', desc: 'I ship in iterations and send Toggl-backed time reports on your chosen cadence.' },
{ title: 'Delivery & handover', desc: 'Reviewed, tested code with documentation — plus optional ongoing support.' }
];
</script>
91 changes: 91 additions & 0 deletions components/freelance/FreelanceServices.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<template>
<section id="services" class="relative px-5 py-24">
<div class="mx-auto max-w-6xl">
<header class="max-w-2xl">
<p class="font-display text-sm font-bold uppercase tracking-[0.2em] text-brand">What I do</p>
<h2 class="mt-3 font-display text-4xl font-black tracking-tight sm:text-5xl">
Services I offer as a freelancer
</h2>
<p class="mt-4 text-lg text-cloud">
Full-stack capability across the whole product lifecycle. Bring me in for a single feature, a focused sprint, or as an
embedded contractor on your team.
</p>
</header>

<div class="mt-12 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
<article
v-for="(service, i) in services"
:key="service.title"
class="group relative overflow-hidden rounded-2xl border border-hair bg-navy-soft/60 p-7 transition-all duration-300 hover:border-brand/50 hover:bg-navy-soft"
:class="service.span"
>
<div class="absolute -right-10 -top-10 h-32 w-32 rounded-full bg-brand/10 blur-2xl opacity-0 transition-opacity duration-300 group-hover:opacity-100" />
<div class="relative">
<span class="inline-flex h-12 w-12 items-center justify-center rounded-xl bg-brand/15 text-brand ring-1 ring-brand/30">
<MdiIcon :icon="service.icon" class="h-6 w-6" />
</span>
<h3 class="mt-5 font-display text-xl font-bold text-white">{{ service.title }}</h3>
<p class="mt-2 text-[15px] leading-relaxed text-cloud">{{ service.desc }}</p>
<ul v-if="service.tags" class="mt-4 flex flex-wrap gap-2">
<li
v-for="tag in service.tags"
:key="tag"
class="rounded-full border border-hair bg-white/5 px-3 py-1 text-xs font-medium text-slatey"
>
{{ tag }}
</li>
</ul>
</div>
<span class="sr-only">{{ i }}</span>
</article>
</div>
</div>
</section>
</template>

<script setup lang="ts">
const services = [
{
title: 'Frontend architecture',
icon: 'mdiVuejs',
desc: 'Scalable Vue/Nuxt & React apps, design systems, and component libraries built for maintainability and speed.',
tags: ['Vue 3', 'Nuxt', 'React', 'TypeScript'],
span: 'lg:col-span-2'
},
{
title: 'AI integration',
icon: 'mdiRobotOutline',
desc: 'Bring LLMs and AI-assisted workflows into your product and your engineering process — practically and safely.',
tags: ['LLMs', 'RAG', 'Tooling'],
span: ''
},
{
title: 'Full-stack delivery',
icon: 'mdiLayersTriple',
desc: 'End-to-end features across Java Spring Boot microservices, Node.js, and modern frontends.',
tags: ['Spring Boot', 'Node.js', 'REST'],
span: ''
},
{
title: 'Performance & observability',
icon: 'mdiSpeedometer',
desc: 'Audits, Core Web Vitals work, Datadog/Grafana tracing and structured logging for real production visibility.',
tags: ['Web Vitals', 'Datadog', 'Grafana'],
span: 'lg:col-span-2'
},
{
title: 'Infrastructure as Code',
icon: 'mdiTerraform',
desc: 'Terraform + AWS/Cloudflare pipelines, CI/CD, and cost-efficient hosting for static and dynamic apps.',
tags: ['Terraform', 'AWS', 'Cloudflare', 'CI/CD'],
span: 'lg:col-span-2'
},
{
title: 'Technical leadership',
icon: 'mdiAccountGroupOutline',
desc: 'RFCs, code reviews, mentorship, and migration planning to level up your team while we ship.',
tags: ['RFCs', 'Mentorship', 'Reviews'],
span: ''
}
];
</script>
Loading
Loading