SEO & Open Graph Images Guide
Complete guide to configuring TinyKit Pro's SEO optimization features, including dynamic Open Graph images, sitemap generation, and search engine optimization.
Complete guide to configuring TinyKit Pro's SEO optimization features, including dynamic Open Graph images, sitemap generation, and search engine optimization.
SEO Features Overview
TinyKit Pro includes comprehensive SEO optimization:
- Database-Driven Dynamic Metadata: Optimized meta tags generated from site settings stored in Convex database
- Open Graph Images: Three dynamic OG image variants with database-driven branding
- XML Sitemap: Auto-generated sitemap with appropriate priorities
- Robots.txt: Configured to allow crawling while protecting private routes
- Structured Data: JSON-LD for better search engine understanding
1. Site Branding Configuration
Admin Settings
Configure site branding through the admin interface:
- Access Site Info: Navigate to
/admin/site-settings?tab=site-infoas a admin - Basic Information: Configure site identity:
// Core site settings
siteName: "TinyKit Pro"; // Main site title
slogan: "Team collaboration made simple"; // Subtitle for OG images
description: "Modern team collaboration platform with real-time features";-
Access OG Images: Navigate to
/admin/og-images(Appearance section) as a admin -
OG Image Settings: Configure visual branding (auto-saves):
// OG image configuration
ogImageSettings: {
primaryColor: "#9333ea"; // Primary brand color (hex format)
secondaryColor: "#dfd9ec"; // Secondary accent color
fontColor: "#3d3c4f"; // Text color for OG images
ogImageId: null; // Custom uploaded image (if any)
}-
OG Image Upload: Admin can upload custom OG images:
- Upload Interface: Drag & drop or click to upload
- Auto-cropping: Built-in crop tool for perfect 1200x630 dimensions
- Format Optimization: Automatic WebP conversion for smaller files
- Live Preview: Immediate preview updates in the main preview area
- Storage Management: Old images automatically deleted when uploading new ones
-
Color Presets: Quick theme application with pre-made color combinations
-
Live Preview: All changes immediately visible in the OG image preview
Environment Variables
Configure site URLs for SEO:
# .env.local (Development)
NEXT_PUBLIC_SITE_URL=http://localhost:3000 # Required for metadata generation
# Production Environment
NEXT_PUBLIC_SITE_URL=https://yourdomain.com # Required for metadata generation2. Dynamic Metadata Generation
TinyKit Pro automatically generates SEO metadata from your site settings stored in the Convex database. This ensures your site's SEO properties stay synchronized with your brand settings.
How Dynamic Metadata Works
The metadata generation system:
- Fetches Site Settings: Retrieves current site configuration from Convex database
- Validates Required Fields: Ensures all required properties are configured (fails fast if missing)
- Generates Metadata: Creates complete Next.js metadata object with:
- Dynamic page titles combining site name and slogan
- SEO-optimized descriptions from site settings
- Open Graph tags with automatic image integration
- Twitter Card configuration
- Structured JSON-LD data
Implementation Details
// src/lib/metadata.ts
export async function generateMetadataFromSettings(): Promise<Metadata> {
// Fetch site settings from Convex (no auth required for public settings)
const settings = await fetchQuery(
api.siteSettings.public.queries.getPublicSettings,
{},
);
// Check for custom OG image
const ogImageUrl = await fetchQuery(
api.siteSettings.public.queries.getOGImageUrl,
{},
);
// Validate required fields (fails fast)
if (!process.env.NEXT_PUBLIC_SITE_URL) {
throw new Error("NEXT_PUBLIC_SITE_URL environment variable is required");
}
// ... additional validations
// Generate complete metadata object
return {
metadataBase: new URL(process.env.NEXT_PUBLIC_SITE_URL),
title: {
default: `${siteName} - ${slogan}`,
template: `%s | ${siteName}`,
},
description: settings.description,
// ... complete metadata configuration
};
}Configuration Requirements
Required Environment Variables:
NEXT_PUBLIC_SITE_URL: Base URL for your application (required for metadata generation)
Required Site Settings:
siteName: Your site's main titledescription: SEO description for your siteslogan: Subtitle used in page titles and OG images
Fail-Fast Principle: The system throws descriptive errors if any required configuration is missing, ensuring you're always aware of incomplete SEO setup.
3. Open Graph Image System
OG Image Options
TinyKit Pro provides two OG image modes with seamless switching:
1. Custom Uploaded Images
- Complete control: Upload your own 1200x630px OG images
- Optimized automatically: WebP format with 85% quality for optimal performance
- Smart cropping: Built-in crop tool ensures perfect dimensions
- Storage management: Automatic cleanup of old images when uploading new ones
- Admin-only: Admin access required for uploads
- Instant preview: Real-time preview updates when uploading/removing
2. Generated Images (Fallback)
- Dynamic generation: Auto-created from your site branding settings
- Database-driven: Uses site name, colors, slogan from admin settings
- Three themes: Default, Landing, Waitlist variants available
- Always available: Used when no custom image is uploaded
- Live updates: Changes when you update branding colors
How OG Images Work
The system intelligently chooses between custom and generated images:
- Priority Check: First checks for uploaded custom image
- Custom Image: If uploaded, serves optimized custom image directly
- Generated Fallback: If no custom image, generates dynamic image using:
- Database Branding: Site name, slogan, colors from
ogImageSettings - HTTP Endpoints:
/og-image-urland/og-settingsfor public access - Edge Runtime: Next.js Edge Runtime generates images efficiently
- Smart Caching: 1-hour cache headers for optimal performance
- Database Branding: Site name, slogan, colors from
- Storage Optimization: Automatic cleanup prevents storage bloat
Technical Implementation
// OG image generation with custom image support
export default async function Image() {
// First check if there's a custom uploaded OG image
const customImageResponse = await getCustomOGImage();
if (customImageResponse) {
return customImageResponse; // Return custom image directly
}
// Fall back to generated image
return generateOGImage();
}
async function getCustomOGImage(): Promise<Response | null> {
// Check for custom OG image URL
const response = await fetch(`${CONVEX_SITE_URL}/og-image-url`);
const data = await response.json();
if (!data.imageUrl) {
return null; // No custom image uploaded
}
// Fetch and return the custom image
const imageResponse = await fetch(data.imageUrl);
return new Response(await imageResponse.arrayBuffer(), {
headers: {
"Content-Type": "image/png",
"Cache-Control": "public, max-age=3600",
},
});
}
async function generateOGImage() {
// Fetch branding data from Convex HTTP endpoint
const response = await fetch(`${CONVEX_SITE_URL}/og-settings`);
const branding = await response.json();
// Generate image with database branding
return new ImageResponse(
(
<div
style={{
background: `linear-gradient(135deg, ${branding.primaryColor}, ${branding.secondaryColor})`,
width: '100%',
height: '100%',
display: 'flex',
// ... styling
}}
>
<h1>{branding.siteName}</h1>
<p>{branding.slogan}</p>
</div>
),
{
width: 1200,
height: 630,
}
);
}4. SEO Metadata Configuration
Page Metadata
Each public page includes optimized metadata:
// Root layout metadata
export const metadata: Metadata = {
title: {
default: "TinyKit Pro - Team Collaboration Platform",
template: "%s | TinyKit Pro",
},
description:
"Modern team collaboration platform with project management and seamless workflow integration.",
keywords: ["team collaboration", "project management", "real-time updates"],
authors: [{ name: "TinyKit Pro Team" }],
creator: "TinyKit Pro",
// Open Graph
openGraph: {
type: "website",
locale: "en_US",
url: "https://yourdomain.com",
siteName: "TinyKit Pro",
images: [
{
url: "/opengraph-image",
width: 1200,
height: 630,
alt: "TinyKit Pro - Team Collaboration Platform",
},
],
},
// Twitter Cards
twitter: {
card: "summary_large_image",
site: "@tinykit",
creator: "@tinykit",
},
// Additional SEO
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
"max-video-preview": -1,
"max-image-preview": "large",
"max-snippet": -1,
},
},
};Dynamic Metadata
For dynamic pages, metadata is generated based on content:
// Team page metadata example
export async function generateMetadata({
params,
}: {
params: { teamSlug: string };
}): Promise<Metadata> {
const team = await getTeamBySlug(params.teamSlug);
return {
title: `${team.name} - Team Workspace`,
description: `Collaborate with ${team.name} team members on shared projects and real-time communication.`,
openGraph: {
title: `${team.name} - Team Workspace`,
description: team.description || `${team.name} team workspace`,
url: `/teams/${team.slug}`,
},
};
}5. XML Sitemap Configuration
Sitemap Structure
Location: /app/sitemap.ts
export default function sitemap(): MetadataRoute.Sitemap {
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL ?? "http://localhost:3000";
return [
{
url: baseUrl,
lastModified: new Date(),
changeFrequency: "weekly",
priority: 1.0,
},
{
url: `${baseUrl}/waitlist`,
lastModified: new Date(),
changeFrequency: "weekly",
priority: 0.8,
},
{
url: `${baseUrl}/auth/sign-in`,
lastModified: new Date(),
changeFrequency: "month",
priority: 0.6,
},
{
url: `${baseUrl}/auth/sign-up`,
lastModified: new Date(),
changeFrequency: "month",
priority: 0.6,
},
];
}Sitemap Priorities
- Landing page: Priority 1.0 (highest)
- Waitlist page: Priority 0.8 (high)
- Auth pages: Priority 0.6 (medium)
- Feature pages: Priority 0.7 (high-medium)
Excluded Pages
These routes are intentionally excluded from SEO:
/home/*- User dashboard (requires authentication)/teams/*- Team workspaces (requires team membership)/admin/*- Admin interface (requires admin privileges)/api/*- API endpoints
6. Robots.txt Configuration
Robots.txt Structure
Location: /app/robots.ts
export default function robots(): MetadataRoute.Robots {
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL ?? "http://localhost:3000";
return {
rules: {
userAgent: "*",
allow: "/",
disallow: [
"/admin/",
"/home/",
"/teams/",
"/api/",
"/_next/",
"/favicon.ico",
"/sitemap.xml",
],
},
sitemap: `${baseUrl}/sitemap.xml`,
};
}SEO Protection
The robots.txt configuration:
- Allows: All public pages (
/) - Disallows: Protected routes, API endpoints, internal files
- Sitemap: References complete sitemap for URL discovery
7. Structured Data (JSON-LD)
Organization Schema
Add structured data for better search understanding:
// Add to root layout or specific pages
const jsonLd = {
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "TinyKit Pro",
"description": "Team collaboration platform with real-time features",
"url": "https://yourdomain.com",
"applicationCategory": "BusinessApplication",
"operatingSystem": "Web",
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "USD"
},
"author": {
"@type": "Organization",
"name": "TinyKit Pro Team"
}
};
// Include in HTML
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>8. Performance SEO
Core Web Vitals
TinyKit Pro is optimized for Core Web Vitals:
- Largest Contentful Paint (LCP): < 2.5s
- First Input Delay (FID): < 100ms
- Cumulative Layout Shift (CLS): < 0.1
Performance Features
- Next.js Image Optimization: Automatic image optimization
- Edge Runtime: Fast OG image generation
- Static Generation: Pre-generated pages where possible
- Code Splitting: Automatic code splitting for faster loads
Performance Monitoring
# Analyze bundle size
bun build && npx @next/bundle-analyzer
# Test Core Web Vitals
# Use Google PageSpeed Insights
# Monitor Vercel Analytics (if enabled)9. Local SEO Testing
Testing OG Images
# Test OG images locally
curl http://localhost:3000/opengraph-image
curl http://localhost:3000/waitlist/opengraph-image
# Validate OG images
# Use Facebook Sharing Debugger: https://developers.facebook.com/tools/debug/
# Use Twitter Card Validator: https://cards-dev.twitter.com/validatorTesting Sitemap
# Access sitemap locally
curl http://localhost:3000/sitemap.xml
# Validate sitemap format
# Use Google Search Console Sitemap Tester
# Use online XML validatorsTesting Robots.txt
# Check robots.txt
curl http://localhost:3000/robots.txt
# Validate robots.txt
# Use Google Search Console Robots.txt Tester10. Production SEO Setup
Search Console Setup
-
Google Search Console:
- Add property for your domain
- Verify domain ownership
- Submit sitemap
- Monitor indexing status
-
Bing Webmaster Tools:
- Add site to Bing Webmaster Tools
- Verify ownership
- Submit sitemap
Social Media Optimization
-
Facebook Sharing:
- Test URLs with Facebook Sharing Debugger
- Ensure OG images load correctly
- Verify metadata appears properly
-
Twitter Cards:
- Test with Twitter Card Validator
- Ensure images and text display correctly
- Monitor social media engagement
SEO Monitoring
Set up monitoring for:
- Indexing Status: Track pages indexed by search engines
- Search Performance: Monitor rankings and click-through rates
- Core Web Vitals: Track performance metrics
- Social Sharing: Monitor social media engagement
11. Troubleshooting SEO
Common Issues
OG images not displaying
# Check if OG image endpoint is accessible
curl https://yourdomain.com/opengraph-image
# Test custom image endpoint
curl https://your-convex-site.convex.site/og-image-url
# Test generated image endpoint
curl https://your-convex-site.convex.site/og-settings
# Solution: Ensure Convex HTTP endpoints are deployed (npx convex deploy)
# Ensure custom image uploads have proper storage permissionsCustom OG image not appearing
# Check custom image storage
curl https://your-convex-site.convex.site/og-image-url
# Should return: {"imageUrl": "https://..."} or {"imageUrl": null}
# Solution:
# 1. Ensure image was uploaded by admin
# 2. Check storage permissions in Convex dashboard
# 3. Verify ogImageId exists in siteSettings table
# 4. Test image URL accessibility directlyGenerated OG image shows default values
# Check site branding settings
curl https://your-convex-site.convex.site/og-settings
# Should return proper ogImageSettings values
# Solution:
# 1. Update site info via /admin/site-settings?tab=site-info
# 2. Update OG images via /admin/og-images
# 3. Ensure ogImageSettings are properly nested
# 4. Check database seeding completed successfullySitemap not accessible
# Check sitemap
curl https://yourdomain.com/sitemap.xml
# Solution: Ensure NEXT_PUBLIC_SITE_URL environment variable is correct
# Verify sitemap.ts is properly configuredSearch engines not indexing pages
# Check robots.txt
curl https://yourdomain.com/robots.txt
# Solution: Ensure robots.txt allows crawling of public pages
# Submit sitemap to Google Search ConsolePoor Core Web Vitals scores
# Analyze performance
npx @next/bundle-analyzer
# Solution: Optimize images, reduce bundle size
# Use Next.js Image component for automatic optimizationDebug Commands
# Test OG image generation locally
curl -I http://localhost:3000/opengraph-image
# Check environment variables
echo $NEXT_PUBLIC_SITE_URL
echo $NEXT_PUBLIC_CONVEX_SITE_URL # Frontend env var for Convex HTTP endpoint
# Validate HTML metadata
curl -s https://yourdomain.com | grep -i "og:"
curl -s https://yourdomain.com | grep -i "twitter:"SEO Validation Tools
- Google PageSpeed Insights: Test performance and Core Web Vitals
- Google Rich Results Test: Validate structured data
- Facebook Sharing Debugger: Test OG images and metadata
- Twitter Card Validator: Validate Twitter cards
- SEO Site Checkup: Comprehensive SEO analysis
12. Advanced SEO Features
International SEO
For multi-language support:
// Add hreflang tags for international versions
<link rel="alternate" hreflang="en" href="https://yourdomain.com/" />
<link rel="alternate" hreflang="es" href="https://yourdomain.com/es/" />Rich Snippets
Add rich snippets for better search appearance:
// FAQ schema for support pages
const faqSchema = {
"@context": "https://schema.org",
"@type": "FAQPage",
mainEntity: [
{
"@type": "Question",
name: "How do I create a team?",
acceptedAnswer: {
"@type": "Answer",
text: "To create a team, go to your dashboard and click the 'Create Team' button...",
},
},
],
};Local Business SEO
If applicable, add local business information:
const localBusinessSchema = {
"@context": "https://schema.org",
"@type": "Organization",
name: "TinyKit Pro",
address: {
"@type": "PostalAddress",
streetAddress: "123 Business St",
addressLocality: "City",
addressRegion: "State",
postalCode: "12345",
},
telephone: "+1-555-123-4567",
};Vercel Deployment
Deploy TinyKit Pro to Vercel with environment configuration and production best practices.
Product Management & Sync System Guide
Complete guide to TinyKit Pro's intelligent product management system that synchronizes products between your seed configuration, Stripe account, and Convex ...