Files
ep-roundcube-skin/README.md
T

199 lines
10 KiB
Markdown

# Eternity Roundcube Skin
`Eternity` is a sharp editorial skin for Roundcube, built in the visual language of Eternity Project: paper-white surfaces, ink-black structure, acid-green actions, and orange signals. It extends Roundcube's maintained Elastic skin, retaining Elastic's responsive layout and interaction model while changing the visual treatment.
## Requirements
- Roundcube 1.6.x
- The bundled `elastic` skin must remain installed
- A web server able to serve static CSS files from Roundcube's `skins` directory
The skin has no build step and no PHP dependencies. Its font stacks use `Space Grotesk` and `DM Mono` when those fonts are available, then fall back to locally installed system fonts. This keeps the login screen usable without a third-party font request.
## Install
1. Copy the `eternity` directory into the Roundcube installation's `skins` directory:
```sh
cp -R eternity /var/www/roundcube/skins/
```
2. Ensure the web-server user can read the copied files:
```sh
chown -R www-data:www-data /var/www/roundcube/skins/eternity
find /var/www/roundcube/skins/eternity -type d -exec chmod 755 {} \;
find /var/www/roundcube/skins/eternity -type f -exec chmod 644 {} \;
```
3. Set the default skin in Roundcube's configuration. Add or update this line in `config/config.inc.php`:
```php
$config['skin'] = 'eternity';
```
4. Clear the browser cache, then load Roundcube. The login view, mailbox list, compose view, menus, controls, and status messages should all use the new palette.
## Eternity Wasteland
`eternity-wasteland` is the dark, warm-industrial Eternity variant. It uses the Wasteland palette: charcoal surfaces, parchment text, olive actions, rust-orange signals, and an orange technical grid.
Install it with the same procedure above, copying `eternity-wasteland` instead of `eternity`, then configure:
```php
$config['skin'] = 'eternity-wasteland';
```
### Login Theme Toggle
Wasteland opens in dark mode. Its login screen includes a **Dark mode** toggle that switches to the Eternity light palette without reloading the page. The choice is stored in the browser's `colorMode` cookie for one year and is applied on later visits to the login screen.
Clearing site cookies resets the Wasteland login screen to dark mode. This setting only changes the Wasteland login page; choose the desired Roundcube interface skin in **Settings > Preferences > User Interface > Interface skin** after signing in.
## Eternity Wasteland v2
`eternity-wasteland-v2` adapts the Daylight and Wasteland theme system from `docker-ep-blog-web-server/themes`. It opens in the paper-white Daylight palette and provides a **WASTELAND** control on the login screen. Selecting it switches the page to the warm charcoal Wasteland palette; the control then reads **DAYLIGHT** to switch back.
The login preference is stored in browser local storage as `ep-theme`. Clearing site storage resets the v2 login screen to Daylight. It is independent from the original `eternity-wasteland` skin's `colorMode` cookie.
Install it with the same procedure above, copying `eternity-wasteland-v2` and configuring:
```php
$config['skin'] = 'eternity-wasteland-v2';
```
## Docker Install
### Docker Compose (persistent)
Place this repository alongside the Compose file, then bind-mount the skin into the Roundcube service. The official `roundcube/roundcubemail` image exposes its application at `/var/www/html`.
```yaml
services:
roundcube:
volumes:
- ./ep-roundcube-skin/eternity-wasteland:/var/www/html/skins/eternity-wasteland:ro
- ./roundcube-config/config.inc.php:/var/roundcube/config/config.inc.php:ro
```
Create `./roundcube-config/config.inc.php` if it does not already exist and include the skin setting with the rest of the deployment configuration:
```php
<?php
$config['skin'] = 'eternity-wasteland';
```
The configuration mount location can vary for non-official images. Check the image documentation or run `docker compose exec roundcube sh -c 'find / -path "*/config.inc.php" 2>/dev/null'` to identify the active configuration file. Restart the service after changing either mount:
```sh
docker compose up -d --force-recreate roundcube
```
### Existing Running Container
Use this method to test the skin on a container that is already running. Replace `roundcube` with the container name or ID shown by `docker ps`.
1. Copy the skin from this repository into the container:
```sh
docker cp ./eternity-wasteland roundcube:/var/www/html/skins/eternity-wasteland
```
2. Confirm Roundcube can see the skin files:
```sh
docker exec roundcube sh -c 'test -f /var/www/html/skins/eternity-wasteland/meta.json && test -f /var/www/html/skins/eternity-wasteland/styles/styles.css'
```
3. Add `$config['skin'] = 'eternity-wasteland';` to the active `config.inc.php` in the container, then restart it:
```sh
docker restart roundcube
```
This live-container approach is not persistent: `docker compose up --force-recreate`, `docker rm`, or an image update removes the copied skin and in-container configuration change. Once the skin is confirmed, add the two bind mounts from the Compose example so both survive container recreation.
After either deployment method, hard-refresh the browser or clear its cache. If the old appearance remains, inspect the browser network panel to confirm that `/skins/eternity-wasteland/styles/styles.css` returns HTTP 200.
If instead the page looks entirely unstyled — login credential fields stacked in the wrong place, an oversized logo, or mailbox toolbars/tabs scattered and hard to read — `styles/styles.css` is loading but its `@import` of `../../elastic/styles/styles.css` is not, so none of Elastic's layout rules apply. Confirm that file exists and is readable:
```sh
docker exec roundcube sh -c 'test -f /var/www/html/skins/elastic/styles/styles.css && echo FOUND || echo MISSING'
```
If it is `MISSING`, the Elastic skin was installed from source without its LESS files being compiled (Elastic ships as `.less` sources and requires `make css-elastic` / `bin/updatecss.sh` to produce `styles/styles.css`). Reinstall Elastic from an official Roundcube release tarball, which ships the compiled CSS, rather than a bare git checkout.
### Verify A Running Container
Run these commands on the Docker host, replacing `roundcube` with the container name or ID from `docker ps`. They distinguish an installation issue from an activation issue:
```sh
docker exec roundcube sh -c 'for file in /var/www/html/skins/eternity-wasteland/meta.json /var/www/html/skins/eternity-wasteland/styles/styles.css /var/www/html/skins/elastic/styles/styles.css; do test -f "$file" && echo "FOUND $file" || echo "MISSING $file"; done'
docker exec roundcube sh -c 'grep -RIn "\$config\[.skin.\]" /var/roundcube/config /var/www/html/config 2>/dev/null || true'
```
The first command must report all three paths as `FOUND`. The second must show `eternity-wasteland` as the configured skin. On the official image, the equivalent persistent environment setting is:
```yaml
environment:
ROUNDCUBEMAIL_SKIN: eternity-wasteland
```
Roundcube can store a skin preference for each user. A user who previously selected another appearance may continue to receive that preference instead of the newly configured default. Sign out and test in a private browser window or select **Eternity** from Roundcube's **Settings > Preferences > User Interface > Interface skin**, when the preference is available.
For a browser-level check, open this URL directly, replacing the hostname with the Roundcube site:
```text
https://webmail.example.com/skins/eternity-wasteland/styles/styles.css
```
It must return CSS beginning with `@import url("../../elastic/styles/styles.css");`. A `404` means the skin is not mounted at the path served by the container. If it returns `200` but Roundcube still looks unchanged, inspect the mailbox page source: it must include a stylesheet URL containing `/skins/eternity-wasteland/styles/styles.css`. If it instead contains `/skins/elastic/`, the active configuration or the user's stored preference still selects Elastic.
## Structure
```text
eternity/
meta.json Skin registration and Elastic inheritance
styles/styles.css Visual overrides for Elastic
eternity-wasteland/
images/logo.svg High-contrast Wasteland login mark
meta.json Skin registration and Elastic inheritance
styles/styles.css Dark and light Wasteland visual overrides
templates/login.html Login form with the theme toggle
watermark.html Wasteland login background
eternity-wasteland-v2/
images/logo.svg Daylight login mark with a dark-mode CSS treatment
meta.json Skin registration and Elastic inheritance
styles/styles.css Source-theme Daylight and Wasteland visual overrides
templates/login.html Login form with the Daylight/Wasteland control
watermark.html Login background that follows ep-theme
```
`styles/styles.css` imports Elastic before applying Eternity's overrides. Do not remove the import: the base skin provides the complete component layout and image assets.
## Customize
The visual palette is declared at the top of `eternity/styles/styles.css`:
| Token | Value | Role |
| --- | --- | --- |
| `--ink` | `#11212b` | Primary text, borders, and primary controls |
| `--paper` | `#f1f1e9` | Page and surface background |
| `--acid` | `#c7ef4b` | Primary hover, selection, and success state |
| `--orange` | `#ff6b35` | Links, secondary hover, quota, and error signal |
| `--line` | `#b9c5bc` | Quiet dividers |
| `--muted` | `#59706b` | Secondary text |
Change these variables to retheme the interface while preserving the semantic states. Test login, inbox, compose, contacts, settings, search, and mobile navigation after any update to Roundcube or Elastic.
## Upgrade Notes
This is an Elastic child skin. When updating Roundcube, keep the `eternity` directory in place and confirm that the upstream Elastic stylesheet remains at `skins/elastic/styles/styles.css`. Recopy the skin after deployments that replace the whole Roundcube `skins` directory.
The skin intentionally uses direct CSS selectors for stable Roundcube surfaces and CSS custom properties for broad Elastic integration. If a future Roundcube release renames markup, inspect that release's Elastic stylesheet and update the matching override selector here.
## License
Licensed under the GNU Affero General Public License, version 3 or later. See [LICENSE](LICENSE).