Goal
Create Hero: the first viewport of the portfolio: role label, headline, short bio, two CTAs, and a circular portrait.
Hero.jsx
function Hero() {
return (
<section
id="about"
className="mx-auto flex max-w-5xl flex-col items-center gap-10 px-6 py-20 md:flex-row"
>
<div className="flex-1">
<p className="mb-3 text-sm font-medium uppercase tracking-wide text-slate-600 dark:text-slate-400">
Software Engineer
</p>
<h1 className="mb-4 text-4xl font-bold text-slate-900 dark:text-slate-100 md:text-5xl">
Building clean interfaces and solid APIs
</h1>
<p className="mb-8 text-lg leading-relaxed text-slate-600 dark:text-slate-400">
I care about readable code, thoughtful UX, and shipping work that
lasts.
</p>
<div className="flex flex-wrap gap-3">
<a
href="#projects"
className="rounded-md bg-blue-600 px-5 py-3 text-sm font-semibold text-white hover:bg-blue-700"
>
View projects
</a>
<a
href="#contact"
className="rounded-md border border-slate-300 bg-white px-5 py-3 text-sm font-semibold text-slate-700 transition hover:bg-slate-100 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100 dark:hover:bg-slate-800"
>
Get in touch
</a>
</div>
</div>
<div className="flex shrink-0 items-center justify-center">
<img
src="https://avatars.githubusercontent.com/u/196466915?s=400&v=4"
alt="Portrait"
className="h-56 w-56 rounded-full object-cover shadow-lg ring-4 ring-blue-100 dark:ring-slate-700"
/>
</div>
</section>
);
}
export default Hero;
Replace the image src, headline, and bio with your own.
Tailwind chunks explained: section layout
| Class |
Meaning |
id="about" |
Target for navbar #about links |
mx-auto |
Center the section in the page |
flex |
Flex container |
max-w-5xl |
Same content width as the navbar |
flex-col |
Stack text above image on mobile |
items-center |
Center items on the cross axis |
gap-10 |
Large space between text block and image |
px-6 |
Side padding |
py-20 |
Tall vertical padding for a hero feel |
md:flex-row |
From md up: text and image sit side by side |
flex-1 |
Let the text column grow and take remaining space |
shrink-0 |
Keep the image from squashing in a row layout |
Tailwind chunks explained: typography
| Class |
Meaning |
mb-3 / mb-4 / mb-8 |
Spacing between text blocks |
text-sm |
Small eyebrow / role label |
font-medium / font-bold / font-semibold |
Weight hierarchy |
uppercase |
All-caps role label |
tracking-wide |
Slightly wider letter spacing |
text-4xl |
Large headline on phones |
md:text-5xl |
Bigger headline from tablet up |
text-lg |
Comfortable bio size |
leading-relaxed |
Looser line height for reading |
text-slate-600 / dark:text-slate-400 |
Muted body copy in both themes |
text-slate-900 / dark:text-slate-100 |
Strong headline colors |
Tailwind chunks explained: CTAs
| Class |
Meaning |
flex flex-wrap gap-3 |
Button row that wraps on narrow screens |
rounded-md |
Soft corners on both buttons |
bg-blue-600 / hover:bg-blue-700 |
Primary solid CTA |
px-5 py-3 |
Comfortable click / tap target |
border border-slate-300 |
Outline secondary button |
bg-white + dark variants |
Secondary style that works in both themes |
transition |
Smooth hover background change |
Tailwind chunks explained: avatar
| Class |
Meaning |
h-56 w-56 |
Fixed square size (14rem) |
rounded-full |
Circle crop |
object-cover |
Fill the circle without distortion |
shadow-lg |
Soft drop shadow |
ring-4 |
Thick outline ring around the image |
ring-blue-100 |
Soft blue ring in light mode |
dark:ring-slate-700 |
Neutral ring in dark mode |
Wire into App.jsx
import Navbar from "./components/Navbar";
import Hero from "./components/Hero";
function App() {
return (
<div className="min-h-screen bg-surface font-sans text-ink antialiased dark:bg-slate-950 dark:text-slate-100">
<Navbar />
<main>
<Hero />
</main>
</div>
);
}
export default App;
Check
Next: build the Skills grid.