Connecting a relationship using a hook in Keystone.js 6

I’m writing this for the weary internet traveler because I spent 3 hours debugging this and finally had some coffee ☕️ and figured it out after running into a ton of errors.

This is my desired outcome: every time a user signs up for my app, I want to associate the “Reader” role with that user. I had the option of doing this from the frontend but I would’ve had to run two mutations which isn’t ideal and I’m sure I was going to encounter a race condition in some cases.

The role list in my app can either be an “Admin”, “Reader”, or “Robot”. Pretty self-explanatory but I wanted to make sure all new users signing up are of the Reader role so they can’t mess with other users etc. Keystone does not come with a lot of built in control for this and I’m following Wes Bos’ example of Roles for Users.

Here’s the code:

// this is the Role schema
Role: list({
    fields: {
      name: text({ validation: { isRequired: true } }),
      assignedTo: relationship({
        ref: "User.role", // this is how the user is related to this list
        many: true,
      }),
    },
  }),
// this is the User schema, truncated to only show the Role relation

role: relationship({
        ref: "Role.assignedTo",
        hooks: {
          resolveInput: async ({ resolvedData, operation, context }) => {
            if (operation === "create") {
              const reader = await context.query.Role.findMany({
                where: { name: { equals: "Reader" } },
              });
              resolvedData.role = { connect: { id: reader[0].id } };
            }
            return resolvedData["role"];
          },
        },
      }),

The part I was struggling with was a vague Prisma error like the following, the UI only said “Prisma error”

Unknown arg `role` in data.role for type UserUncheckedCreateInput. Did you mean `roleId`? Available args:
type UserUncheckedCreateInput {
  id?: String
  name?: String
  username?: String
  email?: String
  password: String
  roleId?: String | Null
  readings?: ReadingUncheckedCreateNestedManyWithoutUserInput
}

I guess this error is not very helpful to someone running into this for the first time so my best understanding of it is that it’s due to the resolvedData being returned incorrect. I was returning resolvedData but instead needed to return resolvedData["role"] where role is the field name.

Some terminology

TermDescription
listKeystone’s way of indicating tables, more documentation: https://keystonejs.com/docs/apis/config#lists
field, or field nameA property on a list, aka a column in a table.

Gardening my projects

For a long time, I’ve attempted to work on side projects outside of work and I have either lost the motivation or strived to build something too big to keep the momentum going. This did result in some sort of a weird burnout feeling within me. I have often felt like a project with good intentions, a lot of motivation, and even decent planning was still run off track because I did something ‘wrong’. This ‘wrong’ feeling I was getting kept alluding me because once the intense motivation went away, I would let the project rot. Either the planning was not done properly or the technologies used were missing something. Needless to say, it had nothing to do with what I was working on, it always was mismanaging my time and motivation, motivation wears out quickly.

Recently, I found a post called My product is my garden, the author talks about how there are moonshot ideas or unicorn startups where growth is the only thing that matters, but then there are projects that are niche, small, and focused on something particular. For me, I’ve spent a long time thinking about how I would go about building a product. It usually boils down to a simple to use product (reduce complexity and resist adding features for the sake of adding features), respectful of the user’s data (don’t track everything), and slowly evolving (no sudden pivots).

The blog post really resonated with me, I had not heard of an analogy similar to this before so I’m fully embracing it now. Step one is trying to build something but step zero is to not build something huge, start it up just like you would start a garden.

Following this approach, I’ve decided to pick up work on Bookends (again, for the 5th time or something). And some other projects I have been neglecting even starting. My hope is that if the trend of the past few months continues, the gardening approach could yield some satisfaction. Satisfaction from my projects will first be achieved by just continuing work on them and also by launching them for my own sake. I don’t have large ambitious goals for my projects becoming the best of the best, just the best I’ve done.

Summer 2021 projects

The past few months have been a mix of productive and lazy days. Some days, I got up and was focused for most hours, got some work done and also some personal tasks done and others were a wash. But overall, I think the pandemic’s languishing feelings are starting to subside as I try to figure out a schedule for myself and a routine that works best for my mental health, physical health, and other factors that contribute to my well-being.

I wanted to recap some projects (of various kinds) that I’ve worked on in the past few months.

GMMK Pro keyboard

This project has been the most relaxing thing I’ve worked on in a long time. Taking apart the switches and the keyboard was new to me. Overall, I would probably build another board but not for awhile since this board is great for now.

Quotes project

I wanted a simple to use quote saving program, this does just that in the command line. I think I spent 2-3 days working on it in total.

House refinancing

Not a technical project but I spent a bunch of hours working on a house refinance. My original interest rate on the house was 3.75% and now it’s 2.5% which is a fairly nice reduction in interest. On top of that, my original loan to value ratio (LTV) was around 90% which required a PMI on that house, now that the value of the house has increased, the LTV ratio was below 80% (the mark which banks considered okay to not require PMI payments) so I’m saving an additional $175 a month on that.

Now Playing for Last.fm

This project is one of my favorite projects I have worked on. I originally built this as a way to learn Svelte and then it turned into a real useful project (I use it almost everyday now). I’ve marked this project as “done” on github because as it sits today, it works as intended and I don’t want to add more features to it.

TIL: null is an object in Javascript

I’ve been in a lull about learning concepts related to programming and web development the past few months so yesterday when I got an email about Just Javascript, I signed up for the course to check out how it will be.

So far, I’m running into pleasant surprises like how there are only nine data types in Javascript.

  1. Numbers (1, 3.14, -500)
  2. Strings (“hello”, ‘samson’, ‘a long sentence’)
  3. Booleans (true and false)
  4. Undefined (undefined)
  5. Null (null)
  6. BigInts (not sure about these yet)
  7. Objects ({})
  8. Functions (sum => x + x)
  9. Symbols (uncommon but used for referring to unchanging values)

Well, after learning about these, I also ran into an interesting quiz question in the course, what is the value of null when checking with typeof()? Turns out it’s "object". This was a surprise to me but I guess it’s been a bug for a long time.

Here’s a lot more info about it from someone who knows JS way better than me:

The history of “typeof null”.

Some digging into embedding comparable images

I recently had an idea to compare two images side by side and ideally having a slider present to be able to see one more than the other. I wanted to get to a MVP of this but after spending a couple of hours, I decided to just jot down my notes about it so far and move on. Another reason is that I’m trying to make this blog into a thought stream instead of just polished posts of some kind.

Examples of embedded objects

This Spotify embedded object is a great example of both functionality and style, it looks and feels like using the Spotify app and it’s easily embeddable.

Some places like WordPress only allow embedding from certain URLs and others like Notion allow embedding anything that doesn’t block embedding, see a screenshot below:

↑ Embeds in notion ↑

I tried a couple of different techniques to try to get two images to be comparable, you can see them in this codepen: https://codepen.io/usmanity/pen/dyYaVpY

Unfortunately, I couldn’t get a working version of it because my approach has been mostly CSS-first and I didn’t want to spend too much time writing JS to handle different parts of the dragging. One attempt I had was to watch drag and other events related to it, more here: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/draggable
This approach didn’t work because draggable is great for moving around elements but there was still no good way to get the difference in dragging unless I spent a fair amount of time calculating differences between the starting point and where the dragged slider was.

I also tried a border size and range input approach, basically use the value from the range slider and set that as the border size, but this didn’t work because the border would increase while decreasing the size of the image itself.

My next attempt will be to use a background size approach but right now I feel pretty burnt out by the past few approaches so I’ll wait on trying that.

Dull lull in July

I’ve been going through a slow time in July and I haven’t been very active on my computer besides using it for work at work. At home, I’ve just been keeping away from the computer almost full-time. There is some good news because of this, I’ve started to spend more time reading, doodling, eating, and doing anything else away from a computer.

After getting away from my computer in June and ending my work on Bookends, I felt a weird sort of burn out, not exhausted by more like a relief and now I’m looking for a new project and trying small things here and there but nothing sticky yet.

Learning Ruby has been slower and less fun than I thought it would be. When I was messing around with Python on my own time, it was fun to create small projects and build things on top of them but…that’s not the case with Ruby. Javascript was always easier to learn and play around with since it’s one language to write for server side and client side code.

I’m writing this post after attempting to write a couple of other drafts which I just couldn’t get myself to finish and it has become a common case for me that I’ll start something and won’t want to finish it. I believe I’m either attempting harder than achievable projects or not being consistent enough to continue working on them. I learned something from Eric Barker’s Barking up the Wrong Tree recently, if you want to achieve something above your current skill level, make it slightly harder not impossible to achieve which will give your brain enough reassurance that it will continue as small, consistent wins are better than large one-off lottery-like wins.

I recently created the following graphic using CSS:

You can see it here: Stop War @ usmanity.com

Goodbye Bookends, for now

Today, I’m stopping work on Bookends. In this post, I’d like to reflect on why I’m stopping work on it, what I’ve learned, and what’s next.

Bookend’s purpose is to help track and discover books. So far, I don’t think I’ve solved this.

What I’ve learned

When I started the project, I had a simple understanding of how to build a web application using Node.js, working on Bookends has helped me learn or solidify my understanding about routing, authentication, hashing, async calls, promises, and building an API. These are just Node related things, there are other things like how to deploy a staging and production server and how to keep a simple deployment flow have been one of the most delightful thing about Bookends.

Developing a project on your own is boring, hard, and slow. That’s one of the biggest lessons I’ve learned. It’s hard to keep going when there’s no users who want to use your product. It’s boring because every time you work on something, there’s no user feedback. And it’s slow because you have nobody to think with.

The tech stack I chose was familiar to me but it’s not very productive to build an application for the first time with a bunch of tools glued together. I chose node.js with express, vue.js, and sequelize as my main stack. Each of these tools, I’ve learned to use and build with better throughout my year with Bookends but it was still slower because there is no convention guiding best practices with any of them apart from the documentation.

Building an app that relies on third party data is tough, all the book info on Bookends was sourced from public APIs like OpenLibrary and that resulted in lower quality results in the end.

Bookends is currently not solving a problem for anyone and I’ve seen myself become detached from it.

Why I’m moving on

The past few weeks have been pretty hard by myself, inside my mind there have been conflicting thoughts that if I stop this, I’m giving up and at the same time, if I stop this I’m buying myself time to do something else. Up until last night, I was working on small features but even after stopping for the night, I felt like I wasn’t happy with the progress for the day. Fighting against my tools every time I work on it has been draining me to the point where I’m unable to go on my personal computer and concentrate on anything else. As you can see with hardly any posts in the past month.

What’s next

I’ve been using ruby and rails at work. I’m in a reverse tech cycle here, most people are moving to node.js and a modern front-end framework like vue.js or react while I’m moving to a more conventional web app framework like ruby on rails. I want to spend more time learning ruby, building things with ruby, and learning better habits for myself as a web developer. There are so many things I still would like to become proficient at like testing, iterating on product ideas, solving real world problems, learning deployment best practices, moving away from weekend projects for a change.

I might come back to working on Bookends when I have more experience building web apps.


Below are some screenshots of the most recent deploy on https://bookends.app. Depending on when you’re reading this, the site might still be up or not.

Serving Vue.js apps on Github Pages

I wanted to share a pretty simple setup on how to serve a Vue.js app using Github Pages. I’m writing this because I had to search around online for awhile before I stumbled upon the Vue.js docs and then had to play with some settings in Github.

For this exercise, I’ll use a sample project you can find here: https://github.com/usmanity/serve-vue-app

So let’s start from the beginning. Let’s use Vue CLI to create an app.

  • Install Vue CLI: https://cli.vuejs.org/
  • Create an app using the above (instructions on the above page): vue create sample-vue-app
  • When you’re prompted with the options for the app, you can choose whatever you want, I went with the default (eslint, babel) setup.
  • After the app is created, cd into the directory and then run npm run serve. If you see the following page, you’re good to go:
  • At this point, let’s configure the vue.config.js file. For reference, I’m using this documentation to set this up: https://cli.vuejs.org/config
  • Your config should look like the following
module.exports = {
  publicPath: "/serve-vue-app",
  outputDir: "docs"
};
  • Save the file and run npm run serve. You should see the localhost URL change to include the publicPath as part of it. This is one way to confirm it’s working.
  • Next, we’ll set up github to serve this. Commit the files and push up to github.
  • After you’ve pushed up the files, go to the repo’s settings
  • Look for the “Github Pages” section and you’ll see something like the following
  • You’ll see the option to serve from the master branch but not from the “master branch /docs folder”. This is because we haven’t built anything for the app.
  • To fix this, just run npm run build in the app folder on your computer.
  • After the build runs, you’ll see a new folder created (it should be called docs).
  • Add this to git, commit and push up. Then you’ll see the docs option available:

After you select this, give github 2-3 minutes to finish building the page and then it will have the URL in the header or just go to whatever URL you configured and keep refreshing 😛.

That’s it, you’re done! Please leave comments if you run into any issues or caught an error with my steps. Thanks!

Setting up Fathom for all my sites

So yesterday, I was learning about how nginx works and how to serve multiple sites (web apps even) from the same machine at different URLs. I wanted to do this because I don’t know much about nginx so I thought of it as an experiment to try.

So after I got it working, I remembered that back in February, I had tried using Fathom for basic analytics as it’s not as deeply detailed as Google Analytics. So I went ahead and did the 1-click install then I realized that the install won’t work as it’s not available for multiple sites. How did I come to this conclusion? I had missed a step during the initial setup that asks you if you’d like your analytics to be public or password protected, and because I didn’t care about the analytics being public, I selected that. This shortcut me to the end of the setup and I was able to check out the analytics. Then I realized, I could only have one site, and that wasn’t what I wanted.

Well later, 2-3 hours of messing around, learning a bit about nginx and other things, I come to a point where I had multiple instances of Fathom running on a single DigitalOcean box and I came across some issue which I thought was worth googling, this then led me to a Github issue which revealed to me that I was logged out the whole time on my original 1-click install.

So, I turned around and did the 1-click install again. And this all to say that I’m moving away from Google Analytics and trying to use Fathom analytics now. 😊

Trying out a new workflow for personal projects

I don’t have any serious personal projects right now because I usually start something small like the following few:

And after starting them, I realize that I got them done in a short spurt of energy but they are not projects I have much consistency with that I will actually keep up with them in the long run. The URL shortener was also a hack that I wanted to try to build in a short amount of time.

But the point of this post is to say that I haven’t really had a space to work on personal projects as I’ve had only a work laptop for the last 3+ years now. Since I left Outbound, I’ve had only a work laptop and it’s fine for small projects but once the project starts to have a database, a lot of assets hanging out in my recent files, and those sort of things, I don’t want it to be on my work computer.

Well, I had mentioned this a couple of times to people and one of those people is my wife. She surprised me with a Mac Mini for Christmas and I just got the computer in the mail today.

It’s the 3.2 Ghz hexa-core version which so far has been blazing fast! I’m excited to get it set up for some larger projects.

Especially Bookends which has been neglected due to the amount of work it takes me to get started with it. So in the coming weeks, I’ll aim to get a beta page up for Bookends and I’ll document the issues I’ve been running into as I’ve worked on it.