Skip to content

3 steps to integrate remix with (almost) every third party service

Posted on:November 23, 2023

It can be quite challenging to integrate different services with your remix application.

Remix is still relatively young and not all services have official integration support/guides. You try to adapt the react/node/nextjs guides to remix, burn hours of precious time, and when you finally think you got over all those error messages you find that edge case that is actually not that edgy.

However, there are only 3 steps to take in order to integrate (almost) every service with remix and they are pretty straightforward.

Handle the dependencies with care

The first thing to do is to make sure you install the right dependencies and that they are bundled correctly. You can probably find installation instructions on the service’s documentation website and follow those.

Many services provide SDKs for different runtimes/libraries/frameworks and you want to make sure to install the most relevant ones. If there is a remix integration, that should be your first (and only) option.

Otherwise, you should install a NodeJS SDK for the server and a ReactJS one for the client. (If there is no ReactJS SDK you should install the typescript/javascript one).

If the server library is ESM only then you have to include it in your remix.config.js under the serverDependenciesToBundle section. (checkout the docs)

Pass the environment variables

The service you are trying to integrate is probably not a hippie non-profit service and therefore hands you some keys in order to use it. Those private keys are yours, and yours alone, and you don’t want to expose them. However, there are also public keys that are way less sensitive and will allow you to instantiate the client SDKs.

Here are the steps to pass those public keys from the server to the client:

  1. Store them as environment variables (usually in a .env file)
.env
SOME_SERVICE_SECRET_KEY="some-sercret-key"
SOME_SERVICE_PUBLIC_KEY="some-public-key"
  1. In your root.tsx loader read thost variables and return them to the client (make sure to only pass the public ones that you are willing to expose)
root.tsx
export async function loader() {
return json({
ENV: {
SOME_SERVICE_PUBLIC_KEY: process.env.SOME_SERVICE_PUBLIC_KEY,
},
});
}
  1. Load those keys to window
root.tsx
export function Root() {
const data = useLoaderData<typeof loader>();
return (
<html lang="en">
<head>
<Meta />
<Links />
</head>
<body>
<Outlet />
<script
dangerouslySetInnerHTML={{
__html: `window.ENV = ${JSON.stringify(
data.ENV
)}`,
}}
/>
<Scripts />
</body>
</html>
);
}

Now on the server, you have access to both keys using process.env.SOME_SERVICE_PUBLIC_KEY and process.env.SOME_SERVICE_SECRET_KEY and on the client using window.SOME_SERVICE_PUBLIC_KEY

Make sure to only use the secret key in loaders/actions or .server.ts files

Expose the SDKs

Now all you need to do is make your SDK available for your needs.

Server SDK

Server SDKs are pretty easy. All you need to do is to:

  1. Create a some-service.server.ts file somewhere in your project.
  2. Import the service from the server SDK
  3. Instantiate it with the keys (from previous step)
  4. export the service instance
some-service.server.ts
import { SomeService } from "some-service/node";
export const someService = new SomeService(process.env.SOME_SERVICE_SECRET_KEY);

Client SDK

Client/SSR modules are a bit trickier, so here is what to do:

export function Root() {
const data = useLoaderData<typeof loader>();
const someServiceInstance = new SomeServiceInstance(data.ENV.SOME_SERVICE_PUBLIC_KEY)
return (
<html lang="en">
<head>
<Meta />
<Links />
</head>
<body>
<SomeServiceProvider instance={someServiceInstance}>
<Outlet />
</SomeServiceProvider>
// In this case we don't even need to put the key on window.
<Scripts />
</body>
</html>
);
}

Gotcha

A common gotcha is when you need those instances higher up the tree (sometimes required for logging and more involved SDKs). In this case instead of wrapping in root.tsx the wrapping should be done in entry.client.ts and entry.server.ts and might need the help of getLoadContext.

Conclusion

Following those steps should integrate most third-party services with your remix application and set you on track to make people happy. Let me know if you found some more troublesome integrations and let’s figure out how to deal with those :)