diff --git a/index.html b/index.html
new file mode 100644
index 0000000..ecf42f2
--- /dev/null
+++ b/index.html
@@ -0,0 +1,24 @@
+
+
+
+ Mastodon Wall
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/script.js b/script.js
new file mode 100644
index 0000000..cc9fa16
--- /dev/null
+++ b/script.js
@@ -0,0 +1,88 @@
+$(document).ready(function() {
+ let existingPosts = [];
+
+ // Function to calculate relative time
+ const timeAgo = function(date) {
+ let seconds = Math.floor((new Date() - date) / 1000);
+ let interval = seconds / 31536000;
+ if (interval > 1) {
+ return Math.floor(interval) + " years ago";
+ }
+ interval = seconds / 2592000;
+ if (interval > 1) {
+ return Math.floor(interval) + " months ago";
+ }
+ interval = seconds / 86400;
+ if (interval > 1) {
+ return Math.floor(interval) + " days ago";
+ }
+ interval = seconds / 3600;
+ if (interval > 1) {
+ return Math.floor(interval) + " hours ago";
+ }
+ interval = seconds / 60;
+ if (interval > 1) {
+ return Math.floor(interval) + " minutes ago";
+ }
+ return Math.floor(seconds) + " seconds ago";
+ }
+
+ // Function to fetch posts for a given hashtag
+ const getPosts = function(hashtag) {
+ return $.get(`https://openbiblio.social/api/v1/timelines/tag/${hashtag}`);
+ }
+
+ // Initialize Masonry
+ $('.masonry-grid').masonry({
+ itemSelector: '.col-sm-3',
+ columnWidth: '.col-sm-3',
+ percentPosition: true,
+ transitionDuration: '0.2s'
+ });
+
+
+ // Fetch posts for each hashtag
+ $.when(getPosts('bibliocon23'), getPosts('111bibliocon'), getPosts('bibliocon')).then(function(bibliocon23Posts, bibliocon111Posts, biblioconPosts) {
+ let allPosts = bibliocon23Posts[0].concat(bibliocon111Posts[0], biblioconPosts[0]);
+
+ // Sort the posts by date/time
+ allPosts.sort((a, b) => new Date(a.created_at) - new Date(b.created_at));
+
+ // Loop through the sorted posts
+ $.each(allPosts, function(i, post) {
+ // Check if the post is not already displayed and is not a mention
+ if (!existingPosts.includes(post.id) && post.in_reply_to_id === null) {
+ // Add the post id to existingPosts
+ existingPosts.push(post.id);
+
+ let cardHTML = `
+
+ `;
+
+
+
+
+
+ // Convert the HTML string into a jQuery object
+ let $card = $(cardHTML);
+
+ // Prepend the new card to the wall
+ $('#wall').prepend($card);
+
+ // Refresh Masonry layout after all new cards have been added
+ $('.masonry-grid').masonry('prepended', $card);
+ }
+ });
+
+ });
+});
diff --git a/styles.css b/styles.css
new file mode 100644
index 0000000..189c335
--- /dev/null
+++ b/styles.css
@@ -0,0 +1,81 @@
+/* Add some custom CSS for the cards */
+.card {
+ margin-bottom: 20px;
+ border-radius: 10px;
+ box-shadow: 0 4px 6px 0 rgba(0, 0, 0, 0.2);
+}
+
+/* Position the avatar and username in the top left of the card */
+.card-avatar {
+ height: 50px;
+ width: 50px;
+ border-radius: 50%;
+ position: absolute;
+ top: 10px;
+ left: 10px;
+}
+
+.card-username {
+ position: absolute;
+ top: 10px;
+ left: 70px;
+}
+
+/* Add padding to the card body to prevent overlay with avatar and username */
+.card-body {
+ padding-top: 40px;
+ padding-bottom: 10px;
+}
+
+/* Style the media image */
+.card-img-top {
+ width: 100%;
+ height: auto;
+}
+
+.card-title {
+ font-weight: normal;
+}
+
+.card-text {
+ margin-bottom: 1px !important;
+}
+
+/* Custom navbar styles */
+.navbar {
+ height: 50px; /* reduce the height of the navbar */
+ background-color: rgb(227, 6, 19);
+ margin-bottom: 10px !important;
+ top: -10px !important;
+}
+
+.navbar-brand {
+ color: #dddddd !important; /* change the text color */
+ margin: 0 auto; /* center the brand name */
+}
+
+.hashtag {
+ margin-right: 10px; /* add space between the hashtags */
+}
+
+/* Set the background color of the body */
+body {
+ background-color: #aaaaaa;
+ margin-top: 00px !important;
+ margin-left: 20px !important;
+ margin-right: 20px !important;
+}
+
+@media (max-width: 1000px) {
+ .col-sm-3 {
+ flex: 0 0 50%;
+ max-width: 50%;
+ }
+}
+
+@media (max-width: 600px) {
+ .col-sm-3 {
+ flex: 0 0 100%;
+ max-width: 100%;
+ }
+}