diff --git a/.envrc b/.envrc
new file mode 100644
index 0000000..44610e5
--- /dev/null
+++ b/.envrc
@@ -0,0 +1 @@
+use flake;
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..92b2793
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.direnv
diff --git a/README.md b/README.md
index 14d339b..815b72e 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,14 @@
# tachikoma
-Patchset for Akkoma
\ No newline at end of file
+Patchset for Akkoma
+
+## patchlists
+
+### akkoma (backend)
+
+_none_
+
+### akkoma-fe (frontend)
+
+- 0001-confirm-favorite: opens a "confirmation" modal on favorites, identical to reposts. (TODO: undo formatting changes)
+- 0002-move-notifications: moves toast notifications to the bottom of the screen
diff --git a/akkoma-fe/0001-confirm-favorite.patch b/akkoma-fe/0001-confirm-favorite.patch
new file mode 100644
index 0000000..52de84d
--- /dev/null
+++ b/akkoma-fe/0001-confirm-favorite.patch
@@ -0,0 +1,144 @@
+diff --git a/src/components/favorite_button/favorite_button.js b/src/components/favorite_button/favorite_button.js
+index d15699f7..e5f1a3c5 100644
+--- a/src/components/favorite_button/favorite_button.js
++++ b/src/components/favorite_button/favorite_button.js
+@@ -1,41 +1,60 @@
+-import { mapGetters } from 'vuex'
+-import { library } from '@fortawesome/fontawesome-svg-core'
+-import { faStar } from '@fortawesome/free-solid-svg-icons'
+-import {
+- faStar as faStarRegular
+-} from '@fortawesome/free-regular-svg-icons'
++import ConfirmModal from "../confirm_modal/confirm_modal.vue";
++import { mapGetters } from "vuex";
++import { library } from "@fortawesome/fontawesome-svg-core";
++import { faStar } from "@fortawesome/free-solid-svg-icons";
++import { faStar as faStarRegular } from "@fortawesome/free-regular-svg-icons";
+
+-library.add(
+- faStar,
+- faStarRegular
+-)
++library.add(faStar, faStarRegular);
+
+ const FavoriteButton = {
+- props: ['status', 'loggedIn'],
+- data () {
++ props: ["status", "loggedIn"],
++ components: {
++ ConfirmModal,
++ },
++ data() {
+ return {
+- animated: false
+- }
++ animated: false,
++ showingConfirmDialog: false,
++ };
+ },
+ methods: {
+- favorite () {
++ favorite() {
++ if (!this.status.favorited && this.shouldConfirmFavorite) {
++ this.showConfirmDialog();
++ } else {
++ this.doFavorite();
++ }
++ },
++ doFavorite() {
+ if (!this.status.favorited) {
+- this.$store.dispatch('favorite', { id: this.status.id })
++ this.$store.dispatch("favorite", { id: this.status.id });
+ } else {
+- this.$store.dispatch('unfavorite', { id: this.status.id })
++ this.$store.dispatch("unfavorite", { id: this.status.id });
+ }
+- this.animated = true
++ this.animated = true;
+ setTimeout(() => {
+- this.animated = false
+- }, 500)
+- }
++ this.animated = false;
++ }, 500);
++ this.hideConfirmDialog();
++ },
++ showConfirmDialog() {
++ this.showingConfirmDialog = true;
++ },
++ hideConfirmDialog() {
++ this.showingConfirmDialog = false;
++ },
+ },
+ computed: {
+- ...mapGetters(['mergedConfig']),
+- remoteInteractionLink () {
+- return this.$store.getters.remoteInteractionLink({ statusId: this.status.id })
+- }
+- }
+-}
++ ...mapGetters(["mergedConfig"]),
++ shouldConfirmFavorite() {
++ return this.mergedConfig.modalOnFavorite;
++ },
++ remoteInteractionLink() {
++ return this.$store.getters.remoteInteractionLink({
++ statusId: this.status.id,
++ });
++ },
++ },
++};
+
+-export default FavoriteButton
++export default FavoriteButton;
+diff --git a/src/components/favorite_button/favorite_button.vue b/src/components/favorite_button/favorite_button.vue
+index 16bf441e..06ed7d59 100644
+--- a/src/components/favorite_button/favorite_button.vue
++++ b/src/components/favorite_button/favorite_button.vue
+@@ -32,6 +32,18 @@
+ >
+ {{ status.fave_num }}
+
++