diff --git a/native/invite-links/manage-public-link-screen.react.js b/native/invite-links/manage-public-link-screen.react.js
--- a/native/invite-links/manage-public-link-screen.react.js
+++ b/native/invite-links/manage-public-link-screen.react.js
@@ -3,12 +3,23 @@
 import * as React from 'react';
 import { Text, View } from 'react-native';
 
+import {
+  createOrUpdatePublicLink,
+  createOrUpdatePublicLinkActionTypes,
+} from 'lib/actions/link-actions.js';
+import { primaryInviteLinksSelector } from 'lib/selectors/invite-links-selectors.js';
+import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
 import type { ThreadInfo } from 'lib/types/thread-types.js';
+import {
+  useDispatchActionPromise,
+  useServerCall,
+} from 'lib/utils/action-utils.js';
 
 import Button from '../components/button.react.js';
 import TextInput from '../components/text-input.react.js';
 import type { RootNavigationProp } from '../navigation/root-navigator.react.js';
 import type { NavigationRoute } from '../navigation/route-names.js';
+import { useSelector } from '../redux/redux-utils.js';
 import { useStyles } from '../themes/colors.js';
 
 export type ManagePublicLinkScreenParams = {
@@ -20,8 +31,28 @@
   +route: NavigationRoute<'ManagePublicLink'>,
 };
 
-// eslint-disable-next-line no-unused-vars
 function ManagePublicLinkScreen(props: Props): React.Node {
+  const { community } = props.route.params;
+  const inviteLink = useSelector(primaryInviteLinksSelector)[community.id];
+  const [name, setName] = React.useState(
+    inviteLink?.name ?? Math.random().toString(36).slice(-9),
+  );
+
+  const dispatchActionPromise = useDispatchActionPromise();
+  const callCreateOrUpdatePublicLink = useServerCall(createOrUpdatePublicLink);
+  const createInviteLink = React.useCallback(() => {
+    dispatchActionPromise(
+      createOrUpdatePublicLinkActionTypes,
+      callCreateOrUpdatePublicLink({
+        name,
+        communityID: community.id,
+      }),
+    );
+  }, [callCreateOrUpdatePublicLink, community.id, dispatchActionPromise, name]);
+  const createOrUpdatePublicLinkStatus = useSelector(
+    createOrUpdatePublicLinkStatusSelector,
+  );
+
   const styles = useStyles(unboundStyles);
 
   return (
@@ -39,11 +70,20 @@
       <View style={styles.section}>
         <View style={styles.inviteLink}>
           <Text style={styles.inviteLinkPrefix}>https://comm.app/invite/</Text>
-          <TextInput style={styles.input} />
+          <TextInput
+            style={styles.input}
+            value={name}
+            onChangeText={setName}
+            autoCorrect={false}
+            autoCapitalize="none"
+            keyboardType="ascii-capable"
+            editable={createOrUpdatePublicLinkStatus !== 'loading'}
+          />
         </View>
         <Button
           style={[styles.button, styles.buttonPrimary]}
-          onPress={() => {}}
+          onPress={createInviteLink}
+          disabled={createOrUpdatePublicLinkStatus === 'loading'}
         >
           <Text style={styles.buttonText}>Save & enable public link</Text>
         </Button>
@@ -52,6 +92,10 @@
   );
 }
 
+const createOrUpdatePublicLinkStatusSelector = createLoadingStatusSelector(
+  createOrUpdatePublicLinkActionTypes,
+);
+
 const unboundStyles = {
   sectionTitle: {
     fontSize: 14,