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

@lalternative/legal

v0.3.0

Published

Shared legal pages for L'Alternative apps (legal notice, cookie policy, pricing terms), publisher identity passed in by the host site

Readme

@lalternative/legal

Shared legal pages for L'Alternative products: legal notice and cookie policy.

The publisher is one legal entity across every product, so the wording that describes who publishes is written once here. What differs per product — prices, subprocessors, retention periods — is not in this package and must not be: a copied subprocessor list is a false declaration under art. 28 GDPR.

Publisher identity stays out of this package

This package is published to the public npm registry. It ships no company registration number, address or civil name. Each site passes its own publisher object from its own code:

import { LegalNotice, type Publisher, type Host } from '@lalternative/legal'

const PUBLISHER: Publisher = {
  name: "L'Alternative Fabrique",
  legalForm: 'entrepreneur individuel (micro-entreprise)',
  address: ['…', '…'],
  registration: '…',
  apeCode: '6201Z',
  publicationDirector: '…',
  vatExempt: true,
}

const HOSTS: Host[] = [
  { name: 'OVH SAS', address: ['2 rue Kellermann', '59100 Roubaix, France'] },
]

export function LegalPage() {
  return (
    <LegalNotice
      publisher={PUBLISHER}
      hosts={HOSTS}
      site={{ product: 'Techtuel', domain: 'techtuel.com', contactEmail: '[email protected]' }}
      updatedAt="2026-09-05"
      locale="fr"
      classNames={{ title: 'font-mono text-3xl font-bold text-ink' }}
    >
      {/* product-specific sections go here: AI processing, subprocessors */}
    </LegalNotice>
  )
}

Cookie policy

strictlyNecessaryOnly drives the legal conclusion the page states. Pass true only while every listed cookie really is necessary to deliver the service the user asked for — session, authentication, display preference. Adding any analytics or advertising cookie ends the consent exemption, and the flag must flip in the same change that adds the tracker.

<CookiesPage
  publisher={PUBLISHER}
  site={SITE}
  hosts={HOSTS}
  updatedAt="2026-09-05"
  strictlyNecessaryOnly
  cookies={[
    { name: 'session_token', purpose: 'Authentification et maintien de session', retention: 'session' },
    { name: 'techtuel_locale', purpose: "Préférence de langue de l'interface", retention: '12 mois' },
  ]}
/>

Pricing terms

The price article of a terms-of-sale page is the same wording for every product; only the figures differ. PricingTerms renders the two sections (prices and billing, price changes) from those figures and the site drops its plan table in as children. Nothing about rates or tiers lives in the package.

import { PricingTerms } from '@lalternative/legal'

<PricingTerms
  publisher={PUBLISHER}
  site={{ ...SITE, paths: { pricing: '/tarifs' } }}
  locale="fr"
  noticeDays={30}
  usage={[
    { label: 'transcription audio', rate: '2 crédits par minute entamée' },
    { label: 'vidéo déjà sous-titrée', rate: '1 crédit par transcription' },
  ]}
  bestTier
  titles={{ pricing: '4. Prix et facturation', revision: '5. Évolution des tarifs' }}
>
  <PlanPrices catalogue={catalogue} />
</PricingTerms>

usage is the metered part of the price, when there is one: every rate listed must be the one the billing system charges. bestTier states that the customer is moved to the cheaper plan matching their consumption without asking; pass it only when the billing code does exactly that. noticeDays is the notice given before a price change takes effect, with free termination until that date, which is what keeps the clause out of the consumer-law blacklist on unilateral price changes. The VAT paragraph follows publisher.vatExempt.

Styling

The package ships structure, not a look. Every class is overridable through classNames, since each site keys on its own palette.

What is deliberately absent

Terms of sale (beyond the price article above), privacy policy and the DPA are not here. They turn on the product's object, price, subprocessors and retention periods, and on whether the product acts as controller or processor — Techtuel is a processor for the media its customers submit, Synthiz a controller for its end users. Sharing that wording would produce documents that are wrong for at least one product.