diff --git a/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue b/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue
index 5b392470e41401d035e2455dc3625935ef1dbf7d..7d08815b03360f3e1e9d90dc3fe14ba6ce501b89 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue
@@ -116,6 +116,7 @@ export default {
           :placeholder="placeholder"
           :value="text"
           class="note-textarea ide-commit-message-textarea"
+          data-qa-selector="ide_commit_message_field"
           dir="auto"
           name="commit-message"
           @scroll="handleScroll"
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index 0be8a4d5472d0593c4c3672cd14df87bd0b54c6a..4732f895b0db4972daec64c2c814e99535145a27 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -106,14 +106,26 @@ def add_license_path
     add_special_file_path(file_name: 'LICENSE')
   end
 
+  def add_license_ide_path
+    ide_edit_path(project, default_branch_or_master, 'LICENSE')
+  end
+
   def add_changelog_path
     add_special_file_path(file_name: 'CHANGELOG')
   end
 
+  def add_changelog_ide_path
+    ide_edit_path(project, default_branch_or_master, 'CHANGELOG')
+  end
+
   def add_contribution_guide_path
     add_special_file_path(file_name: 'CONTRIBUTING.md', commit_message: 'Add CONTRIBUTING')
   end
 
+  def add_contribution_guide_ide_path
+    ide_edit_path(project, default_branch_or_master, 'CONTRIBUTING.md')
+  end
+
   def add_ci_yml_path
     add_special_file_path(file_name: ci_config_path_or_default)
   end
@@ -122,6 +134,10 @@ def add_readme_path
     add_special_file_path(file_name: 'README.md')
   end
 
+  def add_readme_ide_path
+    ide_edit_path(project, default_branch_or_master, 'README.md')
+  end
+
   def license_short_name
     license = repository.license
     license&.nickname || license&.name || 'LICENSE'
@@ -218,9 +234,11 @@ def tags_anchor_data
 
   def new_file_anchor_data
     if current_user && can_current_user_push_to_default_branch?
+      new_file_path = empty_repo? ? ide_edit_path(project, default_branch_or_master) : project_new_blob_path(project, default_branch_or_master)
+
       AnchorData.new(false,
                      statistic_icon + _('New file'),
-                     project_new_blob_path(project, default_branch_or_master),
+                     new_file_path,
                      'missing')
     end
   end
@@ -229,7 +247,7 @@ def readme_anchor_data
     if current_user && can_current_user_push_to_default_branch? && repository.readme.nil?
       AnchorData.new(false,
                      statistic_icon + _('Add README'),
-                     add_readme_path)
+                     empty_repo? ? add_readme_ide_path : add_readme_path)
     elsif repository.readme
       AnchorData.new(false,
                      statistic_icon('doc-text') + _('README'),
@@ -243,7 +261,7 @@ def changelog_anchor_data
     if current_user && can_current_user_push_to_default_branch? && repository.changelog.blank?
       AnchorData.new(false,
                      statistic_icon + _('Add CHANGELOG'),
-                     add_changelog_path)
+                     empty_repo? ? add_changelog_ide_path : add_changelog_path)
     elsif repository.changelog.present?
       AnchorData.new(false,
                      statistic_icon('doc-text') + _('CHANGELOG'),
@@ -264,7 +282,7 @@ def license_anchor_data
       if current_user && can_current_user_push_to_default_branch?
         AnchorData.new(false,
                        content_tag(:span, statistic_icon + _('Add LICENSE'), class: 'add-license-link d-flex'),
-                       add_license_path)
+                       empty_repo? ? add_license_ide_path : add_license_path)
       else
         AnchorData.new(false,
                        icon + content_tag(:span, _('No license. All rights reserved'), class: 'project-stat-value'),
@@ -277,7 +295,7 @@ def contribution_guide_anchor_data
     if current_user && can_current_user_push_to_default_branch? && repository.contribution_guide.blank?
       AnchorData.new(false,
                      statistic_icon + _('Add CONTRIBUTING'),
-                     add_contribution_guide_path)
+                     empty_repo? ? add_contribution_guide_ide_path : add_contribution_guide_path)
     elsif repository.contribution_guide.present?
       AnchorData.new(false,
                      statistic_icon('doc-text') + _('CONTRIBUTING'),
diff --git a/changelogs/unreleased/27535-new-project-ide.yml b/changelogs/unreleased/27535-new-project-ide.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ce06f1c0380cc96fec196be4d8e53d6e41f2f445
--- /dev/null
+++ b/changelogs/unreleased/27535-new-project-ide.yml
@@ -0,0 +1,5 @@
+---
+title: Use Web IDE to create new files in empty repos
+merge_request: 44287
+author:
+type: added
diff --git a/qa/qa/page/project/web_ide/edit.rb b/qa/qa/page/project/web_ide/edit.rb
index 56c8d343cf530a655c2d99d237a7ea3ef74ccb6a..fc33c753230578aff1ea5ae816cf5f487bfdb899 100644
--- a/qa/qa/page/project/web_ide/edit.rb
+++ b/qa/qa/page/project/web_ide/edit.rb
@@ -73,6 +73,10 @@ class Edit < Page::Base
             element :project_path_content
           end
 
+          view 'app/assets/javascripts/ide/components/commit_sidebar/message_field.vue' do
+            element :ide_commit_message_field
+          end
+
           def has_file?(file_name)
             within_element(:file_list) do
               page.has_content? file_name
@@ -83,6 +87,10 @@ def has_project_path?(project_path)
             has_element?(:project_path_content, project_path: project_path)
           end
 
+          def go_to_project
+            click_element(:project_path_content, Page::Project::Show)
+          end
+
           def create_new_file_from_template(file_name, template)
             click_element(:new_file, Page::Component::WebIDE::Modal::CreateNewFile)
 
@@ -115,7 +123,7 @@ def commit_sha
             find_element(:commit_sha_content).text
           end
 
-          def commit_changes(open_merge_request: false)
+          def commit_changes(commit_message = nil, open_merge_request: false)
             # Clicking :begin_commit_button switches from the
             # edit to the commit view
             click_element(:begin_commit_button)
@@ -133,6 +141,10 @@ def commit_changes(open_merge_request: false)
                 has_element?(:commit_button)
             end
 
+            if commit_message
+              fill_element(:ide_commit_message_field, commit_message)
+            end
+
             if open_merge_request
               click_element(:commit_button, Page::MergeRequest::New)
             else
diff --git a/qa/qa/resource/file.rb b/qa/qa/resource/file.rb
index 76c4c71c48df2a3ae6d6c111ca5cd68e9fc5f91b..f573f3e89f0c06f423b7aa1b66d174b7f455d2e8 100644
--- a/qa/qa/resource/file.rb
+++ b/qa/qa/resource/file.rb
@@ -27,11 +27,14 @@ def fabricate!
 
         Page::Project::Show.perform(&:create_first_new_file!)
 
-        Page::File::Form.perform do |form|
-          form.add_name(@name)
-          form.add_content(@content)
-          form.add_commit_message(@commit_message)
-          form.commit_changes
+        Page::Project::WebIDE::Edit.perform do |ide|
+          ide.add_file(@name, @content)
+          ide.commit_changes(@commit_message)
+          ide.go_to_project
+        end
+
+        Page::Project::Show.perform do |project|
+          project.click_file(@name)
         end
       end
 
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb
index 43f4b080c737743224c89e17a20c84a0e4152998..5aa5f0fc0a32517c0fa33f497f81ae743829280e 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb
@@ -18,7 +18,6 @@ module QA
           file.commit_message = commit_message_for_create
         end
 
-        expect(page).to have_content('The file has been successfully created.')
         expect(page).to have_content(file_name)
         expect(page).to have_content(file_content)
         expect(page).to have_content(commit_message_for_create)
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/create_first_file_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/create_first_file_in_web_ide_spec.rb
index ea821f8b3e662f22ce45f131cc83314564a41d5a..f7a2e3081fb49eabb2ac9e7aa5ff60729bca36f5 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/create_first_file_in_web_ide_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/create_first_file_in_web_ide_spec.rb
@@ -10,7 +10,6 @@ module QA
         end
       end
 
-      let(:web_ide_url) { current_url + '-/ide/project/' + project.path_with_namespace }
       let(:file_name) { 'the very first file.txt' }
 
       before do
@@ -18,10 +17,8 @@ module QA
       end
 
       it "creates the first file in an empty project via Web IDE", testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/847' do
-        # In the first iteration, the test opens Web IDE by modifying the URL to address past regressions.
-        # Once the Web IDE button is introduced for empty projects, the test will be modified to go through UI.
-        # See https://gitlab.com/gitlab-org/gitlab/-/issues/27915 and https://gitlab.com/gitlab-org/gitlab/-/issues/27535.
-        page.visit(web_ide_url)
+        project.visit!
+        Page::Project::Show.perform(&:create_first_new_file!)
 
         Page::Project::WebIDE::Edit.perform do |ide|
           ide.create_first_file(file_name)
diff --git a/spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb b/spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb
index a271a4f43a830d6ae01d495c8c0e439266744120..fda2992af8d5ee1208e8a573bc7c0f0c7b782a13 100644
--- a/spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb
+++ b/spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb
@@ -2,7 +2,9 @@
 
 require 'spec_helper'
 
-RSpec.describe 'User creates blob in new project', :js do
+RSpec.describe 'User creates new blob', :js do
+  include WebIdeSpecHelpers
+
   let(:user) { create(:user) }
   let(:project) { create(:project, :empty_repo) }
 
@@ -12,16 +14,19 @@
       visit project_path(project)
     end
 
-    it 'allows the user to add a new file' do
+    it 'allows the user to add a new file in Web IDE' do
       click_link 'New file'
 
-      execute_script("monaco.editor.getModels()[0].setValue('Hello world')")
+      wait_for_requests
+
+      ide_create_new_file('dummy-file', content: "Hello world\n")
 
-      fill_in(:file_name, with: 'dummy-file')
+      ide_commit
 
-      click_button('Commit changes')
+      click_button('Commit')
 
-      expect(page).to have_content('The file has been successfully created')
+      expect(page).to have_content('All changes are committed')
+      expect(project.repository.blob_at('master', 'dummy-file').data).to eql("Hello world\n")
     end
   end
 
diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
index eed1e7aaf1b1669952b33eb53c450bef7ebcb431..d28e31c08dcde41c5b41f037c9f7611a92c72fbd 100644
--- a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
+++ b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
@@ -3,6 +3,8 @@
 require 'spec_helper'
 
 RSpec.describe 'Projects > Files > Project owner sees a link to create a license file in empty project', :js do
+  include WebIdeSpecHelpers
+
   let(:project) { create(:project_empty_repo) }
   let(:project_maintainer) { project.owner }
 
@@ -10,36 +12,35 @@
     sign_in(project_maintainer)
   end
 
-  it 'project maintainer creates a license file from a template' do
+  it 'allows project maintainer creates a license file from a template in Web IDE' do
     visit project_path(project)
     click_on 'Add LICENSE'
-    expect(page).to have_content('New file')
 
-    expect(current_path).to eq(
-      project_new_blob_path(project, 'master'))
-    expect(find('#file_name').value).to eq('LICENSE')
-    expect(page).to have_selector('.license-selector')
+    expect(current_path).to eq("/-/ide/project/#{project.full_path}/edit/master/-/LICENSE")
+
+    expect(page).to have_selector('.qa-file-templates-bar')
 
     select_template('MIT License')
 
-    file_content = first('.file-editor')
-    expect(file_content).to have_content('MIT License')
-    expect(file_content).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}")
+    expect(ide_editor_value).to have_content('MIT License')
+    expect(ide_editor_value).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}")
+
+    ide_commit
+
+    click_button('Commit')
+
+    expect(current_path).to eq("/-/ide/project/#{project.full_path}/tree/master/-/")
 
-    fill_in :commit_message, with: 'Add a LICENSE file', visible: true
-    click_button 'Commit changes'
+    expect(page).to have_content('All changes are committed')
 
-    expect(current_path).to eq(
-      project_blob_path(project, 'master/LICENSE'))
-    expect(page).to have_content('MIT License')
-    expect(page).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}")
+    license_file = project.repository.blob_at('master', 'LICENSE').data
+    expect(license_file).to have_content('MIT License')
+    expect(license_file).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}")
   end
 
   def select_template(template)
-    page.within('.js-license-selector-wrap') do
-      click_button 'Apply a template'
-      click_link template
-      wait_for_requests
-    end
+    click_button 'Choose a template...'
+    click_button template
+    wait_for_requests
   end
 end
diff --git a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
index afa9de5ce86fdd4d88462eb9be48eddd4087742e..189aa45ff758c4050dc99fd590c266b18ff8c4f3 100644
--- a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
+++ b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
@@ -46,21 +46,21 @@
         visit project_path(project)
       end
 
-      it '"New file" button linked to new file page' do
+      it '"New file" button linked to IDE new file page' do
         page.within('.project-buttons') do
-          expect(page).to have_link('New file', href: project_new_blob_path(project, project.default_branch || 'master'))
+          expect(page).to have_link('New file', href: presenter.ide_edit_path(project, project.default_branch || 'master'))
         end
       end
 
-      it '"Add README" button linked to new file populated for a README' do
+      it '"Add README" button linked to IDE new file populated for a README' do
         page.within('.project-buttons') do
-          expect(page).to have_link('Add README', href: presenter.add_readme_path)
+          expect(page).to have_link('Add README', href: presenter.add_readme_ide_path)
         end
       end
 
-      it '"Add license" button linked to new file populated for a license' do
+      it '"Add license" button linked to IDE new file populated for a license' do
         page.within('.project-buttons') do
-          expect(page).to have_link('Add LICENSE', href: presenter.add_license_path)
+          expect(page).to have_link('Add LICENSE', href: presenter.add_license_ide_path)
         end
       end
 
@@ -74,9 +74,9 @@
           visit project_path(project)
         end
 
-        it '"New file" button linked to new file page' do
+        it '"New file" button linked to IDE new file page' do
           page.within('.project-buttons') do
-            expect(page).to have_link('New file', href: project_new_blob_path(project, 'example_branch'))
+            expect(page).to have_link('New file', href: presenter.ide_edit_path(project, 'example_branch'))
           end
         end
       end
@@ -144,7 +144,7 @@
             expect(project.repository.readme).not_to be_nil
 
             page.within('.project-buttons') do
-              expect(page).not_to have_link('Add README', href: presenter.add_readme_path)
+              expect(page).not_to have_link('Add README', href: presenter.add_readme_ide_path)
               expect(page).to have_link('README', href: presenter.readme_path)
             end
           end
@@ -164,7 +164,7 @@
         end
 
         context 'when the project does not have a README' do
-          it 'shows the "Add README" button' do
+          it 'shows the single file editor "Add README" button' do
             allow(project.repository).to receive(:readme).and_return(nil)
 
             visit project_path(project)
diff --git a/spec/features/tags/developer_views_tags_spec.rb b/spec/features/tags/developer_views_tags_spec.rb
index 4888611472c257df6c402b5a5acf6bdeed78d47b..6bae53afe6f07aee361ae9acac18dd45ec252356 100644
--- a/spec/features/tags/developer_views_tags_spec.rb
+++ b/spec/features/tags/developer_views_tags_spec.rb
@@ -3,6 +3,8 @@
 require 'spec_helper'
 
 RSpec.describe 'Developer views tags' do
+  include RepoHelpers
+
   let(:user) { create(:user) }
   let(:group) { create(:group) }
 
@@ -15,10 +17,13 @@
     let(:project) { create(:project_empty_repo, namespace: group) }
 
     before do
-      visit project_path(project)
-      click_on 'Add README'
-      fill_in :commit_message, with: 'Add a README file', visible: true
-      click_button 'Commit changes'
+      project.repository.create_file(
+        user,
+        'README.md',
+        'Example readme',
+        message: 'Add README',
+        branch_name: 'master')
+
       visit project_tags_path(project)
     end