🚀 Astro Docker Kit
🚀 Quick Start
git clone https://github.com/advento-ir/astro-docker-kit
cd astro-docker-kit
npm install
npm run dev
Visit http://localhost:4321.
🐳 Deploy with Docker
cp .env.example .env
docker network create private-net # required once
docker compose up -d
📁 Project Structure
/
├── public/fonts/iran-yekan-x/ # IRANYekanX woff2 files
├── src/
│ ├── components/
│ │ ├── blocks/ # Content block components
│ │ ├── core/ # Base UI components
│ │ ├── layout/ # Header, footer, sidebar
│ │ └── meta/SEO.astro # SEO component
│ ├── layouts/BaseLayout.astro # RTL/FA base layout
│ ├── pages/index.astro # Homepage
│ └── styles/
│ ├── fonts.css # Persian font definitions
│ └── global.css # Global styles + Tailwind
├── Dockerfile
├── docker-compose.yml
└── nginx.conf
🔍 SEO Component
src/components/meta/SEO.astro is a full-featured, drop-in SEO component used inside BaseLayout.astro. It handles every layer of modern SEO — from core meta tags to structured data — with zero external dependencies.
Features at a glance
| Category | What's included |
|---|---|
| Core meta | <title>, description, keywords, author, robots, theme-color, color-scheme, generator |
| Canonical | Auto-detected from Astro.url.href or manually overridden |
| Open Graph | og:type, og:title, og:description, og:image (+ width/height/alt), og:locale, og:site_name |
| OG Article | article:published_time, article:modified_time, article:section, article:tag, article:author |
| Twitter Card | twitter:card, twitter:title, twitter:description, twitter:image, twitter:site, twitter:creator |
| JSON-LD | Auto-generated WebSite, WebPage / Article, BreadcrumbList schemas + custom schema injection |
| hreflang | Alternate locale <link> tags for multilingual sites |
| Resource hints | preconnect and dns-prefetch link tags |
| Favicon | SVG icon, ICO fallback, Apple touch icon, Web App Manifest |
Basic usage
BaseLayout.astro already wires the component up — just pass props when using the layout:
---
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout
title="My Page"
description="A short description of this page."
/>
All other props are optional and tree-shake to nothing when unused.
All props
Core
| Prop | Type | Default | Description |
|---|---|---|---|
title |
string |
required | Page title (also used as OG/Twitter fallback) |
titleTemplate |
string |
'%s' |
Wraps the title — %s is replaced with title. E.g. '%s | Advento' |
description |
string |
required | Meta description (also used as OG/Twitter fallback) |
keywords |
string[] |
— | Comma-joined into <meta name="keywords"> |
author |
string |
— | <meta name="author"> |
themeColor |
string |
'#7c3aed' |
<meta name="theme-color"> |
Canonical & Robots
| Prop | Type | Default | Description |
|---|---|---|---|
canonical |
string |
Astro.url.href |
Absolute canonical URL |
noindex |
boolean |
false |
Add noindex to the robots directive |
nofollow |
boolean |
false |
Add nofollow to the robots directive |
Open Graph
| Prop | Type | Default | Description |
|---|---|---|---|
ogType |
'website' | 'article' | 'profile' |
'website' |
OG object type |
ogTitle |
string |
resolved title |
Override OG title |
ogDescription |
string |
description |
Override OG description |
ogImage |
string |
— | Absolute URL to the OG image (1200×630 recommended) |
ogImageAlt |
string |
— | Alt text for the OG image |
ogImageWidth |
number |
1200 |
OG image width in pixels |
ogImageHeight |
number |
630 |
OG image height in pixels |
ogLocale |
string |
'fa_IR' |
OG locale string |
ogSiteName |
string |
— | og:site_name |
Twitter Card
| Prop | Type | Default | Description |
|---|---|---|---|
twitterCard |
'summary' | 'summary_large_image' | 'app' | 'player' |
'summary_large_image' |
Card type |
twitterSite |
string |
— | Site Twitter handle (e.g. @advento_ir) |
twitterCreator |
string |
— | Author Twitter handle |
twitterTitle |
string |
OG title | Override Twitter title |
twitterDescription |
string |
OG description | Override Twitter description |
twitterImage |
string |
OG image | Override Twitter image URL |
twitterImageAlt |
string |
— | Alt text for the Twitter image |
Article (requires ogType="article")
Pass an article object with the following shape:
interface ArticleMeta {
publishedTime: string; // ISO 8601, e.g. "2025-01-15T10:00:00Z"
modifiedTime?: string;
authors?: string[]; // names or profile URLs
section?: string;
tags?: string[];
}
JSON-LD & Breadcrumbs
| Prop | Type | Description |
|---|---|---|
breadcrumbs |
BreadcrumbItem[] |
Generates a BreadcrumbList schema automatically |
jsonLd |
Record<string, unknown> | Record<string, unknown>[] |
Inject one or more custom schema.org objects |
interface BreadcrumbItem {
name: string;
url: string; // absolute URL
}
Alternates & Resource Hints
| Prop | Type | Description |
|---|---|---|
alternateLocales |
AlternateLocale[] |
Emits <link rel="alternate" hreflang="..."> for each entry |
preconnect |
string[] |
Emits <link rel="preconnect"> for each origin |
dnsPrefetch |
string[] |
Emits <link rel="dns-prefetch"> for each origin |
interface AlternateLocale {
hreflang: string; // e.g. "en", "fa", "x-default"
href: string; // absolute URL
}
Favicon & Manifest
| Prop | Type | Default | Description |
|---|---|---|---|
faviconSvg |
string |
'/favicon.svg' |
Path to SVG favicon |
faviconIco |
string |
— | Path to .ico favicon (legacy browsers) |
appleTouchIcon |
string |
— | Path to Apple touch icon (180×180 PNG) |
manifestHref |
string |
— | Path to manifest.json / manifest.webmanifest |
Full example — article page
---
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout
title="How We Built This Kit"
titleTemplate="%s | Advento"
description="A deep-dive into our Astro + Docker starter setup."
keywords={['Astro', 'Docker', 'Tailwind', 'RTL']}
author="Advento Team"
canonical="https://advento.ir/blog/how-we-built-this-kit"
ogType="article"
ogImage="https://advento.ir/og/how-we-built-this-kit.png"
ogImageAlt="Screenshot of the Astro Docker Kit starter"
ogSiteName="Advento"
twitterSite="@advento_ir"
twitterCreator="@advento_ir"
article={{
publishedTime: '2025-01-15T10:00:00Z',
modifiedTime: '2025-06-01T08:00:00Z',
authors: ['Advento Team'],
section: 'Engineering',
tags: ['Astro', 'Docker', 'SEO'],
}}
breadcrumbs={[
{ name: 'Home', url: 'https://advento.ir' },
{ name: 'Blog', url: 'https://advento.ir/blog' },
{ name: 'How We Built This Kit', url: 'https://advento.ir/blog/how-we-built-this-kit' },
]}
alternateLocales={[
{ hreflang: 'fa', href: 'https://advento.ir/fa/blog/how-we-built-this-kit' },
{ hreflang: 'x-default', href: 'https://advento.ir/blog/how-we-built-this-kit' },
]}
preconnect={['https://fonts.gstatic.com']}
/>
🧞 Commands
| Command | Action |
|---|---|
npm run dev |
Start dev server at localhost:4321 |
npm run build |
Build production site to ./dist/ |
npm run preview |
Preview the production build locally |
npm run format |
Format code with Prettier |
npm run lint |
Lint with ESLint |
docker compose up -d |
Run container in background |
🤝 Contributing
- Fork the repo
- Create a branch:
git checkout -b feature/your-feature - Commit:
git commit -m 'feat: add your feature' - Push and open a Pull Request
🌌 About Advento
At Advento, we are redefining the digital marketing landscape. By harnessing the absolute edge of Artificial Intelligence, we deliver highly scalable, data-driven, and innovative solutions. This repository is part of our commitment to pushing the boundaries of what's possible in digital marketing technology.
📄 License
MIT — see LICENSE for details.
Made with ❤️ by Advento