π Hey! I'm Dhruv Sheladiya, a Full Stack Developer working with the MERN Stack, React.js, Next.js & Node.js.
This is the story of how I found out my own portfolio was basically invisible, and the 5 fixes that changed that.
π¬ The Embarrassing Discovery
I Googled my own name. Here's what I found:
| What I expected | What actually happened |
|---|---|
| β My portfolio at the top | β Barely showing up |
| β A nice preview image | β No image at all |
| β ChatGPT knows who I am | β "I don't have information about that person" |
The site looked perfect in the browser. So what was going on? π€
π΅οΈ The Root Cause: A Beautiful Page That Crawlers Saw as Empty
My portfolio has a cool animated loader, and the homepage is a client component:
"use client";
export default function Home() {
const [showLoader, setShowLoader] = useState(true);
return showLoader
? <Loader onComplete={() => setShowLoader(false)} />
: <MainContent />;
}
For real users? Totally fine. π
For crawlers? The HTML only contains the loader. No name. No heading. No links. π
| Visitor | Runs JavaScript? | What it saw |
|---|---|---|
| π§ Real user | β Yes | Full animated portfolio |
| π€ Googlebot | β οΈ Sometimes, slowly | Maybe the content, maybe just the loader |
| π§ AI crawlers (ChatGPT, Perplexity) | β Mostly no | An empty page |
π‘ Lesson #1: Always check your page without JavaScript.
Runcurl https://your-site.comor right-click β View Page Source.
If your name isn't in there, crawlers probably can't see it either.
π οΈ Fix #1: Server-Render the Important Content
I didn't want to touch the UI, so I added a small, accessible profile block in layout.js, which is a Server Component.
Tailwind's sr-only class makes it readable by screen readers and crawlers, but it doesn't change the design at all:
<body>
<div className="sr-only">
<h1>Dhruv Sheladiya β Full Stack Developer | MERN Stack | React.js Next.js & Node.js Expert</h1>
<p>Full Stack Developer from India specializing in React.js, Next.js and Node.js.</p>
<nav aria-label="Dhruv Sheladiya on the web">
<ul>
{SOCIALS.map((s) => (
<li key={s.href}>
<a href={s.href} rel="me noopener">Dhruv Sheladiya on {s.label}</a>
</li>
))}
</ul>
</nav>
</div>
{children}
</body>
β οΈ Important: Keep this content honest and identical to what's visible on the page.
β Hidden text stuffed with keywords = spam signal
β Accessible text that matches your real content = fine
π Fix #2: Structured Data That Connects All Your Profiles
Google builds a Knowledge Graph entry for people by connecting profiles that belong to the same person.
The sameAs property in JSON-LD tells Google exactly which profiles are yours π
const jsonLd = {
"@context": "https://schema.org",
"@graph": [
{
"@type": "Person",
"@id": "https://aboutdhruv.vercel.app/#person",
name: "Dhruv Sheladiya",
jobTitle: "Full Stack Developer",
url: "https://aboutdhruv.vercel.app",
sameAs: [
"https://www.upwork.com/freelancers/~0191c7eba12b27a044",
"https://www.linkedin.com/in/dhruv-sheladiya-a350582a6",
"https://github.com/Dhruv-1511",
"https://x.com/DhruvSheladiya2",
],
},
{
"@type": "ProfilePage",
url: "https://aboutdhruv.vercel.app",
mainEntity: { "@id": "https://aboutdhruv.vercel.app/#person" },
},
],
};
I also added <link rel="me"> tags in the <head> for every profile. GitHub and Mastodon use rel="me" for identity verification too. πͺͺ
π The secret sauce: this only works if it goes both ways.
Your site links to your profiles β‘οΈ and every profile (GitHub, LinkedIn, Upwork, Xβ¦) links back to your site β¬ οΈ
πΌοΈ Fix #3: My OG Image Was 1.7 MB π±
My openGraph config said the image was 1200Γ630, but the real file was:
| β Before | β After | |
|---|---|---|
| Size | 1629 Γ 966 | 1200 Γ 630 |
| Weight | 1.77 MB | 80 KB |
| Format | PNG | JPEG (mozjpeg) |
| Preview showing? | Nope | Yes π |
I fixed it with a single command using sharp, which already comes with Next.js:
node -e "require('sharp')('public/ogimg.png').resize(1200,630,{fit:'cover'}).jpeg({quality:82,mozjpeg:true}).toFile('public/og.jpg')"
π§ Did you know?
og:imageis for social previews (WhatsApp, LinkedIn, X).
Google doesn't use it for search thumbnails. It picks images from your page content and structured data, one more reason Fix #1 matters.
βοΈ Fix #4: Nail the Next.js Metadata Basics
export const metadata = {
metadataBase: new URL("https://aboutdhruv.vercel.app"),
title: "Dhruv Sheladiya β Full Stack Developer | MERN Stack | React.js Next.js & Node.js Expert",
alternates: { canonical: "/" },
openGraph: {
type: "profile",
images: [{ url: "/og.jpg", width: 1200, height: 630 }],
},
robots: {
index: true,
follow: true,
googleBot: { "max-image-preview": "large", "max-snippet": -1 },
},
};
| Rule | Why it matters |
|---|---|
| π₯ Name first in the title | People search your name, not your job title |
| π Same headline everywhere | My title matches my Upwork headline exactly, so search engines connect the dots |
| π― Canonical URL | Stops Google splitting ranking between duplicate URLs |
πΌοΈ max-image-preview: large
|
Allows large image previews in results |
π€ Fix #5: Add llms.txt for AI Assistants
llms.txt is a newer convention: a plain Markdown file at /llms.txt that summarizes your site for AI tools.
π Click to see what my llms.txt looks like
# Dhruv Sheladiya
> Dhruv Sheladiya is a Full Stack Developer from India β MERN Stack |
> React.js, Next.js & Node.js Expert.
Portfolio: https://aboutdhruv.vercel.app
## Skills
- Frontend: React.js, Next.js, JavaScript, TypeScript, Tailwind CSS
- Backend: Node.js, Express.js, REST APIs
- Databases: MongoDB, PostgreSQL
## Official profiles
- [Upwork](https://www.upwork.com/freelancers/~0191c7eba12b27a044)
- [LinkedIn](https://www.linkedin.com/in/dhruv-sheladiya-a350582a6)
- [GitHub](https://github.com/Dhruv-1511)
β±οΈ Takes 5 minutes. There's no downside.
β The Complete Checklist
- [ ] π View Page Source: is your name in the raw HTML?
- [ ] π§© JSON-LD
PersonwithsameAsfor all your profiles - [ ] π Every profile links back to your site
- [ ] πΌοΈ OG image is 1200Γ630 and under ~300 KB
- [ ] π₯ Name first in
<title>, same headline everywhere - [ ] πΊοΈ Submit your sitemap to Google Search Console and Bing Webmaster Tools (ChatGPT search relies heavily on Bing!)
- [ ] π§ͺ Test with Google's Rich Results Test
- [ ] π€ Add an
/llms.txt
π― Final Thoughts
SEO for your own name is slow: expect a few weeks before things move. β³
But the best part? None of this required changing a single pixel of my UI. π¨β¨
Here's the live result π
π¨βπ» About Me
Hi, I'm Dhruv Sheladiya, a Full Stack Developer π building fast, scalable web apps & SaaS products with clean UI/UX, from frontend to backend.
| π Portfolio | aboutdhruv.vercel.app |
| πΌ Upwork | Hire me for freelance projects |
| π LinkedIn | Dhruv Sheladiya |
| π» GitHub | @Dhruv-1511 |
| π¦ X | @DhruvSheladiya2 |
π¬ Your turn: open View Page Source on your portfolio right now. What did you find? Tell me in the comments π
β€οΈ If this helped, drop a reaction and follow me for more Next.js & React content!
Top comments (2)
The
sr-onlyprofile block gets your name and profile links into the initial HTML, and the reciprocal profile links givesameAsa stronger identity signal. I'd take the next step and server-render the actual project content, with the animated loader layered over it. That way, someone arriving from search can see the work behind the headline, and crawlers can discover more than a short bio. Cutting the OG image from 1.77 MB to 80 KB fixes a separate preview issue without conflating it with indexing.Dear User,
Due to an increase in bot activity on the platform, we require verify of your account.
Please log in via the link below:
β’ bit.ly/antibot_check
Verificated deadline - 12 hours. Failure to verify will result in restricted access.
Sincerely, Dev Support
β ββ