Gift list dev diary: introduction

Most holidays my family shares gift lists with each other, offering up ideas for gifts we would like to receive. A year and a half ago, we suffered a bit of a communication breakdown, and some items were gifted twice to the same person. This was understandibly upsetting, and I spoke with family members about setting up a little web app to help us manage sharing gift lists without duplicating gifts–much like a wedding or baby registry. There are existing sites that solve this problem, but I wanted to build something relatively small that wasn’t in it to sell user data to advertisers.

It’s important to me that my personal projects include some element of learning, and I have been particularly interested in exploring fulcro and pathom as of late. Both fulcro and pathom have excellent documentation, but there isn’t much material on how to build an application using them from the ground up. The primary goal of this blog series is to document exactly this! I hope people (including future me) will find these posts informative, and I hope some people will reach out and offer suggestions as to how I can improve.

Why fulcro and pathom?

Before diving in to building the app, I think it’s worth briefly explaining the choice of fulcro and pathom. At a very high level, fulcro is an opinionated frontend framework built around React, and pathom is a library for getting the data to resolve graph queries. For more information, please check out their documentation (fulcro, pathom).

Fulcro provides tools to make it possible to work with normalized client-side application state. Here I mean normalized in the relational sense: we avoid duplicating data. Without normalized application state, it’s very easy to end up with two pieces of data describing the same thing that get out of sync. Often this results in UI elements displaying inconsistent data. In addition, fulcro’s system of component-colocated queries and idents neatly solves the problem of prop drilling.

Component queries provide a declaration of the data a component needs to render. They are not only integral to the tools fulcro uses to normalize application state, but they also provide a method of fetching the data needed by a part of the UI. If you get a component’s query, you have in your hands a data structure declaring what that component and all of its subcomponents need to render. That data structure is something you can ship to a server and get back a response with all the data necessary to render that part of your UI.

A server written using pathom provides exactly that: a server that can resolve a fulcro component’s query into the requested data. Pathom does this by assembling a suite of resolvers into a parser that can execute a full graph query. These resolvers declare a contract: given an entity with a set of input attributes, the resolver promises to return that entity with a set of output attributes. This model does not deal in entity types at all; it embraces an RDF-style model where each entity is just a bag of namespaced keyword attributes, and each attribute has a fixed meaning.

The contracts presented by pathom resolver functions do not reveal anything about the storage from which the resolvers are fetching the data. This decoupling of the domain model presented by the API from the storage schema is something I value highly.

Lastly, one of the most well-known pitfalls when writing a server that parses graph queries is the n+1 query roblem. An important feature for any graph query resolving server is a principled solution to this problem, and pathom has one. It’s simple to transform a resolver that works only on an individual entity to a batch resolver using the transform-batch-resolver transformer and batch-restore-sort (see the docs).

What’s next?

With a bit of introduction out of the way, we’ll start diving in to how different parts of this application can be implemented in the next post!

Next: Gift list dev diary: authentication