diff --git a/assets/images/task.svg b/assets/images/task.svg
new file mode 100644
index 000000000000..20412f771b69
--- /dev/null
+++ b/assets/images/task.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 27.3.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 20 20" style="enable-background:new 0 0 20 20;" xml:space="preserve">
+<g>
+	<path d="M9.5,5h9C19.3,5,20,4.3,20,3.5S19.3,2,18.5,2h-9C8.7,2,8,2.7,8,3.5S8.7,5,9.5,5z"/>
+	<path d="M18.5,8.5h-9C8.7,8.5,8,9.2,8,10s0.7,1.5,1.5,1.5h9c0.8,0,1.5-0.7,1.5-1.5S19.3,8.5,18.5,8.5z"/>
+	<path d="M18.5,15h-9C8.7,15,8,15.7,8,16.5S8.7,18,9.5,18h9c0.8,0,1.5-0.7,1.5-1.5S19.3,15,18.5,15z"/>
+	<path d="M4.5,1L2.9,3.2L2.4,2.7C1.9,2.3,1.2,2.3,0.8,2.8C0.4,3.3,0.4,4,0.9,4.5l2,1.9c0.1,0.1,0.3,0.2,0.4,0.1
+		c0.1,0,0.3-0.1,0.4-0.2l2.7-3.9c0.4-0.5,0.3-1.2-0.2-1.6C5.5,0.3,4.8,0.5,4.5,1z"/>
+	<path d="M4.5,7L2.9,9.2L2.4,8.7C1.9,8.3,1.2,8.3,0.8,8.8C0.4,9.3,0.4,10,0.9,10.5l2,1.9c0.1,0.1,0.3,0.2,0.4,0.1
+		c0.1,0,0.3-0.1,0.4-0.2l2.7-3.9c0.4-0.5,0.3-1.2-0.2-1.6C5.5,6.3,4.8,6.5,4.5,7z"/>
+	<circle cx="3.5" cy="16.5" r="2.5"/>
+</g>
+</svg>
diff --git a/src/CONST.js b/src/CONST.js
index 20e28c18e928..8677b5ff7f72 100755
--- a/src/CONST.js
+++ b/src/CONST.js
@@ -202,6 +202,7 @@ const CONST = {
         POLICY_ROOMS: 'policyRooms',
         POLICY_EXPENSE_CHAT: 'policyExpenseChat',
         PASSWORDLESS: 'passwordless',
+        TASKS: 'tasks',
     },
     BUTTON_STATES: {
         DEFAULT: 'default',
diff --git a/src/ONYXKEYS.js b/src/ONYXKEYS.js
index 49d5435c8ebd..b0526ae4b61a 100755
--- a/src/ONYXKEYS.js
+++ b/src/ONYXKEYS.js
@@ -188,6 +188,7 @@ export default {
         HOME_ADDRESS_FORM: 'homeAddressForm',
         NEW_ROOM_FORM: 'newRoomForm',
         ROOM_SETTINGS_FORM: 'roomSettingsForm',
+        NEW_TASK_FORM: 'newTaskForm',
         MONEY_REQUEST_DESCRIPTION_FORM: 'moneyRequestDescriptionForm',
     },
 
diff --git a/src/ROUTES.js b/src/ROUTES.js
index 423169d6dd3e..117cd0e6c85a 100644
--- a/src/ROUTES.js
+++ b/src/ROUTES.js
@@ -13,6 +13,7 @@ const IOU_DETAILS = 'iou/details';
 const IOU_REQUEST_CURRENCY = `${IOU_REQUEST}/currency`;
 const IOU_BILL_CURRENCY = `${IOU_BILL}/currency`;
 const IOU_SEND_CURRENCY = `${IOU_SEND}/currency`;
+const NEW_TASK = 'new/task';
 const SETTINGS_PERSONAL_DETAILS = 'settings/profile/personal-details';
 const SETTINGS_CONTACT_METHODS = 'settings/profile/contact-methods';
 
@@ -55,6 +56,7 @@ export default {
     SETTINGS_NEW_CONTACT_METHOD: `${SETTINGS_CONTACT_METHODS}/new`,
     NEW_GROUP: 'new/group',
     NEW_CHAT: 'new/chat',
+    NEW_TASK,
     REPORT,
     REPORT_WITH_ID: 'r/:reportID',
     getReportRoute: reportID => `r/${reportID}`,
@@ -89,6 +91,9 @@ export default {
     IOU_DETAILS_ENABLE_PAYMENTS: `${IOU_DETAILS}/enable-payments`,
     IOU_DETAILS_WITH_IOU_REPORT_ID: `${IOU_DETAILS}/:chatReportID/:iouReportID/`,
     getIouDetailsRoute: (chatReportID, iouReportID) => `iou/details/${chatReportID}/${iouReportID}`,
+    getNewTaskRoute: reportID => `${NEW_TASK}/${reportID}`,
+    NEW_TASK_WITH_REPORT_ID: `${NEW_TASK}/:reportID?`,
+    getTaskDetailsRoute: taskID => `task/details/${taskID}`,
     SEARCH: 'search',
     SET_PASSWORD_WITH_VALIDATE_CODE: 'setpassword/:accountID/:validateCode',
     DETAILS: 'details',
diff --git a/src/components/Icon/Expensicons.js b/src/components/Icon/Expensicons.js
index 976d846dcb81..d3c7c2f4bc57 100644
--- a/src/components/Icon/Expensicons.js
+++ b/src/components/Icon/Expensicons.js
@@ -109,6 +109,7 @@ import Podcast from '../../../assets/images/social-podcast.svg';
 import Linkedin from '../../../assets/images/social-linkedin.svg';
 import Instagram from '../../../assets/images/social-instagram.svg';
 import AddReaction from '../../../assets/images/add-reaction.svg';
+import Task from '../../../assets/images/task.svg';
 
 export {
     ActiveRoomAvatar,
@@ -204,6 +205,7 @@ export {
     Send,
     Shield,
     Sync,
+    Task,
     ThreeDots,
     Transfer,
     Trashcan,
diff --git a/src/languages/en.js b/src/languages/en.js
index 913d4669aac1..b3fd2113f7c3 100755
--- a/src/languages/en.js
+++ b/src/languages/en.js
@@ -1137,6 +1137,13 @@ export default {
             public_announce: 'Public Announce',
         },
     },
+    newTaskPage: {
+        assignTask: 'Assign task',
+        title: 'Title',
+        description: 'Description',
+        shareIn: 'Share in',
+        pleaseEnterTaskName: 'Please enter a title',
+    },
     statementPage: {
         generatingPDF: 'We\'re generating your PDF right now. Please come back later!',
     },
diff --git a/src/languages/es.js b/src/languages/es.js
index ba6e38232047..693308cec735 100644
--- a/src/languages/es.js
+++ b/src/languages/es.js
@@ -1138,6 +1138,13 @@ export default {
             public_announce: 'Anuncio Público',
         },
     },
+    newTaskPage: {
+        assignTask: 'Asignar tarea',
+        title: 'Título',
+        description: 'Descripción',
+        shareIn: 'Compartir en',
+        pleaseEnterTaskName: 'Por favor introduce un título',
+    },
     statementPage: {
         generatingPDF: 'Estamos generando tu PDF ahora mismo. ¡Por favor, vuelve más tarde!',
     },
diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js
index 776508f27864..f033f5a8a243 100644
--- a/src/libs/Navigation/AppNavigator/AuthScreens.js
+++ b/src/libs/Navigation/AppNavigator/AuthScreens.js
@@ -288,6 +288,12 @@ class AuthScreens extends React.Component {
                     component={ModalStackNavigators.IOURequestModalStackNavigator}
                     listeners={modalScreenListeners}
                 />
+                <RootStack.Screen
+                    name="NewTask"
+                    options={modalScreenOptions}
+                    component={ModalStackNavigators.NewTaskModalStackNavigator}
+                    listeners={modalScreenListeners}
+                />
                 <RootStack.Screen
                     name="IOU_Bill"
                     options={modalScreenOptions}
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js
index 957fa8cb6087..607985f5fef2 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js
@@ -202,6 +202,14 @@ const NewChatModalStackNavigator = createModalStackNavigator([{
     name: 'NewChat_Root',
 }]);
 
+const NewTaskModalStackNavigator = createModalStackNavigator([{
+    getComponent: () => {
+        const NewTaskPage = require('../../../pages/NewTaskPage').default;
+        return NewTaskPage;
+    },
+    name: 'NewTask_Root',
+}]);
+
 const SettingsModalStackNavigator = createModalStackNavigator([
     {
         getComponent: () => {
@@ -545,6 +553,7 @@ export {
     SearchModalStackNavigator,
     NewGroupModalStackNavigator,
     NewChatModalStackNavigator,
+    NewTaskModalStackNavigator,
     SettingsModalStackNavigator,
     EnablePaymentsStackNavigator,
     AddPersonalBankAccountModalStackNavigator,
diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js
index 71caa196abd0..f9c1361538ed 100644
--- a/src/libs/Navigation/linkingConfig.js
+++ b/src/libs/Navigation/linkingConfig.js
@@ -206,6 +206,11 @@ export default {
                     NewChat_Root: ROUTES.NEW_CHAT,
                 },
             },
+            NewTask: {
+                screens: {
+                    NewTask_Root: ROUTES.NEW_TASK_WITH_REPORT_ID,
+                },
+            },
             Search: {
                 screens: {
                     Search_Root: ROUTES.SEARCH,
diff --git a/src/libs/Permissions.js b/src/libs/Permissions.js
index 68f1a493f158..d3e407260e20 100644
--- a/src/libs/Permissions.js
+++ b/src/libs/Permissions.js
@@ -94,6 +94,14 @@ function canUsePasswordlessLogins(betas) {
     return _.contains(betas, CONST.BETAS.PASSWORDLESS) || _.contains(betas, CONST.BETAS.ALL);
 }
 
+/**
+ * @param {Array<String>} betas
+ * @returns {Boolean}
+ */
+function canUseTasks(betas) {
+    return _.contains(betas, CONST.BETAS.TASKS) || _.contains(betas, CONST.BETAS.ALL);
+}
+
 export default {
     canUseChronos,
     canUseIOU,
@@ -105,4 +113,5 @@ export default {
     canUsePolicyRooms,
     canUsePolicyExpenseChat,
     canUsePasswordlessLogins,
+    canUseTasks,
 };
diff --git a/src/pages/NewTaskPage.js b/src/pages/NewTaskPage.js
new file mode 100644
index 000000000000..a93025dfd5a6
--- /dev/null
+++ b/src/pages/NewTaskPage.js
@@ -0,0 +1,96 @@
+import React from 'react';
+import {View} from 'react-native';
+import {withOnyx} from 'react-native-onyx';
+import PropTypes from 'prop-types';
+import withLocalize, {withLocalizePropTypes} from '../components/withLocalize';
+import compose from '../libs/compose';
+import HeaderWithCloseButton from '../components/HeaderWithCloseButton';
+import Navigation from '../libs/Navigation/Navigation';
+import ScreenWrapper from '../components/ScreenWrapper';
+import styles from '../styles/styles';
+import ONYXKEYS from '../ONYXKEYS';
+import * as ErrorUtils from '../libs/ErrorUtils';
+import Form from '../components/Form';
+import TextInput from '../components/TextInput';
+import Permissions from '../libs/Permissions';
+
+const propTypes = {
+    /** List of betas available to current user */
+    betas: PropTypes.arrayOf(PropTypes.string),
+
+    ...withLocalizePropTypes,
+};
+const defaultProps = {
+    betas: [],
+};
+
+// NOTE: This page is going to be updated in https://github.com/Expensify/App/issues/16855, this is just a placeholder for now
+const NewTaskPage = (props) => {
+    /**
+     * @param {Object} values - form input values passed by the Form component
+     * @returns {Boolean}
+     */
+    function validate(values) {
+        const errors = {};
+
+        if (!values.taskTitle) {
+            // We error if the user doesn't enter a room name
+            ErrorUtils.addErrorMessage(errors, 'taskTitle', props.translate('newTaskPage.pleaseEnterTaskName'));
+        }
+
+        return errors;
+    }
+
+    function onSubmit() {
+
+    }
+
+    if (!Permissions.canUseTasks(props.betas)) {
+        Navigation.dismissModal();
+        return null;
+    }
+
+    return (
+        <ScreenWrapper includeSafeAreaPaddingBottom={false}>
+            <HeaderWithCloseButton
+                title={props.translate('newTaskPage.assignTask')}
+                onCloseButtonPress={() => Navigation.dismissModal()}
+            />
+            <Form
+                formID={ONYXKEYS.FORMS.NEW_TASK_FORM}
+                submitButtonText={props.translate('newTaskPage.assignTask')}
+                style={[styles.mh5, styles.mt5, styles.flexGrow1]}
+                validate={values => validate(values)}
+                onSubmit={() => onSubmit()}
+                enabledWhenOffline
+            >
+                <View style={styles.mb5}>
+                    <TextInput
+                        autoFocus
+                        inputID="taskTitle"
+                        label={props.translate('newTaskPage.title')}
+                    />
+                </View>
+                <View style={styles.mb5}>
+                    <TextInput
+                        inputID="taskDescription"
+                        label={props.translate('newTaskPage.description')}
+                    />
+                </View>
+            </Form>
+        </ScreenWrapper>
+    );
+};
+
+NewTaskPage.displayName = 'NewTaskPage';
+NewTaskPage.propTypes = propTypes;
+NewTaskPage.defaultProps = defaultProps;
+
+export default compose(
+    withOnyx({
+        betas: {
+            key: ONYXKEYS.BETAS,
+        },
+    }),
+    withLocalize,
+)(NewTaskPage);
diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js
index aca688c797c3..735ea16c50cb 100644
--- a/src/pages/home/report/ReportActionCompose.js
+++ b/src/pages/home/report/ReportActionCompose.js
@@ -52,6 +52,7 @@ import withKeyboardState, {keyboardStatePropTypes} from '../../../components/wit
 import ArrowKeyFocusManager from '../../../components/ArrowKeyFocusManager';
 import OfflineWithFeedback from '../../../components/OfflineWithFeedback';
 import KeyboardShortcut from '../../../libs/KeyboardShortcut';
+import Permissions from '../../../libs/Permissions';
 
 const propTypes = {
     /** Beta features list */
@@ -173,6 +174,7 @@ class ReportActionCompose extends React.Component {
         this.setTextInputRef = this.setTextInputRef.bind(this);
         this.getInputPlaceholder = this.getInputPlaceholder.bind(this);
         this.getMoneyRequestOptions = this.getMoneyRequestOptions.bind(this);
+        this.getTaskOption = this.getTaskOption.bind(this);
         this.addAttachment = this.addAttachment.bind(this);
         this.insertSelectedEmoji = this.insertSelectedEmoji.bind(this);
         this.setExceededMaxCommentLength = this.setExceededMaxCommentLength.bind(this);
@@ -391,6 +393,29 @@ class ReportActionCompose extends React.Component {
         }
     }
 
+    /**
+     * Determines if we can show the task option
+     * @param {Array} reportParticipants
+     * @returns {Boolean}
+     */
+    getTaskOption(reportParticipants) {
+        // We only prevent the task option from showing if it's a DM and the other user is an Expensify default email
+        if (!Permissions.canUseTasks(this.props.betas) || (lodashGet(this.props.report, 'participants', []).length === 1 && _.some(reportParticipants, email => _.contains(
+            CONST.EXPENSIFY_EMAILS,
+            email,
+        )))) {
+            return [];
+        }
+
+        return [
+            {
+                icon: Expensicons.Task,
+                text: this.props.translate('newTaskPage.assignTask'),
+                onSelected: () => Navigation.navigate(ROUTES.getNewTaskRoute(this.props.reportID)),
+            },
+        ];
+    }
+
     /**
      * Clean data related to EmojiSuggestions
      */
@@ -798,7 +823,7 @@ class ReportActionCompose extends React.Component {
                                                     onClose={() => this.setMenuVisibility(false)}
                                                     onItemSelected={() => this.setMenuVisibility(false)}
                                                     anchorPosition={styles.createMenuPositionReportActionCompose}
-                                                    menuItems={[...this.getMoneyRequestOptions(reportParticipants),
+                                                    menuItems={[...this.getMoneyRequestOptions(reportParticipants), ...this.getTaskOption(reportParticipants),
                                                         {
                                                             icon: Expensicons.Paperclip,
                                                             text: this.props.translate('reportActionCompose.addAttachment'),
diff --git a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js
index 426a50e68285..ebff5f4e6a51 100644
--- a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js
+++ b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js
@@ -211,6 +211,13 @@ class FloatingActionButtonAndPopover extends React.Component {
                                 onSelected: () => Navigation.navigate(ROUTES.IOU_BILL),
                             },
                         ] : []),
+                        ...(Permissions.canUseTasks(this.props.betas) ? [
+                            {
+                                icon: Expensicons.Task,
+                                text: this.props.translate('newTaskPage.assignTask'),
+                                onSelected: () => Navigation.navigate(ROUTES.NEW_TASK),
+                            },
+                        ] : []),
                         ...(!this.props.isLoading && !Policy.hasActiveFreePolicy(this.props.allPolicies) ? [
                             {
                                 icon: Expensicons.NewWorkspace,
