Themes take a crucial part while building an app with ScissorHands.NET. It looks after all UI including the landing page, blog posts and pages. Since ScissorHands.NET uses the Blazor's Razor syntax, you can easily build page components and UI components for your theme.
Theme Template – Starter Pack
If you're unsure, you can start from the theme template repository. It includes all the basic page components including _Imports.razor, MainLayout.razor, IndexView.razor, PostView.razor and PageView.razor as well as theme.json that describes the metadata of the theme.
Theme Structure
Each theme has at least the following structure:
.
├── README.md
│
└── src/
├── theme.json
│
├── favicon.ico
│
├── assets/
│ ├── css/
│ │ └── theme.css
│ ├── js/
│ │ └── theme.js
│ └── images/
│ └── theme.png
│
├── _Imports.razor
├── MainLayout.razor
├── IndexView.razor
├── PostView.razor
├── PageView.razor
└── NotFoundView.razor
README.md: README document of the themesrc/theme.json: Theme metadatasrc/favicon.ico: Faviconsrc/assets/css/*.css: CSS files used in the themesrc/assets/js/*.js: JavaScript files used in the themesrc/assets/images/*: Image files used in the themesrc/_Imports.razor: Defines global using directivessrc/MainLayout.razor: Defines the main layoutsrc/IndexView.razor: Defines the landing page view layoutsrc/PostView.razor: Defines blog post view layoutsrc/PageView.razor: Defines page view layoutsrc/NotFoundView.razor: Defines 404 (not found) page view layout
theme.json
theme.json declares the metadata of the theme used by ScissorHands.NET app.
{
"name": "Theme Template",
"version": "1.0.0",
"description": "A theme template for ScissorHands.NET",
"slug": "theme-template",
"stylesheets": [
"/assets/css/theme.css"
],
"scripts": [
"/assets/js/theme.js"
]
}
name: Name of the theme.version: Version of the theme.description: Theme description.slug: Slug of the theme. This MUST be equal to theThemevalue of the site configuration.stylesheets: The list of CSS files used in the theme.scripts: The list of JavaScript files used in the theme.
_Imports.razor
_Imports.razor declares the global using directives and the namespace of the theme.
MainLayout.razor
MainLayout.razor defines the overall layout of the theme. It calls the other view files like IndexView.razor, PostView.razor and PageView.razor as well as other UI components defined in the theme. It MUST declare inheritance of ScissorHands.Theme.MainLayoutBase by adding @inherits ScissorHands.Theme.MainLayoutBase.
Properties of MainLayout.razor
Since MainLayout.razor inherits ScissorHands.Theme.MainLayoutBase, it exposes the following properties for theme developers to use:
PageTitle: Calculated page title byCalculatePageTitle()PageDescription: Calculated page description byCalculatePageDescription()PageLocale: Calculated page locale byCalculatePageLocale()Documents: Parameter. List of content documents – used byIndexView.razorDocument: Parameter. Content document – used byPostView.razorandPageView.razorPlugins: Parameter. List of plugins defined in the Plugins section ofappsettings.jsonTheme: Parameter. Theme configuration defined intheme.jsonSite: Parameter. Site configuration defined in the Site section ofappsettings.json
These properties are passed to IndexView.razor, PostView.razor, PageView.razor and UI components as cascading parameters.
Methods for Overriding
Both PageTitle and PageDescription property values are calculated from the methods, CalculatePageTitle() and CalculatePageDescription() respectively. You can override these two methods to change the property values.
CalculatePageTitle()
protected virtual string CalculatePageTitle()
{
var title = Site?.Title;
if (Document is not null && string.IsNullOrWhiteSpace(Document.Metadata.Title) == false)
{
title = $"{Document.Metadata.Title} | {title}";
}
return title ?? string.Empty;
}
CalculatePageDescription()
protected virtual string CalculatePageDescription()
{
var description = Site?.Description ?? string.Empty;
if (Document is not null && string.IsNullOrWhiteSpace(Document.Metadata.Description) == false)
{
description = Document.Metadata.Description;
}
return description ?? string.Empty;
}
CalculatePageLocale()
protected virtual string CalculatePageLocale()
{
var locale = Site?.Locale ?? string.Empty;
if (Document is not null && string.IsNullOrWhiteSpace(Document.Metadata.Locale) == false)
{
locale = Document.Metadata.Locale;
}
return locale.ToLowerInvariant() ?? string.Empty;
}
IndexView.razor
IndexView.razor describes the landing page view. It also calls other UI components defined in the theme. It MUST declare inheritance of ScissorHands.Theme.IndexViewBase by adding @inherits ScissorHands.Theme.IndexViewBase.
Properties of IndexView.razor
Since IndexView.razor inherits ScissorHands.Theme.IndexViewBase, it exposes the following properties for theme developers to use:
Documents: Cascading Parameter. List of content documents – used byIndexView.razorPlugins: Cascading Parameter. List of plugins defined in the Plugins section ofappsettings.jsonTheme: Cascading Parameter. Theme configuration defined intheme.jsonSite: Cascading Parameter. Site configuration defined in the Site section ofappsettings.json
These properties are passed from MainLayout.razor as cascading parameters.
PostView.razor
PostView.razor describes the blog post view. It also calls other UI components defined in the theme. It MUST declare inheritance of ScissorHands.Theme.PostViewBase by adding @inherits ScissorHands.Theme.PostViewBase.
Properties of PostView.razor
Since PostView.razor inherits ScissorHands.Theme.PostViewBase, it exposes the following properties for theme developers to use:
Document: Cascading Parameter. Content document – used byPostView.razorPlugins: Cascading Parameter. List of plugins defined in the Plugins section ofappsettings.jsonTheme: Cascading Parameter. Theme configuration defined intheme.jsonSite: Cascading Parameter. Site configuration defined in the Site section ofappsettings.json
These properties are passed from MainLayout.razor as cascading parameters.
PageView.razor
PageView.razor describes the page view. It also calls other UI components defined in the theme. It MUST declare inheritance of ScissorHands.Theme.PageViewBase by adding @inherits ScissorHands.Theme.PageViewBase.
Properties of PageView.razor
Since PageView.razor inherits ScissorHands.Theme.PageViewBase, it exposes the following properties for theme developers to use:
Document: Cascading Parameter. Content document – used byPageView.razorPlugins: Cascading Parameter. List of plugins defined in the Plugins section ofappsettings.jsonTheme: Cascading Parameter. Theme configuration defined intheme.jsonSite: Cascading Parameter. Site configuration defined in the Site section ofappsettings.json
These properties are passed from MainLayout.razor as cascading parameters.
NotFoundView.razor
NotFoundView.razor describes the 404 page view. It also calls other UI components defined in the theme. It MUST declare inheritance of ScissorHands.Theme.NotFoundViewBase by adding @inherits ScissorHands.Theme.NotFoundViewBase.
Properties of NotFoundView.razor
Since NotFoundView.razor inherits ScissorHands.Theme.NotFoundViewBase, it exposes the following properties for theme developers to use:
Document: Cascading Parameter. Content document – used byNotFoundView.razorPlugins: Cascading Parameter. List of plugins defined in the Plugins section ofappsettings.jsonTheme: Cascading Parameter. Theme configuration defined intheme.jsonSite: Cascading Parameter. Site configuration defined in the Site section ofappsettings.json
These properties are passed from MainLayout.razor as cascading parameters.
Additional UI Components
In addition to the mandatory page layout components – MainLayout, IndexView, PostView, PageView and NotFoundView, you can add as many UI component as you want. Here's a very simple component you can write up:
@* Component: `AdditionalComponent.razor` *@
@namespace MyAwesomeTheme.Components
<div class="@CssClass">
<p>This is an additional component.</p>
</div>
@code {
[Parameter]
public string? CssClass { get; set; }
[CascadingParameter]
public IEnumerable<ContentDocument>? Documents { get; set; }
[CascadingParameter]
public ContentDocument? Document { get; set; }
[CascadingParameter]
public IEnumerable<PluginManifest>? Plugins { get; set; }
[CascadingParameter]
public ThemeManifest? Theme { get; set; }
[CascadingParameter]
public SiteManifest? Site { get; set; }
}
Then, place this component wherever you like. Make sure that Documents, Document, Plugins, Theme and Site properties are cascading parameters. Therefore, you only need to pass CssClass value in this example. Here's an example of using this component in IndexView.razor:
@* View: `IndexView.razor` *@
@inherits ScissorHands.Theme.IndexViewBase
@layout MainLayout
<section class="home">
<AdditionalComponent CssClass="additional-component" />
...
</section>
List of Themes
Here are the list of themes you can currently use – either official or community contributed.
Official Themes
Community Themes
TBD
👈 Front Matter | 👆 Documentation | Plugins 👉