In this site, I combine gatsby-theme-web-monetization with the excellent Emilia Theme by LekoArts using its starter site. Then I continue with the steps below.
- Install the theme.
yarn add gatsby-theme-web-monetization
# or npm install --save gatsby-theme-web-monetization
- Add theme to gatsby-config. The order does not matter with the plugins used in this repo. If you use this with other plugins and encounter issues, you may have to do some trial and error regarding the plugins order.
// gatsby-config.js
module.exports = {
plugins: [
{
resolve: `gatsby-theme-web-monetization`,
options: {
// Replace with your wallet's payment pointer
paymentPointer: "$wallet.example.com/eka",
},
},
// ... other themes
]
}
- As shown in the basic example, we can use the theme’s components in MDX pages without importing anything. Additionally, we can also use them in our components outside of MDX by importing them.
In this example, I import the WebMonetizedStatus
component and add it to the header.
// src/@lekoarts/gatsby-theme-emilia/components/header.js
// ... other imports
import { WebMonetizedStatus } from "gatsby-theme-web-monetization";
// Pass your message/content as props to the WebMonetizedStatus component
const customActive = "String or component to render if Web Monetization is active";
const customInactive = "String or component to render if Web Monetization is not active";
const Header = () => {
return (
<>
{/* ... header component code */}
<WebMonetizedStatus
active={customActive}
inactive={customInactive}
/>
{/* ... more header component code */}
</>
);
};
export default Header;
- See theme documentation for the list of components you can use.
- In the full code, I use the
sx
props for styling with Theme UI. You can use any other styling methods (Styled Components, CSS Modules, add Tailwind CSS class names, etc). - This file structure comes from “shadowing” the Emilia theme, ie. overriding the theme’s
Header
component with my modified one. You can use the gatsby-theme-web-monetization components anywhere, regardless of the theme shadowing concept.
Now for each photograph, I want to do these:
- Display hi-res image download link only to web monetized users
- Display call to action/message to non-web monetized users
I can achieve it this way in an MDX page. (This is a barebones simplified example which has not addressed CSS styling.)
---
title: My test post
date: 2020-06-03
---
![Description of the photo](./images/some-source.jpg)
<figcaption>Some image caption here</figcaption>
<IfWebMonetized>
[Download hi-res image](https://dropbox.com/some-download-link)
</IfWebMonetized>
<WebMonetizedPaywall>
👋🏼 Want this photo? Hi-res image download is available for web monetized users. [Learn more.](https://coil.com)
</WebMonetizedPaywall>
But it’s tedious, messy, and impractical to repeat these lines for every photograph and every series page. We can abstract these away into a reusable component, as shown in the next step.
- Create a
Photo
component that renders an image from the specified source, a download link for monetized users, and a message for non-monetized users.
// src/components/photo.js (truncated to relevant parts)
// ... other imports
import { WebMonetizedPaywall } from "gatsby-theme-web-monetization";
import { IfWebMonetized } from "react-web-monetization";
import ButtonDownload from "./button-download";
import Cta from "./cta";
import CustomImg from "./custom-img";
const Photo = ({ src, alt, caption, isFree, downloadUrl }) => {
return (
<>
<CustomImg src={src} alt={alt || ""} />
{caption && <figcaption>{caption}</figcaption>}
{downloadUrl &&
(isFree ? (
<ButtonDownload href={downloadUrl} />
) : (
<>
<IfWebMonetized>
<ButtonDownload href={downloadUrl} />
</IfWebMonetized>
<WebMonetizedPaywall>
<Cta />
</WebMonetizedPaywall>
</>
))}
</>
);
};
export default Photo;
- We import
WebMonetizedPaywall
andIfWebMonetized
(the latter from react-web-monetization, which is a dependency of this theme; you don’t need to install it yourself to import the components). - We create and import UI components
ButtonDownload
(the “Download” button) andCta
(the call-to-action message). We also have utility componentCustomImg
to query for image and process it through Gatsby’s Sharp image library (which has neat capabilities like lazy loading, auto resizing,srcset
attribute, etc). These are just an example; you can use any approach, styling decisions, and add or remove any functionalities. - We add
ButtonDownload
insideIfWebMonetized
to display to web monetized users, and addCta
insideWebMonetizedPaywall
for non web monetized users. - In case I want to make some of my photos downloadable by all users, I also have an
isFree
prop.
This Photo
component is not yet available for use in MDX pages. We can either import it (which will also be tedious as we have to do it on every page), or we can create our own MDX Provider and pass the Photo
component there, which will allow us to use Photo
in our MDX pages without importing.
- Create a custom MDXProvider component and pass our
Photo
component there. I’m calling itMyMdxProvider
.
import React from "react";
import { MDXProvider } from "@mdx-js/react";
import Photo from "./photo";
const components = { Photo };
const MyMdxProvider = ({ children }) => (
<MDXProvider components={components}>{children}</MDXProvider>
);
export default MyMdxProvider;
If you build your Gatsby site without a theme, add the Photo
component to your existing MDXProvider instead, and skip the next step. Learn more about MDX Provider.
- We need to wrap our project content with our new
MyMdxProvider
so we can use thePhoto
component without importing. We can do so by shadowing the Emilia theme’s project page layout.
// src/@lekoarts/gatsby-theme-emilia/components/project.js
// ...other imports
import MyMdxProvider from "../../../components/my-mdx-provider";
const Project = ({ data: { project } }) => {
return (
<Layout>
<SEO // ... props
/>
<MyMdxProvider>
<HeaderProject
title={project.title}
description={project.body}
areas={[]}
date={project.date}
/>
</MyMdxProvider>
</Layout>
);
};
export default Project;
- Finally, we use the
Photo
component in MDX pages.
---
title: Sleeping Cats
date: 2020-06-03
---
<Photo
src="sleeping-cats/images/sc1.jpg"
caption="This is not an apple"
alt="Gray tabby kitten sleeping in a wooden storage box that said 'Apples' atop of a pile of newspapers. The handle is full of scratches."
downloadUrl="https://www.dropbox.com/s/nu0xrsje9npbdlx/full_sc1.jpg?dl=0"
/>
- (Nothing to do with gatsby-theme-web-monetization, just how this
Photo
component works.) Due to how the GraphQL file query works, the photosrc
value is relative to theprojects
path, NOT the MDX file. For instance, for image file located incontent/projects/sleeping-cats/images/sc1.jpg
, we writesrc="sleeping-cats/images/sc1.jpg"
.