npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fujocoded/zod-transform-socials

v0.1.0

Published

A Zod schema + transformer for social URLs

Readme

@fujocoded/zod-transform-socials

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).

Setup

  1. 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 add zod to your own package.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, zod is a peer dependency and doesn’t get packaged with this library anymore.

  2. Pick the entry that matches the zod in 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"

How to use it

[!NOTE] Want a project you can copy from? The __examples__/ folder has one per Astro / Zod combination:

1. List the contacts

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/essentialrandomness

In 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". Any AstroIcon name 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:firefox

2. Define the schema

Drop 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,
    });
});

3. Read the parsed contacts

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 was
  • platform => the matched platform name ("tumblr", "github", "mastodon", etc.), or "custom" if nothing matched
  • username => extracted from the URL where possible, otherwise null
  • icon => a ready-to-use AstroIcon name (e.g. simple-icons:tumblr), or null for "custom"

You can find the full list of platform names the transformer recognises in the SOCIAL_TYPES union in src/social-links.ts.

Extra stuff

Typing component props

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;
}

Setting known domains

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.