A PHP GD + TwitterOAuth CLI app to dynamically generate Twitter header images and optionally upload them via the API. This enables you to build cool little tricks, like showing your latest followers or sponsors, your latest content created, a qrcode to something, a progress bar for a goal, and whatever you can think of.
Other types of dynamic banners can also be generated. Dynacover uses erikaheidi/gdaisy for image manipulation based on templates.
This guide shows how Dynacover was built: How to Dynamically Update Twitter Cover Image to Show Latest Followers Using PHP GD and TwitterOAuth. Please notice that the version that is compatible with this tutorial is 0.1.0, the initial release. Newer versions use erikaheidi/gdaisy as dependency to work with JSON templates.
You can run Dynacover in two different ways:
- with Docker: the simplest way to run Dynacover is by using the public erikaheidi/dynacover Docker image.
- to further customize your cover, you can clone the dynacover repo to customize banner resources (JSON template and header images, both located at
app/Resources
), then build a local copy of the Dynacover Docker image to use your custom changes.
- to further customize your cover, you can clone the dynacover repo to customize banner resources (JSON template and header images, both located at
- with a local PHP environment: this will require
php-cli
7.4+, Composer, and a few extensions, such asphp-gd
,php-mbstring
,php-curl
, andphp-json
.
To upload your header images, you'll need to register an application within the Twitter Developers Portal and obtain 4 tokens:
- Consumer / App Token
- Consumer / App Secret
- User / Access Token
- User / Access Token Secret
Additionally, you can set up a Personal GitHub API key to fetch your sponsors, in case you are enrolled in the GitHub Sponsors program. In this case, you should use the included cover_sponsors.json
template. This is optional.
Dynacover has a self-contained Docker image that you can use to run Dynacover with a single command. The container receives API credentials via a .env
file provided at run time.
First, you'll need to set up your API credentials. Check this blog post for detailed instructions on how to obtain these.
Create an environment file using this template. In this example, we'll name the file .dynacover
.
cd ~
nano .dynacover
# Credentials
TW_CONSUMER_KEY=YOUR_APP_KEY
TW_CONSUMER_SECRET=YOUR_APP_SECRET
TW_USER_TOKEN=USER_ACCESS_TOKEN
TW_USER_TOKEN_SECRET=USER_ACCESS_TOKEN_SECRET
GITHUB_TOKEN=GITHUB_PERSONAL_TOKEN
# Default Template
DEFAULT_TEMPLATE=app/Resources/templates/cover_basic.json
Save the file once you're done adding your API credentials there. You can also use this file to set up your default template of choice.
To test that your credentials are valid, you can list your latest followers with the following command, which will spin up a temporary container and inject the environment variables contained in .dynacover
:
docker container run --env-file .dynacover --rm -v $(pwd) erikaheidi/dynacover php dynacover fetch followers
The following command will generate a dynamic cover based on the default template specified in .dynacover
, and upload the resulting image as your Twitter header.
docker container run --env-file .dynacover --rm -v $(pwd) erikaheidi/dynacover php dynacover cover update
To customize your header with your own JSON template file and PNG images, you'll need to build a local Docker image with your changes. You don't need to have PHP installed locally. You need only Docker for that.
Start by cloning this repository to your local development machine:
git clone https://github.com/erikaheidi/dynacover.git
The Dockerfile included within the application will copy the files in the current directory into the image. When you are finished with any changes you made to customize your banner, you can run:
docker build . -t myuser/dynacover
Then, you can run dynacover using your custom image with:
docker container run --env-file .dynacover --rm -v $(pwd) myuser/dynacover php dynacover cover update
It is also possible to run Dynacover in a local PHP environment. This will require:
- PHP (cli only) 7.4+
- GD / PHP-GD
- Curl
- Composer
Installation is done in a few steps: clone, install dependencies, set up credentials, and you are ready to go.
Start by cloning this repository to your local PHP dev environment or remote PHP server:
git clone https://github.com/erikaheidi/dynacover.git
cd dynacover
composer install
This will install a few dependencies and generate a config.php
file in the root folder of your application.
Open the generated config.php
file and set up your credentials:
#config.php
<?php
return [
//Twitter API Keys
'twitter_consumer_key' => getenv('TW_CONSUMER_KEY') ?: 'APP_CONSUMER_KEY',
'twitter_consumer_secret' => getenv('TW_CONSUMER_SECRET') ?: 'APP_CONSUMER_SECRET',
'twitter_user_token' => getenv('TW_USER_TOKEN') ?: 'USER_ACCESS_TOKEN',
'twitter_token_secret' => getenv('TW_USER_TOKEN_SECRET') ?: 'USER_ACCESS_TOKEN_SECRET',
//GitHub Personal Token (for templates using GH Sponsors)
'github_api_bearer' => getenv('GITHUB_TOKEN') ?: 'GITHUB_API_BEARER_TOKEN',
//Default Template
'default_template' => getenv('DEFAULT_TEMPLATE') ?: 'app/Resources/templates/cover_basic.json'
];
The github_api_bearer
token is optional, only in case you want to use the GitHub API to fetch Sponsors.
You need to replace the following strings with the corresponding tokens:
APP_CONSUMER_KEY
APP_CONSUMER_SECRET
USER_ACCESS_TOKEN
USER_ACCESS_TOKEN_SECRET
GITHUB_API_BEARER_TOKEN
To test that your credentials are valid, you can list your latest followers with:
php dynacover fetch followers
If everything is set up correctly, you will see a list with your 10 latest followers.
To preview your cover without uploading it to Twitter, run:
php dynacover generate twitter
This will use the default cover_basic.json
template. You can specify a template with the template=template_path
parameter:
php dynacover generate twitter template=app/Resources/templates/cover_neon.json
Built-in templates are located in the app/Resources/templates
directory. You can also create your own templates in any preferred location and pass the template json path as parameter, relative to the application root folder. Check the included templates to see how it works. Ideally, you should choose a default template and set it up within the dynacover
script configuration.
Covers are generated in the root of the application folder, with the name latest_header.png
. Check the generated image before uploading it to Twitter to confirm it has your latest followers, and it looks like you expect.
To upload the latest generated cover to twitter, run:
php dynacover cover upload
To generate and update your cover using the template that is configured as default in the app config, run:
php dynacover cover update
For this to be completely dynamic and update frequently, you'll need to include the script to your Crontab or equivalent. First make sure you set up the default_template
config parameter in the dynacover
script to your preferred template. By default, this is app/Resources/templates/cover_basic.json
.
To open the current user's crontab, run:
crontab -e
This will open up a text editor. You should include the full paths to both the php
executable and the dynacover
script, like in this example which will update the cover every 5 minutes:
*/5 * * * * /usr/bin/php /home/erika/dynacover/dynacover cover update > /dev/null 2>&1
The default template shows latest 5 Twitter followers.
Similar to the basic cover, but with a more colorful background. Shows latest 5 Twitter followers.
This template shows your latest 5 Twitter followers in smaller size, in a blue-neon style header.
This template uses the Github image source to obtain sponsors and include them in the banner. Make sure you have set up your GH token on the credentials.php
file.
The "interactions banner" is generated based on your recent interactions and can be limited to only include mutuals (people that follows you and you follow them back).
php dynacover generate interactions
For mutuals only, include the --mutuals
flag:
php dynacover generate interactions --mutuals
Please notice that the "mutuals" version may have a limited set of results after filtering your latest interactions (~200 mentions).