astro-loader-tweets
TypeScript icon, indicating that this package has built-in type declarations

1.3.0 • Public • Published

astro-loader-tweets

version jsDocs.io npm downloads

This package provides a tweets loader for Astro, fetching tweets from X (formerly Twitter) by ID for use in Astro projects. It supports customizable HTML/Markdown generation and saving tweets to a custom JSON file.

Installation

npm install -D astro-loader-tweets

Usage

To use the Astro loader, ensure Astro version ^4.14.0 || ^5.0.0. For ^4.14.0, enable the experimental content layer in astro.config.ts:

export default defineConfig({
  experimental: {
    contentLayer: true,
  },
})

In src/content/config.ts (for ^4.14.0) or src/content.config.ts (for ^5.0.0), import and configure the loader to define a new content collection:

import { defineCollection } from "astro:content"
import { tweetsLoader } from "astro-loader-tweets"

const tweets = defineCollection({
  loader: tweetsLoader({
    ids: ['1865968097976586582'],
    // Check the configuration below
  }),
})

export const collections = { tweets }

Query the content collection like any other Astro content collection to render the loaded GitHub PRs:

---
import { getCollection } from "astro:content"

const tweets = await getCollection("tweets")
// Check the entries' Zod schema for available fields below
---

{
  tweets.map(async (tweet) => {
    const { Content } = await render(tweet)
    return (
      <section>
        <Content />
        <p>{tweet.data.tweet.created_at}</p>
      </section>
    )
  })
}

To update the data, trigger a site rebuild, as the loader fetches data only at build time.

Configuration

This loader retrieves tweets via the X API V2 GET /2/tweets endpoint, requiring an X app-only Bearer Token for authentication. Options include:

Option (* required) Type (default) Description
ids* string[] An array of Tweet IDs to fetch content for.
storage 'default' | 'custom' | 'both' (default: 'default') The method to store the loaded tweets:
'default': Uses Astro's default KV store.
'custom': Use a custom JSON file path.
'both': Both default and custom path.
storePath string (default: 'src/data/tweets.json') The custom output path for storing tweets, either absolute or relative to the Astro project root. Must end with .json. Required if storage is 'custom' or 'both'.
removeTrailingUrls boolean (default: true) Whether to remove trailing URLs from the tweet text in the generated text_html and text_markdown, typically used for views or referenced tweets.
linkTextType 'domain-path' | 'post-text' (default: 'post-text') The type of text to display for links when generating text_html and text_markdown:
'domain-path': Displays the link's domain and path.
'post-text': Uses the link text as shown in the tweet.
newlineHandling 'none' | 'break' | 'paragraph' (default: 'none') The way for processing \n in text_html generation:
'none': Keep as is.
'break': Replace consecutive \n with <br>.
'paragraph': Wrap paragraphs with <p> while removing standalone \n.
authToken string (Defaults to the X_TOKEN environment variable) The X app-only Bearer Token for authentication. If configured here, keep confidential and avoid public exposure. See how to create one and configure env vars in an Astro project.

About storage Configuration

Why not use the Astro default store?

  • Each time the content.config.ts is modified, Astro clears the store (i.e., .astro/data-store.json).
  • Under the X API V2 free plan, the endpoint requested are limited: only 1 request per 15 minutes is allowed, with a maximum of 100 tweets retrievable per month.

Benefits of custom JSON file storage

  • Newly loaded Tweets are appended or updated in the specified JSON file.
  • Data can be edited while retaining the id attribute and structure, but repeated requests for the same Tweet ID will overwrite existing data.
  • Stored tweets persist unless the file is manually deleted, allowing up to 100 unique Tweets to be loaded monthly.

Creating content collection from JSON file

After storing tweets in a custom JSON file, you will need to define an additional content collection for rendering purposes:

import { tweetsLoader, TweetSchema } from 'astro-loader-tweets'

const savedTweets = defineCollection({
  loader: file("src/data/tweets.json"),
  schema: TweetSchema
})

export const collections = { ..., savedTweets }

Additionally, use set:html to embed tweets formatted in HTML instead of using the <Content /> component.

---
import { getCollection } from "astro:content"

const savedTweets = await getCollection("savedTweets")
---

{
  savedTweets.map(async (t) => {
    return (
      <section>
        <Fragment set:html={t.data.tweet.text_html}></Fragment>
        <p>{tweet.data.tweet.created_at}</p>
      </section>
    )
  })
}

This is my current solution. If you have a more scalable approach, please share it to address these challenges.

Schema

See the source code for the Zod schema of loaded entries and refer to the Twitter API v2 data dictionary for field details. Astro automatically applies this schema to generate TypeScript interfaces, enabling autocompletion and type-checking for collection queries.

In addition to API-fetched fields, the loader extends fields defined in the TweetV2ExtendedSchema, simplifying the control over tweet content display.

To customize the schema, ensure compatibility with the loader's built-in Zod schema to prevent errors. For additional fields, consider opening an issue.

Changelog

See CHANGELOG.md for the change history of this loader.

Contribution

If you see any errors or room for improvement, feel free to open an issues or pull request . Thank you in advance for contributing! ❤️

Package Sidebar

Install

npm i astro-loader-tweets

Weekly Downloads

20

Version

1.3.0

License

MIT

Unpacked Size

84.2 kB

Total Files

5

Last publish

Collaborators

  • lin-stephanie