diff --git a/lib/reducers/invite-links-reducer.js b/lib/reducers/invite-links-reducer.js
new file mode 100644
--- /dev/null
+++ b/lib/reducers/invite-links-reducer.js
@@ -0,0 +1,26 @@
+// @flow
+
+import { fetchPrimaryInviteLinkActionTypes } from '../actions/link-actions.js';
+import type { InviteLinksStore } from '../types/link-types.js';
+import type { BaseAction } from '../types/redux-types.js';
+
+function reduceInviteLinks(
+  state: InviteLinksStore,
+  action: BaseAction,
+): InviteLinksStore {
+  if (action.type === fetchPrimaryInviteLinkActionTypes.success) {
+    const links = {};
+    for (const link of action.payload.links) {
+      links[link.communityID] = {
+        primaryLink: link,
+        ...state.links[link.communityID],
+      };
+    }
+    return {
+      links,
+    };
+  }
+  return state;
+}
+
+export default reduceInviteLinks;
diff --git a/lib/reducers/master-reducer.js b/lib/reducers/master-reducer.js
--- a/lib/reducers/master-reducer.js
+++ b/lib/reducers/master-reducer.js
@@ -7,6 +7,7 @@
 import { reduceDraftStore } from './draft-reducer.js';
 import reduceEnabledApps from './enabled-apps-reducer.js';
 import { reduceEntryInfos } from './entry-reducer.js';
+import reduceInviteLinks from './invite-links-reducer.js';
 import reduceLifecycleState from './lifecycle-state-reducer.js';
 import { reduceLoadingStatuses } from './loading-reducer.js';
 import reduceNextLocalID from './local-id-reducer.js';
@@ -123,6 +124,7 @@
         state.commServicesAccessToken,
         action,
       ),
+      inviteLinksStore: reduceInviteLinks(state.inviteLinksStore, action),
     },
     storeOperations: {
       draftStoreOperations,
diff --git a/lib/selectors/invite-links-selectors.js b/lib/selectors/invite-links-selectors.js
new file mode 100644
--- /dev/null
+++ b/lib/selectors/invite-links-selectors.js
@@ -0,0 +1,24 @@
+// @flow
+
+import { createSelector } from 'reselect';
+
+import type { InviteLink, InviteLinks } from '../types/link-types.js';
+import type { AppState } from '../types/redux-types.js';
+
+const primaryInviteLinksSelector: (state: AppState) => {
+  +[communityID: string]: InviteLink,
+} = createSelector(
+  (state: AppState) => state.inviteLinksStore.links,
+  (links: InviteLinks) => {
+    const primaryLinks = {};
+    for (const communityID in links) {
+      const communityLinks = links[communityID];
+      if (communityLinks.primaryLink) {
+        primaryLinks[communityID] = communityLinks.primaryLink;
+      }
+    }
+    return primaryLinks;
+  },
+);
+
+export { primaryInviteLinksSelector };
diff --git a/lib/types/link-types.js b/lib/types/link-types.js
--- a/lib/types/link-types.js
+++ b/lib/types/link-types.js
@@ -43,3 +43,15 @@
 export type FetchInviteLinksResponse = {
   +links: $ReadOnlyArray<InviteLink>,
 };
+
+export type CommunityLinks = {
+  +primaryLink: ?InviteLink,
+};
+
+export type InviteLinks = {
+  +[communityID: string]: CommunityLinks,
+};
+
+export type InviteLinksStore = {
+  +links: InviteLinks,
+};
diff --git a/lib/types/redux-types.js b/lib/types/redux-types.js
--- a/lib/types/redux-types.js
+++ b/lib/types/redux-types.js
@@ -38,6 +38,7 @@
 import type { LifecycleState } from './lifecycle-state-types.js';
 import type {
   FetchInviteLinksResponse,
+  InviteLinksStore,
   InviteLinkVerificationResponse,
 } from './link-types.js';
 import type { LoadingStatus, LoadingInfo } from './loading-types.js';
@@ -124,6 +125,7 @@
   userPolicies: UserPolicies,
   deviceToken: ?string,
   +commServicesAccessToken: ?string,
+  +inviteLinksStore: InviteLinksStore,
   ...
 };
 
diff --git a/native/redux/redux-setup.js b/native/redux/redux-setup.js
--- a/native/redux/redux-setup.js
+++ b/native/redux/redux-setup.js
@@ -119,6 +119,9 @@
   frozen: false,
   userPolicies: {},
   commServicesAccessToken: null,
+  inviteLinksStore: {
+    links: {},
+  },
 }: AppState);
 
 function reducer(state: AppState = defaultState, action: Action) {
diff --git a/native/redux/state-types.js b/native/redux/state-types.js
--- a/native/redux/state-types.js
+++ b/native/redux/state-types.js
@@ -8,6 +8,7 @@
 import type { EntryStore } from 'lib/types/entry-types.js';
 import type { CalendarFilter } from 'lib/types/filter-types.js';
 import type { LifecycleState } from 'lib/types/lifecycle-state-types.js';
+import type { InviteLinksStore } from 'lib/types/link-types.js';
 import type { LoadingStatus } from 'lib/types/loading-types.js';
 import type { MessageStore } from 'lib/types/message-types.js';
 import type { UserPolicies } from 'lib/types/policy-types.js';
@@ -57,4 +58,5 @@
   frozen: boolean,
   userPolicies: UserPolicies,
   +commServicesAccessToken: ?string,
+  +inviteLinksStore: InviteLinksStore,
 };
diff --git a/web/redux/redux-setup.js b/web/redux/redux-setup.js
--- a/web/redux/redux-setup.js
+++ b/web/redux/redux-setup.js
@@ -22,6 +22,7 @@
 import type { EntryStore } from 'lib/types/entry-types.js';
 import { type CalendarFilter } from 'lib/types/filter-types.js';
 import type { LifecycleState } from 'lib/types/lifecycle-state-types.js';
+import type { InviteLinksStore } from 'lib/types/link-types.js';
 import type { LoadingStatus } from 'lib/types/loading-types.js';
 import type { MessageStore } from 'lib/types/message-types.js';
 import type { UserPolicies } from 'lib/types/policy-types.js';
@@ -95,6 +96,7 @@
   pushApiPublicKey: ?string,
   _persist: ?PersistState,
   +commServicesAccessToken: ?string,
+  +inviteLinksStore: InviteLinksStore,
 };
 
 export type Action =