### CI/CD Setup for Seoslug Static Manifest Source: https://seoslug.emiliano-go.com/integrations/nuxt Example GitHub Actions workflow for setting up Python, installing Seoslug and PyYAML, generating SEO data, and running an npm build. ```yaml - uses: actions/setup-python@v5 with: python-version: "3.x" - run: pip install "seoslug>=2.0.1" pyyaml - run: python scripts/generate_seo.py - run: npm ci - run: npm run generate ``` -------------------------------- ### Sub-path Deployment Example Configuration Source: https://seoslug.emiliano-go.com/url-normalization Example of configuring SEOConfig and URLPolicy for a sub-path deployment, ensuring canonical URLs work correctly. ```python from seoslug import SEOConfig, URLPolicy config = SEOConfig( canonical_host="example.com", public_base_url="https://example.com/blog", url_policy=URLPolicy( lowercase_paths=True, trailing_slash="never", collapse_duplicate_slashes=True, strip_tracking_params=True, ), ) # Given route "/about" # Result: "https://example.com/blog/about" # Given route "/" # Result: "https://example.com/blog" ``` -------------------------------- ### Install seoslug with Development Dependencies Source: https://seoslug.emiliano-go.com/contributing Clone the repository and install the project in editable mode with testing and fast extras for development. ```bash git clone https://github.com/emiliano-go/seoslug.git cd seoslug pip install -e ".[test,fast]" # or ".[test,light]" for minimal ``` -------------------------------- ### Install seoslug with Minimal Dependencies Source: https://seoslug.emiliano-go.com/faq Install a minimal, pure-Python version of seoslug without lxml or detrack using the `[light]` extras marker. ```bash pip install "seoslug[light]" ``` -------------------------------- ### Install seoslug with Fast Extras Source: https://seoslug.emiliano-go.com/getting-started Install the seoslug library with lxml and detrack for optimized HTML parsing and tracking-parameter stripping. Requires Python 3.10 or later. ```bash pip install "seoslug[fast]" ``` -------------------------------- ### Example Usage of SEOOverrides Source: https://seoslug.emiliano-go.com/api-reference Demonstrates how to instantiate the SEOOverrides dataclass with specific values to customize SEO metadata and control template usage. ```python overrides = SEOOverrides( meta_title="Custom Title", skip_title_template=True, twitter_creator="@author", omit_schema=True, ) ``` -------------------------------- ### Install seoslug with Npm Source: https://seoslug.emiliano-go.com/integrations/strapi Install the seoslug Node.js package using npm for runtime dependency installation. ```bash RUN npm install seoslug ``` -------------------------------- ### Install and Run Mypy for Type Checking Source: https://seoslug.emiliano-go.com/contributing Install the mypy type checker and run it on the seoslug source code to verify type hints. ```bash pip install mypy mypy src/seoslug/ ``` -------------------------------- ### Astro CI/CD Pipeline Setup Source: https://seoslug.emiliano-go.com/integrations/astro Integrate SEO slug generation into your CI/CD workflow before the Astro build. Ensure Python is set up, dependencies are installed, and the generation script is executed. ```yaml - uses: actions/setup-python@v5 with: python-version: "3.x" - run: pip install "seoslug>=2.0.1" pyyaml - run: python scripts/generate_seo.py - run: npm ci - run: npm run build ``` -------------------------------- ### Build Zensical Documentation Source: https://seoslug.emiliano-go.com/integrations/zensical Install necessary packages and run the `zensical build` command. The seoslug extension integrates seamlessly without requiring pre-build steps or modifications to CI commands. ```bash # .github/workflows/deploy-docs.yml - run: pip install "seoslug>=2.0.1" zensical - run: zensical build --clean ``` -------------------------------- ### Install seoslug with Pip Source: https://seoslug.emiliano-go.com/integrations/strapi Install the seoslug Python package using pip for Dockerfile or CI environments. ```bash # Dockerfile or CI RUN pip install "seoslug>=2.0.1" ``` -------------------------------- ### Starlette App Setup with Routes Source: https://seoslug.emiliano-go.com/integrations/starlette Configure your Starlette application by defining routes for different endpoints. ```python from starlette.applications import Starlette from starlette.routing import Route routes = [ Route("/", home), Route("/{slug}", post_detail), ] app = Starlette(routes=routes) ``` -------------------------------- ### Update CI Workflow for seoslug and Quartz Build Source: https://seoslug.emiliano-go.com/integrations/quartz Configure your CI workflow to set up Python, install seoslug and pyyaml, run the seoslug pre-build script, and then build the Quartz site. ```yaml - uses: actions/setup-python@v5 with: python-version: '3.x' - run: pip install "seoslug>=2.0.1" pyyaml - run: python scripts/generate_seo.py - run: npm ci - run: npm run build ``` -------------------------------- ### HTML Template Rendering for Multi-Language Source: https://seoslug.emiliano-go.com/recipes/multi-language Example of an HTML section demonstrating how to render canonical URLs, alternate hreflang links, and Open Graph locale tags for a multi-language site. ```html {{ en_payload.title }} ``` -------------------------------- ### Add SEO Slug Generation to Gatsby CI/CD Source: https://seoslug.emiliano-go.com/integrations/gatsby This snippet shows how to add a step to install Python dependencies, run a Python script for SEO slug generation, and then proceed with the standard npm installation and Gatsby build. Ensure 'seoslug' and 'pyyaml' are installed and the 'generate_seo.py' script exists. ```yaml - uses: actions/setup-python@v5 with: python-version: "3.x" - run: pip install "seoslug>=2.0.1" pyyaml - run: python scripts/generate_seo.py - run: npm ci - run: npm run build ``` -------------------------------- ### Frontmatter with SEO HTML Source: https://seoslug.emiliano-go.com/integrations/zensical Example of a Markdown file's frontmatter after the seoslug script has processed it, showing the added 'seo_html' key. ```markdown --- title: Getting Started description: How to install and configure seoslug. seo_html: "Getting Started - Your Site\n" --- ``` -------------------------------- ### Generated SEO Payload Example Source: https://seoslug.emiliano-go.com/recipes/blog-post An example of the resulting JSON payload after generating SEO data, including title, description, canonical URL, OG data, Twitter card data, and structured schema.jsonld for both BlogPosting and BreadcrumbList. ```json { "title": "Hello World - My Blog", "description": "A brief introduction to the blog.", "canonical": "https://blog.example.com/blog/hello-world", "robots": "index,follow", "og": { "type": "article", "title": "Hello World - My Blog", "description": "A brief introduction to the blog.", "url": "https://blog.example.com/blog/hello-world", "image": "https://cdn.example.com/hello.jpg", "image:width": 1200, "image:height": 630, "image:alt": "Hello World featured image", "site_name": "My Blog", }, "twitter": { "card": "summary_large_image", "title": "Hello World - My Blog", "description": "A brief introduction to the blog.", "image": "https://cdn.example.com/hello.jpg", "image:alt": "Hello World featured image", }, "schema_jsonld": [ { "@context": "https://schema.org", "@type": "BlogPosting", "headline": "Hello World - My Blog", "url": "https://blog.example.com/blog/hello-world", "mainEntityOfPage": {"@id": "https://blog.example.com/blog/hello-world"}, "description": "A brief introduction to the blog.", "image": "https://cdn.example.com/hello.jpg", "datePublished": "2025-01-15", "dateModified": "2025-02-01", "author": {"@type": "Person", "name": "Jane Doe"}, "publisher": { "@type": "Organization", "name": "My Company", }, }, { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [ {"@type": "ListItem", "position": 1, "name": "Home", "item": "https://blog.example.com/"}, {"@type": "ListItem", "position": 2, "name": "Blog", "item": "https://blog.example.com/blog"}, ], }, ], } ``` -------------------------------- ### Updating seoslug Dependencies for Optional Extras Source: https://seoslug.emiliano-go.com/migration In 2.0.0, lxml and detrack are optional extras. Update your pip install command to include '[fast]' for lxml+detrack (recommended) or '[light]' for pure-Python fallbacks. ```bash # Old pip install seoslug # New - same behavior as 1.x (recommended) pip install "seoslug[fast]" # New - pure Python only (minimal) pip install "seoslug[light]" ``` -------------------------------- ### SEO Configuration Setup Source: https://seoslug.emiliano-go.com/recipes/blog-post Configures SEO settings including canonical host, public base URL, URL policies, title template, site name, publisher details, default OG image, schema type mapping, and the custom schema registry. ```python config = SEOConfig( canonical_host="blog.example.com", public_base_url="https://blog.example.com", url_policy=URLPolicy( strip_tracking_params=True, lowercase_paths=True, trailing_slash="never", ), title_template="{title} - My Blog", site_name="My Blog", publisher_name="My Company", default_og_image="https://cdn.example.com/default.jpg", schema_type_map={"post": "BlogPosting"}, schema_registry=registry, ) ``` -------------------------------- ### MkDocs Plugin Configuration Source: https://seoslug.emiliano-go.com/integrations/ssg Integrate seoslug with MkDocs to generate SEO metadata for pages. This example sets up the SEOConfig and the on_page_markdown hook. ```python from seoslug import SEOConfig, URLPolicy, SEOEntity, build_seo_payload config = SEOConfig( canonical_host="docs.example.com", public_base_url="https://docs.example.com", url_policy=URLPolicy(), ) def on_page_markdown(markdown, page, config, files): entity = SEOEntity( entity_type="page", title=page.title, status="published", ) page.seo_payload = build_seo_payload(entity, page.url, config) ``` -------------------------------- ### CI Workflow for Seoslug and Zensical Build Source: https://seoslug.emiliano-go.com/integrations/zensical This snippet shows how to update a CI workflow to install seoslug and zensical, run the SEO generation script, and then build the Zensical site. This ensures SEO frontmatter is generated before the site is built. ```yaml - run: pip install "seoslug>=2.0.1" zensical - run: python scripts/generate_seo.py - run: zensical build --clean ``` -------------------------------- ### Use Seoslug Plugin Service in Controller Source: https://seoslug.emiliano-go.com/integrations/strapi This example demonstrates how to use the custom seoslug plugin service within a Strapi controller. It fetches entities, enriches them with SEO data using `buildSeo`, and returns the combined data, providing structured SEO information alongside content. ```javascript module.exports = ({ strapi }) => ({ async find(ctx) { const entities = await strapi.entityService.findMany(ctx.query); const route = ctx.request.path; const enriched = entities.map((entity) => { const seo = strapi .plugin("seoslug") .service("seoslugService") .buildSeo(entity, route); return { ...entity, seo }; }); return enriched; }, }); ``` -------------------------------- ### Render SEO Tags with next/head Source: https://seoslug.emiliano-go.com/integrations/nextjs Use `next/head` in your layout or page component to render SEO tags dynamically based on provided `seo` data. This example includes handling default tags if `seo` data is not available. ```javascript import Head from "next/head"; export default function Page({ seo, children }) { return ( <> {seo ? ( <> {seo.title} {seo.schema_jsonld && ( ``` ```vue ``` -------------------------------- ### FAQPage Entity Builder Source: https://seoslug.emiliano-go.com/schema-jsonld Builds Schema.org FAQPage JSON-LD. Use this to structure frequently asked questions and their answers for better search visibility. ```python from seoslug import FAQItem entity = SEOEntity( entity_type="faq", title="FAQ", faq_items=[ FAQItem(question="Q1?", answer="A1."), FAQItem(question="Q2?", answer="A2."), ], ) ``` -------------------------------- ### Filter Hidden Files and Directories Source: https://seoslug.emiliano-go.com/integrations/ssg This Python code filters out hidden files and directories (those starting with '.') when globbing for Markdown files. This ensures that SEO payloads are not generated for hidden drafts or temporary folders. ```python md_files = sorted( f for f in content_dir.rglob("*.md") if not any(part.startswith(".") for part in f.relative_to(content_dir).parts) ) ``` -------------------------------- ### SchemaRegistry Operations: Register, Get, Unregister Source: https://seoslug.emiliano-go.com/registry Shows the basic operations for managing generators within the SchemaRegistry: registering a generator function, retrieving it, and unregistering it. Raises ValueError for empty schema type strings. ```python registry = SchemaRegistry() # Register registry.register("Podcast", my_generator) # Look up gen = registry.get("Podcast") # returns my_generator or None # Unregister registry.unregister("Podcast") registry.get("Podcast") # None ``` -------------------------------- ### Normalize Path Source: https://seoslug.emiliano-go.com/api-reference Normalizes a URL path without host or scheme, applying lowercase, trailing slash, and duplicate-slash rules. Always returns a path starting with '/'. Raises `URLPolicyError` for non-string input. ```python def normalize_path( path: str, policy: URLPolicy, ) -> str ``` ```python normalize_path("/Blog//Post", URLPolicy()) # "/blog/post" ``` -------------------------------- ### Example SEO Payload Result Source: https://seoslug.emiliano-go.com/recipes/product-page The generated SEO payload includes metadata for title, description, canonical URL, robots directives, Open Graph tags, Twitter card tags, and structured JSON-LD for schema.org. ```json { "title": "Wireless Headphones Pro - My Shop", "description": "Premium wireless headphones with active noise cancellation.", "canonical": "https://shop.example.com/products/headphones-pro", "robots": "index,follow", "og": { "type": "website", "title": "Wireless Headphones Pro - My Shop", "description": "Premium wireless headphones with active noise cancellation.", "url": "https://shop.example.com/products/headphones-pro", "image": "https://cdn.example.com/headphones.jpg", "image:width": 1200, "image:height": 1200, "image:alt": "Wireless Headphones Pro", "site_name": "My Shop", }, "twitter": { "card": "summary_large_image", "title": "Wireless Headphones Pro - My Shop", "description": "Premium wireless headphones with active noise cancellation.", "image": "https://cdn.example.com/headphones.jpg", "image:alt": "Wireless Headphones Pro", }, "schema_jsonld": [ { "@context": "https://schema.org", "@type": "Product", "name": "Wireless Headphones Pro - My Shop", "url": "https://shop.example.com/products/headphones-pro", "description": "Premium wireless headphones with active noise cancellation.", "image": "https://cdn.example.com/headphones.jpg", "sku": "WH-PRO-001", "offers": { "@type": "Offer", "price": "79.99", "priceCurrency": "USD", "availability": "https://schema.org/InStock", }, }, { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [ {"@type": "ListItem", "position": 1, "name": "Home", "item": "https://shop.example.com/"}, {"@type": "ListItem", "position": 2, "name": "Audio", "item": "https://shop.example.com/audio"}, {"@type": "ListItem", "position": 3, "name": "Headphones", "item": "https://shop.example.com/audio/headphones"}, ], }, ], } ``` -------------------------------- ### Configure SEO with Sub-Path Deployment Source: https://seoslug.emiliano-go.com/configuration/seo-config Set the public_base_url to include the full path when your site runs under a path prefix. This ensures all canonical URLs are correctly prepended. ```python SEOConfig( canonical_host="example.com", public_base_url="https://example.com/blog/", url_policy=URLPolicy(), ) ``` -------------------------------- ### Async seoslug Integration Source: https://seoslug.emiliano-go.com/integrations For asynchronous frameworks, import the `build_seo_payload_async` function from `seoslug.async_builder`. ```python from seoslug.async_builder import build_seo_payload_async ``` -------------------------------- ### Initialize SEOConfig with URL Policy Source: https://seoslug.emiliano-go.com/configuration/seo-config Specify URL normalization rules using a URLPolicy instance. This controls how URLs are processed and formatted. ```python SEOConfig( canonical_host="blog.example.com", public_base_url="https://blog.example.com", url_policy=URLPolicy(trailing_slash="always"), ) ``` -------------------------------- ### Generate Metadata in Next.js App Router Source: https://seoslug.emiliano-go.com/integrations/nextjs Use the `generateMetadata` function in Next.js App Router to dynamically set metadata for each route. This example shows how to fetch or define SEO entities and build the SEO payload using `seoslug`. ```javascript import type { Metadata } from "next"; import { SEOConfig, SEOEntity, build_seo_payload } from "seoslug"; const SEO_CONFIG = new SEOConfig({ canonical_host: "yoursite.com", public_base_url: "https://yoursite.com/", site_name: "Your Site", title_template: "{title} | Your Site", }); export async function generateMetadata({ params }): Promise { const entity = new SEOEntity({ entity_type: "page", title: "Page Title", excerpt: "Page description...", }); const payload = build_seo_payload(entity, `/${params.slug}/`, SEO_CONFIG); if (!payload) return {}; return { title: payload.title, description: payload.description, robots: payload.robots, openGraph: payload.og, twitter: payload.twitter, other: { "application/ld+json": JSON.stringify(payload.schema_jsonld), }, }; } ``` -------------------------------- ### Custom Podcast Schema Generation with Detailed Fields Source: https://seoslug.emiliano-go.com/registry An advanced example of a custom podcast generator that includes conditional logic for adding description, image, author, and sameAs fields based on the entity and provided data. It demonstrates how to build a more complete schema. ```python from seoslug import SchemaRegistry, SEOConfig, URLPolicy, SEOEntity, build_seo_payload registry = SchemaRegistry() def podcast_gen(entity, config, canonical, title, description, og_image): schema = { "@context": "https://schema.org", "@type": "Podcast", "name": title, "url": canonical, } if description: schema["description"] = description if og_image: schema["image"] = og_image if entity.author_name: schema["author"] = {"@type": "Person", "name": entity.author_name} if entity.same_as: schema["sameAs"] = entity.same_as return schema registry.register("Podcast", podcast_gen) config = SEOConfig( canonical_host="podcast.example.com", public_base_url="https://podcast.example.com", url_policy=URLPolicy(), schema_type_map={"post": "Podcast"}, schema_registry=registry, ) entity = SEOEntity( entity_type="post", title="Episode 42: The Future of AI", author_name="Jane Doe", same_as=["https://twitter.com/mypodcast"], ) payload = build_seo_payload(entity, "/episodes/42", config) # payload["schema_jsonld"]["@type"] == "Podcast" ``` -------------------------------- ### Build an SEO Entity Source: https://seoslug.emiliano-go.com/api-reference Use the fluent builder to construct an SEOEntity object. Ensure all required fields like entity_type are set before building. ```python entity = ( SEOEntityBuilder() .entity_type("product") .title("Widget") .sku("W-001") .price(29.99) .availability("InStock") .build() ) ```