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

@plugdash/shortlink

v0.2.2

Published

Short URLs for EmDash posts - shareable links created on publish

Readme

@plugdash/shortlink

Every CMS post deserves a short URL, but most setups leave that to external services. Generates short URLs backed by EmDash's KV store and writes them to post metadata on publish. Ships CopyLink.astro - a copy-to-clipboard button that fits the engagement bar. The EmDash equivalent of Pretty Links (basic tier).

Install

pnpm add @plugdash/shortlink

Register

// astro.config.mjs
import { defineConfig } from "astro/config";
import emdash from "emdash";
import { shortlinkPlugin } from "@plugdash/shortlink";

export default defineConfig({
  integrations: [
    emdash({
      plugins: [shortlinkPlugin()],
    }),
  ],
});

Add the redirect page

The plugin ships a ready-to-use Astro page. Create one file in your site:

---
// src/pages/s/[code].astro
import RedirectPage from "@plugdash/shortlink/RedirectPage.astro";
---
<RedirectPage />

That's it. The page resolves the code server-side, issues a 301 redirect to the target on hit, returns 404 for unknown codes, and 410 Gone for expired links. Requires Astro output: "server" or output: "hybrid".

Redirect page props (optional)

| Prop | Type | Default | Description | | ------------- | -------------------- | ------- | ----------------------------------- | | status | 301 \| 302 \| 307 \| 308 | 301 | Redirect status code | | expiredHtml | string | default | HTML body for 410 Gone responses | | notFoundHtml | string | default | HTML body for 404 responses |

To customise the expired/not-found pages:

---
import RedirectPage from "@plugdash/shortlink/RedirectPage.astro";
---
<RedirectPage
  status={302}
  expiredHtml="<h1>This link retired.</h1>"
  notFoundHtml="<h1>No such link.</h1>"
/>

If you need a different prefix than /s/, place the page at a matching path (e.g. src/pages/link/[code].astro) and update the plugin's prefix config in the admin UI.

Config options

Configuration is stored in the plugin's KV store and can be changed via the admin UI at /_emdash/admin/shortlinks. Defaults are seeded on install.

| Option | Type | Default | Description | | ---------- | --------- | ------- | -------------------------------------------------- | | prefix | string | /s/ | Route prefix for short URLs | | codeLength | number | 4 | Length of auto-generated codes (2-12) | | autoCreate | boolean | true | Create shortlinks automatically on publish | | domain | string | site URL | Custom domain for full short URLs |

Companion component

---
import CopyLink from "@plugdash/shortlink/CopyLink.astro";
---

<CopyLink post={post} />

Props

| Prop | Type | Default | Description | | ------- | -------------------------------- | ---------- | ------------------------------ | | post | Record<string, unknown> | required | The post object from EmDash | | showUrl | boolean | false | Show short URL text next to icon | | variant | "circle" \| "pill" \| "ghost" | "circle" | Visual style | | size | "sm" \| "md" \| "lg" | "md" | Button size | | theme | "auto" \| "dark" \| "light" | "auto" | Color theme | | class | string | "" | Additional CSS class |

CSS custom properties

| Token | Default | Description | | ---------------------------------- | ---------------------------------------- | ------------------- | | --plugdash-engage-size | 2rem | Circle button size | | --plugdash-engage-radius | 9999px | Border radius | | --plugdash-engage-border | rgb(from currentColor r g b / 0.15) | Border color | | --plugdash-engage-bg | rgb(from currentColor r g b / 0.04) | Background | | --plugdash-engage-bg-hover | rgb(from currentColor r g b / 0.08) | Hover background | | --plugdash-engage-transition | 150ms ease | Transition timing | | --plugdash-copy-success-color | #22c55e | Check icon color | | --plugdash-copy-success-duration | 2000ms | Check display time | | --plugdash-font-ui | "Lexend", system-ui, sans-serif | UI font family | | --plugdash-font-mono | "IBM Plex Mono", monospace | URL text font |

Metadata written

On publish, writes to post.data.metadata.shortlink:

{
  code: string    // e.g. "ab3k"
  url: string     // e.g. "/s/ab3k"
  fullUrl: string // e.g. "https://example.com/s/ab3k"
}

What it does

  • Fires on content:afterSave when status is published
  • Generates a random alphanumeric code (configurable length)
  • Stores shortlink data in KV with a reverse index for O(1) duplicate checks
  • Writes shortlink metadata to the content record (read-merge-write)
  • Provides a public resolve route for redirect lookup
  • Ships a Block Kit admin page for managing shortlinks and creating custom slugs
  • Handles code collisions with retry and length escalation

What it does not do

  • Does not create shortlinks for drafts, archived, or scheduled content
  • Does not claim the /s/[code] URL path by itself - EmDash plugins cannot mount top-level routes, so you drop RedirectPage.astro into your site's src/pages/s/[code].astro (one line)
  • Does not track click counts - that is the clickcount plugin's job
  • Does not generate cryptographically random codes - do not use shortlinks for secret or access-controlled URLs
  • Does not delete shortlinks when content is deleted (orphaned links stay until manually removed via admin)
  • Does not support custom slugs via the content editor - use the admin page