Static Tweet Cards

How I create static Tweet cards to use on this site

Twitter's embed API has a few things that are less than desireable. Here's an example of the embed code Twitter gives for this tweet.

<!-- I've formatted it here so it is more readable. This is given as a single line from Twitter -->
<blockquote class="twitter-tweet" data-dnt="true">
  <p lang="en" dir="ltr">
    Tweets embed on my blog are now statically-generated as part of the page and
    its images are optimized using Next.js 10’s &lt;Image /&gt; component
    <br /><br />
    Meaning:<br />
    - the tweets are available at page load<br />
    - no more cumulative layout shift (page jumping around) caused by loading
    embed tweets
    <a href="https://t.co/fWCpiNN4Bo">pic.twitter.com/fWCpiNN4Bo</a>
  </p>
  &mdash; Jane Manchun Wong (@wongmjane)
  <a
    href="https://twitter.com/wongmjane/status/1330273157245243394?ref_src=twsrc%5Etfw"
    >November 21, 2020</a
  >
</blockquote>
<script
  async
  src="https://platform.twitter.com/widgets.js"
  charset="utf-8"
></script>

As Jane alludes to in the embed code above, with the Twitter embed, the Tweet card isn't available at page load. You could just use the given blockquote, and that would get you pretty far, but if you wanted a more Twitter like experience you also need to load Twitter's widgets.js script. Which then in turn means cumulative layout shift caused by the script replacing the blockquote with an iframe. You can see in the first couple of seconds in Lee Robinson's YouTube video what this looks like. (This video as well as the provided links given in the video description were very helpful for me creating static Tweet cards for my site - it's worth it to watch the whole video if you are interested in doing this as well)

On top of that, loading in the widgets.js script and accompanying iframe is not "free". Including Jane's Tweet using the embed code would have added an additional 1.4MB of resources to the page - which feels like a lot for mostly static content.

The Google Chrome developer console showing 1.4mb of resources loaded using Twitter's embed code

So for this site, I decided I wanted to do what a lot of people like Jane and Lee have already been doing and use static Tweet cards.

I took inspiration (and code) from Lee's mentioned YouTube video. But one difference is, Lee is using Next.js where I am currenlty using Remix. So instead of querying for Tweets in getStaticProps I wanted to be able to just embed the needed data in my MDX file. This would mean stats for the Tweet - replies, retweets, likes - would get stale over time, but I'm fine with that for now. If someone is interested enough they can click on the link and see the updated stats in Twitter.

To make it easier for myself, I created a route in my Remix app which I can pass a Tweet ID and it returns back a formatted JSON object of the Tweet data from the Twitter API. I can then pass this data to the Tweet component created for use in my MDX files.

Here's how I am using it in the MDX file:

<Tweet
  {...{
    id: "1330273157245243394",
    text: "Tweets embed on my blog are now statically-generated as part of the page and its images are optimized using Next.js 10’s <Image /> component\n\nMeaning:\n- the tweets are available at page load\n- no more cumulative layout shift (page jumping around) caused by loading embed tweets https://t.co/fWCpiNN4Bo",
    author_id: "337119125",
    public_metrics: {
      retweet_count: 22,
      reply_count: 16,
      like_count: 494,
      quote_count: 7,
    },
    created_at: "2020-11-21T22:13:30.000Z",
    attachments: { media_keys: ["3_1330270041997271041"] },
    media: [
      {
        width: 1636,
        media_key: "3_1330270041997271041",
        height: 1800,
        type: "photo",
        url: "https://pbs.twimg.com/media/EnYRjhyXYAEclVi.jpg",
      },
    ],
    author: {
      name: "Jane Manchun Wong",
      url: "https://t.co/q7v0DjHk9o",
      profile_image_url:
        "https://pbs.twimg.com/profile_images/1499012482975014912/lp2juUP3_normal.jpg",
      id: "337119125",
      protected: false,
      verified: true,
      username: "wongmjane",
    },
  }}
/>

I might change this up in the future and have the Tweet component retrieve the latest stats after the initial render. But like I said, I'm fine with the stats getting stale over time for now. It doesn't really take away from the main point of the Tweet card and is extra complexity I don't want to worry about at the moment.

So to recap...

Here's an example of using just the blockquote from the Twitter embed code:

And here's an example of using the static Tweet card:

Tweets embed on my blog are now statically-generated as part of the page and its images are optimized using Next.js 10’s <Image /> component Meaning: - the tweets are available at page load - no more cumulative layout shift (page jumping around) caused by loading embed tweets
Tweets embed on my blog are now statically-generated as part of the page and its images are optimized using Next.js 10’s <Image /> component

Meaning:
- the tweets are available at page load
- no more cumulative layout shift (page jumping around) caused by loading embed tweets https://t.co/fWCpiNN4Bo

I think the static Tweet card looks much nicer. Plus, if you checkout the developer console, the resources loaded for this page are probably less than 1.4MB altogether, so that's nice too.