一键导入
sitecore-classic
Apply when working with Sitecore 10.x projects, Helix architecture, MVC renderings, or Sitecore APIs
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Apply when working with Sitecore 10.x projects, Helix architecture, MVC renderings, or Sitecore APIs
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
C# backend patterns for Optimizely CMS projects
Modern frontend patterns for headless Optimizely CMS (React, Next.js)
Razor view patterns for Optimizely CMS projects
Optimizely Content Cloud (DXP) and headless API patterns
Core Optimizely CMS development patterns and best practices
Modern frontend patterns for Optimizely Experimentation
| name | sitecore-classic |
| description | Apply when working with Sitecore 10.x projects, Helix architecture, MVC renderings, or Sitecore APIs |
| globs | ["**/*.cshtml","**/App_Config/**/*.config","**/*.module.json","**/code/**/*.cs","**/sitecore.json","**/*.scss","**/*.css","**/scripts/**/*.js","**/js/**/*.js"] |
This plugin includes the following additional skills for comprehensive development context:
| Skill | Purpose |
|---|---|
frontend-classic | CSS/SASS organization, JavaScript/jQuery patterns, BEM naming |
frontend-razor | Razor view syntax, layouts, partials, tag helpers |
backend-csharp | C#/.NET DI patterns, service architecture, async/await |
fullstack-classic | jQuery AJAX integration, form handling, anti-forgery tokens |
These skills are automatically included when you install the Sitecore Classic Analyzer plugin.
Foundation Layer
Feature Layer
Project Layer
Project → Feature → Foundation
Features must NEVER reference other Features. If shared logic is needed, extract to Foundation.
src/
├── Foundation/
│ └── {Module}/
│ ├── code/
│ │ ├── DependencyInjection/
│ │ ├── Services/
│ │ └── Foundation.{Module}.csproj
│ └── serialization/
│ └── {Module}.module.json
├── Feature/
│ └── {Module}/
│ ├── code/
│ │ ├── Controllers/
│ │ ├── Models/
│ │ ├── Services/
│ │ ├── Repositories/
│ │ └── Feature.{Module}.csproj
│ └── serialization/
│ ├── Templates/
│ ├── Renderings/
│ └── {Module}.module.json
└── Project/
└── {Site}/
├── code/
│ ├── Layouts/
│ └── Project.{Site}.csproj
└── serialization/
├── Content/
└── {Site}.module.json
using Microsoft.Extensions.DependencyInjection;
using Sitecore.DependencyInjection;
public class RegisterDependencies : IServicesConfigurator
{
public void Configure(IServiceCollection services)
{
// Transient: New instance each time
services.AddTransient<ISearchService, SearchService>();
// Scoped: One instance per HTTP request
services.AddScoped<INavigationService, NavigationService>();
// Singleton: One instance for application lifetime
services.AddSingleton<ICacheService, CacheService>();
}
}
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<services>
<configurator type="Foundation.DI.RegisterDependencies, Foundation.DI" />
</services>
</sitecore>
</configuration>
public class NavigationController : Controller
{
private readonly INavigationService _navigationService;
private readonly ILogger<NavigationController> _logger;
public NavigationController(
INavigationService navigationService,
ILogger<NavigationController> logger)
{
_navigationService = navigationService;
_logger = logger;
}
public ActionResult Index()
{
var datasource = RenderingContext.Current.Rendering.Item;
if (datasource == null)
{
_logger.LogWarning("Navigation datasource is null");
return new EmptyResult();
}
var model = _navigationService.GetNavigation(datasource);
return View(model);
}
}
public class SearchRepository : ISearchRepository
{
private readonly ISearchIndex _index;
public SearchRepository(ISearchIndexResolver indexResolver)
{
_index = indexResolver.GetIndex("sitecore_web_index");
}
public IEnumerable<ArticleSearchResult> GetArticles(
ID templateId,
string language,
int maxResults = 100)
{
using (var context = _index.CreateSearchContext())
{
return context.GetQueryable<ArticleSearchResult>()
.Where(x => x.TemplateId == templateId)
.Where(x => x.Language == language)
.OrderByDescending(x => x.Created)
.Take(maxResults)
.ToList();
}
}
}
// BAD - Tree traversal, O(n) where n = tree size
var items = item.Axes.SelectItems(".//*[@@templateid='{GUID}']");
// BAD - Even "fast:" queries traverse the tree
var items = Database.SelectItems("fast:/sitecore/content//*");
// GOOD - Use Content Search instead
var items = searchContext.GetQueryable<SearchResultItem>()
.Where(x => x.TemplateId == templateId)
.ToList();
// BAD - Loads entire subtree into memory
var allItems = rootItem.GetDescendants().ToList();
// GOOD - Use Content Search with path filter
var items = searchContext.GetQueryable<SearchResultItem>()
.Where(x => x.Paths.Contains(rootItem.ID))
.Take(1000)
.ToList();
Configure in rendering item or config:
<r>
<d id="{FE5D7FDF-89C0-4D99-9AA3-B5FBD009C9F3}">
<r uid="{RENDERING-UID}"
s:caching="1"
s:varybydata="1"
s:varybydevice="0"
s:varybylogin="0"
s:varybyuser="0"
s:varybyquerystirng="0"
s:timeout="01:00:00" />
</d>
</r>
public class NavigationCache : CustomCache
{
public NavigationCache(string name, long maxSize)
: base(name, maxSize)
{
}
public NavigationModel Get(string cacheKey)
{
return GetObject<NavigationModel>(cacheKey);
}
public void Set(string cacheKey, NavigationModel model, TimeSpan duration)
{
SetObject(cacheKey, model, duration);
}
}
Register cache:
public class RegisterCaches : IServicesConfigurator
{
public void Configure(IServiceCollection services)
{
services.AddSingleton<NavigationCache>(provider =>
new NavigationCache("NavigationCache", StringUtil.ParseSizeString("50MB")));
}
}
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<settings>
<setting name="MySetting" value="MyValue" />
</settings>
</sitecore>
</configuration>
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"
xmlns:env="http://www.sitecore.net/xmlconfig/env/">
<sitecore>
<settings>
<!-- Only in Production -->
<setting name="Analytics.Enabled" env:require="Production">
<patch:attribute name="value">true</patch:attribute>
</setting>
<!-- Only in Development -->
<setting name="Analytics.Enabled" env:require="Development">
<patch:attribute name="value">false</patch:attribute>
</setting>
</settings>
</sitecore>
</configuration>
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"
xmlns:role="http://www.sitecore.net/xmlconfig/role/">
<sitecore>
<settings>
<!-- Only on Content Management servers -->
<setting name="Preview.Enabled" role:require="ContentManagement">
<patch:attribute name="value">true</patch:attribute>
</setting>
<!-- Only on Content Delivery servers -->
<setting name="Preview.Enabled" role:require="ContentDelivery">
<patch:attribute name="value">false</patch:attribute>
</setting>
</settings>
</sitecore>
</configuration>
public class EnrichContextProcessor : HttpRequestProcessor
{
public override void Process(HttpRequestArgs args)
{
// Early exit for efficiency
if (Context.Item == null) return;
if (Context.Site == null) return;
if (Context.PageMode.IsExperienceEditor) return;
// Processor logic here
EnrichContext();
}
private void EnrichContext()
{
// Custom enrichment logic
}
}
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<httpRequestBegin>
<processor type="Feature.Context.EnrichContextProcessor, Feature.Context"
patch:after="processor[@type='Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel']" />
</httpRequestBegin>
</pipelines>
</sitecore>
</configuration>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<contentSearch>
<configuration>
<indexes>
<index id="custom_articles_index">
<configuration ref="contentSearch/indexConfigurations/defaultSolrIndexConfiguration">
<documentOptions>
<fields hint="raw:AddComputedIndexField">
<field fieldName="article_author" returnType="string">
Feature.Articles.ComputedFields.ArticleAuthor, Feature.Articles
</field>
<field fieldName="article_category" returnType="stringCollection">
Feature.Articles.ComputedFields.ArticleCategories, Feature.Articles
</field>
</fields>
</documentOptions>
</configuration>
</index>
</indexes>
</configuration>
</contentSearch>
</sitecore>
</configuration>
public class ArticleAuthor : IComputedIndexField
{
public string FieldName { get; set; }
public string ReturnType { get; set; }
public object ComputeFieldValue(IIndexable indexable)
{
var item = (indexable as SitecoreIndexableItem)?.Item;
if (item == null) return null;
var authorItem = item.GetReferenceField("Author")?.TargetItem;
return authorItem?["Name"];
}
}
{
"namespace": "Feature.Navigation",
"items": {
"includes": [
{
"name": "templates",
"path": "/sitecore/templates/Feature/Navigation",
"allowedPushOperations": "CreateUpdateAndDelete"
},
{
"name": "renderings",
"path": "/sitecore/layout/Renderings/Feature/Navigation",
"allowedPushOperations": "CreateUpdateAndDelete"
},
{
"name": "settings",
"path": "/sitecore/system/Settings/Feature/Navigation",
"allowedPushOperations": "CreateUpdateAndDelete"
}
]
}
}
# Pull items from Sitecore to disk
dotnet sitecore ser pull
# Push items from disk to Sitecore
dotnet sitecore ser push
# Validate serialization
dotnet sitecore ser validate
[SitecoreType(TemplateId = "{GUID}", AutoMap = true)]
public class ArticlePage
{
[SitecoreId]
public virtual Guid Id { get; set; }
[SitecoreField("Title")]
public virtual string Title { get; set; }
[SitecoreField("Content")]
public virtual string Content { get; set; }
[SitecoreField("Author")]
public virtual Author Author { get; set; }
[SitecoreChildren]
public virtual IEnumerable<RelatedArticle> RelatedArticles { get; set; }
}
public class ArticleService : IArticleService
{
private readonly ISitecoreService _sitecoreService;
public ArticleService(ISitecoreService sitecoreService)
{
_sitecoreService = sitecoreService;
}
public ArticlePage GetArticle(Guid id)
{
return _sitecoreService.GetItem<ArticlePage>(id);
}
}
// BAD - N+1 queries with lazy loading
foreach (var article in articles)
{
var author = article.Author; // Lazy load for each article
}
// GOOD - Eager load or use Content Search
var articleIds = articles.Select(a => a.Id).ToList();
var authors = searchContext.GetQueryable<AuthorSearchResult>()
.Where(x => articleIds.Contains(x.ArticleId))
.ToList();