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

tinybeast-services

v2.0.63

Published

This nuxt theme is suitable for service website

Readme

Tiny Beast theme: services

This nuxt theme is suitable for service website

Setup

Make sure to install the dependencies:

pnpm install

Working on your layer

The layer is at the root of this repository, it is exactly like a regular Nuxt project, except you can publish it on NPM.

The .playground directory should help you on trying your layer during development.

Running pnpm dev will prepare and boot .playground directory, which imports your layer itself.

Distributing your layer

Your Nuxt layer is shaped exactly the same as any other Nuxt project, except you can publish it on NPM.

To do so, you only have to check if files in package.json are valid, then run:

npm publish --access public

Once done, your users will only have to run:

npm install --save your-layer

Then add the dependency to their extends in nuxt.config:

defineNuxtConfig({
  extends: 'tinybeast-services'
})

Development Server

Start the development server on http://localhost:3000

pnpm dev

Production

Build the application for production:

pnpm build

Or statically generate it with:

pnpm generate

Locally preview production build:

pnpm preview

Storyblok

Storyblok is used for content management. To pull components from Storyblok, run:

storyblok pull-components --space <space_id>

storyblok cli 4

storyblok components --space <space_id> pull

To push components to Storyblok, run:

storyblok push-components --space <space_id> <path_to_schema_file>

storyblok cli 4

storyblok components push --space <space_id> --from <path_to_schema_file or space_id>

Required Environment Variables

  • BASE_URL=your_base_url
  • NUXT_PUBLIC_NODE_ENV=your_node_env
  • STORYBLOK_ACCESS_TOKEN=your_storyblok_access_token

Favicons

Add the following favicon files to the public/ directory (or .playground/public/ for development):

  • favicon.ico - Standard favicon (16x16 or 32x32)
  • favicon-16x16.png - 16x16 PNG favicon
  • favicon-32x32.png - 32x32 PNG favicon
  • apple-touch-icon.png - 180x180 PNG for Apple devices

These are configured in nuxt.config.ts and will be automatically included in all pages.

Internationalization (i18n)

This theme supports dynamic locale configuration through environment variables.

Default Behavior

By default, the site runs with Danish only (da) as a single-language website with clean URLs (no language prefixes).

Adding Multiple Languages

To enable multiple languages, set the following environment variables:

# Add multiple languages (JSON format)
NUXT_PUBLIC_I18N_LOCALES='[{"code":"da","name":"Danish","language":"da-DK"},{"code":"en","name":"English","language":"en-US"}]'

# Optionally change the default locale
NUXT_PUBLIC_I18N_DEFAULT_LOCALE='da'

Settings in Storyblok

You have to go and enable internationalization in Storyblok. Go to Settings > Internationalization and enable it. If you want AI translation, you can enable it in Settings > Labs > AI Translation.

Translatable Slugs (Field-Based Translation)

When using field-based translation mode (default), you can configure translatable slugs in Storyblok:

  1. Go to your story in Storyblok
  2. Click on the "Translate" tab
  3. Enable "Translatable slug" for each language
  4. Set custom slugs for each language (e.g., /contact in English becomes /kontakt in Danish)

Important: With field-based translation and the Translatable Slugs app:

  • The default language story lives at the original slug (e.g., /contact)
  • Translated versions use their translated slugs with language prefix (e.g., /da/kontakt)
  • The system uses Storyblok's alternates array (from Links API) or translated_slugs array (from Story API)
  • Only the translated slug URL will work for non-default languages (e.g., /da/kontakt works, /da/contact returns 404)
  • Sitemap automatically generates correct URLs for each language
  • Internal links in menu/footer automatically use translated slugs

Example:

  • English (default): /contact
  • Danish: /da/kontakt (NOT /da/contact - this will 404)
  • French: /fr/contact-nous (NOT /fr/contact - this will 404)

How it works:

  1. In Storyblok, the story has slug: "contact" and translated_slugs: [{lang: "da", path: "kontakt"}]
  2. When fetching with language: "da", Storyblok only recognizes the slug kontakt
  3. The menu/footer links check the alternates array and use the translated path
  4. The sitemap generates separate entries for each language with correct slugs

Examples

English + Danish:

NUXT_PUBLIC_I18N_LOCALES='[{"code":"da","name":"Danish","language":"da-DK"},{"code":"en","name":"English","language":"en-US"}]'

Multiple languages:

NUXT_PUBLIC_I18N_LOCALES='[{"code":"da","name":"Danish","language":"da-DK"},{"code":"en","name":"English","language":"en-US"},{"code":"fr","name":"French","language":"fr-FR"}]'

SEO Features

The theme automatically handles:

  • ✅ Canonical URLs with proper locale prefixes
  • ✅ Hreflang alternate links for international SEO
  • ✅ Open Graph locale tags (og:locale, og:locale:alternate)
  • ✅ Proper lang and dir attributes on HTML elements
  • ✅ Language-specific meta tags

URL Structure

  • Single language (Danish): /about, /contact
  • Multiple languages: /about (Danish), /en/about (English)

Changelog for important updates that either could break or should be known

2.0.23

  • Added support for contact form in CtaVariant2, component CtaVariant2.json should be pulled and pushed to Storyblok for field update.

2.0.25

  • Added support for a new form builder using resend for email notifications in HeroVariant2, component HeroVariant2.json should be pulled and pushed to Storyblok for field and component update. You should delete the old contact_form and form_item components and make sure you go through components where this is used and update them to use the new form builder.
  • new env variables needed:
    • RESEND_API_KEY=your_resend_api_key_here
    • [email protected]
    • [email protected]
    • FORM_EMAIL_SUBJECT="Ny formular indsendelse"
    • FORM_EMAIL_DESCRIPTION="Du har modtaget en ny formular indsendelse med følgende detaljer:"
  • components that you need to pull push and update: (main component.json are updated with all latest components but you still need to delete old components)
    • SbForm
    • SbFormField
    • form_field_option
    • HeroVariant3
    • hero-variant-2
    • CtaVariant2

2.0.30

  • Added the following new components that needs to be pushed to your project:
    • CardGridWithFilter
    • CardGridWithFilterItem
    • Progress
    • ProgressStep
    • Timeline
    • TimelineEvent
    • BentoGrid
    • BentoGridItem

2.0.48

  • Translatable Slugs Support: Added full support for Storyblok's translatable slugs feature in field-based translation mode
    • Pages now correctly resolve when accessed via translated slugs (e.g., /da/kontakt for Danish contact page)
    • Sitemap automatically generates correct URLs with translated slugs for each language
    • Internal links in components automatically use translated slugs when available
    • Prevents duplicate content issues by using language-specific slugs
    • Updated files:
      • app/pages/[...slug].vue - Added translated slug resolution logic
      • server/api/__sitemap__/urls.ts - Enhanced sitemap generation with translated slug support
      • app/composables/useStoryblokLinks.js - Added translated slug handling for internal links
    • See "Translatable Slugs (Field-Based Translation)" section for setup instructions

2.0.49

  • URL Improvements:
    • Configured Nuxt to remove trailing slashes from all URLs for cleaner, more SEO-friendly links
    • Added global middleware to redirect URLs with trailing slashes to non-trailing slash versions (301 redirect)
    • Ensures consistent URL structure across all hosting platforms (Vercel, Netlify, etc.)
    • Updated all components to use centralized getFormattedStoryblokLink composable for consistent link handling
    • Components updated: GlobalMenu, GlobalFooter, PricingVariant1, CardGridWithFilter, LogoCloudVariant2