Features
SEO
Built-in SEO optimization — automatic meta tags, Open Graph, Twitter Cards, XML sitemap, robots.txt, JSON-LD structured data.
TikShip is built on Next.js App Router's native metadata API, giving you fine-grained SEO control on every page with zero third-party libraries.
Meta Tags
Static Metadata
// src/app/layout.tsx
export const metadata = {
title: 'TikShip — Ship your SaaS in days',
description: 'Production-ready Next.js SaaS boilerplate.',
keywords: ['SaaS', 'Next.js', 'boilerplate', 'starter kit'],
}Dynamic Metadata (per article / product)
// src/app/blog/[slug]/page.tsx
export async function generateMetadata({ params }: { params: { slug: string } }) {
const post = await getPost(params.slug)
return {
title: post.seoTitle || post.title,
description: post.seoDescription || post.excerpt,
openGraph: {
title: post.seoTitle || post.title,
description: post.seoDescription || post.excerpt,
images: post.featuredImage ? [post.featuredImage] : [],
},
}
}Per-article seoTitle and seoDescription fields are managed from the Content Management editor. If left blank, the post title and excerpt are used as fallbacks.
Open Graph
export const metadata = {
openGraph: {
title: 'TikShip',
description: 'Ship your SaaS in days',
url: 'https://yourdomain.com',
siteName: 'TikShip',
images: [
{
url: 'https://yourdomain.com/og-image.png',
width: 1200,
height: 630,
alt: 'TikShip',
},
],
locale: 'en_US',
type: 'website',
},
}Twitter Cards
export const metadata = {
twitter: {
card: 'summary_large_image',
title: 'TikShip',
description: 'Ship your SaaS in days',
images: ['https://yourdomain.com/twitter-image.png'],
creator: '@yourusername',
},
}Sitemap
Automatic XML sitemap generation. The sitemap includes all published articles and pages:
// src/app/sitemap.ts
export default async function sitemap() {
const posts = await prisma.post.findMany({
where: { status: 'published' },
select: { slug: true, type: true, updatedAt: true },
})
const postUrls = posts.map((post) => ({
url: `https://yourdomain.com/${post.type === 'article' ? 'blog' : 'pages'}/${post.slug}`,
lastModified: post.updatedAt,
changeFrequency: 'weekly' as const,
priority: 0.8,
}))
return [
{ url: 'https://yourdomain.com', lastModified: new Date(), changeFrequency: 'daily' as const, priority: 1 },
...postUrls,
]
}Access the sitemap at: https://yourdomain.com/sitemap.xml
Robots.txt
// src/app/robots.ts
export default function robots() {
return {
rules: [
{
userAgent: '*',
allow: '/',
disallow: ['/admin/', '/api/'],
},
],
sitemap: 'https://yourdomain.com/sitemap.xml',
}
}Access it at: https://yourdomain.com/robots.txt
JSON-LD Structured Data
Organization
const jsonLd = {
'@context': 'https://schema.org',
'@type': 'Organization',
name: 'TikShip',
url: 'https://yourdomain.com',
logo: 'https://yourdomain.com/logo.png',
}
export default function RootLayout({ children }) {
return (
<html>
<head>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
</head>
<body>{children}</body>
</html>
)
}Article
const jsonLd = {
'@context': 'https://schema.org',
'@type': 'Article',
headline: post.title,
description: post.excerpt,
image: post.featuredImage,
datePublished: post.publishedAt,
dateModified: post.updatedAt,
author: { '@type': 'Person', name: post.author.name },
}Product
const jsonLd = {
'@context': 'https://schema.org',
'@type': 'Product',
name: product.name,
description: product.description,
image: product.image,
offers: {
'@type': 'Offer',
price: product.price,
priceCurrency: product.currency,
availability: 'https://schema.org/InStock',
},
}Canonical URLs
Prevent duplicate-content penalties:
export const metadata = {
alternates: {
canonical: 'https://yourdomain.com/blog/my-article',
},
}See Internationalization for locale configuration.
Performance
Image Optimization
import Image from 'next/image'
<Image
src={post.featuredImage}
alt={post.title}
width={1200}
height={630}
priority // for above-the-fold images
/>Best Practices
| Element | Guideline |
|---|---|
<title> | Under 60 characters; unique per page; front-load keyword |
| Meta description | Under 160 characters; include a call-to-action |
| H1 | One per page; matches primary keyword intent |
| Image alt text | Descriptive; avoid keyword stuffing |
| URLs | Lowercase, hyphenated, no special characters |
| Canonical | Set on all paginated and filtered views |
Monitoring
- Submit
sitemap.xmlto Google Search Console - Use PageSpeed Insights for Core Web Vitals
- Validate structured data with Google's Rich Results Test
- Check mobile usability with Mobile-Friendly Test
Next Steps
- Internationalization — multi-language SEO setup
- Content Management — per-article SEO fields
- Admin Panel — manage SEO fields from the dashboard