/ README.md
README.md
  1  <div align="center">
  2    <img src="public/logo-192.png" width="128" height="128" alt="">
  3  
  4  Agora
  5  ===
  6  
  7  **Follow your interests across social networks!**
  8  </div>
  9  
 10  
 11  
 12  ## Features
 13  - You can log in to a Mastodon, Bluesky, or Nostr account on Agora and it'll pull in your following/followers list from that account, while still allowing you to view/interact with posts from the other 2 protocols using bridges behind the scenes.
 14  - Intelligently loads your instance's version of a post so that you can like/boost/comment on it without having to think about what instance it's on.
 15  - I've integrated those bridges into the search, so that if you search for a Bluesky handle like [aoc.bsky.social](https://agorasocial.app/#/fosstodon.org/a/111133786401697678) or a nostr users hex code like [Jack Dorsey's](https://agorasocial.app/#/fosstodon.org/a/109934331230225572), and it'll automatically know to use the bridges for those protocols and search for the bridged profile. You can even search for [elonmusk@twitter.com](https://agorasocial.app/#/fosstodon.org/a/109418526633386531) and it'll treat Twitter like another instance, and load up the bridged version of the account!
 16  - When you follow a hashtag like #linux, it'll automatically follow the corresponding [Lemmy community](https://agorasocial.app/#/fosstodon.org/a/107294672647205675) for that topic in your feed.
 17  - 👪 Multiple accounts
 18  - 🪟 Compose window pop-out/in
 19  - 🌗 Light/dark/auto theme
 20  - 🔔 Grouped notifications
 21  - 🪺 Nested comments thread
 22  - 📬 Unsent draft recovery
 23  - 🎠 Boosts Carousel™️
 24  - #️⃣ Multi-hashtag timeline
 25  
 26  ## Subtle UI implementations
 27  
 28  ### User name display
 29  
 30  ![User name display](readme-assets/user-name-display.jpg)
 31  
 32  - On the timeline, the user name is displayed as `[NAME] @[username]`.
 33  - For the `@[username]`, always exclude the instance domain name.
 34  - If the `[NAME]` *looks the same* as the `@[username]`, then the `@[username]` is excluded as well.
 35  
 36  ### Boosts Carousel
 37  
 38  ![Boosts Carousel](readme-assets/boosts-carousel.jpg)
 39  
 40  - From the fetched posts (e.g. 20 posts per fetch), if number of boosts are more than quarter of total posts or more than 3 consecutive boosts, boosts carousel UI will be triggered.
 41  - If number of boosts are more than 3 quarters of total posts, boosts carousel UI will be slotted at the end of total posts fetched (per "page").
 42  - Else, boosts carousel UI will be slotted in between the posts.
 43  
 44  ### Thread number badge (e.g. Thread 1/X)
 45  
 46  ![Thread number badge](readme-assets/thread-number-badge.jpg)
 47  
 48  - Check every post for `inReplyToId` from cache or additional API requests, until the root post is found.
 49  - If root post is found, badge will show the index number of the post in the thread.
 50  - Limit up to 3 API requests as the root post may be very old or the thread is super long.
 51  - If index number couldn't be found, badge will fallback to showing `Thread` without the number.
 52  
 53  ### Hashtag stuffing collapsing
 54  
 55  ![Hashtag stuffing collapsing](readme-assets/hashtag-stuffing-collapsing.jpg)
 56  
 57  - First paragraph of post content with more than 3 hashtags will be collapsed to max 3 lines.
 58  - Subsequent paragraphs after first paragraph with more than 3 hashtags will be collapsed to 1 line.
 59  - Adjacent paragraphs with more than 1 hashtag after collapsed paragraphs will be collapsed to 1 line.
 60  - If there are text around or between the hashtags, they will not be collapsed.
 61  - Collapsed hashtags will be appended with `...` at the end.
 62  - They are also slightly faded out to reduce visual noise.
 63  - Opening the post view will reveal the hashtags uncollapsed.
 64  
 65  ### Filtered posts
 66  
 67  - "Hide completely"-filtered posts will be hidden, with no UI to reveal it.
 68  - "Hide with a warning"-filtered posts will be partially hidden, showing the filter name and author name.
 69    - Content can be partially revealed by hovering over the post, with tooltip showing the post text.
 70    - Clicking it will open the Post page.
 71    - Long-pressing or right-clicking it will "peek" the post with a bottom sheet UI.
 72    - On boosts carousel, they are sorted to the end of the carousel.
 73  
 74  ## Development
 75  
 76  Prerequisites: Node.js 18+
 77  
 78  - `npm install` - Install dependencies
 79  - `npm run dev` - Start development server
 80  - `npm run build` - Build for production
 81  - `npm run preview` - Preview the production build
 82  - `npm run fetch-instances` - Fetch instances list from [instances.social](https://instances.social/), save it to `src/data/instances.json`
 83    - requires `.env.dev` file with `INSTANCES_SOCIAL_SECRET_TOKEN` variable set
 84  - `npm run sourcemap` - Run `source-map-explorer` on the production build
 85  
 86  ## Self-hosting
 87  
 88  This is a **pure static web app**. You can host it anywhere you want. Build it by running `npm run build` (after `npm install`) and serve the `dist` folder.
 89  
 90  I personally use Vercel to host Agora.
 91  
 92  ## Tech stack
 93  
 94  - [Vite](https://vitejs.dev/) - Build tool
 95  - [Preact](https://preactjs.com/) - UI library
 96  - [Valtio](https://valtio.pmnd.rs/) - State management
 97  - [React Router](https://reactrouter.com/) - Routing
 98  - [masto.js](https://github.com/neet/masto.js/) - Mastodon API client
 99  - [Iconify](https://iconify.design/) - Icon library
100    - [MingCute icons](https://www.mingcute.com/)
101  - Vanilla CSS - *Yes, I'm old school.*
102  
103  Some of these may change in the future. The front-end world is ever-changing.
104  
105  ## Alternative web clients
106  
107  - [Pinafore](https://pinafore.social/) ([retired](https://nolanlawson.com/2023/01/09/retiring-pinafore/)) - forks ↓
108    - [Semaphore](https://semaphore.social/)
109    - [Enafore](https://enafore.social/)
110  - [Cuckoo+](https://www.cuckoo.social/)
111  - [Sengi](https://nicolasconstant.github.io/sengi/)
112  - [Soapbox](https://fe.soapbox.pub/)
113  - [Elk](https://elk.zone/) - forks ↓
114    - [elk.fedified.com](https://elk.fedified.com/)
115  - [Mastodeck](https://mastodeck.com/)
116  - [Trunks](https://trunks.social/)
117  - [Tooty](https://github.com/n1k0/tooty)
118  - [Litterbox](https://litterbox.koyu.space/)
119  - [Statuzer](https://statuzer.com/)
120  - [Tusked](https://tusked.app/)
121  - [More...](https://github.com/hueyy/awesome-mastodon/#clients)
122  
123  ## 💁‍♂️ Notice to all other social media client developers
124  
125  Please, please copy the UI ideas and experiments from this app. I think some of them are pretty good and it would be great if more apps have them.
126  
127  If you're not a developer, please tell your favourite social media client developers about this app and ask them to copy the UI ideas and experiments.
128  
129  ## License
130  
131  [MIT](https://cheeaun.mit-license.org/).