diff --git a/shared/blocks.py b/shared/blocks.py
index 869a45551714a4a4f23442f72b47135a7d125f94..87031401f18e99b5ad16deae83897f70df0c3933 100644
--- a/shared/blocks.py
+++ b/shared/blocks.py
@@ -730,7 +730,9 @@ class ChartRedmineIssueDataset(blocks.StructBlock):
         required=False,
     )
 
-    def _get_issues_url(self, value, project_id: typing.Union[None, str, list[str]] = None):
+    def _get_issues_url(
+        self, value, project_id: typing.Union[None, str, list[str]] = None
+    ):
         url = "https://redmine.pirati.cz/issues.json"
         params = [
             ("sort", "created_on"),
@@ -1042,6 +1044,21 @@ class ChartBlock(blocks.StructBlock):
 Zobrazí se tolik definovaných sloupců, kolik existuje skupin."""
 
 
+class MastodonFeedBlock:
+    url = blocks.URLBlock(
+        required=True,
+        label="URL pro mastodon feed",
+        default="https://mastodon.pirati.cz",
+    )
+    userId = blocks.IntegerBlock(required=False, label="ID uživatele mastodonu")
+    userName = blocks.CharBlock(required=False, label="Uživatelské jméno pro mastodon")
+
+    class Meta:
+        label = "Mastodon feed"
+        icon = "link"
+        template = "shared/blocks/mastodon_feed_block.html"
+
+
 DEFAULT_CONTENT_BLOCKS = [
     (
         "text",
diff --git a/shared/static/shared/js/mastodon_helper.js b/shared/static/shared/js/mastodon_helper.js
new file mode 100644
index 0000000000000000000000000000000000000000..5a5207e1c8580a4dbe8a67f585de9cae2383aa32
--- /dev/null
+++ b/shared/static/shared/js/mastodon_helper.js
@@ -0,0 +1,51 @@
+window.resources ||= {};
+
+/**
+ * @param {string} url
+ * @returns {Promise<string>}
+ */
+const fetchResource = async (url) => {
+    return await (await window.fetch(url)).text();
+};
+
+/**
+ * @param {string} url
+ */
+const loadResource = async (url) => {
+    if (window.resources[url]) {
+        return window.resources[url];
+    }
+    window.resources[url] = fetchResource(url);
+    return await window.resources[url];
+};
+
+/**
+ * @param {HTMLElement} parent
+ * @param {string} content
+ */
+const applyScript = async (parent, content) => {
+    const base64 = btoa(content);
+    if (!document.querySelector(`script[data-content='${base64}']`)) {
+        const scriptTag = document.createElement("script");
+        scriptTag.setAttribute("type", "text/javascript");
+        scriptTag.dataset.content = base64;
+        scriptTag.innerHTML = script;
+        parent.appendChild(scriptTag);
+    }
+}
+
+loadResource("https://gitlab.com/idotj/mastodon-embed-feed-timeline/-/raw/91677cc3a76b300428ed478f4cd4e546e34f827b/src/mastodon-timeline.min.js");
+loadResource("https://gitlab.com/idotj/mastodon-embed-feed-timeline/-/raw/91677cc3a76b300428ed478f4cd4e546e34f827b/src/mastodon-timeline.min.css");
+
+/**
+ * @param {HTMLElement} feedElement
+ */
+const createMastodonScript = async (feedElement) => {
+    if (!feedElement.dataset.init) {
+
+
+        feedElement.dataset.init = "true";
+    }
+};
+
+[...document.querySelectorAll("[data-mastodon]")].forEach(createMastodonScript);
diff --git a/shared/templates/shared/blocks/mastodon_feed_block.html b/shared/templates/shared/blocks/mastodon_feed_block.html
new file mode 100644
index 0000000000000000000000000000000000000000..f56e811734f99bf0d8874829e0caa44a5a178602
--- /dev/null
+++ b/shared/templates/shared/blocks/mastodon_feed_block.html
@@ -0,0 +1,6 @@
+<script type="text/javascript" src="{% static "shared/js/mastodon_helper.js" %}" data-mastodon="true" data-feed="{{ self.url }}" data-user-id="{{ self.userId }}" data-user-name="{{ self.userName }}"></script>
+<div class="mt-timeline">
+    <div id="mt-body" class="mt-body" role="feed">
+        <div class="loading-spinner"></div>
+    </div>
+</div>