Overview
In Fess 15.9, the search screen is always a static theme. A static theme is an independent SPA (Single Page Application) that uses the /api/v2/* API. Themes are distributed as ZIP files, uploaded through the admin console, and enabled there. When no theme is selected, Fess uses bootstrap, the static theme bundled with it.
To change how the search screen looks, either install another theme (see Theme) or make your own: the quickest way is to copy the bundled theme and change the copy, as described in Customizing the Bundled Theme.
Note
Static themes are available in Fess 15.7 and later, and became the default search screen in 15.9. JAR theme plugins, which replaced the JSPs of the search screen, were removed in 15.9; see JAR Theme Plugin (Removed in 15.9).
Static Theme
A static theme is a collection of static resources that includes a theme.yml manifest and index.html. Implement the theme itself as a front-end application that calls the Fess /api/v2/* API.
Structure
A static theme has the following directory structure.
Manifest (theme.yml)
theme.yml is a required manifest placed at the root of the ZIP file. The following is an example of a minimal configuration.
The fields that can be specified are as follows.
| Field | Required | Description |
|---|---|---|
apiVersion | Required | Fixed value fess.codelibs.org/v1. |
kind | Required | Fixed value StaticTheme. |
name | Required | The theme name. Must match |
displayName | Required | The name displayed in the admin console. |
version | Required | Semantic versioning format (e.g., |
author | Optional | The author’s name. |
description | Optional | A description of the theme. |
license | Optional | The license. |
homepage | Optional | The homepage URL. |
minFessVersion | Optional | The minimum Fess version the theme supports. Keep it equal to the |
supportedLocales | Optional | A list of supported locales (e.g., [en, ja, de]). |
entry | Optional | The SPA entry HTML. Defaults to index.html. |
spaFallback | Optional | Deprecated. Accepted for compatibility but no longer read: since 15.9 the entry HTML is always served for the search screen paths. |
Note
When uploading via ZIP, the destination directory name is determined automatically from name. If you place a theme manually in the themes/ directory, make sure the directory name matches name. Themes whose directory name does not match are ignored on rescan.
Note
The preview thumbnail is placed at the root of the theme with the fixed name thumbnail.png (it is displayed in the theme list in the admin console). This image is recognized by its file name, not by a manifest field. A size of 512KB or less and 512x512 pixels or less is recommended.
Serving and API
A static theme is served under
/themes/<name>/(<name>is thenameintheme.yml).The entry HTML (
index.htmlby default) is returned for the paths/,/search,/advance,/help,/error,/profile,/cache, and/chat, and subsequent routing is handled by the SPA. Since 15.9 this happens whateverspaFallbacksays; the field is no longer read.Errors are rendered by the theme as well: when a request fails, a browser receives the theme’s entry HTML at the requested URL, with the real HTTP status.
The admin console (
/admin/*),/api/*, the login screen, and similar are not covered by the static theme and are handled by the Fess core.{{themePath}}in the entry HTML is replaced withthemes/<name>when the page is served. Refer to the theme’s own files fromindex.htmlas{{themePath}}/assets/styles.cssand so on. The theme name is then not written into the page, so the theme loads its own files under whatever name it is installed.The entry HTML is served with a
Content-Security-Policyheader that allows scripts, styles, images and connections only from Fess itself (inline styles are allowed; inline scripts are not). Fonts or scripts from an external CDN are therefore not loaded; ship them in the theme.The
Content-Security-Policyof the entry HTML containsframe-ancestors 'none', and the response also carriesX-Frame-Options: DENY, so the page is not shown in a frame of another page. Theframe-ancestorsvalue can be changed withtheme.index.frame.ancestorsinfess_config.properties(default:'none'). An empty value dropsframe-ancestors(X-Frame-Options: DENYis still sent). Underframe-ancestors 'none', WebKit-based browsers such as Safari leave blank the frames that a theme shows from ablob:URL (a PDF preview or a cached copy). Set the value to empty to show them.The theme’s SPA retrieves data such as search results and chat from the
/api/v2/*API.
Packaging
Using scripts/package.sh from the fess-themes repository, you can package a theme into a ZIP for distribution.
dist/example-<version>.zip is generated (<version> is the version in theme.yml).
Note
theme.yml must be placed at the root of the ZIP. If it is placed in a subdirectory, it will not be recognized when uploaded.
Publishing
The themes the Fess project develops are published under https://maven.codelibs.org/release/org/codelibs/fess/themes/ , at <name>/<version>/<name>-<version>.zip with a .sha1 beside it, and a per-theme maven-metadata.xml listing the published versions. bin/fess-setup install theme <name> reads that metadata to pick the version built for the running Fess.
Version a theme on the Fess line it targets and raise the version whenever you change what the archive ships. A published version is never overwritten, so a change that keeps its version is simply never distributed.
This is also why there is no upper-bound field in the manifest. Because a published archive never changes, an upper bound could not be added later for a theme that stops working on a newer Fess. Not publishing that theme for the newer line says the same thing, at the point it is known.
Note
Enumerate the published versions from maven-metadata.xml rather than from a directory listing. The directory index is generated periodically, so a newly published theme is readable through its metadata before it appears in any listing.
Installation and Activation
In the admin console, open “System” -> “Theme” (
/admin/theme/).Upload the ZIP file you created. A published theme can instead be installed from the command line with
bin/fess-setup install theme <name>; see fess-setup Command.On the list page, select the target theme from the “Default Theme” drop-down and click the “Set” button to enable it.
The activation mechanism works as follows.
Clicking “Set” saves the selected theme name to the
theme.defaultsystem property, making it the system-wide default theme.If you match the theme name to a virtual host key, the theme is applied only when that virtual host is accessed. This lets you switch themes per virtual host.
If you update the
themes/directory on disk directly, you can rescan it with “Reload”.
Note
There are limits on ZIP uploads, such as file size, total size after extraction, and number of entries, which can be adjusted with the theme.* properties in fess_config.properties (for example, theme.upload.max.size defaults to 50MB, and theme.directory.path defaults to themes). During extraction, validation is performed to prevent ZIP Slip and zip bomb attacks.
Customizing the Bundled Theme
The bundled theme bootstrap is in app/themes/bootstrap/ of the Fess installation (/usr/share/fess/app/themes/bootstrap/ for the RPM/DEB packages). Do not edit it in place: an upgrade replaces it, and the name bootstrap is reserved for it, so it can be neither deleted nor replaced by an upload. Copy it under a new name instead.
Copy the directory, for example to
mytheme:In
theme.yml, changenametomythemeand changedisplayName.namemust match the directory name.Leave
index.htmlas it is. The bundledindex.htmlrefers to its own files, such as the stylesheet, the logos and the script, as{{themePath}}/assets/..., and Fess replaces{{themePath}}withthemes/<name>(thenameintheme.yml) when it serves the page. Renaming the copy is therefore enough for it to load its own files. When you add a file thatindex.htmlrefers to, write its URL as{{themePath}}/assets/...as well.Make your changes:
Colors and layout:
assets/styles.css.Logos:
assets/logo-head.png(header) andassets/logo.png(search top page).Texts, such as the footer (
footer.copyright_org): thei18n/messages.<locale>.jsonfiles, one per language.Page structure:
index.html.
Package the directory as a ZIP with
theme.ymlat its root, and upload it on “System” > “Theme” in the admin console:Alternatively, place the directory in
app/themes/and click “Reload” on the same page.Select
mythemeas the default theme on that page.
Note
Replace the copy with a fresh one from the bundled theme after each Fess upgrade and reapply your changes, as the bundled theme follows the /api/v2/* API of its Fess version.
JAR Theme Plugin (Removed in 15.9)
The JAR theme plugin type, which put JSPs, CSS and images in a fess-theme-* JAR and applied them as the theme named after a virtual host key, was removed in Fess 15.9. 15.9 does not extract a JAR theme and does not use it for any screen.
Installing one from “System” > “Plugin” in the admin UI only places it in
app/WEB-INF/plugin/as a generic JAR of typejar; no screen changes. Afess-theme-*.jarleft over from an earlier version is listed the same way, and can be deleted on that page or withbin/fess-setup remove plugin <name>.bin/fess-setupneither lists nor installsfess-theme-*.
Move the changes you made in a JAR theme to a static theme:
For the colors, layout and logo of the search screen, copy the bundled theme and change the copy (see Customizing the Bundled Theme).
If you changed the look per virtual host, install a static theme named after the virtual host (see Virtual Host).
The login screen (
/login/) is the same for every virtual host. A theme cannot change it.
Examples of Existing Themes
fess-themes - A collection of static themes (includes multiple static themes such as
codesearchanddocsearch)
Reference
Plugin Architecture - Plugin architecture
Plugin - Plugin installation