diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md
index bc41af3d0a649fd1fb098baf0c89cd0f8704d6d7..a8059725c3dc3a080cec8590076e7ee052e2708b 100644
--- a/docs/usage/configuration-options.md
+++ b/docs/usage/configuration-options.md
@@ -674,8 +674,8 @@ This option is evaluated at PR/MR creation time.
 
 <!-- prettier-ignore -->
 !!! note
-    GitLab and Gitea implement draft status by checking if the PR's title starts with certain strings.
-    This means that `draftPR` on GitLab and Gitea are incompatible with the legacy method of triggering Renovate to rebase a PR by renaming the PR to start with `rebase!`.
+    Gitea and GitLab implement draft status by checking if the PR's title starts with certain strings.
+    This means that `draftPR` on Gitea and GitLab are incompatible with the legacy method of triggering Renovate to rebase a PR by renaming the PR to start with `rebase!`.
 
 ## enabled
 
diff --git a/docs/usage/faq.md b/docs/usage/faq.md
index 77163463f95d29541fa09418949bb339af5db78b..571b248c792925c7337d2c57b4d2c8e1cc855765 100644
--- a/docs/usage/faq.md
+++ b/docs/usage/faq.md
@@ -33,8 +33,8 @@ If you're self hosting Renovate, use the latest release if possible.
 
 | Feature              | Platforms which lack feature                      | See Renovate issue(s)                                        |
 | -------------------- | ------------------------------------------------- | ------------------------------------------------------------ |
-| Dependency Dashboard | BitBucket, BitBucket Server, Azure                | [#9592](https://github.com/renovatebot/renovate/issues/9592) |
-| Hosted app           | GitLab, BitBucket, BitBucket Server, Azure, Gitea |                                                              |
+| Dependency Dashboard | Azure, BitBucket, BitBucket Server                | [#9592](https://github.com/renovatebot/renovate/issues/9592) |
+| Hosted app           | Azure, BitBucket, BitBucket Server, Gitea, GitLab |                                                              |
 
 ## Major platform features not supported by Renovate
 
diff --git a/docs/usage/getting-started/use-cases.md b/docs/usage/getting-started/use-cases.md
index 39ab7c0e76910c0d03a49cde8288c9563ad8f9b9..860a5b9d633daab939d6d30e77a63e547573bbc7 100644
--- a/docs/usage/getting-started/use-cases.md
+++ b/docs/usage/getting-started/use-cases.md
@@ -177,9 +177,9 @@ You can set the time ranges during which Renovate creates updates in the `schedu
 
 You can use Renovate's "Dependency Dashboard" on platforms which support dynamic Markdown checkboxes:
 
+- Gitea
 - GitHub
 - GitLab
-- Gitea
 
 When you enable the Dependency Dashboard, Renovate creates a "Dependency Dashboard" issue.
 This issue lists all updates which are pending, in progress, or were previously closed ignored.
diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts
index 6203eeef4d0e6de014c6a5aefd4d8eb4ba04a233..6a2aed7a40410b019e26a646bd47092f72754908 100644
--- a/lib/config/options/index.ts
+++ b/lib/config/options/index.ts
@@ -405,7 +405,7 @@ const options: RenovateOptions[] = [
       'Set to enable rebase/retry markdown checkbox for onboarding PRs.',
     type: 'boolean',
     default: false,
-    supportedPlatforms: ['github', 'gitlab', 'gitea'],
+    supportedPlatforms: ['gitea', 'github', 'gitlab'],
     globalOnly: true,
     experimental: true,
     experimentalIssues: [17633],
@@ -1528,7 +1528,7 @@ const options: RenovateOptions[] = [
     description: 'Label to make Renovate stop updating a PR.',
     type: 'string',
     default: 'stop-updating',
-    supportedPlatforms: ['azure', 'github', 'gitlab', 'gitea'],
+    supportedPlatforms: ['azure', 'gitea', 'github', 'gitlab'],
   },
   {
     name: 'stabilityDays',
diff --git a/lib/config/presets/local/index.spec.ts b/lib/config/presets/local/index.spec.ts
index 051a739378aa1211e76e513ad4f02e622e2676ed..54a29f8b8796d57ac3813b9c2bd012ba90dabb1b 100644
--- a/lib/config/presets/local/index.spec.ts
+++ b/lib/config/presets/local/index.spec.ts
@@ -232,7 +232,7 @@ describe('config/presets/local/index', () => {
 
     it('forwards to gitlab', async () => {
       GlobalConfig.set({
-        platform: 'GitLab',
+        platform: 'gitlab',
       });
       const content = await local.getPreset({
         repo: 'some/repo',
@@ -272,7 +272,7 @@ describe('config/presets/local/index', () => {
     });
 
     it('forwards to gitlab with a tag', async () => {
-      GlobalConfig.set({ platform: 'GitLab' });
+      GlobalConfig.set({ platform: 'gitlab' });
       const content = await local.getPreset({
         repo: 'some/repo',
         presetName: 'default',
diff --git a/lib/config/presets/local/index.ts b/lib/config/presets/local/index.ts
index d66dd903c46921344264a03ab3ee3a0906347294..ac8e2a69703049c7683930994277ac2d0b3c4b13 100644
--- a/lib/config/presets/local/index.ts
+++ b/lib/config/presets/local/index.ts
@@ -6,14 +6,25 @@ import * as gitlab from '../gitlab';
 import type { Preset, PresetConfig } from '../types';
 import * as local from './common';
 
+interface Resolver {
+  getPresetFromEndpoint(
+    repo: string,
+    filePreset: string,
+    presetPath?: string,
+    endpoint?: string,
+    tag?: string
+  ): Promise<Preset | undefined>;
+}
+
 const resolvers = {
   azure: local,
   bitbucket: local,
   'bitbucket-server': local,
+  codecommit: null,
   gitea,
   github,
   gitlab,
-} as const;
+} satisfies Record<PlatformId, Resolver | null>;
 
 export function getPreset({
   repo,
@@ -25,11 +36,10 @@ export function getPreset({
   if (!platform) {
     throw new Error(`Missing platform config for local preset.`);
   }
-  const resolver = resolvers[platform.toLowerCase() as PlatformId];
+  const resolver = resolvers[platform];
   if (!resolver) {
     throw new Error(
-      // TODO: can be undefined? #7154
-      `Unsupported platform '${platform}' for local preset.`
+      `The platform you're using ($platform) does not support local presets.`
     );
   }
   return resolver.getPresetFromEndpoint(
diff --git a/lib/constants/platforms.ts b/lib/constants/platforms.ts
index dfd4d3e4b39c7dd415a2db08e15bbb564bef4c9d..07a3094ef50a3b42cbe249922be200f7b15b1931 100644
--- a/lib/constants/platforms.ts
+++ b/lib/constants/platforms.ts
@@ -1,5 +1,6 @@
 export type PlatformId =
   | 'azure'
+  | 'codecommit'
   | 'bitbucket'
   | 'bitbucket-server'
   | 'gitea'
diff --git a/lib/modules/manager/gomod/artifacts.ts b/lib/modules/manager/gomod/artifacts.ts
index 831db23a21aaa942d586828fa9b10902a8226411..e42a57a6aa7ff66d2b3723ad88902b8f50590594 100644
--- a/lib/modules/manager/gomod/artifacts.ts
+++ b/lib/modules/manager/gomod/artifacts.ts
@@ -1,6 +1,7 @@
 import is from '@sindresorhus/is';
 import upath from 'upath';
 import { GlobalConfig } from '../../../config/global';
+import type { PlatformId } from '../../../constants';
 import { TEMPORARY_ERROR } from '../../../constants/error-messages';
 import { logger } from '../../../logger';
 import type { HostRule } from '../../../types';
@@ -61,7 +62,7 @@ function getGitEnvironmentVariables(): NodeJS.ProcessEnv {
     'gitea',
     'github',
     'gitlab',
-  ]);
+  ] satisfies PlatformId[]);
 
   // for each hostRule without hostType we add additional authentication variables to the environmentVariables
   for (const hostRule of hostRules) {
diff --git a/lib/modules/platform/api.ts b/lib/modules/platform/api.ts
index 3a0a16e3da3528c0dd03d7913776b5fd1eda0ac5..e135592568620d55f03cdc7591424758a13b31fa 100644
--- a/lib/modules/platform/api.ts
+++ b/lib/modules/platform/api.ts
@@ -1,3 +1,4 @@
+import type { PlatformId } from '../../constants';
 import * as azure from './azure';
 import * as bitbucket from './bitbucket';
 import * as bitbucketServer from './bitbucket-server';
@@ -7,7 +8,7 @@ import * as github from './github';
 import * as gitlab from './gitlab';
 import type { Platform } from './types';
 
-const api = new Map<string, Platform>();
+const api = new Map<PlatformId, Platform>();
 export default api;
 
 api.set('azure', azure);
diff --git a/lib/modules/platform/gitea/index.md b/lib/modules/platform/gitea/index.md
index c883172144548fca66937276600f870b003b7ad6..e1784f377b5c3a1b83b798494616441c33f34559 100644
--- a/lib/modules/platform/gitea/index.md
+++ b/lib/modules/platform/gitea/index.md
@@ -1,8 +1,6 @@
 # Gitea
 
-Renovate uses modern Git upload filters to suppress large blob downloads.
-For Gitea you need to manually enable upload filters.
-Read the official [Gitea docs](https://docs.gitea.io/en-us/clone-filters/) for more information.
+Renovate supports [Gitea](https://gitea.io).
 
 ## Authentication
 
@@ -18,8 +16,9 @@ Either the account should have full name and email address set to allow Renovate
 
 ## Unsupported platform features/concepts
 
-- **Adding reviewers to PRs not supported**: Gitea versions older than v1.14.0 do not have the required API.
+- **Adding reviewers to PRs not supported**: Gitea versions older than `v1.14.0` do not have the required API.
 - **Setting `platformAutomerge` to use platform-native automerge for PRs not supported**: Gitea versions older than v1.17.0 do not have the required API.
+- **Git upload filters**: If you're using a Gitea version older than `v1.16.0` then you must enable [clone filters](https://docs.gitea.io/en-us/clone-filters/).
 
 ## Features awaiting implementation
 
diff --git a/lib/modules/platform/index.ts b/lib/modules/platform/index.ts
index be1315a76b88360ad8d7fcd7260a230fcac76f16..16f9b937cd3159171b5bf3e79365ec7664cb8504 100644
--- a/lib/modules/platform/index.ts
+++ b/lib/modules/platform/index.ts
@@ -1,5 +1,6 @@
 import URL from 'url';
 import type { AllConfig } from '../../config/types';
+import type { PlatformId } from '../../constants';
 import { PLATFORM_NOT_FOUND } from '../../constants/error-messages';
 import { logger } from '../../logger';
 import type { HostRule } from '../../types';
@@ -26,7 +27,7 @@ const handler: ProxyHandler<Platform> = {
 
 export const platform = new Proxy<Platform>({} as any, handler);
 
-export function setPlatformApi(name: string): void {
+export function setPlatformApi(name: PlatformId): void {
   if (!platforms.has(name)) {
     throw new Error(
       `Init: Platform "${name}" not found. Must be one of: ${getPlatformList().join(