Skip to content

Repository files navigation

🐦 TweetX-web

— The dashboard half of your Developer-First Tweet Automation Toolkit

TweetX-web is a small Sinatra dashboard for the TweetX tweet scheduler. Write tweets, sort them into categories, browse what's queued, and see what has already gone out — all backed by plain CSV files.

✅ One file of Ruby, Bootstrap from a CDN, and a CSV datastore. No database, no build step.

This repo is the dashboard. The CLI that actually posts lives in TweetX — see Two repos, one tool below.

💡 What it does

  • ✍️ Add tweets in bulk, assigned to one or more categories
  • 📋 Browse the queue and the published archive, with filters for category, ID and text
  • 🔍 Preview the exact formatting a tweet will get before it posts
  • 📋 Copy a formatted tweet to the clipboard
  • 🗂 Manage the category list — add, rename, delete
  • 🔐 Session-based login for a single user

🚀 Getting started

git clone https://github.com/cdrrazan/TweetX-web.git
cd TweetX-web
bundle install            # Ruby 3.2.2, pinned in the Gemfile

cp .env.sample .env       # then fill it in

ruby app.rb               # http://localhost:4567
bundle exec rackup        # same thing, via config.ru

Two things will stop you booting if you skip them:

SESSION_SECRET must be at least 64 characters. Rack refuses to start otherwise:

ruby -rsecurerandom -e 'puts SecureRandom.hex(64)'

Run it from the repo root. app.rb reads data/tweet_collection.csv by relative path, so it only works with the repository root as your working directory.

Set TWEETX_USER and TWEETX_PASS to whatever you want to log in with.

🧪 Tests and linting

bundle exec rspec       # 126 examples
bundle exec rubocop     # -a to autocorrect

Both are clean on main. The suite never touches the network and never writes to data/ — the X client is stubbed globally and the CSV paths are redirected to a temp directory for every example.

⚠️ "Tweet Now" does not post

The Tweet button in the dashboard is deliberately a simulation in this repo. It formats the tweet, returns a preview, and tells you plainly that nothing was sent. No API call, nothing written to the archive, nothing removed from the queue.

This is the safe default for anyone cloning the project. Everything needed to make it real is already in Scheduler, and the comment on POST /tweet-now/:id names the exact lines to swap in.

Before you do that, please read SECURITY.md. This app was written for localhost single-user use, and wiring up real posting means an endpoint that publishes to a live account sits behind a plaintext password check with no CSRF protection.

🔐 Before you deploy this anywhere

Short version: don't, without reading SECURITY.md first.

The login form ships with admin / password prefilled as a local convenience. Authentication is a plaintext == against two environment variables, with no rate limiting. There's no CSRF protection, and deletion happens over GET. These are documented, accepted properties of a personal tool — not a threat model for the public internet.

🗂 The datastore

Plain CSV under data/, committed to git:

File Columns Role
tweet_collection.csv id,category,tweet the queue
tweet_published.csv id,category,tweet,timestamp the archive; id is the X tweet ID
categories.txt one per line category list

Every mutation rewrites the whole file, with no locking. "Already published" is decided by matching tweet text, not by ID, because the CLI never deletes the row it posted.

Category names are compared with == against the scheduler's hour map, so renaming a category here can quietly make a whole time slot post nothing.

📂 Layout

TweetX-web/
├── app.rb                         # the entire web app: routes, helpers, auth
├── config.ru                      # rack entry point
├── views/                         # ERB + Bootstrap 5, partials in views/partials/
├── lib/tweetx/scheduler.rb        # vendored from TweetX; the only X API client
├── lib/tweetx/tweet_formatter.rb  # shared by the dashboard and the CLI
├── bin/tweetx                     # vendored CLI
├── data/                          # the CSV datastore
└── spec/                          # RSpec suite

🧩 Two repos, one tool

Repo What it is
TweetX-web (here) the dashboard
TweetX the CLI and scheduler that actually posts, plus the GitHub Actions workflow

They share lib/tweetx/ and data/ by copy, not by dependency — no gem, no submodule. A fix to shared code needs applying in both.

📦 Built with

Ruby 3.2 · Sinatra · Bootstrap 5 · SweetAlert2 · CSV · RSpec · RuboCop

🙌 Contributing

Pull requests welcome. Read CONTRIBUTING.md first — it covers setup and the handful of things here that break silently rather than loudly. Everyone participating is expected to follow the Code of Conduct.

Found a security issue? Please don't open an issue — see SECURITY.md.

📘 Ideas for later

Thread support · tweet analytics · AI-assisted drafting · multi-user roles

👨‍💻 Created by

Rajan Bhattarai — Ruby developer, product hacker, open-source enthusiast.

📜 License

MIT — free for personal and commercial use.

⭐ Star the project if it helps you.

About

[Web] — Dashboard for TweetX - Tweet Automation Toolkit. Built using Ruby & Sinatra!

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages