
Security News
Google’s OSV Fix Just Added 500+ New Advisories — All Thanks to One Small Policy Change
A data handling bug in OSV.dev caused disputed CVEs to disappear from vulnerability feeds until a recent fix restored over 500 advisories.
@mannisto/astro-head
Advanced tools
Composable Astro components for managing your HTML <head> in Astro projects.
A collection of composable Astro components for managing your HTML <head>
: meta tags, favicons, Open Graph, Twitter cards, and more.
Component | Purpose |
---|---|
Author | Meta author |
Canonical | Canonical link |
Description | Meta description |
Favicon | Favicon and touch icons |
Follow | Robots follow/nofollow |
Head | All-in-one head manager |
Index | Robots index/noindex |
Keywords | Meta keywords |
Link | Generic link elements |
Meta | Generic meta elements |
OpenGraph | Open Graph meta tags |
Script | Script elements |
ThemeColor | Theme color meta tag |
Title | Page title with template support |
Twitter | Twitter card meta tags |
A common and recommended pattern is to let your Layout
component manage your site's <head>
tags using the Head
component. This way, you can:
Layout
.Layout
.Layout
handles all head-related logic and defaults.You can also pass custom elements (for example: analytics scripts) as children to the Head
component in your layout. If your project uses multiple different layouts, consider creating a top-level Root
layout that manages all the Head logic. This way, your Root
layout can wrap your other layouts as children, keeping your head management consistent across the entire site.
---
// layouts/Layout.astro
import Head from "@mannisto/Head.astro";
interface Props {
title?: string
description?: string
keywords?: string[]
// Other props you want to make configurable from pages
}
const {
title = "Default Title",
description = "Default description foo faa lorem ipsum",
keywords = ["Default", "Keywords"]
} = Astro.props;
---
<!DOCTYPE html>
<html lang="en">
<Head
title={title}
template="%s | Acme Studio"
description={description}
image="/images/social-banner.jpg"
keywords={keywords}
author="Acme Studio"
themeColor="#1a1a1a"
>
<script src="https://faa-analytics.example?id=123456"></script>
<script src="https://foo-analytics.example?id=123456"></script>
</Head>
<body>
<slot/>
</body>
</html>
---
// pages/index.astro
import Layout from "../layouts/Layout.astro"
---
<Layout
title="Homepage"
description="Welcome to my foo faa lorem ipsum"
>
<!-- My page content ... -->
</Layout>
Prop | Type | Description | Default |
---|---|---|---|
value | string | Author name/content | undefined |
<Head author="Jane Doe" />
---
import Head from "@mannisto/Author.astro";
---
<Author value="Jane Doe" />
Prop | Type | Description | Default |
---|---|---|---|
value | string | Canonical URL | undefined |
<Head canonical="https://example.com/page" />
---
import Head from "@mannisto/Canonical.astro";
---
<Canonical value="https://example.com/page" />
Prop | Type | Description | Default |
---|---|---|---|
value | string | Meta description | undefined |
<Head description="A page description." />
<Description value="A page description." />
Prop | Type | Description | Default |
---|---|---|---|
favicons | FaviconLink[] | Array of favicon configs | favicon.ico |
By default the app expects one favicon.ico
file in the root of the public
folder, if the prop is left empty. Preset options are ico
, png
, svg
, or apple
.
<Head
favicons={[
{ preset: "ico", href: "/favicon/favicon.ico" },
{ preset: "png", href: "/favicon/favicon-16.png", size: 16 },
{ preset: "png", href: "/favicon/favicon-32.png", size: 32 },
{ preset: "png", href: "/favicon/favicon-192.png", size: 192 },
{ preset: "png", href: "/favicon/favicon-512.png", size: 512 },
{ preset: "apple", href: "/favicon/apple-touch-icon.png", size: 180 }
]}
/>
---
import Head from "@mannisto/Favicon.astro";
---
<Favicon icons={[
{ preset: "ico", href: "favicon.ico" },
]} />
Prop | Type | Description | Default |
---|---|---|---|
value | boolean | Allow following links | undefined |
<Head follow={true} />
---
import Head from "@mannisto/Follow.astro";
---
<Follow value={true} />
The Head
component is the main component that handles all head elements in one place.
Prop | Type | Description | Default |
---|---|---|---|
title | string | Page title | "Untitled" |
template | string | Title template with %s placeholder | undefined |
description | string | Meta description | undefined |
image | string | Social sharing image URL | undefined |
keywords | string[] | Meta keywords array | undefined |
index | boolean | Allow search engine indexing | true |
follow | boolean | Allow following links | true |
canonical | string | Canonical URL | undefined |
author | string | Page author | undefined |
themeColor | string | Browser theme color | undefined |
favicons | FaviconLink[] | Array of favicon configurations | "favicon.ico" |
---
import Head from "@mannisto/Head.astro";
---
<Head
title="About Us"
template="%s | Acme Studio"
description="Learn about our company and mission"
image="/images/social-banner.jpg"
keywords={["company", "about", "mission"]}
index={true}
follow={true}
canonical="https://example.com/about"
author="Acme Studio"
themeColor="#1a1a1a"
favicons={[
{ icon: "ico", href: "/favicon/favicon.ico" },
{ icon: "png", href: "/favicon/favicon-16.png", size: 16 },
{ icon: "png", href: "/favicon/favicon-32.png", size: 32 },
{ icon: "png", href: "/favicon/favicon-192.png", size: 192 },
{ icon: "png", href: "/favicon/favicon-512.png", size: 512 },
{ icon: "apple", href: "/favicon/apple-touch-icon.png", size: 180 }
]}
/>
Prop | Type | Description | Default |
---|---|---|---|
value | boolean | Allow search engine indexing | undefined |
<Head index={true} />
---
import Head from "@mannisto/Index.astro";
---
<Index value={true} />
Prop | Type | Description | Default |
---|---|---|---|
value | string[] | Meta keywords array | undefined |
<Head keywords={["astro", "web", "components"]} />
---
import Head from "@mannisto/Keywords.astro";
---
<Keywords value={["astro", "web", "components"]} />
Prop | Type | Description | Default |
---|---|---|---|
rel | string | Link relationship | undefined |
href | string | Link URL or path | undefined |
as | string | Resource type for preload, etc. | undefined |
blocking | string | Blocking tokens | undefined |
crossorigin | string | CORS setting | undefined |
disabled | boolean | Disable stylesheet | undefined |
fetchpriority | string | Fetch priority | undefined |
hreflang | string | Language of resource | undefined |
imagesizes | string | Preload image sizes | undefined |
imagesrcset | string | Preload image srcset | undefined |
integrity | string | Subresource integrity | undefined |
media | string | Media query | undefined |
referrerpolicy | string | Referrer policy | undefined |
sizes | string | Icon sizes | undefined |
title | string | Alternate stylesheet title | undefined |
type | string | MIME type | undefined |
[key] | any | Any additional custom attributes | undefined |
<Head
links={[
{ rel: "icon", href: "/favicon-32.png", type: "image/png", sizes: "32x32" },
{ rel: "stylesheet", href: "https://cdn.example.com/fonts/fake-font.css" },
{ rel: "preconnect", href: "https://fonts.example.com", crossorigin: "anonymous" }
]}
/>
---
import Head from "@mannisto/Link.astro";
---
<Link rel="icon" href="/favicon-32.png" type="image/png" sizes="32x32" />
<Link rel="stylesheet" href="https://cdn.example.com/fonts/fake-font.css" />
<Link rel="preconnect" href="https://fonts.example.com" crossorigin="anonymous" />
Prop | Type | Description | Default |
---|---|---|---|
charset | string | Character encoding | "utf-8" |
content | string | Value of the meta tag | undefined |
httpEquiv | string | HTTP header equivalent | undefined |
media | string | Media query for the meta tag | undefined |
name | string | Name of the meta tag | undefined |
property | string | Property (for OpenGraph, etc.) | undefined |
[key] | any | Any additional custom attributes | undefined |
<Head
meta={[
{ name: "viewport", content: "width=device-width, initial-scale=1" },
{ httpEquiv: "X-UA-Compatible", content: "IE=edge" }
]}
/>
---
import Head from "@mannisto/Meta.astro";
---
<Meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta httpEquiv="X-UA-Compatible" content="IE=edge" />
Prop | Type | Description | Default |
---|---|---|---|
title | string | Open Graph title | undefined |
description | string | Open Graph description | undefined |
image | string | Open Graph image URL | undefined |
url | string | Open Graph URL | undefined |
type | string | Open Graph type | "website" |
If you use the Head
component and do not provide OpenGraph props, it will automatically use the page's title, description, canonical URL, and image. You can override any of these by passing an openGraph
prop to Head
.
<Head openGraph={{
title: "About Us",
description: "Learn about our company",
image: "/banner.png",
url: "https://example.com/about"
}} />
---
import Head from "@mannisto/OpenGraph.astro";
---
<OpenGraph
title="About Us"
description="Learn about our company"
image="/banner.png"
url="https://example.com/about"
/>
Prop | Type | Description | Default |
---|---|---|---|
src | string | Script source URL | undefined |
type | string | Script MIME type | undefined |
async | boolean | Load script asynchronously | undefined |
defer | boolean | Defer script execution | undefined |
crossorigin | string | CORS setting | undefined |
integrity | string | Subresource integrity | undefined |
attributionsrc | string | Attribution reporting source | undefined |
blocking | string | Blocking tokens | undefined |
fetchpriority | string | Fetch priority | undefined |
nomodule | boolean | Only for browsers without modules | undefined |
nonce | string | Cryptographic nonce | undefined |
referrerpolicy | string | Referrer policy | undefined |
<Head
scripts={[
{ src: "https://cdn.example.com/analytics.js", async: true },
{ content: "console.log('Hello from inline module!')", type: "module" }
]}
/>
---
import Head from "@mannisto/Script.astro";
---
<Script src="https://cdn.example.com/analytics.js" async />
<Script type="module">console.log('Hello from inline module!')</Script>
Prop | Type | Description | Default |
---|---|---|---|
value | string | Theme color | undefined |
<Head themeColor="#ffffff" />
---
import Head from "@mannisto/ThemeColor.astro";
---
<ThemeColor value="#ffffff" />
Prop | Type | Description | Default |
---|---|---|---|
value | string | Page title | undefined |
template | string | Title template with %s | "%s" |
<Head title="About Us" template="%s | Acme Studio" />
---
import Head from "@mannisto/Title.astro";
---
<Title value="About Us" template="%s | Acme Studio" />
Prop | Type | Description | Default |
---|---|---|---|
title | string | Twitter card title | undefined |
description | string | Twitter card description | undefined |
image | string | Twitter card image URL | undefined |
card | string | Card type | "summary_large_image" |
If you use the Head
component and do not provide Twitter props, it will automatically fall back to the page's title, description, and image. You can override any of these by passing a twitter
prop to Head
.
<Head twitter={{
title: "About Us",
description: "Learn about our company",
image: "/twitter-og.jpg",
card: "summary"
}} />
---
import Head from "@mannisto/Twitter.astro";
---
<Twitter
title="About Us"
description="Learn about our company"
image="/twitter-og.jpg"
card="summary"
/>
FAQs
Composable Astro components for managing your HTML <head> in Astro projects.
We found that @mannisto/astro-head demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
A data handling bug in OSV.dev caused disputed CVEs to disappear from vulnerability feeds until a recent fix restored over 500 advisories.
Research
/Security News
175 malicious npm packages (26k+ downloads) used unpkg CDN to host redirect scripts for a credential-phishing campaign targeting 135+ organizations worldwide.
Security News
Python 3.14 adds template strings, deferred annotations, and subinterpreters, plus free-threaded mode, an experimental JIT, and Sigstore verification.