diff --git a/package-lock.json b/package-lock.json
index 75b4a90839b0ac2778a40dd8391053a39d60ffb6..06091264e03612e681b834de6b07e5d6b1ba24f5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10949,19 +10949,12 @@
       }
     },
     "pullstate": {
-      "version": "1.20.4",
-      "resolved": "https://registry.npmjs.org/pullstate/-/pullstate-1.20.4.tgz",
-      "integrity": "sha512-SksJ70iYNrC+YsGjMx54pXT2/iYYUu3zg9hezjHNjPPwyViglo4lh+N0I4DwB6xw92s+9NagD3AXMGMfiIt76g==",
+      "version": "1.20.5",
+      "resolved": "https://registry.npmjs.org/pullstate/-/pullstate-1.20.5.tgz",
+      "integrity": "sha512-9+QAXjf5WugIPEFHgMTwKM42uDx8ezB1BDobh7gpg9OCta5rp1XdFxa6tLljB/4NUxnI5YqoiE2s15ZOh+sl4A==",
       "requires": {
         "fast-deep-equal": "^3.1.3",
         "immer": "^7.0.1"
-      },
-      "dependencies": {
-        "immer": {
-          "version": "7.0.15",
-          "resolved": "https://registry.npmjs.org/immer/-/immer-7.0.15.tgz",
-          "integrity": "sha512-yM7jo9+hvYgvdCQdqvhCNRRio0SCXc8xDPzA25SvKWa7b1WVPjLwQs1VYU5JPXjcJPTqAa5NP5dqpORGYBQ2AA=="
-        }
       }
     },
     "pump": {
diff --git a/package.json b/package.json
index f872dfd04e8980e48d1a04697589551f23a12fd0..a0a7779a728ea2f2b6f26335144ae102ddf45069 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,7 @@
     "immer": "^7.0.15",
     "keycloak-js": "^10.0.2",
     "lodash": "^4.17.20",
-    "pullstate": "^1.20.4",
+    "pullstate": "^1.20.5",
     "react": "^16.13.1",
     "react-device-detect": "^1.13.1",
     "react-dom": "^16.13.1",
diff --git a/src/actions/announcements.js b/src/actions/announcements.js
index f4eee78850938963413c87a5ed271a9c5e75ac36..2681527d12637cad70f31cbbb4fd60eaa09ef0a2 100644
--- a/src/actions/announcements.js
+++ b/src/actions/announcements.js
@@ -1,3 +1,5 @@
+import findIndex from "lodash/findIndex";
+import remove from "lodash/remove";
 import { createAsyncAction, successResult } from "pullstate";
 
 import { AnnouncementStore } from "stores";
@@ -20,9 +22,59 @@ export const addAnnouncement = createAsyncAction(
   },
   {
     postActionHook: ({ result }) => {
-      AnnouncementStore.update((state) => {
-        state.items.push(result.payload);
-      });
+      if (!result.error) {
+        AnnouncementStore.update((state) => {
+          state.items.push(result.payload);
+        });
+      }
+    },
+  }
+);
+
+/**
+ * Delete existing announcement.
+ */
+export const deleteAnnouncement = createAsyncAction(
+  /**
+   *
+   * @param {CF2021.Announcement} item
+   */
+  async (item) => {
+    return successResult(item);
+  },
+  {
+    postActionHook: ({ result }) => {
+      if (!result.error) {
+        AnnouncementStore.update((state) => {
+          remove(state.items, { id: result.payload.id });
+        });
+      }
+    },
+  }
+);
+
+/**
+ * Update content of an announcement.
+ */
+export const updateAnnouncementContent = createAsyncAction(
+  /**
+   *
+   * @param {CF2021.Announcement} item
+   * @param {string} newContent
+   */
+  async (item, newContent) => {
+    return successResult({ item, newContent });
+  },
+  {
+    postActionHook: ({ result }) => {
+      if (!result.error) {
+        AnnouncementStore.update((state) => {
+          const itemIdx = findIndex(state.items, {
+            id: result.payload.item.id,
+          });
+          state.items[itemIdx].content = result.payload.newContent;
+        });
+      }
     },
   }
 );
diff --git a/src/actions/program.js b/src/actions/program.js
index 2c4584258cdd1d1463c126e524d0cc8c243891eb..7a70b07d510b1201b71434c1552ea0a5ecb59850 100644
--- a/src/actions/program.js
+++ b/src/actions/program.js
@@ -1,13 +1,13 @@
+import { fetch } from "api";
 import pick from "lodash/pick";
 import { createAsyncAction, errorResult, successResult } from "pullstate";
-import fetch from "unfetch";
 
 import { ProgramStore } from "stores";
 
 export const loadProgram = createAsyncAction(
   async () => {
     try {
-      const resp = await fetch(`${process.env.REACT_APP_API_BASE_URL}/program`);
+      const resp = await fetch("/program");
       const mappings = await resp.json();
       return successResult(mappings);
     } catch (err) {
diff --git a/src/api.js b/src/api.js
new file mode 100644
index 0000000000000000000000000000000000000000..b5674b23a27b520b49a022268b230ba660e8414a
--- /dev/null
+++ b/src/api.js
@@ -0,0 +1,16 @@
+import baseFetch from "unfetch";
+
+import { AuthStore } from "./stores";
+
+export const fetch = (url, opts) => {
+  const { isAuthenticated, user } = AuthStore.getRawState();
+
+  opts = opts || {};
+  opts.headers = opts.headers || {};
+
+  if (isAuthenticated) {
+    // opts.headers.Authorization = "Bearer " + user.accessToken;
+  }
+
+  return baseFetch(process.env.REACT_APP_API_BASE_URL + url, opts);
+};
diff --git a/src/components/annoucements/AnnouncementEditModal.jsx b/src/components/annoucements/AnnouncementEditModal.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..29624d8acd9f0d3dc9fc7ed00f8e1bfba8c8ea27
--- /dev/null
+++ b/src/components/annoucements/AnnouncementEditModal.jsx
@@ -0,0 +1,70 @@
+import React, { useState } from "react";
+
+import Button from "components/Button";
+import { Card, CardActions, CardBody, CardHeadline } from "components/cards";
+import Modal from "components/modals/Modal";
+
+const AnnouncementEditModal = ({
+  announcement,
+  onCancel,
+  onConfirm,
+  ...props
+}) => {
+  const [text, setText] = useState(announcement.content);
+
+  const onTextInput = (evt) => {
+    setText(evt.target.value);
+  };
+
+  const confirm = (evt) => {
+    if (!!text) {
+      onConfirm(text);
+    }
+  };
+
+  return (
+    <Modal containerClassName="max-w-md" onRequestClose={onCancel} {...props}>
+      <Card>
+        <CardBody>
+          <div className="flex items-center justify-between mb-4">
+            <CardHeadline>Upravit oznámení</CardHeadline>
+            <button onClick={onCancel}>
+              <i className="ico--close"></i>
+            </button>
+          </div>
+          <div className="form-field">
+            <div className="form-field__wrapper form-field__wrapper--shadowed">
+              <textarea
+                className="text-input form-field__control "
+                value={text}
+                rows="8"
+                placeholder="Vyplňte text oznámení"
+                onChange={onTextInput}
+              ></textarea>
+            </div>
+          </div>
+        </CardBody>
+        <CardActions right className="space-x-1">
+          <Button
+            hoverActive
+            color="blue-300"
+            className="text-sm"
+            onClick={confirm}
+          >
+            Uložit
+          </Button>
+          <Button
+            hoverActive
+            color="red-600"
+            className="text-sm"
+            onClick={onCancel}
+          >
+            Zrušit
+          </Button>
+        </CardActions>
+      </Card>
+    </Modal>
+  );
+};
+
+export default AnnouncementEditModal;
diff --git a/src/components/cards/Card.jsx b/src/components/cards/Card.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..58ce9fd99c642c1b3bdf9c2a1deb054fb5527101
--- /dev/null
+++ b/src/components/cards/Card.jsx
@@ -0,0 +1,9 @@
+import React from "react";
+import classNames from "classnames";
+
+const Card = ({ children, elevation = 21, className }) => {
+  const cls = classNames("card", `elevation-${elevation}`, className);
+  return <div className={cls}>{children}</div>;
+};
+
+export default Card;
diff --git a/src/components/cards/CardActions.jsx b/src/components/cards/CardActions.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..0dc8e51178c7e2e1c77dc51de54511d541337651
--- /dev/null
+++ b/src/components/cards/CardActions.jsx
@@ -0,0 +1,13 @@
+import React from "react";
+import classNames from "classnames";
+
+const CardActions = ({ children, right, className }) => {
+  const cls = classNames(
+    "card-actions",
+    { "card-actions--right": !!right },
+    className
+  );
+  return <div className={cls}>{children}</div>;
+};
+
+export default CardActions;
diff --git a/src/components/cards/CardBody.jsx b/src/components/cards/CardBody.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..3bf08153e5fce78eb4f2f131d6fcfc33e6782861
--- /dev/null
+++ b/src/components/cards/CardBody.jsx
@@ -0,0 +1,9 @@
+import React from "react";
+import classNames from "classnames";
+
+const CardBody = ({ children, className }) => {
+  const cls = classNames("card__body", className);
+  return <div className={cls}>{children}</div>;
+};
+
+export default CardBody;
diff --git a/src/components/cards/CardBodyText.jsx b/src/components/cards/CardBodyText.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..7fb8944a63d7c5b7ce4c14b9967e6d95cda9dc25
--- /dev/null
+++ b/src/components/cards/CardBodyText.jsx
@@ -0,0 +1,7 @@
+import React from "react";
+
+const CardBodyText = ({ children }) => {
+  return <div className="card-body-text">{children}</div>;
+};
+
+export default CardBodyText;
diff --git a/src/components/cards/CardHeadline.jsx b/src/components/cards/CardHeadline.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..fda727c7705cc2e1367da2e761bb433ca6891a94
--- /dev/null
+++ b/src/components/cards/CardHeadline.jsx
@@ -0,0 +1,7 @@
+import React from "react";
+
+const CardHeadline = ({ children }) => {
+  return <h1 className="card-headline">{children}</h1>;
+};
+
+export default CardHeadline;
diff --git a/src/components/cards/index.js b/src/components/cards/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..51bf741f452a0a70d30bc8da2997ceb5189ad5f5
--- /dev/null
+++ b/src/components/cards/index.js
@@ -0,0 +1,5 @@
+export { default as Card } from "./Card";
+export { default as CardActions } from "./CardActions";
+export { default as CardBody } from "./CardBody";
+export { default as CardBodyText } from "./CardBodyText";
+export { default as CardHeadline } from "./CardHeadline";
diff --git a/src/components/modals/ModalConfirm.jsx b/src/components/modals/ModalConfirm.jsx
index 0863fb9908f2813ed4ea6c75cfe9b24ca1fa8767..b427affd4af39b6350f6707b1aea10c150aaa7eb 100644
--- a/src/components/modals/ModalConfirm.jsx
+++ b/src/components/modals/ModalConfirm.jsx
@@ -1,6 +1,13 @@
 import React from "react";
 
 import Button from "components/Button";
+import {
+  Card,
+  CardActions,
+  CardBody,
+  CardBodyText,
+  CardHeadline,
+} from "components/cards";
 
 import Modal from "./Modal";
 
@@ -15,19 +22,19 @@ const ModalConfirm = ({
 }) => {
   return (
     <Modal containerClassName="max-w-md" onRequestClose={onCancel} {...props}>
-      <div className="card elevation-21">
-        <div className="card__body">
+      <Card>
+        <CardBody>
           <div className="flex items-center justify-between mb-4">
-            <h1 className="card-headline">{title}</h1>
+            <CardHeadline>{title}</CardHeadline>
             <button onClick={onCancel}>
               <i className="ico--close"></i>
             </button>
           </div>
-          <p className="card-body-text">{children}</p>
-        </div>
-        <div className="card-actions card-actions--right space-x-1">
+          <CardBodyText>{children}</CardBodyText>
+        </CardBody>
+        <CardActions right className="space-x-1">
           <Button
-            hoveractive
+            hoverActive
             color="blue-300"
             className="text-sm"
             onClick={onConfirm}
@@ -35,15 +42,15 @@ const ModalConfirm = ({
             {yesActionLabel}
           </Button>
           <Button
-            hoveractive
+            hoverActive
             color="red-600"
             className="text-sm"
-            onClick={onConfirm}
+            onClick={onCancel}
           >
             {cancelActionLabel}
           </Button>
-        </div>
-      </div>
+        </CardActions>
+      </Card>
     </Modal>
   );
 };
diff --git a/src/containers/AnnoucementsContainer.jsx b/src/containers/AnnoucementsContainer.jsx
index dc7204de90f9d0613a5abd562d8bfed57e72b128..e3b5322e8a1a981e23304d6616c0af6820728e2a 100644
--- a/src/containers/AnnoucementsContainer.jsx
+++ b/src/containers/AnnoucementsContainer.jsx
@@ -1,25 +1,68 @@
-import React from "react";
+import React, { useCallback, useState } from "react";
 
+import {
+  deleteAnnouncement,
+  updateAnnouncementContent,
+} from "actions/announcements";
+import AnnouncementEditModal from "components/annoucements/AnnouncementEditModal";
 import AnnouncementList from "components/annoucements/AnnouncementList";
+import ModalConfirm from "components/modals/ModalConfirm";
 import { AnnouncementStore } from "stores";
 
 const AnnoucementsContainer = () => {
+  const [itemToDelete, setItemToDelete] = useState(null);
+  const [itemToEdit, setItemToEdit] = useState(null);
   const items = AnnouncementStore.useState((state) => state.items);
 
-  const onEdit = (announcement) => {
-    console.log("edit", announcement);
-  };
-  const onDelete = (announcement) => {
-    console.log("delete", announcement);
-  };
+  const confirmEdit = useCallback(
+    async (newContent) => {
+      if (itemToEdit && newContent) {
+        await updateAnnouncementContent.run(itemToEdit, newContent);
+        setItemToEdit(null);
+      }
+    },
+    [itemToEdit, setItemToEdit]
+  );
+
+  const cancelEdit = useCallback(() => {
+    setItemToEdit(null);
+  }, [setItemToEdit]);
+
+  const confirmDelete = useCallback(async () => {
+    await deleteAnnouncement.run(itemToDelete);
+    setItemToDelete(null);
+  }, [setItemToDelete, itemToDelete]);
+
+  const cancelDelete = useCallback(() => {
+    setItemToDelete(null);
+  }, [setItemToDelete]);
 
   return (
-    <AnnouncementList
-      items={items}
-      displayActions={true}
-      onDelete={onDelete}
-      onEdit={onEdit}
-    />
+    <>
+      <AnnouncementList
+        items={items}
+        displayActions={true}
+        onDelete={setItemToDelete}
+        onEdit={setItemToEdit}
+      />
+      <ModalConfirm
+        isOpen={!!itemToDelete}
+        onConfirm={confirmDelete}
+        onCancel={cancelDelete}
+        title="Opravdu chcete toto oznámení smazat?"
+        yesActionLabel="Smazat"
+      >
+        Opravdu chcete ukončit rozpravu?
+      </ModalConfirm>
+      {itemToEdit && (
+        <AnnouncementEditModal
+          isOpen={true}
+          announcement={itemToEdit}
+          onConfirm={confirmEdit}
+          onCancel={cancelEdit}
+        />
+      )}
+    </>
   );
 };