diff --git a/.changeset/gold-sloths-unite.md b/.changeset/gold-sloths-unite.md
new file mode 100644
index 00000000000..d81e7ea1640
--- /dev/null
+++ b/.changeset/gold-sloths-unite.md
@@ -0,0 +1,24 @@
+---
+'@astrojs/starlight': minor
+---
+
+Makes `social` configuration more flexible.
+
+⚠️ **BREAKING CHANGE:** The `social` configuration option has changed syntax. You will need to update this in `astro.config.mjs` when upgrading.
+
+Previously, a limited set of platforms were supported using a shorthand syntax with labels built in to Starlight. While convenient, this approach was less flexible and required dedicated code for each social platform added.
+
+Now, you must specify the icon and label for each social link explicitly and you can use any of [Starlight’s built-in icons](https://starlight.astro.build/reference/icons/) for social links.
+
+The following example shows updating the old `social` syntax to the new:
+
+```diff
+- social: {
+- github: 'https://github.com/withastro/starlight',
+- discord: 'https://astro.build/chat',
+- },
++ social: [
++ { icon: 'github', label: 'GitHub', href: 'https://github.com/withastro/starlight' },
++ { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' },
++ ],
+```
diff --git a/.changeset/swift-hotels-move.md b/.changeset/swift-hotels-move.md
new file mode 100644
index 00000000000..78a43e6d032
--- /dev/null
+++ b/.changeset/swift-hotels-move.md
@@ -0,0 +1,5 @@
+---
+'@astrojs/starlight': patch
+---
+
+Fixes Starlight’s autogenerated `` tags when a Twitter link is set in `social` config. Previously these incorrectly rendered `content="/username"` and now correctly render `content="@username"`.
diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs
index 9906df38447..7923a0e74bc 100644
--- a/docs/astro.config.mjs
+++ b/docs/astro.config.mjs
@@ -45,10 +45,10 @@ export default defineConfig({
editLink: {
baseUrl: 'https://github.com/withastro/starlight/edit/main/docs/',
},
- social: {
- github: 'https://github.com/withastro/starlight',
- discord: 'https://astro.build/chat',
- },
+ social: [
+ { icon: 'github', label: 'GitHub', href: 'https://github.com/withastro/starlight' },
+ { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' },
+ ],
head: [
{
tag: 'script',
diff --git a/docs/src/components/social-links-type.astro b/docs/src/components/social-links-type.astro
index fc62630de1a..d60e2071639 100644
--- a/docs/src/components/social-links-type.astro
+++ b/docs/src/components/social-links-type.astro
@@ -1,7 +1,10 @@
---
-import { socialLinks } from '../../../packages/starlight/schemas/social';
-
-const socials = [...socialLinks].sort((a, b) => a.localeCompare(b, 'en'));
+import { getRelativeLocaleUrl } from 'astro:i18n';
+const href = getRelativeLocaleUrl(Astro.currentLocale ?? 'en', '/reference/icons/');
---
-{`Partial `'${social}'`).join(' | ')}, string>>`}
+
+
+ label: string; icon: StarlightIcon; href: string
+
+
diff --git a/docs/src/content/docs/guides/customization.mdx b/docs/src/content/docs/guides/customization.mdx
index c77b0cee610..c53fa0ba982 100644
--- a/docs/src/content/docs/guides/customization.mdx
+++ b/docs/src/content/docs/guides/customization.mdx
@@ -200,10 +200,15 @@ defineConfig({
Starlight has built-in support for adding links to your social media accounts to the site header via the [`social`](/reference/configuration/#social) option in the Starlight integration.
-You can find a full list of supported link icons in the [Configuration Reference](/reference/configuration/#social).
-Let us know on GitHub or Discord if you need support for another service!
+Each entry in the `social` array must be an object with three properties:
-```js {9-12}
+- `icon`: one of Starlight’s [built-in icons](/reference/icons/), e.g. `"github"`.
+- `label`: an accessible label for the link, e.g. `"GitHub"`.
+- `href`: the URL for the link, e.g. `"https://github.com/withastro/starlight"`.
+
+The following example adds links to the Astro Discord chat and the Starlight GitHub repository:
+
+```js {9-16}
// astro.config.mjs
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
@@ -212,10 +217,14 @@ export default defineConfig({
integrations: [
starlight({
title: 'Docs With Social Links',
- social: {
- discord: 'https://astro.build/chat',
- github: 'https://github.com/withastro/starlight',
- },
+ social: [
+ { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' },
+ {
+ icon: 'github',
+ label: 'GitHub',
+ href: 'https://github.com/withastro/starlight',
+ },
+ ],
}),
],
});
diff --git a/docs/src/content/docs/reference/configuration.mdx b/docs/src/content/docs/reference/configuration.mdx
index 62107d8c4a2..8a9f2638ac8 100644
--- a/docs/src/content/docs/reference/configuration.mdx
+++ b/docs/src/content/docs/reference/configuration.mdx
@@ -341,28 +341,21 @@ The default locale will be used to provide fallback content where translations a
### `social`
-import SocialLinksType from '~/components/social-links-type.astro';
+**type:** {`Array<{ label: string; icon: `}[StarlightIcon](/reference/icons/){`; href: string }>`}
-**type:**
-
-Optional details about the social media accounts for this site. Adding any of these will display them as icon links in the site header.
+Optional details about the social media accounts for this site.
+Each entry will be displayed as an icon link in the site header.
```js
starlight({
- social: {
- codeberg: 'https://codeberg.org/knut/examples',
- discord: 'https://astro.build/chat',
- github: 'https://github.com/withastro/starlight',
- gitlab: 'https://gitlab.com/delucis',
- linkedin: 'https://www.linkedin.com/company/astroinc',
- mastodon: 'https://m.webtoo.ls/@astro',
- threads: 'https://www.threads.net/@nmoodev',
- twitch: 'https://www.twitch.tv/bholmesdev',
- twitter: 'https://twitter.com/astrodotbuild',
- 'x.com': 'https://x.com/astrodotbuild',
- youtube: 'https://youtube.com/@astrodotbuild',
- },
-});
+ social: [
+ { icon: 'codeberg', label: 'Codeberg', href: 'https://codeberg.org/knut' },
+ { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' },
+ { icon: 'github', label: 'GitHub', href: 'https://github.com/withastro' },
+ { icon: 'gitlab', label: 'GitLab', href: 'https://gitlab.com/delucis' },
+ { icon: 'mastodon', label: 'Mastodon', href: 'https://m.webtoo.ls/@astro' },
+ ],
+}),
```
### `customCss`
diff --git a/docs/src/content/docs/reference/plugins.md b/docs/src/content/docs/reference/plugins.md
index d170a4fd1af..1c46004aad5 100644
--- a/docs/src/content/docs/reference/plugins.md
+++ b/docs/src/content/docs/reference/plugins.md
@@ -163,19 +163,23 @@ Provide the root-level configuration keys you want to override.
To update nested configuration values, you must provide the entire nested object.
To extend an existing config option without overriding it, spread the existing value into your new value.
-In the following example, a new [`social`](/reference/configuration/#social) media account is added to the existing configuration by spreading `config.social` into the new `social` object:
+In the following example, a new [`social`](/reference/configuration/#social) media account is added to the existing configuration by spreading `config.social` into the new `social` array:
-```ts {6-11}
+```ts {6-15}
// plugin.ts
export default {
name: 'add-twitter-plugin',
hooks: {
'config:setup'({ config, updateConfig }) {
updateConfig({
- social: {
+ social: [
...config.social,
- twitter: 'https://twitter.com/astrodotbuild',
- },
+ {
+ icon: 'twitter',
+ label: 'Twitter',
+ href: 'https://twitter.com/astrodotbuild',
+ },
+ ],
});
},
},
diff --git a/examples/basics/astro.config.mjs b/examples/basics/astro.config.mjs
index 1b393646856..9a25601baa4 100644
--- a/examples/basics/astro.config.mjs
+++ b/examples/basics/astro.config.mjs
@@ -7,9 +7,7 @@ export default defineConfig({
integrations: [
starlight({
title: 'My Docs',
- social: {
- github: 'https://github.com/withastro/starlight',
- },
+ social: [{ icon: 'github', label: 'GitHub', href: 'https://github.com/withastro/starlight' }],
sidebar: [
{
label: 'Guides',
diff --git a/examples/markdoc/astro.config.mjs b/examples/markdoc/astro.config.mjs
index 7f814cbb5af..949f3fcc1bc 100644
--- a/examples/markdoc/astro.config.mjs
+++ b/examples/markdoc/astro.config.mjs
@@ -9,9 +9,7 @@ export default defineConfig({
markdoc(),
starlight({
title: 'My Docs',
- social: {
- github: 'https://github.com/withastro/starlight',
- },
+ social: [{ icon: 'github', label: 'GitHub', href: 'https://github.com/withastro/starlight' }],
sidebar: [
{
label: 'Guides',
diff --git a/examples/tailwind/astro.config.mjs b/examples/tailwind/astro.config.mjs
index a3a3ba5ee08..872a2896deb 100644
--- a/examples/tailwind/astro.config.mjs
+++ b/examples/tailwind/astro.config.mjs
@@ -8,9 +8,7 @@ export default defineConfig({
integrations: [
starlight({
title: 'Docs with Tailwind',
- social: {
- github: 'https://github.com/withastro/starlight',
- },
+ social: [{ icon: 'github', label: 'GitHub', href: 'https://github.com/withastro/starlight' }],
sidebar: [
{
label: 'Guides',
diff --git a/packages/starlight/__tests__/basics/config-errors.test.ts b/packages/starlight/__tests__/basics/config-errors.test.ts
index a010015f80c..6f9dad71943 100644
--- a/packages/starlight/__tests__/basics/config-errors.test.ts
+++ b/packages/starlight/__tests__/basics/config-errors.test.ts
@@ -122,8 +122,10 @@ test('errors with bad social icon config', () => {
"[AstroUserError]:
Invalid config passed to starlight integration
Hint:
- **social.unknown**: Invalid enum value. Expected 'twitter' | 'mastodon' | 'github' | 'gitlab' | 'bitbucket' | 'discord' | 'gitter' | 'codeberg' | 'codePen' | 'youtube' | 'threads' | 'linkedin' | 'twitch' | 'azureDevOps' | 'microsoftTeams' | 'instagram' | 'stackOverflow' | 'x.com' | 'telegram' | 'rss' | 'facebook' | 'email' | 'reddit' | 'patreon' | 'signal' | 'slack' | 'matrix' | 'openCollective' | 'hackerOne' | 'blueSky' | 'discourse' | 'zulip' | 'pinterest' | 'tiktok' | 'nostr' | 'backstage' | 'farcaster' | 'confluence' | 'jira' | 'storybook' | 'npm' | 'sourcehut' | 'substack', received 'unknown'
- **social.unknown**: Invalid url"
+ Starlight v0.33.0 changed the \`social\` configuration syntax. Please specify an array of link items instead of an object.
+ See the Starlight changelog for details: https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md#0330
+
+ **social**: Expected type \`"array"\`, received \`"object"\`"
`
);
});
diff --git a/packages/starlight/__tests__/basics/user-config.test.ts b/packages/starlight/__tests__/basics/user-config.test.ts
index e3eeb723df3..c0f115f65c4 100644
--- a/packages/starlight/__tests__/basics/user-config.test.ts
+++ b/packages/starlight/__tests__/basics/user-config.test.ts
@@ -4,11 +4,11 @@ import { StarlightConfigSchema } from '../../utils/user-config';
test('preserve social config order', () => {
const config = StarlightConfigSchema.parse({
title: 'Test',
- social: {
- twitch: 'https://www.twitch.tv/bholmesdev',
- github: 'https://github.com/withastro/starlight',
- discord: 'https://astro.build/chat',
- },
+ social: [
+ { icon: 'twitch', label: 'Twitch', href: 'https://www.twitch.tv/bholmesdev' },
+ { icon: 'github', label: 'GitHub', href: 'https://github.com/withastro/starlight' },
+ { icon: 'discord', label: 'Discord', href: 'https://astro.build/chat' },
+ ],
});
- expect(Object.keys(config.social || {})).toEqual(['twitch', 'github', 'discord']);
+ expect((config.social || []).map(({ icon }) => icon)).toEqual(['twitch', 'github', 'discord']);
});
diff --git a/packages/starlight/__tests__/head/head.test.ts b/packages/starlight/__tests__/head/head.test.ts
index 966635ef47c..46205b89ff3 100644
--- a/packages/starlight/__tests__/head/head.test.ts
+++ b/packages/starlight/__tests__/head/head.test.ts
@@ -23,6 +23,18 @@ test('includes custom tags defined in the Starlight configuration', () => {
});
});
+test('includes `twitter:site` based on Starlight `social` configuration', () => {
+ const head = getTestHead();
+ expect(head).toContainEqual({
+ tag: 'meta',
+ attrs: {
+ name: 'twitter:site',
+ content: '@astrodotbuild',
+ },
+ content: '',
+ });
+});
+
test('merges two
tags', () => {
const head = getTestHead([{ tag: 'title', content: 'Override', attrs: {} }]);
expect(head.filter((tag) => tag.tag === 'title')).toEqual([
diff --git a/packages/starlight/__tests__/head/vitest.config.ts b/packages/starlight/__tests__/head/vitest.config.ts
index 889b9dd5306..b13fef59216 100644
--- a/packages/starlight/__tests__/head/vitest.config.ts
+++ b/packages/starlight/__tests__/head/vitest.config.ts
@@ -17,4 +17,5 @@ export default defineVitestConfig({
},
},
],
+ social: [{ icon: 'twitter', label: 'Twitter', href: 'https://twitter.com/astrodotbuild' }],
});
diff --git a/packages/starlight/components/SocialIcons.astro b/packages/starlight/components/SocialIcons.astro
index ad9056ff05c..b8c5bd4c352 100644
--- a/packages/starlight/components/SocialIcons.astro
+++ b/packages/starlight/components/SocialIcons.astro
@@ -2,18 +2,16 @@
import config from 'virtual:starlight/user-config';
import Icon from '../user-components/Icon.astro';
-type Platform = keyof NonNullable;
-type SocialConfig = NonNullable[Platform]>;
-const links = Object.entries(config.social || {}) as [Platform, SocialConfig][];
+const links = config.social || [];
---
{
links.length > 0 && (
<>
- {links.map(([platform, { label, url }]) => (
-
+ {links.map(({ label, href, icon }) => (
+
{label}
-
+
))}
>
diff --git a/packages/starlight/schemas/hero.ts b/packages/starlight/schemas/hero.ts
index 86105523596..e1af1f90676 100644
--- a/packages/starlight/schemas/hero.ts
+++ b/packages/starlight/schemas/hero.ts
@@ -1,8 +1,6 @@
import { z } from 'astro/zod';
import type { SchemaContext } from 'astro:content';
-import { Icons, type StarlightIcon } from '../components/Icons';
-
-const iconNames = Object.keys(Icons) as [StarlightIcon, ...StarlightIcon[]];
+import { IconSchema } from './icon';
export const HeroSchema = ({ image }: SchemaContext) =>
z.object({
@@ -55,9 +53,9 @@ export const HeroSchema = ({ image }: SchemaContext) =>
* Can be an inline `