Introduction

Themes can be used to customize the look and feel of any aspect of an
ownCloud installation. They can override the default JavaScript,
CSS, image, and template files, as well as the user interface
translations with custom versions.
They can also affect both the web front-end and the ownCloud Desktop client.
However, this documentation only covers customizing the web front-end, so far.

Before ownCloud 10, theming was done via the config.php entry 'theme' ⇒ ''.
This is deprecated in ownCloud 10.
Users who have this entry in their config.php should remove it and use a theme app to customize their ownCloud instance instead.

Here are 7 commands to get a theme quickly:
(adjust the names and paths accordingly)

Throughout this section of the documentation, for sakes of simplicity,
it will be assumed that your owncloud installation directory is
/owncloud. If you’re following this guide to create or customise a
theme, please make sure you change any references to match the location
of your owncloud installation.

To save you time and effort, you can use the shell script below, to
create the basis of a new theme from ownCloud’s example theme.

Using this script (and the following one, read-config.php), you will have a new theme, ready to go, in less than
five seconds.
You can execute this script with two variables; the first one is the theme name and the second one is your ownCloud directory.

For example:

theme-bootstrap.sh mynewtheme /var/www/owncloud

Don’t forget to create read-config.php from the included code below, before you attempt to run
theme-bootstrap.sh, otherwise theme-bootstrap.sh will fail.

#!/usr/bin/php
<?php
/**
* @author Matthew Setter <matthew@matthewsetter.com> & Martin Mattel <github@diemattels.at>
* @copyright Copyright (c) 2018, ownCloud GmbH
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
/**
* Class SimpleConfigReader
* @package ConfigReader
*/
class SimpleConfigReader
{
/**
* @var array
*/
private $config = [];
/**
* String returned to the user.
* @var string
*/
private $output = '';
/**
* SimpleConfigReader constructor.
* @param string $config
*/
public function __construct($config = '')
{
$this->config = $config;
}
/**
* Find a writable app directory path that is either defined by key 'apps_paths'
* or use the default owncloud_root/apps path if the key is not set
*
* @return string
* @throws \Exception
*/
function findPath($ocAppsPath) {
// default path = /apps
if (!array_key_exists('apps_paths', $this->config)) {
$this->output = $ocAppsPath;
return $this->output;
}
foreach ($this->config['apps_paths'] as $path) {
if ($path['writable'] == true && is_writable($path['path'])) {
$this->output = $path['path'];
return $this->output;
}
}
return "Key 'apps_paths' found, but no writable path defined or path found not writeable";
}
}
/*
* As per the PHP manual: The first argument $argv[0] is always the name that
* was used to run the script. So we need at least two to access the new app's
* name, as well as the running script's name.
* @see https://secure.php.net/manual/en/reserved.variables.argv.php
*/
if (count($argv) != 2) {
echo "Command usage: read-config.php <full path to ownCloud root dir> \n";
echo "Please provide the path to the ownCloud directory. \n";
exit(1);
}
// create a realpath and remove trailing "/" from argument if present
$ocRoot = rtrim( (string) $argv[1], "/");
$ownCloudConfigFile = sprintf("%s/config/config.php", $ocRoot);
if (!realpath($ownCloudConfigFile)) {
// if path/file does not exist, return an error message
echo 'File not found: ' . $ownCloudConfigFile . PHP_EOL;
} else {
// return the path, identified by a leading "/" and no new line character at the end
require_once($ownCloudConfigFile);
$result = (new SimpleConfigReader($CONFIG))->findPath($ocRoot . '/apps');
if (!strpos($result, '/')) {
// return an error string which does not start with a leading "/"
echo $result . PHP_EOL;
} else {
// return the path, identified by a leading "/" and no new line character at the end
echo $result;
}
}

The value of the id element needs to be the name of your theme’s
folder. We recommend that it always be prefixed with theme-. The main
reason for doing so, is that it is alphabetically sorted in a terminal
when handling app folders.

The type element needs to be the same as is listed above, so that
ownCloud knows to handle the app as a theme. The dependencies element
needs to be present to set the minimum and maximum versions of ownCloud
which are supported. If it’s not present, a warning will be displayed in
ownCloud 10 and an error will be thrown in the upcoming ownCloud 11.

While the remaining elements are optional, they help when working with
the theme in the ownCloud Admin dashboard. Please consider filling out
as many as possible, as completely as possible.

Theme Signing

If you are going to publish the theme as an app in
the marketplace, you need to sign it.
However, if you are only creating a private theme for your own ownCloud
installation, then you do not need to.

That said, to avoid a signature warning in the ownCloud UI, you need to
add it to the integrity.ignore.missing.app.signature list in
config/config.php. The following example allows the app whose
application id is app-id to have no signature.

'integrity.ignore.missing.app.signature' => [
'app-id',
],

How to Override Images

Any image, such as the default logo, can be overridden by including one
with the same path structure in your theme. For example, let’s say that
you want to replace the logo on the login-page above the credentials-box
which, by default has the path: owncloud/core/img/logo-icon.svg. To
override it, assuming that your custom theme was called theme-example
(which will be assumed for the remainder of the theming
documentation), add a new file with the following path:
owncloud/apps/theme-example/core/img/logo-icon.svg. After the theme is
activated, this image will override the default one.

Default Image Paths

To make building a new theme that much easier, below is a list of a
range of the image paths used in the default theme.

Description

Section

Location

The logo at the login-page above the credentials-box

General

owncloud/core/img/logo-icon.svg

The logo in the left upper corner after login

owncloud/core/img/logo-icon.svg

All files folder image

owncloud/core/img/folder.svg

Favorites star image

owncloud/core/img/star.svg

Shared with you/others image

owncloud/core/img/shared.svg

Shared by link image

owncloud/core/img/public.svg

Tags image

owncloud/core/img/tag.svg

Deleted files image

owncloud/core/img/delete.svg

Settings image

owncloud/core/img/actions/settings.svg

Search image

owncloud/core/img/actions/search-white.svg

Breadcrumbs home image

owncloud/core/img/places/home.svg

Breadcrumbs separator

owncloud/core/img/breadcrumb.svg

Dropdown arrow

Admin Menu

owncloud/core/img/actions/caret.svg

Personal image

owncloud/settings/img/personal.svg

Users image

owncloud/settings/img/users.svg

Help image

owncloud/settings/img/help.svg

Admin image

owncloud/settings/img/admin.svg

Logout image

owncloud/core/img/actions/logout.svg

Apps menu - Files image

owncloud/apps/files/img/app.svg

Apps menu - Plus image

owncloud/settings/img/apps.svg

Upload image

Personal

owncloud/core/img/actions/upload.svg

Folder image

owncloud/core/img/filetypes/folder.svg

Trash can image

owncloud/core/img/actions/delete.svg

When overriding the favicon, make sure your custom theme includes and override for both
owncloud/apps/core/img/favicon.svg and owncloud/apps/core/img/favicon.png, to cover any
future updates to favicon handling.

When using custom filetype icons in a custom theme, it is necessary to run
occ maintenance:mimetype:update-js to activate them. For more information please refer to
mimetypes management.

How to Change the Background Image

This guide assumes that you are in the folder of your custom theme, for example: /var/www/owncloud/apps/my_custom_theme/.

How to Change the Login Background Image

Put the new background image in core/img/background.jpg.

Change the owner and group permissions of the file to your web server user and group.

How to Override Settings Page Icons

ownCloud provides the ability to override Personal and Admin settings page icons.
To do so requires two things:

A custom (SVG) icon; and

Refactoring SettingsManager.php

For example, say that you wanted to override the Admin Encryption settings icon.
To do that, first add a custom icon to an app’s img directory (ideally one that makes sense) e.g., </path/to/owncloud>/apps/encryption/img/gnu.svg.

Then, update the getBuiltInSections function of lib/private/Settings/SettingsManager.php.
There, you need to change the final argument to the relevant call to new Section, for the settings section that you want to change, as in the example below.

new Section('encryption', $this->l->t('Encryption'), 85, 'gnu'),

In the example above, I’ve changed the encryption section’s icon, by changing the final argument to be the custom icon’s name — minus the file extension.

Icons must be in SVG format.
No other file formats are supported.

How to Override the Default Colors

To override the default style sheet, create a new CSS style sheet in
your theme, in the theme’s css directory, called styles.css.

How to Override Translations

You can override the translation of any string in your theme. To do so:

Create the l10n folder inside your theme, for the app that you want to override.

In the l10n folder, create the translation file for the language that you want to customize.

For example, if you want to overwrite the German translation of
`Download` in the files app, you would create the file
owncloud/apps/theme-example/apps/files/l10n/de_DE.js. Note that the
structure is the same as for images. You just mimic the original file
location inside your theme. You would then put the following code in the file:

Both files (.js and .json) are needed. The first is needed to enable
translations in the JavaScript code and the second one is read by the
PHP code and provides the data for translated terms.

How to Override Names, Slogans, and URLs

In addition to translations, the ownCloud theme allows a lot of the
names that are shown on the web interface to be changed. This is done in
defaults.php, which needs to be located within the theme’s root
folder. You can find a sample version in
owncloud/app/theme-example/defaults.php. In there, you need to define
a class named OC_Theme and implement the methods that you want to
overwrite.

How to Test a Theme

If you’re using a tool like the Inspector tools inside Mozilla you can test out the CSS-Styles
immediately inside the css-attributes, while you’re looking at the page.

If you have a development server, you can test out the effects in a live environment.

Settings Page Registration

How Can an App Register a Section in the Admin or Personal Section?

As of ownCloud 10.0, apps must register admin and personal section
settings in info.xml. As a result, all calls to
OC_App::registerPersonal and OC_App::registerAdmin should now be
removed. The settings panels of any apps that are still using these
calls will now be rendered in the Additional section of the
dashboard .

For each panel an app wishes to register, two things are required:

An update to info.xml

A controller class

Updating info.xml

First, an entry must be added into the <settings> element in
info.xml, specifying the class name responsible for rendering the
panel. These will be loaded automatically when an app is enabled. For
example, to register an admin and a personal section would require the
following configuration..

The Controller Class

Next, a controller class which implements the OCP\Settings\ISettings
interface must be created to represent the panel. Doing so enforces that
the necessary settings panel information is returned. The interface
specifies three methods:

getSectionID

getPanel

getPriority

getSectionID: This method returns the identifier of the section that
this panel should be shown under. ownCloud Server comes with a
predefined list of sections which group related settings together; the
intention of which is to improve the user experience. This can be found
here in
this example:

getPanel: This method returns the OCP\Template or
OCP\TemplateReponse which is used to render the panel. The method may
also return null if the panel should not be shown to the user.

getPriority: An integer between 0 and 100 representing the importance
of the panel (higher is more important). Most apps should return a
value:

between 20 and 50 for general information.

greater than 50 for security information and notices.

lower than 20 for tips and debug output.

Here’s an example implementation of a controller class for creating a
personal panel in the security section.

Create Custom Sections

At the moment, there is no provision for apps creating their own
settings sections. This is to encourage sensible and intelligent
grouping of the settings panels which in turn should improve the overall
user experience. If you think a new section should be added to core
however, please create a PR with the appropriate changes to
OC\Settings\SettingsManager.