diff --git a/ee/app/assets/javascripts/analytics/cycle_analytics/components/create_value_stream_form/constants.js b/ee/app/assets/javascripts/analytics/cycle_analytics/components/create_value_stream_form/constants.js
index f6b51a7e7dd282367a8d41dbfdf758dda25bbfc9..02f3de2153ab4e9826b17c02c6a04bc1937aa112 100644
--- a/ee/app/assets/javascripts/analytics/cycle_analytics/components/create_value_stream_form/constants.js
+++ b/ee/app/assets/javascripts/analytics/cycle_analytics/components/create_value_stream_form/constants.js
@@ -1,32 +1,52 @@
-import { __, s__ } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
+import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
+
+export const NAME_MAX_LENGTH = 100;
 
 export const I18N = {
-  RECOVER_HIDDEN_STAGE: s__('CustomCycleAnalytics|Recover hidden stage'),
-  RECOVER_STAGE_TITLE: s__('CustomCycleAnalytics|Default stages'),
-  RECOVER_STAGES_VISIBLE: s__('CustomCycleAnalytics|All default stages are currently visible'),
-  SELECT_START_EVENT: s__('CustomCycleAnalytics|Select start event'),
-  SELECT_END_EVENT: s__('CustomCycleAnalytics|Select end event'),
-  FORM_FIELD_NAME: s__('CustomCycleAnalytics|Name'),
-  FORM_FIELD_NAME_PLACEHOLDER: s__('CustomCycleAnalytics|Enter a name for the stage'),
-  FORM_FIELD_START_EVENT: s__('CustomCycleAnalytics|Start event'),
-  FORM_FIELD_START_EVENT_LABEL: s__('CustomCycleAnalytics|Start event label'),
-  FORM_FIELD_END_EVENT: s__('CustomCycleAnalytics|End event'),
-  FORM_FIELD_END_EVENT_LABEL: s__('CustomCycleAnalytics|End event label'),
-  BTN_UPDATE_STAGE: s__('CustomCycleAnalytics|Update stage'),
-  BTN_ADD_STAGE: s__('CustomCycleAnalytics|Add stage'),
-  TITLE_EDIT_STAGE: s__('CustomCycleAnalytics|Editing stage'),
-  TITLE_ADD_STAGE: s__('CustomCycleAnalytics|New stage'),
+  FORM_TITLE: __('Create Value Stream'),
+  FORM_CREATED: __("'%{name}' Value Stream created"),
+  RECOVER_HIDDEN_STAGE: s__('CreateValueStreamForm|Recover hidden stage'),
+  RESTORE_HIDDEN_STAGE: s__('CreateValueStreamForm|Restore stage'),
+  RECOVER_STAGE_TITLE: s__('CreateValueStreamForm|Default stages'),
+  RECOVER_STAGES_VISIBLE: s__('CreateValueStreamForm|All default stages are currently visible'),
+  SELECT_START_EVENT: s__('CreateValueStreamForm|Select start event'),
+  SELECT_END_EVENT: s__('CreateValueStreamForm|Select end event'),
+  FORM_FIELD_NAME_LABEL: s__('CreateValueStreamForm|Name'),
+  FORM_FIELD_NAME_PLACEHOLDER: s__('CreateValueStreamForm|Enter a name for the stage'),
+  FIELD_STAGE_NAME_PLACEHOLDER: s__('CreateValueStreamForm|Enter stage name'),
+  FORM_FIELD_START_EVENT: s__('CreateValueStreamForm|Start event'),
+  FORM_FIELD_START_EVENT_LABEL: s__('CreateValueStreamForm|Start event label'),
+  FORM_FIELD_END_EVENT: s__('CreateValueStreamForm|End event'),
+  FORM_FIELD_END_EVENT_LABEL: s__('CreateValueStreamForm|End event label'),
+  DEFAULT_FIELD_START_EVENT_LABEL: s__('CreateValueStreamForm|Start event: '),
+  DEFAULT_FIELD_END_EVENT_LABEL: s__('CreateValueStreamForm|End event: '),
+  BTN_UPDATE_STAGE: s__('CreateValueStreamForm|Update stage'),
+  BTN_ADD_STAGE: s__('CreateValueStreamForm|Add stage'),
+  TITLE_EDIT_STAGE: s__('CreateValueStreamForm|Editing stage'),
+  TITLE_ADD_STAGE: s__('CreateValueStreamForm|New stage'),
   BTN_CANCEL: __('Cancel'),
+  STAGE_INDEX: s__('CreateValueStreamForm|Stage %{index}'),
+  HIDDEN_DEFAULT_STAGE: s__('CreateValueStreamForm|%{name} (default)'),
 };
 
 export const ERRORS = {
-  START_EVENT_REQUIRED: s__('CustomCycleAnalytics|Please select a start event first'),
-  STAGE_NAME_EXISTS: s__('CustomCycleAnalytics|Stage name already exists'),
+  MIN_LENGTH: s__('CreateValueStreamForm|Name is required'),
+  MAX_LENGTH: sprintf(s__('CreateValueStreamForm|Maximum length %{maxLength} characters'), {
+    maxLength: NAME_MAX_LENGTH,
+  }),
+  START_EVENT_REQUIRED: s__('CreateValueStreamForm|Please select a start event first'),
+  STAGE_NAME_EXISTS: s__('CreateValueStreamForm|Stage name already exists'),
   INVALID_EVENT_PAIRS: s__(
-    'CustomCycleAnalytics|Start event changed, please select a valid end event',
+    'CreateValueStreamForm|Start event changed, please select a valid end event',
   ),
 };
 
+export const STAGE_SORT_DIRECTION = {
+  UP: 'UP',
+  DOWN: 'DOWN',
+};
+
 export const defaultErrors = {
   id: [],
   name: [],
@@ -44,3 +64,16 @@ export const defaultFields = {
   endEventIdentifier: null,
   endEventLabelId: null,
 };
+
+export const DEFAULT_STAGE_CONFIG = ['issue', 'plan', 'code', 'test', 'review', 'staging'].map(
+  id => ({
+    id,
+    name: capitalizeFirstCharacter(id),
+    startEventIdentifier: null,
+    endEventIdentifier: null,
+    startEventLabel: null,
+    endEventLabel: null,
+    custom: false,
+    hidden: false,
+  }),
+);
diff --git a/ee/app/assets/javascripts/analytics/cycle_analytics/components/create_value_stream_form/custom_stage_fields.vue b/ee/app/assets/javascripts/analytics/cycle_analytics/components/create_value_stream_form/custom_stage_fields.vue
index adcb22e672c0aab03c86bf2cce729df3f998b04c..aa96e66c26eb08ca1b303489e70a721e11b330c7 100644
--- a/ee/app/assets/javascripts/analytics/cycle_analytics/components/create_value_stream_form/custom_stage_fields.vue
+++ b/ee/app/assets/javascripts/analytics/cycle_analytics/components/create_value_stream_form/custom_stage_fields.vue
@@ -69,7 +69,7 @@ export default {
 <template>
   <div>
     <gl-form-group
-      :label="$options.I18N.FORM_FIELD_NAME"
+      :label="$options.I18N.FORM_FIELD_NAME_LABEL"
       label-for="custom-stage-name"
       :state="hasFieldErrors('name')"
       :invalid-feedback="fieldErrorMessage('name')"
diff --git a/ee/app/assets/javascripts/analytics/cycle_analytics/components/create_value_stream_form/default_stage_fields.vue b/ee/app/assets/javascripts/analytics/cycle_analytics/components/create_value_stream_form/default_stage_fields.vue
new file mode 100644
index 0000000000000000000000000000000000000000..24d5e47a3487b7d96845d5221ee21d7a92a2dd6c
--- /dev/null
+++ b/ee/app/assets/javascripts/analytics/cycle_analytics/components/create_value_stream_form/default_stage_fields.vue
@@ -0,0 +1,84 @@
+<script>
+import { GlFormGroup, GlFormInput, GlFormText } from '@gitlab/ui';
+import StageFieldActions from './stage_field_actions.vue';
+import { I18N } from './constants';
+
+export default {
+  name: 'DefaultStageFields',
+  components: {
+    StageFieldActions,
+    GlFormGroup,
+    GlFormInput,
+    GlFormText,
+  },
+  props: {
+    index: {
+      type: Number,
+      required: true,
+    },
+    totalStages: {
+      type: Number,
+      required: true,
+    },
+    stage: {
+      type: Object,
+      required: true,
+    },
+    errors: {
+      type: Object,
+      required: false,
+      default: () => {},
+    },
+  },
+  methods: {
+    isValid(field) {
+      return !this.errors[field]?.length;
+    },
+    renderError(field) {
+      return this.errors[field]?.join('\n');
+    },
+  },
+  I18N,
+};
+</script>
+<template>
+  <div class="gl-mb-4">
+    <div class="gl-display-flex">
+      <gl-form-group
+        class="gl-flex-grow-1 gl-mb-0"
+        :state="isValid('name')"
+        :invalid-feedback="renderError('name')"
+      >
+        <gl-form-input
+          v-model.trim="stage.name"
+          :name="`create-value-stream-stage-${index}`"
+          :placeholder="$options.I18N.FIELD_STAGE_NAME_PLACEHOLDER"
+          required
+          @input="$emit('input', $event)"
+        />
+      </gl-form-group>
+      <stage-field-actions
+        :index="index"
+        :stage-count="totalStages"
+        @move="$emit('move', $event)"
+        @hide="$emit('hide', $event)"
+      />
+    </div>
+    <div class="gl-display-flex" :data-testid="`stage-start-event-${index}`">
+      <span class="gl-m-0 gl-vertical-align-middle gl-mr-3 gl-font-weight-bold">{{
+        $options.I18N.DEFAULT_FIELD_START_EVENT_LABEL
+      }}</span>
+      <gl-form-text>{{ stage.startEventIdentifier }}</gl-form-text>
+      <gl-form-text v-if="stage.startEventLabel"
+        >&nbsp;-&nbsp;{{ stage.startEventLabel }}</gl-form-text
+      >
+    </div>
+    <div class="gl-display-flex" :data-testid="`stage-end-event-${index}`">
+      <span class="gl-m-0 gl-vertical-align-middle gl-mr-3 gl-font-weight-bold">{{
+        $options.I18N.DEFAULT_FIELD_START_EVENT_LABEL
+      }}</span>
+      <gl-form-text>{{ stage.endEventIdentifier }}</gl-form-text>
+      <gl-form-text v-if="stage.endEventLabel">&nbsp;-&nbsp;{{ stage.endEventLabel }}</gl-form-text>
+    </div>
+  </div>
+</template>
diff --git a/ee/app/assets/javascripts/analytics/cycle_analytics/components/create_value_stream_form/stage_field_actions.vue b/ee/app/assets/javascripts/analytics/cycle_analytics/components/create_value_stream_form/stage_field_actions.vue
new file mode 100644
index 0000000000000000000000000000000000000000..8272b2b7c13d216fe0a01f8a9fcbc286671b332d
--- /dev/null
+++ b/ee/app/assets/javascripts/analytics/cycle_analytics/components/create_value_stream_form/stage_field_actions.vue
@@ -0,0 +1,57 @@
+<script>
+import { GlButton, GlButtonGroup } from '@gitlab/ui';
+import { STAGE_SORT_DIRECTION } from './constants';
+
+export default {
+  name: 'StageFieldActions',
+  components: {
+    GlButton,
+    GlButtonGroup,
+  },
+  props: {
+    index: {
+      type: Number,
+      required: true,
+    },
+    stageCount: {
+      type: Number,
+      required: true,
+    },
+  },
+  computed: {
+    lastStageIndex() {
+      return this.stageCount - 1;
+    },
+    isFirstActiveStage() {
+      return this.index === 0;
+    },
+    isLastActiveStage() {
+      return this.index === this.lastStageIndex;
+    },
+  },
+  STAGE_SORT_DIRECTION,
+};
+</script>
+<template>
+  <div>
+    <gl-button-group class="gl-px-2">
+      <gl-button
+        :data-testid="`stage-action-move-down-${index}`"
+        :disabled="isLastActiveStage"
+        icon="arrow-down"
+        @click="$emit('move', { index, direction: $options.STAGE_SORT_DIRECTION.DOWN })"
+      />
+      <gl-button
+        :data-testid="`stage-action-move-up-${index}`"
+        :disabled="isFirstActiveStage"
+        icon="arrow-up"
+        @click="$emit('move', { index, direction: $options.STAGE_SORT_DIRECTION.UP })"
+      />
+    </gl-button-group>
+    <gl-button
+      :data-testid="`stage-action-hide-${index}`"
+      icon="archive"
+      @click="$emit('hide', index)"
+    />
+  </div>
+</template>
diff --git a/ee/spec/frontend/analytics/cycle_analytics/components/create_value_stream_form/default_stage_fields_spec.js b/ee/spec/frontend/analytics/cycle_analytics/components/create_value_stream_form/default_stage_fields_spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..b6e32848de710a331a62686aa1e219120c300810
--- /dev/null
+++ b/ee/spec/frontend/analytics/cycle_analytics/components/create_value_stream_form/default_stage_fields_spec.js
@@ -0,0 +1,105 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlFormGroup } from '@gitlab/ui';
+import StageFieldActions from 'ee/analytics/cycle_analytics/components/create_value_stream_form/stage_field_actions.vue';
+import DefaultStageFields from 'ee/analytics/cycle_analytics/components/create_value_stream_form/default_stage_fields.vue';
+
+let wrapper = null;
+
+const defaultStageIndex = 0;
+const totalStages = 5;
+const stageNameError = 'Name is required';
+const defaultErrors = { name: [stageNameError] };
+const defaultStage = {
+  name: 'Cool new stage',
+  startEventIdentifier: 'some_start_event',
+  endEventIdentifier: 'some_end_event',
+  endEventLabel: 'some_label',
+};
+
+describe('DefaultStageFields', () => {
+  function createComponent({ stage = defaultStage, errors = {} } = {}) {
+    return shallowMount(DefaultStageFields, {
+      propsData: {
+        index: defaultStageIndex,
+        totalStages,
+        stage,
+        errors,
+      },
+      stubs: {
+        'labels-selector': false,
+        'gl-form-text': false,
+      },
+    });
+  }
+
+  const findStageFieldName = () => wrapper.find('[name="create-value-stream-stage-0"]');
+  const findStartEvent = () => wrapper.find('[data-testid="stage-start-event-0"]');
+  const findEndEvent = () => wrapper.find('[data-testid="stage-end-event-0"]');
+  const findFormGroup = () => wrapper.find(GlFormGroup);
+  const findFieldActions = () => wrapper.find(StageFieldActions);
+
+  beforeEach(() => {
+    wrapper = createComponent();
+  });
+
+  afterEach(() => {
+    wrapper.destroy();
+    wrapper = null;
+  });
+
+  it('renders the stage field name', () => {
+    expect(findStageFieldName().exists()).toBe(true);
+    expect(findStageFieldName().html()).toContain(defaultStage.name);
+  });
+
+  it('renders the field start event', () => {
+    expect(findStartEvent().exists()).toBe(true);
+    expect(findStartEvent().html()).toContain(defaultStage.startEventIdentifier);
+  });
+
+  it('renders the field end event', () => {
+    const content = findEndEvent().html();
+    expect(content).toContain(defaultStage.endEventIdentifier);
+    expect(content).toContain(defaultStage.endEventLabel);
+  });
+
+  it('renders an event label if it exists', () => {
+    const content = findEndEvent().html();
+    expect(content).toContain(defaultStage.endEventLabel);
+  });
+
+  it('on field input emits an input event', () => {
+    expect(wrapper.emitted('input')).toBeUndefined();
+
+    const newInput = 'coooool';
+    findStageFieldName().vm.$emit('input', newInput);
+    expect(wrapper.emitted('input')[0]).toEqual([newInput]);
+  });
+
+  describe('StageFieldActions', () => {
+    it('when the stage is hidden emits a `hide` event', () => {
+      expect(wrapper.emitted('hide')).toBeUndefined();
+
+      const stageMoveParams = { index: defaultStageIndex, direction: 'UP' };
+      findFieldActions().vm.$emit('move', stageMoveParams);
+      expect(wrapper.emitted('move')[0]).toEqual([stageMoveParams]);
+    });
+
+    it('when the stage is moved emits a `move` event', () => {
+      expect(wrapper.emitted('move')).toBeUndefined();
+
+      findFieldActions().vm.$emit('move', defaultStageIndex);
+      expect(wrapper.emitted('move')[0]).toEqual([defaultStageIndex]);
+    });
+  });
+
+  describe('with field errors', () => {
+    beforeEach(() => {
+      wrapper = createComponent({ errors: defaultErrors });
+    });
+
+    it('displays the field error', () => {
+      expect(findFormGroup().html()).toContain(stageNameError);
+    });
+  });
+});
diff --git a/ee/spec/frontend/analytics/cycle_analytics/components/create_value_stream_form/stage_field_actions_spec.js b/ee/spec/frontend/analytics/cycle_analytics/components/create_value_stream_form/stage_field_actions_spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..a118e2c2aa5b4dbea5be458289905d234e6e7fe5
--- /dev/null
+++ b/ee/spec/frontend/analytics/cycle_analytics/components/create_value_stream_form/stage_field_actions_spec.js
@@ -0,0 +1,71 @@
+import { shallowMount } from '@vue/test-utils';
+import StageFieldActions from 'ee/analytics/cycle_analytics/components/create_value_stream_form/stage_field_actions.vue';
+
+const defaultIndex = 0;
+const stageCount = 3;
+
+describe('StageFieldActions', () => {
+  function createComponent({ index = defaultIndex }) {
+    return shallowMount(StageFieldActions, {
+      propsData: {
+        index,
+        stageCount,
+      },
+    });
+  }
+
+  let wrapper = null;
+  const findMoveDownBtn = () => wrapper.find('[data-testid^="stage-action-move-down"]');
+  const findMoveUpBtn = () => wrapper.find('[data-testid^="stage-action-move-up"]');
+  const findHideBtn = () => wrapper.find('[data-testid^="stage-action-hide"]');
+
+  beforeEach(() => {
+    wrapper = createComponent({});
+  });
+
+  afterEach(() => {
+    wrapper.destroy();
+    wrapper = null;
+  });
+
+  it('will render the move up action', () => {
+    expect(findMoveUpBtn().exists()).toBe(true);
+  });
+
+  it('will render the move down action', () => {
+    expect(findMoveDownBtn().exists()).toBe(true);
+  });
+
+  it('will render the hide action', () => {
+    expect(findHideBtn().exists()).toBe(true);
+  });
+
+  it('disables the move up button', () => {
+    expect(findMoveUpBtn().props('disabled')).toBe(true);
+  });
+
+  it('when the down button is clicked will emit a `move` event', () => {
+    findMoveDownBtn().vm.$emit('click');
+    expect(wrapper.emitted('move')[0]).toEqual([{ direction: 'DOWN', index: 0 }]);
+  });
+
+  it('when the up button is clicked will emit a `move` event', () => {
+    findMoveUpBtn().vm.$emit('click');
+    expect(wrapper.emitted('move')[0]).toEqual([{ direction: 'UP', index: 0 }]);
+  });
+
+  it('when the hide button is clicked will emit a `move` event', () => {
+    findHideBtn().vm.$emit('click');
+    expect(wrapper.emitted('hide')[0]).toEqual([0]);
+  });
+
+  describe('when the current index is the same as the total number of stages', () => {
+    beforeEach(() => {
+      wrapper = createComponent({ index: 2 });
+    });
+
+    it('disables the move down button', () => {
+      expect(findMoveDownBtn().props('disabled')).toBe(true);
+    });
+  });
+});
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 48eb4cc2812d4626a234bd3977f98cfa8a2dd862..8ef548abb9b842a5ba99e3836f5b25a8e5a662b6 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -8180,6 +8180,84 @@ msgstr ""
 msgid "CreateTokenToCloneLink|create a personal access token"
 msgstr ""
 
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+msgstr ""
+
+msgid "CreateValueStreamForm|Default stages"
+msgstr ""
+
+msgid "CreateValueStreamForm|Editing stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|End event"
+msgstr ""
+
+msgid "CreateValueStreamForm|End event label"
+msgstr ""
+
+msgid "CreateValueStreamForm|End event: "
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter a name for the stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Restore stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Select end event"
+msgstr ""
+
+msgid "CreateValueStreamForm|Select start event"
+msgstr ""
+
+msgid "CreateValueStreamForm|Stage %{index}"
+msgstr ""
+
+msgid "CreateValueStreamForm|Stage name already exists"
+msgstr ""
+
+msgid "CreateValueStreamForm|Start event"
+msgstr ""
+
+msgid "CreateValueStreamForm|Start event changed, please select a valid end event"
+msgstr ""
+
+msgid "CreateValueStreamForm|Start event label"
+msgstr ""
+
+msgid "CreateValueStreamForm|Start event: "
+msgstr ""
+
+msgid "CreateValueStreamForm|Update stage"
+msgstr ""
+
 msgid "Created"
 msgstr ""
 
@@ -8357,57 +8435,21 @@ msgstr ""
 msgid "CustomCycleAnalytics|Add stage"
 msgstr ""
 
-msgid "CustomCycleAnalytics|All default stages are currently visible"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Default stages"
-msgstr ""
-
 msgid "CustomCycleAnalytics|Editing stage"
 msgstr ""
 
-msgid "CustomCycleAnalytics|End event"
-msgstr ""
-
 msgid "CustomCycleAnalytics|End event label"
 msgstr ""
 
-msgid "CustomCycleAnalytics|Enter a name for the stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Name"
-msgstr ""
-
 msgid "CustomCycleAnalytics|New stage"
 msgstr ""
 
-msgid "CustomCycleAnalytics|Please select a start event first"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Recover hidden stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select end event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Select start event"
-msgstr ""
-
 msgid "CustomCycleAnalytics|Stage name already exists"
 msgstr ""
 
-msgid "CustomCycleAnalytics|Start event"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event changed, please select a valid end event"
-msgstr ""
-
 msgid "CustomCycleAnalytics|Start event label"
 msgstr ""
 
-msgid "CustomCycleAnalytics|Update stage"
-msgstr ""
-
 msgid "Customer Portal"
 msgstr ""