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

@revova/hydrogen

v1.1.0

Published

Official Revova review widgets for Shopify Hydrogen storefronts

Readme

@revova/hydrogen

Official Revova review widgets for Shopify Hydrogen storefronts.

Installation

npm install @revova/hydrogen

Requirements

  • React 18+
  • Shopify Hydrogen storefront with the Revova app installed on the store

How it works

Components and hooks call your Revova backend directly over HTTPS with a shop query parameter and a Bearer token:

GET https://yourapp.trycloudflare.com/api/reviews?shop=yourstore.myshopify.com&...
Authorization: Bearer <apiToken>

No Shopify App Proxy. No CORS issues. No API keys exposed beyond what you pass in.


Setup (Hydrogen)

1 — Add your credentials to the environment

# .env
PUBLIC_REVOVA_API_URL=https://yourapp.trycloudflare.com
PUBLIC_STORE_DOMAIN=yourstore.myshopify.com
PUBLIC_REVOVA_API_TOKEN=your_token_here

Expose them through your Hydrogen loader:

// app/root.tsx or any route loader
export async function loader({ context }: LoaderArgs) {
  return {
    apiUrl:   context.env.PUBLIC_REVOVA_API_URL,
    shop:     context.env.PUBLIC_STORE_DOMAIN,
    apiToken: context.env.PUBLIC_REVOVA_API_TOKEN,
  };
}

2 — Spread credentials into any component

Every component accepts apiUrl, shop, and apiToken. The easiest pattern is to spread a single creds object:

const creds = {
  apiUrl:   env.PUBLIC_REVOVA_API_URL,
  shop:     env.PUBLIC_STORE_DOMAIN,
  apiToken: env.PUBLIC_REVOVA_API_TOKEN,
};

<ReviewWidget {...creds} productId={product.id} />

Quick Start

// app/routes/products.$handle.tsx
import '@revova/hydrogen/styles.css'; // import once in app/root.tsx instead
import { ReviewWidget, FloatingReviewButton } from '@revova/hydrogen';

export async function loader({ context, params }: LoaderArgs) {
  const product = await getProduct(params.handle);
  return {
    product,
    apiUrl:   context.env.PUBLIC_REVOVA_API_URL,
    shop:     context.env.PUBLIC_STORE_DOMAIN,
    apiToken: context.env.PUBLIC_REVOVA_API_TOKEN,
  };
}

export default function ProductPage() {
  const { product, apiUrl, shop, apiToken } = useLoaderData<typeof loader>();
  const creds = { apiUrl, shop, apiToken };

  return (
    <>
      <h1>{product.title}</h1>
      <ReviewWidget {...creds} productId={product.id} />
      <FloatingReviewButton {...creds} productId={product.id} />
    </>
  );
}

API Credentials (ApiProps)

All components and hooks require these three props. Spread them as a group for convenience.

| Prop | Type | Description | |---|---|---| | apiUrl | string | Revova backend base URL (e.g. https://yourapp.trycloudflare.com) | | shop | string | Store myshopify.com domain (e.g. yourstore.myshopify.com) | | apiToken | string | Bearer token for authorization |


Components

<ReviewWidget>

Full review list with pagination, sorting, and an inline submission form.

import { ReviewWidget } from '@revova/hydrogen';

<ReviewWidget
  {...creds}
  productId={product.id}
  pageSize={10}
  showForm
  locale="fr"
/>

| Prop | Type | Default | Description | |---|---|---|---| | ...creds | ApiProps | — | apiUrl, shop, apiToken | | productId | string | — | Shopify product GID | | locale | string | — | Locale code for translated reviews (e.g. fr) | | pageSize | number | 10 | Reviews per page | | showForm | boolean | true | Show the write-review button and form | | starColor | string | #f59e0b | Star fill colour | | className | string | — | CSS class on the wrapper |


<ReviewForm>

Standalone submission form — use when you want the form separate from the list.

import { ReviewForm } from '@revova/hydrogen';

// `form` comes from the ReviewsResponse returned by useReviews
<ReviewForm
  {...creds}
  productId={product.id}
  form={data.form}
  onSuccess={() => console.log('submitted')}
/>

Props: ...creds, productId, form (required — ResolvedForm), onSuccess?, className?


<StarRating>

Renders star icons for any numeric rating. Supports half-stars via linear gradient fill.

import { StarRating } from '@revova/hydrogen';

<StarRating rating={4.5} size={20} color="#f59e0b" />

Props: rating (0–5), max? (default 5), size? (px, default 16), color?, className?


<ReviewCount>

Aggregate rating + review count badge. Great for product cards and PDP headers.

import { ReviewCount } from '@revova/hydrogen';

<ReviewCount {...creds} starSize={14} />

Props: ...creds, starColor?, starSize?, className?


<ReviewCarousel>

Auto-advancing carousel of recent reviews. Includes previous/next arrows and dot indicators.

import { ReviewCarousel } from '@revova/hydrogen';

<ReviewCarousel {...creds} limit={10} autoPlay intervalMs={4000} />

Props: ...creds, limit? (default 10), autoPlay? (default true), intervalMs? (default 4000), starColor?, className?


<ReviewGallery>

Masonry photo grid of reviews that have images. Clicking any photo opens a lightbox with the full review.

import { ReviewGallery } from '@revova/hydrogen';

<ReviewGallery {...creds} columns={3} limit={20} />

Props: ...creds, limit? (default 20), columns? (default 3), starColor?, className?


<QnAWidget>

Product Q&A — lists questions with answers and includes an ask-a-question form.

import { QnAWidget } from '@revova/hydrogen';

<QnAWidget {...creds} productId={product.id} />

Props: ...creds, productId, className?


<TrustBadge>

Aggregate rating badge in three styles: pill (default), inline, or card.

import { TrustBadge } from '@revova/hydrogen';

<TrustBadge {...creds} style="pill" />
<TrustBadge {...creds} style="card" />
<TrustBadge {...creds} style="inline" />

Props: ...creds, style? ('pill' | 'inline' | 'card', default 'pill'), starColor?, className?


<ReviewTicker>

A continuously scrolling marquee of recent review snippets — ideal for homepages and hero sections.

import { ReviewTicker } from '@revova/hydrogen';

<ReviewTicker {...creds} limit={20} speedSeconds={30} />

Props: ...creds, limit? (default 20), speedSeconds? (default 30), starColor?, className?


<SocialProofPopup>

A timed floating popup showing recent reviews one at a time. Add once to your root layout.

import { SocialProofPopup } from '@revova/hydrogen';

<SocialProofPopup
  {...creds}
  position="bottom-left"
  intervalMs={8000}
  displayMs={5000}
/>

Props: ...creds, position? ('bottom-left' | 'bottom-right', default 'bottom-left'), intervalMs? (default 8000), displayMs? (default 5000), starColor?, className?


<FloatingReviewsTab>

A sticky tab fixed to the left or right edge of the viewport. Clicking it slides out a panel of recent reviews.

import { FloatingReviewsTab } from '@revova/hydrogen';

<FloatingReviewsTab {...creds} label="Reviews" position="right" />

Props: ...creds, label? (default 'Reviews'), position? ('left' | 'right', default 'right'), color?, limit? (default 5), starColor?, className?


<FloatingReviewButton>

A fixed "Write a Review" button that opens a modal with the submission form.

import { FloatingReviewButton } from '@revova/hydrogen';

<FloatingReviewButton
  {...creds}
  productId={product.id}
  text="Write a Review"
  position="bottom-right"
/>

Props: ...creds, productId, text? (default 'Write a Review'), color?, position? ('bottom-left' | 'bottom-right', default 'bottom-right'), className?


Hooks

Use hooks to build fully custom UIs while Revova handles data fetching.

useReviews(options)

Paginated reviews for a product with sorting controls.

import { useReviews } from '@revova/hydrogen';

const { data, loading, error, setPage, setSort, currentPage, currentSort, refetch } = useReviews({
  ...creds,
  productId: product.id,
  limit: 5,
  sort: 'helpful',   // 'recent' | 'helpful' | 'rating_high' | 'rating_low'
  locale: 'fr',      // optional — returns translated content
});

useWidgetGlobals(options)

Shop-level stats and recent reviews. Used internally by most global widgets.

import { useWidgetGlobals } from '@revova/hydrogen';

const { data, loading, error } = useWidgetGlobals({ ...creds, limit: 20 });

// data.stats.averageRating  — "4.8"
// data.stats.totalReviews   — 142
// data.reviews              — recent GlobalReview[]
// data.config               — merchant widget settings

useSubmitReview(creds)

Submit a new review programmatically.

import { useSubmitReview } from '@revova/hydrogen';

const { submit, submitting, success, error, result, reset } = useSubmitReview(creds);

await submit({
  productId: 'gid://shopify/Product/123',
  email: '[email protected]',
  formId: 'form-id-from-loader',
  fieldAnswers: [
    { fieldId: 'star-field-id', value: 5 },
    { fieldId: 'title-field-id', value: 'Great product!' },
    { fieldId: 'body-field-id', value: 'Really happy with this purchase.' },
  ],
});

useQnA(options)

Fetch and submit Q&A for a product.

import { useQnA } from '@revova/hydrogen';

const { data, loading, setPage, submitQuestion, submitAnswer, submitState, resetSubmit } = useQnA({
  ...creds,
  productId: product.id,
});

await submitQuestion({
  intent: 'question',
  productId: product.id,
  email: '[email protected]',
  body: 'Does this come in blue?',
});

useHelpfulVote(creds)

Cast a helpful / not-helpful vote on a review.

import { useHelpfulVote } from '@revova/hydrogen';

const { vote, loading, voted } = useHelpfulVote(creds);

<button onClick={() => vote({ reviewId: review.id, vote: 'helpful' })} disabled={voted}>
  Helpful ({review.helpfulCount})
</button>

Styling

The package ships a bundled CSS file. Import it once in your app root (e.g. app/root.tsx):

import '@revova/hydrogen/styles.css';

This applies the full rv-* design system — cards, stars, modal, form, ticker animation, popup, gallery lightbox, and all widget layouts. All class names are prefixed rv- so they won't conflict with your theme styles.

To customise, pass a className prop on any component and override the relevant rv-* classes in your own CSS. The starColor prop (default #f59e0b) is available on every component that renders stars.


Placement Guide

| Widget | Where to use | |---|---| | <ReviewWidget> | Product detail page | | <ReviewForm> | Custom PDP, post-purchase page | | <StarRating> | Anywhere — product cards, PDPs, search results | | <ReviewCount> | Product cards, PDP header | | <ReviewCarousel> | Homepage, collection pages | | <ReviewGallery> | Homepage, dedicated reviews page | | <QnAWidget> | Product detail page (below reviews) | | <TrustBadge> | Homepage hero, footer, landing pages | | <ReviewTicker> | Homepage hero, announcement bar | | <SocialProofPopup> | Root layout (renders once site-wide) | | <FloatingReviewsTab> | Root layout (renders once site-wide) | | <FloatingReviewButton> | Product detail page |