Skip to main content

Easily monetise your Remix application (with Salable)

In this guide, I'm going to showcase just how easy it is to monetise web applications built using the Remix.run framework. Within this guide, we'll take a basic example application and turn it into a real-world application that could generate revenue.

Before we jump in though, let's talk a little bit about the tools we will be utilising along the way. The first is Remix itself - if you're unfamiliar, Remix is a full-stack web framework focused on web standards and modern web app UX. If you'd like to know a bit more about Remix more generally before we get started, I'd recommend you read through the Remix Tutorial.

Next, let's talk a little bit about Salable. As mentioned, Salable is a platform that allows you to easily monetise your application - this is achieved through the collection of payments, the ability to give your users licenses, being able to authorise actions based on permissions, among other things. If you've neverused Salable before, don't worry - this guide doesn't assume any prior experience or knowledge of the platform!

Getting Started

Now we've covered what we're going to be building, let's get cracking. The first thing you're going to want to do is to generate a new Remix application using the indie-stack template. This template will bootstrap a lot of great and helpful stuff for us, a lot of it we can ignore for the purposes of this guide. If you're interested in reading in more depth about exactly what is included in the indie-stack then check out the Indie Stack Repository.

For our purposes here, we mostly care about the default functionality that is included in the template. This is a built-in authentication system, and a basic "note taking" system. This system allows users to create, read, update, and delete notes. Classic "CRUD" stuff!

To look at this functionality in action, let's get the template downloaded and running. First, head over to your terminal and run the following:

npx create-remix --template remix-run/indie-stack

You will be asked a few questions through the process of creating the application. Call the application whatever you please and answer "Y" (Yes) to all of the follow-up questions. Once you have done this, cd into the folder that was just created containing your new application.

Now, let's get the application running:

npm run dev

Remix Indie stack

To view the default notes functionality, you will have to create an account and log in, go ahead and do that now.

Initial application overview

Feel free, at this point, to have a quick play around and familiarise yourself with the system. As part of this guide, we're going to be making the creation of notes a paid for feature.

When you're ready, let's dive in. So, first things first - you will need to create a Salable account. Next, toggle on "Test Mode" via the sidebar. Test Mode means that we can accept fake payments via Stripe without having to link a bank account, or similar. It makes it much simpler to get up-and-running while you're in the development phase.

Salable test mode toggle

Now, that we have test mode enabled - we still need to hook up a "Payment Integration", let's do this the simplest way possible. The Salable integration type uses Stripe. This can be set up by clicking "Settings" on the sidebar and then visiting the "Integrations" tab. The name of the integration itself doesn't matter, in this case I will opt to call mine "Main Test" (seeing) as we're in "Test Mode".

Once you have the integration set up, let's start by configuring a Product here on the Salable platform that will represent the monetisation structure we want. Let's create a product called "Remix Notes". Leave the description blank and pick an "App Type" of "Custom". Next, we'll set up the Payment Information. We will make this a paid product and use the Payment Integration we set up earlier. Choose whichever currency you would prefer to collect payments in - for the purposes of this tutorial I will choose Great British Pounds (GBP).

Now we have our product set up and ready to go, let's add a "Pro" plan that the user will need in order to create notes. Before this, we need to create a "Capability" on the Salable platform. In this case, let's create a Capability named "Create". Now we have this capability, let's set up a "Paid" and "Licensed" plan that adds this capability - feel free to call this plan whatever you like; I am going for "Pro".

Right. With that all done, let's get to writing some code.

Open the Remix template you cloned in your favourite coding editor and let's begin! First of all, let's get the "pricing table" set up so users can look at the available plans, select one, and then pay for a license.

To do this, we will make use of the @salable/react-sdk to easily show the table. Run the following in your terminal:

npm install @salable/react-sdk

Now we have that installed, we will set up a pricing page at /pricing to show the table. We can do this by creating the following file:

app/routes/pricing.tsx

In that file, let's add the following contents:

import { json } from '@remix-run/node';
import { useLoaderData } from '@remix-run/react';
import { SalablePricingTableReact } from '@salable/react-sdk';
import { useUser } from '~/utils';

export const loader = () => {
const productUuid = process.env.SALABLE_PRODUCT_UUID as string;
const apiKey = process.env.SALABLE_API_KEY as string;
return json({ productUuid, apiKey });
};

const Pricing = () => {
const user = useUser();
const { productUuid, apiKey } = useLoaderData<typeof loader>();
return (
<SalablePricingTableReact
envConfig={{
productUuid,
apiKey,
globalPlanOptions: {
granteeId: user.id,
successUrl: '/notes',
cancelUrl: '/pricing',
},
}}
checkoutConfig={{
member: user.id,
customer: {
email: user.email,
},
}}
/>
);
};

export default Pricing;

Now, let's add the following environment variables to our .env file - these are required to show the above pricing table correctly.

SALABLE_PRODUCT_UUID="YOUR_PRODUCT_UUID_HERE"
SALABLE_API_KEY="YOUR_API_KEY_HERE"

Now, if you visit /pricing in your browser while signed in - you should see our pricing table! Users can use this to get themselves an upgraded license.

Salable pricing table

Now, subscribe to the plan on the account you've created so you have an upgraded license. This will be helpful to test our functionality is working correctly when we require an upgraded license in order to create notes.

Let's go in and add that functionality to lock the feature behind the plan.

Before we do that though, let's simplify the notes/_index.tsx route to only allow note creation from the sidebar. This isn't a required change but will be simpler for the purposes of this guide as it means we'll only have to authorise our user in one place.

export default function NoteIndexPage() {
return <p>No note selected. Create one from the sidebar.</p>;
}

With that out of the way, let's make this feature paid!

First, we need to fetch the current user's capabilities in the Remix loader.

export const loader = async ({ request }: LoaderFunctionArgs) => {
const userId = await requireUserId(request);
const noteListItems = await getNoteListItems({ userId });
const response = await fetch(`https://api.salable.app/licenses/granteeId/${userId}`, {
headers: {
'x-api-key': process.env.SALABLE_API_KEY as string,
},
});
try {
const userLicenses = await response.json();

const canCreateNotes: boolean = userLicenses?.some((license: any) =>
license.capabilities.some(
(capability: any) => capability.name === 'Create' && capability.status === 'ACTIVE'
)
);

return json({ noteListItems, canCreateNotes });
} catch (error) {
return json({
noteListItems,
canCreateNotes: false,
});
}
};

In the above code, we fetch the user's licenses and then iterate through them to check whether they have the correct capabilities in order to be able to create the new notes. We then return a boolean value canCreateNotes to the client which we will use to check whether the user can see the "+ New Note" button.

{
data.canCreateNotes ? (
<Link to="new" className="block p-4 text-xl text-blue-500">
+ New Note
</Link>
) : null;
}

Wrap the "+ New Note" button in the above condition and now only users who have that capability can use the feature!

And there we have it, let's conclude what we've covered:

  • Introduced Remix
  • Set up a Remix project
  • Created a test mode Payment Integration on Salable
  • Created our product, plans, and capability.
  • Used the Salable REST API to fetch the users licenses.
  • Conditionally granted access to a feature based on the user's permissions.

And this is just the beginning. Now you have the knowledge of how to create, license, and authorise features with React.js, Remix, and Salable - the world is your oyster! Go and build something great!