Transforms a list of social media contacts into a list of username + website name + site icon with the power of Zod transforms (and, optionally, Astro).
-
Install the package:
npm install @fujocoded/zod-transform-socials
[!IMPORTANT]
For non-Astro projects, if you see
Cannot find module 'zod', it means you need should addzodto your ownpackage.json.# Zod 3 projects npm install @fujocoded/zod-transform-socials zod@^3.25.0 # Zod 4 projects npm install @fujocoded/zod-transform-socials zod@^4.0.0
Starting with
v0.1.0,zodis a peer dependency and doesn’t get packaged with this library anymore. -
Pick the entry that matches the
zodin your project:- Astro 5 / Zod 3 =>
import { SocialLinks } from "@fujocoded/zod-transform-socials" - Astro 6 / Zod 4 =>
import { SocialLinks } from "@fujocoded/zod-transform-socials/zod4"
- Astro 5 / Zod 3 =>
Note
Want a project you can copy from? The
__examples__/ folder has one per Astro / Zod
combination:
01-astro-5-loader=> Astro 5 (Zod 3)02-astro-6-loader=> Astro 6 (Zod 4)03-zod-3-standalone=> plain Node + Zod 304-zod-4-standalone=> plain Node + Zod 4
Write down the data however you or your content collection want to load it. For example, with YAML:
name: essential-randomness
contacts:
- https://essentialrandomness.com
- https://essential-randomness.tumblr.com
- https://twitter.com/essentialrandom
- url: https://indiepocalypse.social/@essentialrandom
platform: mastodon
- https://github.com/essential-randomness
- https://patreon.com/essentialrandomness
- https://ko-fi.com/essentialrandomnessIn this list, each item must be either:
- a user’s social profile URL (a bare string), or
- an object with an URL + a series of (optional) overrides:
url(required) => the social profile URL.platform(optional) => use when the URL alone can’t identify the platform. For exampke, Mastodon instances live on arbitrary domains.icon(optional) => use when you want a different icon than the default for that platform, or any icon at all for a URL that would otherwise resolve to"custom". AnyAstroIconname works (e.g.simple-icons:firefox).username(optional) => use when the URL doesn’t carry a handle the transformer knows how to extract, or the one it extracted is wrong.
For example, putting a custom icon on a personal homepage that would
otherwise resolve to "custom" with no icon:
name: ms boba
contacts:
- url: https://essentialrandomness.com
icon: simple-icons:firefoxDrop SocialLinks into a content collection (or any other Zod object):
import { SocialLinks } from "@fujocoded/zod-transform-socials";
// zod import depends on version
export const teamCollection = defineCollection({
type: "data",
schema: (tools) =>
z.object({
name: z.name(),
// contacts will contain your list of social URLs
contacts: SocialLinks,
});
});const team = await getCollection("team");
for (const member of team) {
for (const contact of member.data.contacts) {
console.log(contact.platform, contact.username, contact.url);
}
}Each contact in member.data.contacts has been transformed from the
raw input into a flat object with four fields:
{
url: "https://essential-randomness.tumblr.com",
platform: "tumblr",
username: "essential-randomness",
icon: "simple-icons:tumblr",
}url=> whatever the input URL wasplatform=> the matched platform name ("tumblr","github","mastodon", etc.), or"custom"if nothing matchedusername=> extracted from the URL where possible, otherwisenullicon=> a ready-to-useAstroIconname (e.g.simple-icons:tumblr), ornullfor"custom"
You can find the full list of platform names the transformer recognises in the
SOCIAL_TYPES union in src/social-links.ts.
To hint at the shape of this data (for example when passing contacts to a component) use the exported SocialLinksData type:
import type { SocialLinksData } from "@fujocoded/zod-transform-socials";
interface Props {
name: string;
avatar: string;
contacts: SocialLinksData;
}For platforms without a fixed domain, like mastodon, the built-in matchers
can only know a fixed set of domains (e.g. mastodon.social,
mastodon.world). If you use a different instance and you're tired of
spelling out platform: mastodon every time, you can use createSocialsTransformer
and pass platform domains via domains:
import { createSocialsTransformer } from "@fujocoded/zod-transform-socials";
const { SocialLinks, transformSocial } = createSocialsTransformer({
domains: {
mastodon: ["blorbo.social", "tech.lgbt", "indiepocalypse.social"],
},
});
export const teamCollection = defineCollection({
type: "data",
schema: (tools) =>
z.object({
// ...
contacts: SocialLinks,
}),
});Only platforms with a registered URL shape can be configured this way
(currently: mastodon). If you need a platform that isn't covered, please
open a PR to add its URL-shape builder to DOMAIN_PATTERNS in the library.