Skip to content
This repository has been archived by the owner on Apr 9, 2024. It is now read-only.

Commit

Permalink
Chore/update hydrogen (#109)
Browse files Browse the repository at this point in the history
* chore: update packages

* chore: move meta to function

* chore: update remix 2 types

* chore: update hydrogen-sanity preview implementation

* chore: update to useRootLoaderData

* chore: add live reload

* chore: add csp

* docs: update readme

* chore: add Layout type

* chore: remove nonce file

* chore: update analytics

* chore: update deps

* fix: cart footer. fixes #91

* chore: update node version

* fix: csp
  • Loading branch information
thebiggianthead authored Dec 14, 2023
1 parent 4bfe59a commit 462c8d0
Show file tree
Hide file tree
Showing 42 changed files with 16,979 additions and 10,904 deletions.
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# AKVA - An example storefront powered by Sanity + Hydrogen

This demo is compatible with `@shopify/hydrogen >= 2023.1.0` built on Remix.
This demo is compatible with `@shopify/hydrogen >= 2023.10.0` built on Remix.

> For a more complex reference example, please see our [demo-ecommerce repo](https://github.com/sanity-io/demo-ecommerce) which features a monorepo with an embedded Sanity Studio, full live preview, more content models and added internationalisation.
> For the legacy Hydrogen v1 template, please refer to the [hydrogen-v1 branch](https://github.com/sanity-io/hydrogen-sanity-demo/tree/hydrogen-v1).
<img src="https://user-images.githubusercontent.com/209129/173065853-77b26be2-dd15-4b4d-8164-850e70247b88.png" width="1000" />
Expand Down Expand Up @@ -31,12 +32,12 @@ In addition to this, we've created a `query` utility, which uses [Hydrogen's cac
It's possible to make calls to the Sanity API either with `query`:

```tsx
import {json, type LoaderArgs} from '@shopify/remix-oxygen';
import {json, type LoaderFunctionArgs} from '@shopify/remix-oxygen';
import type {SanityProductPage} from '~/lib/sanity';

const QUERY = `*[_type == 'product' && slug.current == $slug]`;

export async function loader({params, context}: LoaderArgs) {
export async function loader({params, context}: LoaderFunctionArgs) {
const cache = context.storefront.CacheLong();

const sanityContent = await context.sanity.query<SanityProductPage>({
Expand All @@ -56,12 +57,12 @@ or directly with the Sanity client:
```tsx
// <root>/app/routes/($lang).products.$handle.tsx
import {useLoaderData} from '@remix-run/react';
import {json, type LoaderArgs} from '@shopify/remix-oxygen';
import {json, type LoaderFunctionArgs} from '@shopify/remix-oxygen';
import type {SanityProductPage} from '~/lib/sanity';

const QUERY = `*[_type == 'product' && slug.current == $slug]`;

export async function loader({params, context}: LoaderArgs) {
export async function loader({params, context}: LoaderFunctionArgs) {
const sanityContent = await context.sanity.client.fetch<SanityProductPage>(
QUERY,
{
Expand All @@ -86,13 +87,13 @@ You can also use the [`defer` and `Await` utilities](https://remix.run/docs/en/1
// <root>/app/routes/($lang).products.$handle.tsx
import {Suspense} from 'react';
import {Await, useLoaderData} from '@remix-run/react';
import {defer, type LoaderArgs} from '@shopify/remix-oxygen';
import {defer, type LoaderFunctionArgs} from '@shopify/remix-oxygen';
import type {SanityProductPage, LessImportant} from '~/lib/sanity';

const QUERY = `*[_type == 'product' && slug.current == $slug]`;
const ANOTHER_QUERY = `*[references($id)]`;

export async function loader({params, context}: LoaderArgs) {
export async function loader({params, context}: LoaderFunctionArgs) {
/* Await the important content here */
const sanityContent = await context.sanity.query<SanityProductPage>({
query: QUERY,
Expand Down
5 changes: 2 additions & 3 deletions app/components/Link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import {
type LinkProps as RemixLinkProps,
NavLink as RemixNavLink,
type NavLinkProps as RemixNavLinkProps,
useMatches,
} from '@remix-run/react';
import {forwardRef} from 'react';
import {useRootLoaderData} from '~/root';

type LinkProps = Omit<RemixLinkProps, 'className'> & {
className?: RemixNavLinkProps['className'] | RemixLinkProps['className'];
Expand All @@ -30,8 +30,7 @@ const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
*/
export const Link = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => {
const {to, className, ...resOfProps} = props;
const [root] = useMatches();
const selectedLocale = root.data?.selectedLocale;
const {selectedLocale} = useRootLoaderData();

let toWithLocale = to;

Expand Down
6 changes: 2 additions & 4 deletions app/components/cart/Cart.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {useMatches} from '@remix-run/react';
import {CartForm} from '@shopify/hydrogen';
import type {
Cart,
Expand All @@ -22,6 +21,7 @@ import RemoveIcon from '~/components/icons/Remove';
import SpinnerIcon from '~/components/icons/Spinner';
import {Link} from '~/components/Link';
import {useCartFetchers} from '~/hooks/useCartFetchers';
import {useRootLoaderData} from '~/root';

export function CartLineItems({
linesObj,
Expand Down Expand Up @@ -264,12 +264,10 @@ export function CartSummary({cost}: {cost: CartCost}) {
}

export function CartActions({cart}: {cart: Cart}) {
const [root] = useMatches();
const {storeDomain} = useRootLoaderData();

if (!cart || !cart.checkoutUrl) return null;

const storeDomain = root?.data?.storeDomain;

const shopPayLineItems = flattenConnection(cart.lines).map((line) => ({
id: line.merchandise.id,
quantity: line.quantity,
Expand Down
2 changes: 1 addition & 1 deletion app/components/cart/CartDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ function CartHeader({

function CartFooter({cart}: {cart: Cart}) {
return (
<footer className="sticky bottom-0">
<footer className="sticky bottom-0 bg-white">
<div className="relative flex flex-col">
<CartSummary cost={cart.cost} />

Expand Down
4 changes: 2 additions & 2 deletions app/components/global/CountrySelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import RadioIcon from '~/components/icons/Radio';
import {countries} from '~/data/countries';
import {DEFAULT_LOCALE} from '~/lib/utils';
import type {Locale} from '~/types/shopify';
import {useRootLoaderData} from '~/root';

type Props = {
align?: 'center' | 'left' | 'right';
Expand All @@ -22,8 +23,7 @@ export function CountrySelector({align = 'center'}: Props) {

const fetcherLocaleLabel = fetcher?.formData?.get('label');

const [root] = useMatches();
const selectedLocale = root.data?.selectedLocale ?? DEFAULT_LOCALE;
const selectedLocale = useRootLoaderData()?.selectedLocale ?? DEFAULT_LOCALE;
const selectedLocalePrefix = `${selectedLocale?.language}-${selectedLocale?.country}`;
const {pathname, search} = useLocation();
const pathWithoutLocale = `${pathname.replace(
Expand Down
6 changes: 2 additions & 4 deletions app/components/global/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import {useMatches} from '@remix-run/react';
import clsx from 'clsx';

import SanityFooter from '~/components/global/SanityFooter';
import LogoIcon from '~/components/icons/Logo';
import {Link} from '~/components/Link';
import PortableText from '~/components/portableText/PortableText';
import type {SanityLink} from '~/lib/sanity';
import {useRootLoaderData} from '~/root';

/**
* A component that specifies the content of the footer on the website
*/
export default function Footer() {
const [root] = useMatches();

const layout = root.data?.layout;
const {layout} = useRootLoaderData();
const {footer} = layout || {};

const renderLinks = footer?.links?.map((link: SanityLink) => {
Expand Down
6 changes: 2 additions & 4 deletions app/components/global/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import {useMatches} from '@remix-run/react';
import clsx from 'clsx';

import HeaderActions from '~/components/global/HeaderActions';
import HeaderBackground from '~/components/global/HeaderBackground';
import MobileNavigation from '~/components/global/MobileNavigation';
import Navigation from '~/components/global/Navigation';
import {useRootLoaderData} from '~/root';

/**
* A server component that specifies the content of the header on the website
*/
export default function Header() {
const [root] = useMatches();

const layout = root.data?.layout;
const {layout} = useRootLoaderData();
const {menuLinks} = layout || {};

return (
Expand Down
19 changes: 14 additions & 5 deletions app/components/global/HeaderActions.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {useMatches} from '@remix-run/react';
import {Await} from '@remix-run/react';
import {CartForm} from '@shopify/hydrogen';
import {Cart} from '@shopify/hydrogen/storefront-api-types';
import clsx from 'clsx';
import {useEffect} from 'react';

Expand All @@ -9,11 +10,11 @@ import {CountrySelector} from '~/components/global/CountrySelector';
import {UserIcon} from '~/components/icons/User';
import {Link} from '~/components/Link';
import {useCartFetchers} from '~/hooks/useCartFetchers';
import {useRootLoaderData} from '~/root';

export default function HeaderActions() {
const {isOpen, openDrawer, closeDrawer} = useDrawer();
const [root] = useMatches();
const cart = root.data?.cart;
const {cart} = useRootLoaderData();

// Grab all the fetchers that are adding to cart
const addToCartFetchers = useCartFetchers(CartForm.ACTIONS.LinesAdd);
Expand Down Expand Up @@ -59,11 +60,19 @@ export default function HeaderActions() {
</Link>
{/* Cart */}
<div className="ml-2 mr-4 flex h-full items-center justify-center py-4">
<CartToggle cart={cart} isOpen openDrawer={openDrawer} />
<Await resolve={cart}>
{(cart) => (
<CartToggle cart={cart as Cart} isOpen openDrawer={openDrawer} />
)}
</Await>
</div>
</div>

<CartDrawer cart={cart} open={isOpen} onClose={closeDrawer} />
<Await resolve={cart}>
{(cart) => (
<CartDrawer cart={cart as Cart} open={isOpen} onClose={closeDrawer} />
)}
</Await>
</>
);
}
2 changes: 1 addition & 1 deletion app/components/global/NotFound.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function NotFound({
notFoundPage,
notFoundCollection,
}: {
notFoundPage: SanityNotFoundPage;
notFoundPage?: SanityNotFoundPage;
notFoundCollection?: Promise<{collection: Collection}>;
}) {
return (
Expand Down
6 changes: 2 additions & 4 deletions app/components/media/ImageWithProductHotspots.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import {useMatches} from '@remix-run/react';

import SanityImage from '~/components/media/SanityImage';
import ProductHotspot from '~/components/product/Hotspot';
import type {SanityImageWithProductHotspots} from '~/lib/sanity';
import {useRootLoaderData} from '~/root';

type Props = {
content: SanityImageWithProductHotspots;
};

export default function ImageWithProductHotspots({content}: Props) {
const [root] = useMatches();
const {sanityDataset, sanityProjectID} = root.data;
const {sanityDataset, sanityProjectID} = useRootLoaderData();

return (
<>
Expand Down
5 changes: 2 additions & 3 deletions app/components/modules/CallToAction.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {useMatches} from '@remix-run/react';
import clsx from 'clsx';

import Link from '~/components/elements/Link';
Expand All @@ -9,6 +8,7 @@ import type {
SanityModuleCallToAction,
SanityProductWithVariant,
} from '~/lib/sanity';
import {useRootLoaderData} from '~/root';

type Props = {
module: SanityModuleCallToAction;
Expand Down Expand Up @@ -69,8 +69,7 @@ function ModuleContent({
}: {
content: SanityAssetImage | SanityProductWithVariant;
}) {
const [root] = useMatches();
const {sanityDataset, sanityProjectID} = root.data;
const {sanityDataset, sanityProjectID} = useRootLoaderData();

switch (content?._type) {
case 'image': {
Expand Down
5 changes: 2 additions & 3 deletions app/components/modules/Image.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {useMatches} from '@remix-run/react';
import clsx from 'clsx';

import Button from '~/components/elements/Button';
Expand All @@ -7,6 +6,7 @@ import SanityImage from '~/components/media/SanityImage';
import ProductHotspot from '~/components/product/Hotspot';
import ProductTag from '~/components/product/Tag';
import type {SanityModuleImage} from '~/lib/sanity';
import {useRootLoaderData} from '~/root';

type Props = {
module: SanityModuleImage;
Expand Down Expand Up @@ -77,8 +77,7 @@ export default function ImageModule({module}: Props) {

const ImageContent = ({module}: Props) => {
const image = module.image;
const [root] = useMatches();
const {sanityDataset, sanityProjectID} = root.data;
const {sanityDataset, sanityProjectID} = useRootLoaderData();

return (
<div
Expand Down
5 changes: 2 additions & 3 deletions app/components/portableText/blocks/Grid.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import type {PortableTextBlock} from '@portabletext/types';
import {useMatches} from '@remix-run/react';
import clsx from 'clsx';

import SanityImage from '~/components/media/SanityImage';
import PortableText from '~/components/portableText/PortableText';
import type {SanityModuleGrid} from '~/lib/sanity';
import {useRootLoaderData} from '~/root';

type Props = {
value: PortableTextBlock & SanityModuleGrid;
};

export default function GridBlock({value}: Props) {
const [root] = useMatches();
const {sanityDataset, sanityProjectID} = root.data;
const {sanityDataset, sanityProjectID} = useRootLoaderData();

return (
<div
Expand Down
Loading

0 comments on commit 462c8d0

Please sign in to comment.