Building a Tweet Scheduler using Upstash
In this step-by-step guide, I talk about how I built a Tweet Scheduler using Upstash QStash, Upstash Redis, Next.js Server Actions and Vercel. Scheduling Twitter posts helps you maintain a consistent presence, engage with your audience at optimal times, and efficiently manage your content strategy.
Prerequisites
You will need the following:
- Node.js 18 or later
- An Upstash account
- A Twitter account
- A Vercel Account
Tech Stack
Following technologies are used in this guide:
| Technology | Description | | --- | --- | | Upstash | Serverless database platform. We're using both Upstash Queue & QStash for storing tweets in a queue and POST-ing schedule API at a given frequency, respectively. | | Next.js | The React Framework for the Web. We’re using the populate shadcn/ui for rapid UI prototyping. | | TailwindCSS | CSS framework for building custom designs. | | Vercel | A cloud platform for deploying and scaling web applications. | | Prettier | Opinionated code formatter for consistent code style. |
Steps
To complete this guide and deploy your own tweet scheduler, you will need to follow these steps:
- Setting up Upstash Redis
- Setting up Upstash QStash
- Setting up Twitter Developer Application
- Create a new Next.js application
- Implement User Authentication with Twitter OAuth 2.0
- Build the User Interface To Schedule Tweets
- Schedule Tweets using Upstash QStash
- Deploy To Vercel
Setting up Upstash Redis
Once you have created an Upstash account and are logged in you are going to go to the Redis tab and create a database.
After you have created your database, scroll down until you find the REST API section and select the .env
button. Copy the content and save it somewhere safe.
Setting up Upstash QStash
To schedule POST requests to the scheduling endpoint at a given interval, you will use QStash. Go to the QStash tab and scroll down to the Request Builder tab.
Copy the QStash URL, TOKEN, Current Signing Key and Next Signing Key and save them somewhere safe.
Setting up Twitter Developer Application
To set up authentication with Twitter OAuth 2.0, you're going to create an application in Twitter Developer Portal. To set up a Twitter application, do the following:
- Open Twitter's Developer Portal > Projects.
- Create a Project.
- Go the Settings tab in your application settings, and do the following:
- Select
Read and write and Direct message
in the App permissions. - Select
Web App, Automated App or Bot
in the Type of App. - Enter
http://localhost:3000/api/auth/callback/twitter
as the Callback URI / Rediect URL.
- Select
- Go to the
Keys and tokens
tab in your application settings, scroll down and do the following:- Copy the
Client ID
and store it somewhere safe asTWITTER_CLIENT_ID
. - Copy the
Client Secret
and store it somewhere safe asTWITTER_CLIENT_SECRET
.
- Copy the
That is all you needed to set succesfully set up your Twitter Developer Application for OAuth 2.0.
Create a new Next.js application
Let’s get started by creating a new Next.js project. Open your terminal and run the following command:
When prompted, choose:
Yes
when prompted to use TypeScript.No
when prompted to use ESLint.Yes
when prompted to use Tailwind CSS.No
when prompted to usesrc/
directory.Yes
when prompted to use App Router.No
when prompted to customize the default import alias (@/*
).
Once that is done, move into the project directory and start the app in developement mode by executing the following command:
The app should be running on localhost:3000.
Now, create a .env
file at the root of your project. You are going to add the items we saved from the above sections.
It should look something like this:
Integrating shadcn/ui components
To quickly prototype the user interface, you’ll set up the shadcn/ui
with Next.js. shadcn/ui
is a collection of beautifully designed components that you can copy and paste into your apps. In your terminal window, run the command below to start setting up the shadcn/ui
:
You will be asked a few questions to configure a components.json
, choose the following:
Yes
when prompted to use TypeScript.Default
when prompted to select the style to use.Slate
when prompted to choose the base color.app/globals.css
when prompted to enter the global CSS file.yes
when prompted to use CSS variables for colors.Leave blank
when prompted to enter a custom tailwind prefix.tailwind.config.ts
when prompted to enter the location of tailwind.config.js.@/components
when prompted to configure the alias for components.@/lib/utils
when prompted to configure the alias for utils.Yes
when prompted to choose usage of React Server Components.Yes
when prompted to proceed with writing the configuration to components.json.
Once that is done, you have set up a CLI that allows us to easily add React components to your Next.js application. Next, In your terminal window, run the command below to get the button, input, textarea, popover, calendar and toast elements:
Once that is done, you would now see a ui
directory inside the app/components
directory containing button.tsx
, input.tsx
, calendar.tsx
, input.tsx
, popover.tsx
, textarea.tsx
, toast.tsx
, toaster.tsx
, and use-toast.ts
.
Next, open up the app/layout.tsx
file, and make the following additions:
In the code changes above, you have imported the Toaster
component (created by shadcn/ui
), and made sure that it’s present in your entire Next.js application. It enables you to show toast notifications from anywhere in your code via the useToast
hook.
Create an Upstash Queue to Store Scheduled Tweets
In this section, you will learn how to use the Upstash Queue to store scheduled tweets information. You will learn how to create server-side code which is invoked as a function instead of over an API route, using Next.js Server Actions.
First, in your terminal window, execute the following to install the Upstash SDKs:
The above command installs the following packages:
@upstash/qstash
: SDK to interact with your Upstash QStash instance over HTTP requests.@upstash/queue
: SDK to manage stream based message queue, backed by Upstash Redis.@upstash/redis
: SDK to interact over HTTP requests with Redis, built on top of Upstash REST API.
Initialize Upstash Redis and Upstash Queue Clients
To use the libraries installed above to interact with your Upstash Queue, create a file lib/upstash.ts
with the following code:
The code above does the following:
- Imports the
Redis
andQueue
classes exported by the packages. - Exports a
redis
instance pointing to the Upstash Redis URL with the request authorization token. - Exports a
queue
instance pointing to the Upstash Redis created above. It sets the queue name totweets
and theconcurrencyLimit
to 5, allowing up to 5 concurrent message processing.
Using the queue instance, you will create a Next.js Server Action that will accept the tweet text and the tweet date to form and push the tweet object into the queue for future processing. Create a file app/schedule.server.tsx
with the following code:
The code above does the following:
- Imports the
queue
instance - Exports a server action named
schedule
, that accepts a form submission containing to-be scheduled tweet's text and date. - Computes the time between then to the time the tweet is scheduled for.
- Inserts the tweet object containing date and text with the delay set to the time computed above.
With this, you have ensured that the tweet is pushed to the queue only when it is scheduled for. This eases the process of maintaining the state of the queue, ensuring that only the tweets scheduled on any given day are available in the queue.
Let's move onto obtaining authorization from the user to tweet on their behalf using OAuth 2.0 PKCE flow.
Implement User Authentication with Twitter OAuth 2.0
In this section, you will learn how to set up Twitter OAuth 2.0 authentication flow in your application by configuring the Twitter OAuth client, and using the helper functions provided by Twitter SDK for authentication tasks. The authentication flow involves creating authorization and callback endpoints, enabling users to grant access and receive tokens, with the access token being stored in Upstash Redis. you will also create an authentication status through an endpoint indicating the presence of a valid access token in Upstash Redis.
First, in your terminal window, run the command below to install the necessary library for implementing Twitter OAuth 2.0 Authentication:
The above command installs the following package:
twitter-api-sdk
: A TypeScript SDK for the Twitter API.
Create a Twitter Authentication Client
To be able to generate an authorization URL without delving into the complexities of the Twitter API, you are going to use auth client by Twitter SDK. Create a file twitter.ts
inside the lib
directory with the following code:
The code above begins with importing the auth helper from the Twitter SDK. Then, it exports the auth client that will save the time of learning Twitter API syntax by providing helper functions to generate authorization URL and requesting access token from an authenticated user.
Prepare Twitter Authorization URL
The first step in the OAuth 2.0 flow is that user gets redirected to an authorization URL. Authorization URL is an endpoint provided by the OAuth 2.0 server where the user is redirected to begin the authorization process by granting permissions to the client application. Usually, a user is presented with multiple choices (such as Continue with Twitter
, Continue with Google
, etc.) at the sign in/up screen, and then are taken to the platform's (here, Twitter) hosted authorization screen.
Create a file app/api/auth/twitter/route.ts
with the following code:
The code above does the following:
- Imports the
NextResponse
helper function that extends the Web Response API. - Imports the
authClient
created earlier. - Exports a
GET
HTTP Handler which responds to incoming GET requests on/api/auth/twitter
. - Generates an authorization URL using the
generateAuthURL
helper function of Twitter SDK. - Redirects to the generated authorization URL using
redirect
method of NextResponse.
Let's move onto creating an endpoint that responds to the request when a user authorizes your Twitter application with the access.
Prepare Authorization Callback URL
The second step in the OAuth 2.0 flow is responding to callbacks from authentication platform. To handle incoming authorization callback request from Twitter, you will configure an endpoint in your application where the user will be redirected after granting access. This callback URL is essential for receiving the authorization code, enabling your application to save the access token obtained in Upstash Redis. With that token, you can automate tweets over an API in your application.
Create a file app/api/auth/callback/twitter/route.ts
with the following code:
The code above does the following:
- Imports the
redis
instance that is using Upstash Redis. - Imports the
NextResponse
helper function that extends the Web Response API. - Imports the
authClient
created earlier. - Exports a
GET
HTTP Handler which responds to incoming GET requests on/api/auth/callback/twitter
. - Destructures
code
query parameter from the callback URL. - Creates an authorization URL like earlier as a hack to update the internal state created by SDK.
- Calls the
requestAccessToken
function by Twitter SDK to obtain the access and refresh tokens, that will allow you to create tweets over an API. - Destructures the
access_token
from thetoken
object obtained. - Saves the access token value obtained with
twitter_oauth_access_token
as the key in Upstash Redis. - Redirects to the index URL (
/
) usingredirect
method of NextResponse.
You are now done with the Twitter OAuth 2.0 flow.
Having a valid twitter_oauth_access_token
in the Upstash Redis instance is an indicator of the authentication flow status. To communicate the same in the user interface, create a file app/api/auth/twitter/authenticated/route.ts
with the following code:
The code above does the following:
- Imports the
redis
instance that is using Upstash Redis. - Imports the
NextResponse
helper function that extends the Web Response API. - Exports a
GET
HTTP Handler which responds to incoming GET requests on/api/auth/twitter/authenticated
. - Fetches the value associated with
twitter_oauth_access_token
key in Upstash Redis. - Returns a JSON response containing an
ok
boolean indicating if there's a valid access token present in Upstash Redis.
Let's move to creating the user interface to consume these API endpoints you have created.
Build the User Interface To Schedule Tweets
In this section, you will learn how to create reactive form states using React hooks useFormState
and useFormStatus
, and invoke the server action to schedule tweets.
First, you are going to create a React component that renders a form containing to-be scheduled tweet's information and shows a toast notification indicating if the tweet information . Create a file app/form.tsx
with the following code:
The code above does the following:
- Imports the components created by
shadcn/ui
CLI commands earlier. - Exports a React component that renders a visually hidden
input
HTML element describing the date of the scheduled tweet. - The component also renders a
textarea
HTML element to accept the text of the tweet visually from the user. - The component also renders a
Button
which is disabled conditionally based on the status of previous form submission(s). - The component also uses the
useEffect
hook to reset the form if the server action resulted in success. Either way, it shows a toast notification on the bottom right corner to indicate the status of the request.
Next, you are going to create a component that shows the status of user's Twitter authentication status. Create a file components/twitter.tsx
with the following code:
The code above does the following:
- Imports the
useEffect
anduseState
hooks by React to use them to fetch the status of user authentication. - Exports a React component that renders the
Button
component (byshadcn/ui
) in different states, associating each with user's Twitter authentication status.
To render a form for the users that allows them to interact and schedule a tweet as they open the index route (i.e. /
), create a file app/page.tsx
with the following code:
The code above does the following:
- Imports
Form
andTwitter
components created earlier. - Imports the
useFormState
hook by React to be able to process the data returned by the Next.js server action using thestate
variable, and allow invocation of server action through form submission. - Imports the
schedule
server action created earlier. - Expors a React component that contains a
<form>
component withschedule_form
id and is set to invoke theformAction
when the form is submitted by the user.
Schedule Tweets using Upstash QStash
To schedule tweets on behalf of the user, you will create an endpoint that will consume the tweet data stored in Upstash Queue and then POST to Twitter API to perform the tweets. Create a file app/api/schedule/route.ts
with the following code:
The code above does the following:
- Imports the
redis
andqueue
instances that are using Upstash Redis and Upstash Queue respectively. - Imports the
verifySignatureAppRouter
function by Upstash that will verify the request signature to ensure that the request is from QStash only. - Creates a function
tweet
that accepts a tweet text and access token to perform tweets on behalf of the authenticated user. - Creates a
POST
HTTP Handler which responds to incoming POST requests on/api/schedule
. It fetches 4 messages from the Upstash Queue and invokes thetweet
function to perform tweets on behalf of the user.
Using Upstash QStash, you can schedule the process of performing tweets. Say you want to automate it such that every day at midnight, the process starts itself and the tweets go out. To do that, you will use the endpoint created earlier: /api/schedule
in QStash.
Go to the QStash tab in Upstash console, scroll down to the Request Builder tab and do the following:
- Select
Endpoint
tab. - Enter the
URL
as the absolute URL to your/api/schedule
endpoint. - Select
Type
asScheduled
. - Select
Every
asevery day at midnight
. - Click
Schedule
.
With the steps above, you have created a job that POST's to /api/schedule
every day at midnight.
That was a lot of learning! You’re all done now ✨
Deploy to Vercel
The repository, is now ready to deploy to Vercel. Use the following steps to deploy:
- Start by creating a GitHub repository containing your app's code.
- Then, navigate to the Vercel Dashboard and create a New Project.
- Link the new project to the GitHub repository you just created.
- In Settings, update the
Environment Variables
to match those in your local.env
file. - Click
Deploy
.
More Information
For more detailed insights, explore the references cited in this post.
- GitHub Repository
- Twitter OAuth 2.0 Flow
- Generating Twitter App Tokens
- React Form Hooks
- Next.js Server Actions
Conclusion
In this guide, you learned how to build a robust Tweet Scheduler leveraging Upstash's powerful Redis database and QStash queue. Upstash's scalability ensures reliable storage and scheduling of tweets combined with seamless deployment on Vercel create a fully automated system.