Posts

Part 6 - Fragments

This is part 6 of series

This part is based on the Fragments section of this tutorial

useFragment

After all the work we have done so far, following Fragments section in Relay tutorial is a breeze.

Commit: https://github.com/tuan/newsfeed-demo-app/commit/b3ce37e71a9007a9cd717ebd06d6cc5efa78ee64

There are a few things related to fragment that might be beneficial if you’re new to Relay:

  • Think of the Relay query as a tree: each fragment is a node. This Relay tree is a mirror of React component tree. With this in mind, when you re-use your component in an existing part of the component tree, you should also re-use, i.e. spread, your component’s fragment in the corresponding part of the Relay tree.
  • Use the following naming convention when naming your fragment: ComponentNameFragment_componentPropName. Here’s an example in Image.tsx:
    const ImageFragment = graphql`
      fragment ImageFragment_image on Image {
        url
      }
    `;
    
  • The type of your fragment key always has the suffix $key
  • Your fragment key is the nearest parent node in the Relay query where you spread your fragment

After making the changes, you should now see the timestamp rendered correctly

Part 5 - Refactoring resolvers

This is part 5 of series

At the end of part 4 we have a working API that resolves topStory field. This is the setup:

# schema.py
@strawberry.type
class Query:
    top_story: Story | None = strawberry.field(resolver=top_story.resolve)

# top_story.py
def resolve() -> Story | None:
    first = next(node for node in db.nodes if node.get("__typename") == "Story")
    if not first:
        return None

    return Story(
        id=str(first.get("id")),
        created_at=first.get("createdAt", ""),
        title=first.get("title", ""),
        summary=first.get("summary", ""),
        updated_at=first.get("updated_at", ""),
        like_count=first.get("like_count", ""),
        does_viewer_like=first.get("does_viewer_like", ""),
        category=Category[str(first.get("category"))],
        attachments=[
            Image.from_raw_data(attachment)
            for attachment in first.get("attachments", [])
        ],
        thumbnail=Image.from_raw_data(first.get("thumbnail")),
        poster=actor.resolve(str(first.get("authorID"))),
    )

This works, but I’m not happy with how this looks. There are 2 main issues with the current design:

Part 4 - Relay Query Basics

This is part 4 of this series

Let’s recap what we have done so far:

  • We set up Django project
  • We set up Vite project
  • We configure Django to retrieve client side’s assets from Vite
  • We set up GraphQL Endpoint using Strawberry
  • We prepare the demo data

Phew, that’s a lot! I think we’re ready to dive into Relay now!

Relay installation

The npm dependencies and boilerplate code to set up Relay on client side can all be done using one command:

Part 3 - Prepare demo data

This is part 3 in this series

Now that we have our GraphQL endpoint working. It’s time to get some data for newsfeed demo app.

Create fake database

If you’re looking at the source of Newsfeed Demo app here, you can see that they hardcode the data in a nodes variable. Let’s do just that, but in Python.

Outline:

  • Copy and paste fake data from relay-examples
  • Update urls for the images hardcoded in fake data
  • Create a db module to use as the “database” for our demo app.

Here’s the json file that we have after step 1 & 2: https://github.com/tuan/newsfeed-demo-app/commit/3b5c3ef2dc31108446caef8f44f6175d70e00aa4 Notice that, compared to the urls in relay-examples, our urls start with /static. This is to match with current STATIC_URL we have in settings.py.

Part 1 - Django & Vite

This is part 1 of this series

In part 1, we focus on getting a basic Django project up and running with React and Typescript using Vite.

Set up dev environment

Python virtual environment

There are many options to manage virtual environments and dependencies in Python. Here I’m using pipenv.

Create a new virtual environment and activate it:

pipenv shell

Install Django

pipenv install django

Git

This is a good website to create a gitignore file gitignore.io - Create Useful .gitignore Files For Your Project You can select options that are specific to your development environment to create the right gitignore file. In my case I select: macOS, VisualStudioCode, Python, and Node.

Fullstack app using Django, Vite, React, Graphql, and Relay

I’ve recently needed to set up a new web app. In my last job (currently on a one year break!), the tech stack was well-established. Now, out of the cage and with the freedom to choose (which is awesome!), I’m feeling a bit overwhelmed by the sheer number of options available.

To avoid analysis paralysis, I’ve decided to pick the things I liked about my previous job’s stack and see if there are suitable alternatives for each element.

Scoped Search With Page Redirect Extension

I’m having so much fun with this Page Redirect extension I’ve created. Initially, it was created for two main usecases I have:

  • Automatically set a homepage. For example, it can change the Facebook homepage (Newsfeed) to the Facebook Feeds tab.
  • Open the current YouTube video in Invidious. This removes ads before you watch.

Thanks to the use of regular expressions, the extension helps me in other scenarios as well. The one I want to talk about in this post is scoped search.

Redirect Youtube to Invidious

Redirect Youtube to Invidious

Since YouTube started cracking down on ad blockers, I’ve been using Invidious more and more. There are many public instances of Invidious (https://instances.invidio.us/) that I can choose from.

However, Invidious isn’t great for content discovery. I find myself frequently going back to the YouTube homepage to browse content. For each video I want to watch, I copy the ID and open it in Invidious. But that gets tedious quickly.

I’ve found a creative use for the Safari extension, Page Redirect, that I blogged about recently. When I want to watch a video, I just use the extension to jump to Invidious. In other words, I go back and forth between YouTube and Invidious: YouTube for browsing & Invidious for watching. The extension I use has automatic redirection as well, but I mostly use it in manual mode because it’s easier that way to mix YouTube and Invidious in the same session.

Redirect Newsfeed to Feeds tab

My Facebook Newsfeed is full of irrelevant content. I keep getting suggested posts from people and sites I don’t even follow.

In 2022, Facebook announced a new Feeds tab which, according to the announcement, is:

a new way to find the most recent posts from your friends, Favorites, Pages and groups. You can curate a Favorites list of the friends and Pages you care about most and filter their content in this new tab.