diff --git a/Directory.Packages.props b/Directory.Packages.props
index 8ee6b60..6c1d620 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -59,6 +59,7 @@
+
diff --git a/OrchardCoreContrib.Modules.slnx b/OrchardCoreContrib.Modules.slnx
index 237bedf..2def2b3 100644
--- a/OrchardCoreContrib.Modules.slnx
+++ b/OrchardCoreContrib.Modules.slnx
@@ -33,6 +33,7 @@
+
@@ -47,6 +48,7 @@
+
diff --git a/src/OrchardCoreContrib.Modules.Web/OrchardCoreContrib.Modules.Web.csproj b/src/OrchardCoreContrib.Modules.Web/OrchardCoreContrib.Modules.Web.csproj
index b1cfaf0..380117d 100644
--- a/src/OrchardCoreContrib.Modules.Web/OrchardCoreContrib.Modules.Web.csproj
+++ b/src/OrchardCoreContrib.Modules.Web/OrchardCoreContrib.Modules.Web.csproj
@@ -37,6 +37,7 @@
+
diff --git a/src/OrchardCoreContrib.Templating.Razor/Extensions/ServiceCollectionExtensions.cs b/src/OrchardCoreContrib.Templating.Razor/Extensions/ServiceCollectionExtensions.cs
new file mode 100644
index 0000000..6613cca
--- /dev/null
+++ b/src/OrchardCoreContrib.Templating.Razor/Extensions/ServiceCollectionExtensions.cs
@@ -0,0 +1,22 @@
+using OrchardCoreContrib.Templating;
+using OrchardCoreContrib.Templating.Razor.Services;
+
+namespace Microsoft.Extensions.DependencyInjection;
+
+///
+/// Provides extension methods for registering the Razor template engine services in an .
+///
+public static class ServiceCollectionExtensions
+{
+ ///
+ /// Registers the Razor template engine services in the specified .
+ ///
+ /// The to add the services to.
+ /// The updated .
+ public static IServiceCollection AddRazorTemplating(this IServiceCollection services)
+ {
+ services.AddSingleton();
+
+ return services;
+ }
+}
diff --git a/src/OrchardCoreContrib.Templating.Razor/Manifest.cs b/src/OrchardCoreContrib.Templating.Razor/Manifest.cs
new file mode 100644
index 0000000..6b631fc
--- /dev/null
+++ b/src/OrchardCoreContrib.Templating.Razor/Manifest.cs
@@ -0,0 +1,11 @@
+using OrchardCore.Modules.Manifest;
+using ManifestConstants = OrchardCoreContrib.Modules.Manifest.ManifestConstants;
+
+[assembly: Module(
+ Name = "Razor Templating",
+ Author = ManifestConstants.Author,
+ Website = ManifestConstants.Website,
+ Version = "1.0.0",
+ Description = "Provides Razor template engine integration.",
+ Category = "Templating"
+)]
diff --git a/src/OrchardCoreContrib.Templating.Razor/OrchardCoreContrib.Templating.Razor.csproj b/src/OrchardCoreContrib.Templating.Razor/OrchardCoreContrib.Templating.Razor.csproj
new file mode 100644
index 0000000..d9b6923
--- /dev/null
+++ b/src/OrchardCoreContrib.Templating.Razor/OrchardCoreContrib.Templating.Razor.csproj
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/OrchardCoreContrib.Templating.Razor/Services/RazorTemplateEngine.cs b/src/OrchardCoreContrib.Templating.Razor/Services/RazorTemplateEngine.cs
new file mode 100644
index 0000000..3632aab
--- /dev/null
+++ b/src/OrchardCoreContrib.Templating.Razor/Services/RazorTemplateEngine.cs
@@ -0,0 +1,33 @@
+using Microsoft.Extensions.Localization;
+using OrchardCoreContrib.Infrastructure;
+using RazorLight;
+
+namespace OrchardCoreContrib.Templating.Razor.Services;
+
+///
+/// Represents a template engine that uses the Razor templating language.
+///
+public class RazorTemplateEngine(IStringLocalizer S) : ITemplateEngine
+{
+ private readonly RazorLightEngine _engine = new RazorLightEngineBuilder()
+ .UseMemoryCachingProvider()
+ .Build();
+
+ ///
+ public async Task> RenderAsync(string template, TemplateContext context)
+ {
+ Guard.ArgumentNotNullOrEmpty(template, nameof(template));
+ Guard.ArgumentNotNull(context, nameof(context));
+
+ try
+ {
+ var result = await _engine.CompileRenderStringAsync(Guid.NewGuid().ToString(), template, context.Model);
+
+ return Result.Success(result);
+ }
+ catch (Exception ex)
+ {
+ return Result.Failed(S["Rendering razor template failed: {0}", ex.Message]);
+ }
+ }
+}
diff --git a/src/OrchardCoreContrib.Templating.Razor/Startup.cs b/src/OrchardCoreContrib.Templating.Razor/Startup.cs
new file mode 100644
index 0000000..35250bd
--- /dev/null
+++ b/src/OrchardCoreContrib.Templating.Razor/Startup.cs
@@ -0,0 +1,9 @@
+using Microsoft.Extensions.DependencyInjection;
+using OrchardCore.Modules;
+
+namespace OrchardCoreContrib.Templating.Liquid;
+
+public sealed class Startup : StartupBase
+{
+ public override void ConfigureServices(IServiceCollection services) => services.AddRazorTemplating();
+}
diff --git a/test/OrchardCoreContrib.Templating.Razor.Tests/Extensions/ServiceCollectionExtensionsTests.cs b/test/OrchardCoreContrib.Templating.Razor.Tests/Extensions/ServiceCollectionExtensionsTests.cs
new file mode 100644
index 0000000..4a421fd
--- /dev/null
+++ b/test/OrchardCoreContrib.Templating.Razor.Tests/Extensions/ServiceCollectionExtensionsTests.cs
@@ -0,0 +1,28 @@
+using Microsoft.Extensions.DependencyInjection;
+using OrchardCoreContrib.Templating.Razor.Services;
+
+namespace OrchardCoreContrib.Templating.Razor.Tests.Extensions;
+
+public class ServiceCollectionExtensionsTests
+{
+ [Fact]
+ public void AddRazorTemplating_RegistersRazorTemplateEngineAsSingleton()
+ {
+ // Arrange
+ var services = new ServiceCollection()
+ .AddLogging()
+ .AddLocalization();
+
+ // Act
+ services.AddRazorTemplating();
+
+ // Assert
+ using var provider = services.BuildServiceProvider();
+
+ var first = provider.GetRequiredService();
+ var second = provider.GetRequiredService();
+
+ Assert.IsType(first);
+ Assert.Same(first, second);
+ }
+}
diff --git a/test/OrchardCoreContrib.Templating.Razor.Tests/OrchardCoreContrib.Templating.Razor.Tests.csproj b/test/OrchardCoreContrib.Templating.Razor.Tests/OrchardCoreContrib.Templating.Razor.Tests.csproj
new file mode 100644
index 0000000..b3cd9f6
--- /dev/null
+++ b/test/OrchardCoreContrib.Templating.Razor.Tests/OrchardCoreContrib.Templating.Razor.Tests.csproj
@@ -0,0 +1,32 @@
+
+
+
+ true
+ false
+ true
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/OrchardCoreContrib.Templating.Razor.Tests/Services/RazorTemplateEngineTests.cs b/test/OrchardCoreContrib.Templating.Razor.Tests/Services/RazorTemplateEngineTests.cs
new file mode 100644
index 0000000..66cd967
--- /dev/null
+++ b/test/OrchardCoreContrib.Templating.Razor.Tests/Services/RazorTemplateEngineTests.cs
@@ -0,0 +1,51 @@
+using Microsoft.Extensions.Localization;
+using Moq;
+
+namespace OrchardCoreContrib.Templating.Razor.Services.Tests;
+
+public class RazorTemplateEngineTests
+{
+ private readonly RazorTemplateEngine _templateEngine;
+
+ public RazorTemplateEngineTests()
+ {
+ var stringLocalizerMock = new Mock>();
+
+ stringLocalizerMock.Setup(localizer => localizer[It.IsAny()])
+ .Returns((string k) => new LocalizedString(k, k));
+
+ stringLocalizerMock.Setup(localizer => localizer[It.IsAny(), It.IsAny