Effect + NextJs + ConvertKit: the future of Typescript

Sandro Maglione

Sandro Maglione

Web development

This week project is a glimpse into the future.

In fact, this week is all about Effect. I implemented a NextJs app that allows a user to sign up to your newsletter on ConvertKit.

Let's dive in!


Tech stack

  • Effect: library that exploits the full power of the Typescript type system to make your programs more reliable and easier to maintain
  • ConvertKit: marketing platform that I use for this newsletter
  • NextJs: React framework

Setup

The app is built using NextJs. Running npx create-next-app@latest is enough to get started:

npx create-next-app@latest

I then switched to pnpm instead of npm. This just requires installing pnpm (I used homebrew to do it), delete package-lock.json, and then run pnpm install. Highly recommended!

Get started

My goal was for the app to be 100% Effect. Everything is based on 3 packages in the Effect ecosystem:

  • effect
  • @effect/schema
  • @effect/platform

I had not previous experience with @effect/platform.

The first step was looking at the API reference and the Github README. The README provided a clear example for an HTTP request, which was enough to get started.

The app contains a single form to submit you email. The app will send a request to the ConvertKit API to subscribe the user.

Here are the links to all the documentation needed for this project:

There is more.

Every week I build a new open source project, with a new language or library, and teach you how I did it, what I learned, and how you can do the same. Join me and other 600+ readers.

Implementation

The mental model I followed when using Effect is:

  1. Plan and define all the services (Context.Tag)
  2. Define all the required configuration (Config)
  3. Define all the schemas (using @effect/schema)
  4. Implement all the services

Implementing the services requires composing all the previously defined configurations:

  • Services can be composed with each other using Layer
  • Effect.config allows to read any configuration value (Config)
  • Validate all the data using schemas (with methods like parseEither or Http.request.schemaBody)

Important: A common error I often made is to use some "global" variable or function inside the implementation.

All dependencies should be composed using Config or services. These errors cause problems during testing, because you cannot inject fake or mocked values.

Now we have a working program. Effect collects all dependencies, errors, and return value on the Effect type (Effect.Effect<Dependencies, Errors, ReturnValue>).

The last steps are:

  1. Providing all the dependencies (Effect.provide)
  2. Handling all errors (Effect.catchTags, Effect.catchAll or similar)
  3. Running the effect (Effect.runPromise)

Done! Effect exploits the full power of the Typescript type-system, so I was confident that no type errors meant that everything was going to work as expected ("If it complies it works").

Just to make sure, I implemented some tests. Testing with Effect is not only easy, but extremely satisfying. I used vitest and msw (HTTP mocking), and everything worked as expected.

👉 For all the details and code snippets you can read the full article containing all the details of the implementation.

Takeaways

  • It takes some time to get used to Effect, but it's worth it
  • NextJs is not necessary, any framework (or no framework) works as well. NextJs was convenient because it allows to implement client components and API routes in the same project
  • A lot can go wrong with a simple API request. Effect does a great job with error handling
  • It took some time to setup a working configuration to test the app (using vitest and msw), but the satisfaction of seeing the tests passing was worth it!

Fun fact: I never actually run the app, no need to. Using Effect and implementing some tests is enough to make sure that everything is working correctly. Type-safe and powerful!


You should definitely try Effect, it's the future of Typescript. I am migrating all my projects to it, so expect more news and tutorials.

That's it for this week project. Looking forward to start another one for next week!

See you next 👋

Start here.

Every week I build a new open source project, with a new language or library, and teach you how I did it, what I learned, and how you can do the same. Join me and other 600+ readers.