/// <summary>
        /// Adds all core Umbraco services required to run which may be replaced later in the pipeline
        /// </summary>
        public static IUmbracoBuilder AddCoreInitialServices(this IUmbracoBuilder builder)
        {
            builder
            .AddMainDom()
            .AddLogging();

            builder.Services.AddSingleton <IUmbracoDatabaseFactory, UmbracoDatabaseFactory>();
            builder.Services.AddSingleton(factory => factory.GetRequiredService <IUmbracoDatabaseFactory>().CreateDatabase());
            builder.Services.AddSingleton(factory => factory.GetRequiredService <IUmbracoDatabaseFactory>().SqlContext);
            builder.NPocoMappers().Add <NullableDateMapper>();
            builder.PackageMigrationPlans().Add(() => builder.TypeLoader.GetPackageMigrationPlans());

            builder.Services.AddSingleton <IRuntimeState, RuntimeState>();
            builder.Services.AddSingleton <IRuntime, CoreRuntime>();
            builder.Services.AddSingleton <PendingPackageMigrations>();
            builder.AddNotificationAsyncHandler <RuntimeUnattendedInstallNotification, UnattendedInstaller>();
            builder.AddNotificationAsyncHandler <RuntimeUnattendedUpgradeNotification, UnattendedUpgrader>();

            // composers
            builder
            .AddRepositories()
            .AddServices()
            .AddCoreMappingProfiles()
            .AddFileSystems()
            .AddWebAssets();

            // register persistence mappers - required by database factory so needs to be done here
            // means the only place the collection can be modified is in a runtime - afterwards it
            // has been frozen and it is too late
            builder.Mappers().AddCoreMappers();

            // register the scope provider
            builder.Services.AddSingleton <ScopeProvider>(); // implements both IScopeProvider and IScopeAccessor
            builder.Services.AddSingleton <IScopeProvider>(f => f.GetRequiredService <ScopeProvider>());
            builder.Services.AddSingleton <IScopeAccessor>(f => f.GetRequiredService <ScopeProvider>());
            builder.Services.AddScoped <IHttpScopeReference, HttpScopeReference>();

            builder.Services.AddSingleton <IJsonSerializer, JsonNetSerializer>();
            builder.Services.AddSingleton <IConfigurationEditorJsonSerializer, ConfigurationEditorJsonSerializer>();
            builder.Services.AddSingleton <IMenuItemCollectionFactory, MenuItemCollectionFactory>();

            // register database builder
            // *not* a singleton, don't want to keep it around
            builder.Services.AddTransient <DatabaseBuilder>();

            // register manifest parser, will be injected in collection builders where needed
            builder.Services.AddSingleton <IManifestParser, ManifestParser>();

            // register the manifest filter collection builder (collection is empty by default)
            builder.ManifestFilters();

            builder.MediaUrlGenerators()
            .Add <FileUploadPropertyEditor>()
            .Add <ImageCropperPropertyEditor>();

            builder.Services.AddSingleton <IPublishedContentTypeFactory, PublishedContentTypeFactory>();

            builder.Services.AddSingleton <IShortStringHelper>(factory
                                                               => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(factory.GetRequiredService <IOptions <RequestHandlerSettings> >().Value)));

            builder.Services.AddSingleton <IMigrationPlanExecutor, MigrationPlanExecutor>();
            builder.Services.AddSingleton <IMigrationBuilder>(factory => new MigrationBuilder(factory));

            builder.AddPreValueMigrators();

            builder.Services.AddSingleton <IPublishedSnapshotRebuilder, PublishedSnapshotRebuilder>();

            // register the published snapshot accessor - the "current" published snapshot is in the umbraco context
            builder.Services.AddSingleton <IPublishedSnapshotAccessor, UmbracoContextPublishedSnapshotAccessor>();

            builder.Services.AddSingleton <IVariationContextAccessor, HybridVariationContextAccessor>();

            // Config manipulator
            builder.Services.AddSingleton <IConfigManipulator, JsonConfigManipulator>();

            builder.Services.AddSingleton <RichTextEditorPastedImages>();
            builder.Services.AddSingleton <BlockEditorConverter>();

            // both TinyMceValueConverter (in Core) and RteMacroRenderingValueConverter (in Web) will be
            // discovered when CoreBootManager configures the converters. We will remove the basic one defined
            // in core so that the more enhanced version is active.
            builder.PropertyValueConverters()
            .Remove <SimpleTinyMceValueConverter>();

            // register *all* checks, except those marked [HideFromTypeFinder] of course
            builder.Services.AddSingleton <IMarkdownToHtmlConverter, MarkdownToHtmlConverter>();

            builder.Services.AddSingleton <IContentLastChanceFinder, ContentFinderByConfigured404>();

            builder.Services.AddScoped <UmbracoTreeSearcher>();

            // replace
            builder.Services.AddSingleton <IEmailSender, EmailSender>(
                services => new EmailSender(
                    services.GetRequiredService <ILogger <EmailSender> >(),
                    services.GetRequiredService <IOptions <GlobalSettings> >(),
                    services.GetRequiredService <IEventAggregator>(),
                    services.GetService <INotificationHandler <SendEmailNotification> >(),
                    services.GetService <INotificationAsyncHandler <SendEmailNotification> >()));

            builder.Services.AddSingleton <IExamineManager, ExamineManager>();

            builder.Services.AddScoped <ITagQuery, TagQuery>();

            builder.Services.AddSingleton <IUmbracoTreeSearcherFields, UmbracoTreeSearcherFields>();
            builder.Services.AddSingleton <IPublishedContentQueryAccessor, PublishedContentQueryAccessor>();
            builder.Services.AddScoped <IPublishedContentQuery>(factory =>
            {
                var umbCtx         = factory.GetRequiredService <IUmbracoContextAccessor>();
                var umbracoContext = umbCtx.GetRequiredUmbracoContext();
                return(new PublishedContentQuery(umbracoContext.PublishedSnapshot, factory.GetRequiredService <IVariationContextAccessor>(), factory.GetRequiredService <IExamineManager>()));
            });

            // register accessors for cultures
            builder.Services.AddSingleton <IDefaultCultureAccessor, DefaultCultureAccessor>();

            builder.Services.AddSingleton <IFilePermissionHelper, FilePermissionHelper>();

            builder.Services.AddSingleton <IUmbracoComponentRenderer, UmbracoComponentRenderer>();

            builder.Services.AddSingleton <IBackOfficeExamineSearcher, NoopBackOfficeExamineSearcher>();

            builder.Services.AddSingleton <UploadAutoFillProperties>();

            builder.Services.AddSingleton <ICronTabParser, NCronTabParser>();

            // Add default ImageSharp configuration and service implementations
            builder.Services.AddSingleton(SixLabors.ImageSharp.Configuration.Default);
            builder.Services.AddSingleton <IImageDimensionExtractor, ImageSharpDimensionExtractor>();
            builder.Services.AddSingleton <IImageUrlGenerator, ImageSharpImageUrlGenerator>();

            builder.Services.AddSingleton <PackageDataInstallation>();

            builder.AddInstaller();

            // Services required to run background jobs (with out the handler)
            builder.Services.AddSingleton <IBackgroundTaskQueue, BackgroundTaskQueue>();

            return(builder);
        }