Skip to main content

Overview

This portfolio implements comprehensive SEO best practices including metadata optimization, Open Graph tags, Twitter Cards, structured data, sitemap generation, and robots.txt configuration.

Metadata Configuration

The base metadata is configured in src/app/layout.tsx using Next.js App Router metadata API.

Root Layout Metadata

import type { Metadata } from "next";
import content from "@/utils/content.json";

const siteUrl = process.env.NEXT_PUBLIC_URL || "http://localhost:3000";

export const metadata: Metadata = {
  title: content.metadata.title.en,
  description: content.metadata.description.en,
  keywords: [
    "Thalyson Rafael",
    "Desenvolvedor Full Stack",
    "Software Architect",
    "Next.js Developer",
    "NestJS Expert",
    "TypeScript",
    "React",
    "Node.js",
    "Arquitetura Monorepo",
    "SaaS Architecture"
  ],
  metadataBase: new URL(siteUrl),
  alternates: {
    canonical: "/"
  },
  openGraph: {
    title: content.metadata.title.en,
    description: content.metadata.ogDescription.en,
    url: siteUrl,
    siteName: content.metadata.siteName.en,
    images: [
      {
        url: "/og-image.webp",
        width: 1200,
        height: 630,
        alt: content.metadata.title.en
      }
    ],
    locale: "en_US",
    type: "website"
  },
  robots: {
    index: true,
    follow: true,
    googleBot: {
      index: true,
      follow: true,
      "max-video-preview": -1,
      "max-image-preview": "large",
      "max-snippet": -1
    }
  },
  twitter: {
    card: "summary_large_image",
    title: content.metadata.title.en,
    description: content.metadata.twitterDescription.en,
    images: ["/og-image.webp"],
    creator: "@thalyson_rb"
  },
  icons: {
    icon: "/favicon.ico",
    apple: "/apple-touch-icon.webp"
  }
};

Key Metadata Components

PropertyPurposeSEO Impact
titlePage title in search resultsHigh - Primary ranking signal
descriptionMeta description snippetHigh - Affects click-through rate
keywordsSearch keywordsLow - Mostly deprecated
metadataBaseBase URL for relative URLsMedium - Ensures correct URLs
canonicalPrevent duplicate contentHigh - Consolidates page authority
robotsControl indexingHigh - Visibility control
The metadata uses content from a JSON file, making it easy to manage multilingual SEO content.

Open Graph Tags

Open Graph tags control how your portfolio appears when shared on social media platforms like Facebook, LinkedIn, and Slack.

Implementation

openGraph: {
  title: content.metadata.title.en,
  description: content.metadata.ogDescription.en,
  url: siteUrl,
  siteName: content.metadata.siteName.en,
  images: [
    {
      url: "/og-image.webp",
      width: 1200,
      height: 630,
      alt: content.metadata.title.en
    }
  ],
  locale: "en_US",
  type: "website"
}

Open Graph Image Requirements

1

Create OG Image

Design an image with dimensions 1200×630 pixels (optimal for all platforms).
2

Save as WebP

Save as /public/og-image.webp for better performance and smaller file size.
3

Include Branding

Include your name, title, and key visual elements that represent your brand.
4

Test Preview

Use Open Graph Debugger to preview how it looks.
Use high-contrast, readable text on your OG image. Many users will see it at small sizes in their social feeds.

Twitter Card Configuration

Twitter Cards provide rich previews when your portfolio is shared on Twitter/X.

Implementation

twitter: {
  card: "summary_large_image",
  title: content.metadata.title.en,
  description: content.metadata.twitterDescription.en,
  images: ["/og-image.webp"],
  creator: "@thalyson_rb"
}

Twitter Card Types

  • summary: Small card with thumbnail
  • summary_large_image: Large card with prominent image (recommended for portfolios)
  • app: Mobile app card
  • player: Video/audio player card

Testing Twitter Cards

  1. Visit Twitter Card Validator
  2. Enter your portfolio URL
  3. Preview how it appears on Twitter
  4. Make adjustments to title, description, or image as needed
The same OG image works for both Open Graph and Twitter Cards, reducing file duplication.

Sitemap Generation

The sitemap helps search engines discover and index all pages on your portfolio.

Dynamic Sitemap

import type { MetadataRoute } from "next";

export default function sitemap(): MetadataRoute.Sitemap {
  const base = process.env.NEXT_PUBLIC_URL || "http://localhost:3000";
  const now = new Date();
  const withBase = (path: string) => `${base}${path}`;
  
  return [
    {
      url: withBase("/"),
      lastModified: now,
      changeFrequency: "weekly",
      priority: 1
    },
    {
      url: withBase("/privacy-policy"),
      lastModified: now,
      changeFrequency: "yearly",
      priority: 0.3
    }
  ];
}

Sitemap Properties

PropertyDescriptionValues
urlFull URL of the pageMust include domain
lastModifiedWhen the page was last updatedDate object
changeFrequencyHow often the page changesalways, hourly, daily, weekly, monthly, yearly, never
priorityRelative importance0.0 to 1.0

Expanding Your Sitemap

For a portfolio with dynamic content (blog posts, projects), generate sitemap entries dynamically:
import type { MetadataRoute } from "next";
import { getAllProjects } from "@/lib/projects";

export default async function sitemap(): MetadataRoute.Sitemap {
  const base = process.env.NEXT_PUBLIC_URL || "http://localhost:3000";
  const now = new Date();
  const withBase = (path: string) => `${base}${path}`;

  // Static pages
  const routes = [
    {
      url: withBase("/"),
      lastModified: now,
      changeFrequency: "weekly" as const,
      priority: 1
    },
    {
      url: withBase("/privacy-policy"),
      lastModified: now,
      changeFrequency: "yearly" as const,
      priority: 0.3
    }
  ];

  // Dynamic project pages
  const projects = await getAllProjects();
  const projectRoutes = projects.map((project) => ({
    url: withBase(`/projects/${project.slug}`),
    lastModified: project.updatedAt || now,
    changeFrequency: "monthly" as const,
    priority: 0.8
  }));

  return [...routes, ...projectRoutes];
}
Access your sitemap at /sitemap.xml. Submit this URL to Google Search Console and Bing Webmaster Tools.

Robots.txt Configuration

The robots.txt file tells search engine crawlers which pages they can access.

Implementation

import type { MetadataRoute } from "next";

export default function robots(): MetadataRoute.Robots {
  const base = process.env.NEXT_PUBLIC_URL;
  
  return {
    rules: {
      userAgent: "*",
      allow: "/"
    },
    sitemap: base ? [`${base}/sitemap.xml`] : []
  };
}

Robots.txt Rules

Allow All (Current Configuration):
User-agent: *
Allow: /
Sitemap: https://yoursite.com/sitemap.xml
Block Specific Paths:
rules: [
  {
    userAgent: "*",
    allow: "/",
    disallow: ["/admin", "/private"]
  }
]
Different Rules for Different Bots:
rules: [
  {
    userAgent: "Googlebot",
    allow: "/"
  },
  {
    userAgent: "GPTBot",
    disallow: "/"
  }
]
Be careful with disallow rules. Accidentally blocking important pages can hurt your SEO.

Structured Data (JSON-LD)

Structured data helps search engines understand your content and can enable rich results in search.

Person Schema

<Script id="jsonld-person" type="application/ld+json" strategy="afterInteractive">
  {`
    {
      "@context": "https://schema.org",
      "@type": "Person",
      "name": "Thalyson Rafael",
      "jobTitle": "Full Stack Developer",
      "url": "${process.env.NEXT_PUBLIC_URL ?? ""}",
      "sameAs": [
        "https://github.com/ThalysonRibeiro",
        "https://www.linkedin.com/in/thalyson-rafael-br"
      ]
    }
  `}
</Script>

Additional Schema Types for Portfolios

{
  "@context": "https://schema.org",
  "@type": "ProfilePage",
  "dateCreated": "2024-01-01T00:00:00-00:00",
  "dateModified": "2024-03-09T00:00:00-00:00",
  "mainEntity": {
    "@type": "Person",
    "name": "Thalyson Rafael",
    "alternateName": "Thalyson Ribeiro",
    "description": "Full Stack Developer specializing in Next.js and NestJS",
    "image": "https://yoursite.com/profile.jpg",
    "sameAs": [
      "https://github.com/ThalysonRibeiro",
      "https://www.linkedin.com/in/thalyson-rafael-br"
    ]
  }
}
Use Google’s Rich Results Test to validate your structured data.

Performance Optimization for SEO

Page speed is a ranking factor. Here’s how this portfolio optimizes performance:

Image Optimization

next.config.ts
images: {
  remotePatterns: [
    {
      protocol: "https",
      hostname: "res.cloudinary.com"
    }
  ]
}
Best Practices:
  • Use WebP format for images
  • Implement Next.js Image component for automatic optimization
  • Use lazy loading for below-the-fold images
  • Serve images from CDN (Cloudinary)

Code Splitting

  • Next.js automatically splits code by route
  • Use dynamic imports for heavy components
  • Turbopack in development for faster builds

Font Optimization

import { Geist, Geist_Mono } from "next/font/google";

const geistSans = Geist({
  variable: "--font-geist-sans",
  subsets: ["latin"]
});
Benefits:
  • Self-hosted fonts (no external requests)
  • Automatic font subsetting
  • Font display optimization
Next.js App Router provides automatic optimizations for fonts, reducing layout shift and improving Core Web Vitals.

Portfolio SEO Best Practices

Content Optimization

1

Unique Page Titles

Each page should have a unique, descriptive title (50-60 characters).
2

Compelling Meta Descriptions

Write descriptions that encourage clicks (150-160 characters).
3

Header Hierarchy

Use proper heading structure: H1 for page title, H2 for sections, etc.
4

Descriptive URLs

Use clean, readable URLs: /projects/ecommerce-platform not /p?id=123.

Technical SEO Checklist

  • HTTPS enabled (required for modern web)
  • Mobile-responsive design
  • Fast page load times (< 3 seconds)
  • Sitemap submitted to search engines
  • Robots.txt configured correctly
  • Structured data implemented
  • Canonical URLs set
  • Open Graph tags present
  • Twitter Card tags present
  • Favicon and app icons configured

Portfolio-Specific SEO Tips

  1. Project Pages: Create individual pages for major projects with detailed descriptions
  2. Skills Section: Include relevant technology keywords naturally
  3. About Page: Write a comprehensive bio with your expertise and location
  4. Contact Information: Make it easy for recruiters to reach you
  5. Case Studies: Document your problem-solving process to rank for technical queries
  6. Blog Posts: Write technical articles to establish expertise
Update your metadata when you learn new skills or complete significant projects to keep your SEO current.

Monitoring SEO Performance

Google Search Console

1

Verify Ownership

Add your site to Google Search Console and verify ownership.
2

Submit Sitemap

Submit your sitemap URL: https://yoursite.com/sitemap.xml
3

Monitor Performance

Track impressions, clicks, and average position for your pages.
4

Fix Issues

Address any indexing issues or mobile usability problems.

Key Metrics to Track

  • Organic Traffic: Visitors from search engines
  • Search Impressions: How often your site appears in search
  • Click-Through Rate: Percentage of impressions that result in clicks
  • Average Position: Where your pages rank for specific queries
  • Core Web Vitals: Performance metrics (LCP, FID, CLS)

SEO Tools

  • Google Search Console: Official Google insights
  • Google Analytics: Traffic analysis and user behavior
  • Lighthouse: Performance and SEO auditing
  • PageSpeed Insights: Detailed performance recommendations
  • Bing Webmaster Tools: Bing search visibility

Troubleshooting SEO Issues

Page Not Indexed

  1. Check robots.txt isn’t blocking the page
  2. Verify the page is in your sitemap
  3. Check for noindex meta tags
  4. Submit URL for indexing in Search Console

Poor Rankings

  1. Analyze competitor content and metadata
  2. Improve page content quality and length
  3. Add more relevant keywords naturally
  4. Build quality backlinks to your portfolio
  5. Improve page load speed

Missing Rich Results

  1. Validate structured data with Rich Results Test
  2. Check for JSON-LD syntax errors
  3. Ensure required properties are present
  4. Wait for Google to recrawl (can take weeks)
SEO is a long-term strategy. Don’t expect immediate results. Focus on creating quality content and technical excellence.

Next Steps

  1. Submit to Search Engines: Add your portfolio to Google Search Console and Bing Webmaster Tools
  2. Create Content: Write blog posts or case studies about your projects
  3. Build Backlinks: Share your portfolio on professional networks
  4. Monitor Performance: Regularly check analytics and search console data
  5. Keep Updated: Update metadata when you complete new projects or learn new skills
Set up Google Analytics and Google Search Console on day one to start collecting data immediately, even if you don’t have traffic yet.

Build docs developers (and LLMs) love