Background study
The live DEPO header and footer with two empty screens between them, so nothing covers the site's animated background — soft green spots that fade in, drift to new places and fade out. Every setting of the animation is exposed and documented, with live controls at ?tune.
Summary
A study page for the background of the DEPO site. It shows exactly what dev0.dphub.net shows around its content — the site header, the site footer and the animated background — and nothing else: two screens of empty page in between, so the background can be watched and tuned on its own. The animation is the live one, ported into one script whose every number sits in a documented CONFIG; ?tune adds live controls and copies the resulting settings.
Prompt
The brief this page was built from.
Build a study page for the background of the DEPO site: the live dev0.dphub.net header, two
empty full-height screens and the live footer, with the site's animated background exactly as
live.
- Port the live background (soft green light spots that fade in, glow and fade out, moving while
invisible) into one script whose every number is a documented setting: colours, spot count and
size, cycle and per-spot offsets and pauses, fade curves, intensity, smoothing, placement
rules, layer and z-index, a semi-transparent veil, grain against banding.
- Apply the production values of depo.place; describe every setting in Ukrainian.
- ?tune adds live controls, named presets kept in a separate settings file, presets saved from
the page (validated on the server), and "copy config" with only the changed keys.
- Fades as smooth as possible: no visible rings or peaks; optional stretched, drifting,
breathing spots and colour palettes.
Look
- Type: the site's own — Lato (menu, text), Poppins (headings), Lazurski (the "Join DEPO" pill, "We are in beta"), self-hosted in
public/demo20/fonts/. - Palette: page
#18171a; light spots#53f57e(rgb 83 245 126) at 0–38 % opacity; header menurgba(255,255,255,.5)→ white on hover; accent green#469a58; yellow#ffb500. - Layout: the live header (70 px, logo, menu, Log in, Join DEPO); two empty full-height screens (
100svheach); the live footer (logo, contacts, DEPO and Help menus, Contact us, socials, language, copyright). - Motion: two round spots of light, each on a 16 s cycle, offset so that one is always glowing; a spot fades in, peaks around a third of its cycle, fades out, and while it is invisible jumps to a new place at least 48 % of the screen from its last place and 58 % from the other spot. The layer is fixed, so the page scrolls over it.
Background settings
All settings live in public/demo20/js/settings.js (described there in Ukrainian), separate from the engine js/background.js:
DEPO_BACKGROUND_BASE— every setting with its demo20 value;DEPO_BACKGROUND_PRESETS— named variants with only the keys that differ:demo20,depo.place(exactly the production site),calm,lively,frosted,demo20 stretched(stretched, drifting, breathing greens),nebula(after el3.html: deep ground, a five-colour palette, stretched spots that drift and breathe, mixed withscreen),golden;DEPO_BACKGROUND_DEFAULT— the preset the page opens with (demo20), unless another one was chosen for everyone in?tune(Make “…” the default →public/_db/demo20-default.json, given bypresets.phpasDEPO_BACKGROUND_PAGE_DEFAULT; Back to “demo20” undoes it).
The page uses BASE + the preset (?preset=<name>, else the default) + window.DEPO_BACKGROUND if a <script> before background.js sets one. On ?tune the panel has a Preset list (built-in and saved) with its permanent link under it (Copy link / Open: /demo20/?preset=<name>, the page without the panel — to show a preset; the address follows the chosen preset too), sliders for every main setting and, per spot, its start inside the cycle and its pause after it; Save as… stores the current settings under a name for everyone (presets.php → public/_db/demo20-presets.json, every value checked; built-in names are reserved; up to 50; Delete removes your saved one), and Copy config gives a ready line to paste into PRESETS in settings.js, which is how a good variant gets into the repository. In the console: depoBackground.apply({ cycle: 8 }), depoBackground.load('calm'). "depo.place" is the value on the production site https://depo.place/ (its Next.js CSS module Ellipses and the component in the layout bundle, read on 2026-10-18); dev0.dphub.net uses the same numbers except zIndex (0). The comments in CONFIG describe every setting in Ukrainian.
| Setting | depo.place | What it does | Range / values |
|---|---|---|---|
base | #18171a | page colour under the spots (also sets --bg) | any CSS colour |
color | #53f57e | colour of the light spots | hex #rrggbb |
spots | 2 (demo20: 3) | number of spots | 1–6 |
size | 42 (demo20: 22) | spot radius in vmax (% of the larger screen side) | 10–90 |
falloff | [[0,1],[18,.78],[40,.45],[62,.18],[82,.05],[100,0]] (demo20: a smooth bell [[0,1],[15,.93],[30,.75],[45,.52],[60,.3],[75,.13],[88,.04],[100,0]]) | control points of the light from the centre to the edge: [distance in % of the radius, share of the current opacity]. Straight segments with sharp bends (depo.place) show a ring at every bend and a bright point in the centre; the bell has a flat centre and fades into zero at the edge | list of pairs, 0–100 / 0–1 |
falloffStep | — (demo20: 4) | step, % of the radius, of the smooth spline drawn through the falloff points — one gradient colour stop every 4 %, so no ring at the points; 0 = straight segments | 0–20 |
grain | — (demo20: 0.04) | faint grey noise over the spots (dithering, ::before of the layer, an SVG noise tile): a dim gradient on a dark page has only a few 8-bit shades and breaks into visible rings, the noise hides the steps. 0.03–0.06 hides the rings while the noise itself stays invisible; it lifts the page by about 3 / 255 at 0.04 | 0–0.3 |
colors | — (demo20: []) | palette, hex colours; empty = every spot in color | up to 8 |
colorMode | — (cycle) | cycle: spot N takes colour N; random: a random palette colour after every move (changed while the spot is invisible) | cycle, random |
stretch | — ([1, 1]) | [from, to] width : height of a spot; after every move it takes a random value in between, keeping the same area; 1 = round | 0.3–4 |
stretchTurn | — (true) | a stretched spot lies or stands at random; false = always lying | true, false |
drift | — (0) | how far a spot wanders while it glows, % of the screen (sine paths with a random phase and speed per spot); turns on per-frame animation | 0–40 |
driftPeriod | — (40) | seconds per drift loop | 2–300 |
breathe | — (0) | the spot's size swells and shrinks, ± share of the size (0.2 = 80–120 %); per-frame | 0–1 |
breathePeriod | — (25) | seconds per breath | 2–300 |
spotBlend | — (normal) | how overlapping spots mix (background-blend-mode): screen adds colours softly with no edges | normal, screen, lighten, plus-lighter, color-dodge |
softness | — (0) | filter: blur() of the whole layer, px — extra fog (el3 uses 250); heavy on large screens | 0–300 |
cycle | 16 (demo20: 9.5) | seconds for one spot to fade in, glow and fade out | 2–60 |
offsets | [-4.8, -8.8] (demo20: [-1, -4.2, -7.3]) | where each spot starts in its cycle, seconds; negative = already running at load (the page never opens black). Keep spots about cycle / spots apart or they glow at the same time; missing entries are spread evenly, cycle / spots apart | seconds |
pauses | — (demo20: [0, 0, 0]) | per spot, seconds of invisible rest after each fade-out: one iteration lasts cycle + pause. Equal pauses keep the stagger of offsets; different pauses make spots drift apart so they never stay in sync | 0–60 |
curves | two curves, peak 0.34 and 0.38, a jump 0 → 0.15 in the first 3 % (demo20: no peaks — soft rise over 0–32 %, flat 0.24 / 0.28 over 32–45 %, then a long fade over 45–100 % following (1 − t)^1.6: it slows down towards the end and leaves a quiet tail near zero, so the spot melts away instead of vanishing — at low opacity the spot's edges disappear first and a short fade looks like it speeds up) | control points of each spot's opacity over the cycle: [% of the cycle, opacity]; spots beyond the list reuse it; keep 0 at start and end (the spot moves at 0) | pairs, 0–100 / 0–1 |
smooth | — (demo20: 3) | step, % of the cycle, of the smooth curve the script draws through the control points (monotone cubic spline, no overshoot, flat at both ends) — one keyframe every 2 % instead of straight segments with visible kinks; 0 = straight segments as on depo.place | 0–10 |
intensity | 1 (demo20: 0.85) | multiplies every opacity of the curves | 0–3 |
easing | linear | timing between curve points | any CSS timing function |
start | {72,24}, {20,76} | first positions, % of the screen | 0–100 |
area | {min: 6, max: 94} | spots appear between these % of width and height | 0–100 |
minFromPrevious | 48 (demo20: 45) | how far (% of the screen) a spot jumps from its last place at least | 0–90 |
minFromOther | 58 (demo20: 40 — with three spots 58 is almost never possible and the fallback kept parking a spot in a corner) | minimum distance from every other spot | 0–90 |
attempts | 40 | random points tried before the fallback (corners, side middles, inner corners, the edges, then the whole grid — the depo.place order) | 1–200 |
layer | fixed | fixed: stays behind the screen while scrolling; absolute: covers the page height and scrolls | fixed, absolute |
zIndex | -1 | stacking of the layer: -1 = under all page content (depo.place; dev0 uses 0). The page colour is set on body, which paints the canvas, so the layer stays visible at -1 | integer |
blend | normal | CSS mix-blend-mode of the layer | normal, screen, lighten, overlay … |
reducedMotion | animate | with the system "reduce motion": keep animating (live), static (spots at their peak, still), off | animate, static, off |
paused | false | freeze the animation | true, false |
veilColor | — (demo20: #18171a) | colour of the veil laid over the spots | hex #rrggbb |
veilOpacity | — (demo20: 0.07) | opacity of the veil: 0 = no veil (as on depo.place), 1 = spots hidden | 0–1 |
veilBlur | — (demo20: 9) | blur of what is under the veil, px (backdrop-filter): softer, "frosted" spots | 0–80 |
veilGradient | — (demo20: none) | optional gradient over the veil colour, e.g. linear-gradient(180deg, transparent 60%, #18171a) for a darker bottom | CSS gradient or none |
The veil is demo20's addition (depo.place has none): a semi-transparent layer over the spots that dims them or adds contrast for text. It is the ::after pseudo-element of the background layer itself, so it always sits above the spots and below all page content (it shares the layer's z-index: -1) without an extra element; a separate element or body::before would need its own place in the stacking order between the background and the content.
When even the fallback finds no point (many spots, big distances) — depo.place would throw here — the script takes the farthest point of a grid.
Recipes: exactly like depo.place — veilOpacity: 0, smooth: 0, cycle: 16 and the depo.place curves / falloff from the table; calmer — cycle: 24, intensity: 0.7; livelier — cycle: 8, minFromPrevious: 30; three spots — spots: 3, minFromOther: 40; another brand colour — color: '#ffb500'; softer edges — falloff: [[0, 1], [50, 0.35], [100, 0]].
The shared background (/bg)
https://album.dev0.dphub.net/bg/ is this demo under a second address (public/bg is a symlink to public/demo20); there the ?tune panel is always open and the page opens with the current shared default. The panel's All demos block:
- Use for all demos stores the current settings (under the current preset's name) as the default for every demo that takes part; Clear default gives every demo its own background back.
- The list shows every demo that takes part — its page loads
/demo20/js/shared.js(data-demo="<slug>"): demo1–4 and the Connect demos 36–45 — ticked when it follows the default. Unticking a demo keeps its own background. Demos whose doc saysbackground: own-only(demo20 itself, demo30) edit their own background and are locked. - On a ticked demo
js/shared.jsaskspresets.php?shared=<slug>; with a default set it hides the demo's own.ellipsesand runsjs/background.jswith the default on a layer of its own (no panel there). Each demo's own parameter isbackground:in its doc (shared,own,own-only; agent/rules/post.md). - The default and the ticks are stored in
public/_db/bg-shared.json(every value of the default passes the same check as a saved preset).
Built with
| Part | What |
|---|---|
| HTML | public/demo20/index.html — the live header and footer markup, two empty <section>s |
| Settings | public/demo20/js/settings.js — BASE, named presets, default preset (Ukrainian notes) |
| Server | public/demo20/presets.php — saved presets (GET as JS, POST save / delete), data in public/_db/demo20-presets.json; the shared default for all demos (?shared=<slug>, ?demos, POST default / default-clear / demo), data in public/_db/bg-shared.json |
| Shared | public/demo20/js/shared.js — loaded by other demos: draws the shared default instead of their own background; public/bg → demo20 symlink |
| CSS | public/demo20/css/site.css, site-chrome.css, header.css — copies of the live front CSS (the old .ellipses block removed); public/demo20/css/demo20.css — layout and the ?tune panel |
| JS | public/demo20/js/background.js — the configurable background (vanilla; CSS @property, @keyframes, animationiteration); public/demo20/js/header.js — burger and scrolled state from front's site.js |
| Libraries | none |
| Fonts | Lato, Poppins, Lazurski — self-hosted in public/demo20/fonts/ |
| Images | /_img/site/ — logo, footer logo, social icons, icon sprite |
Borrowed
el3.html("туманность", uploaded by the owner on 2026-10-18): the ideas of stretched ellipses, slow sine drift, breathing size, a colour palette,screenmixing, a strong blur and a noise layer against banding — reimplemented inside this engine as thestretch,drift,breathe,colors,spotBlend,softnessandgrainsettings (no code copied; el3 moves<div>ellipses with transforms, here they stay CSS gradients).
- https://depo.place/ (production): the Next.js CSS module
Ellipses(.Ellipses_ellipses__…, keyframesfade-relocate-a/b) and the component in the layout chunk — the source of every default inCONFIG(2026-10-18). front/public/js/ellipses.jsand the.ellipsesblock offront/public/css/site.css(this repository, as served on dev0.dphub.net on 2026-10-18): the algorithm (spacing rules, fallback, relocate onanimationiteration) and every live value; generalised to N spots and moved intoCONFIG. The live code is itself a plain-JS port of the old Next.jsellipses.tsx.- Header and footer markup from the dev0.dphub.net home page;
site.css,site-chrome.css,header.csscopied fromfront/public/css/; the burger code fromfront/public/js/site.js.
Config
config/demo20/nginx.conf: an exact location = /demo20/presets.php to the front php-fpm pool (the vhost otherwise refuses every PHP file but the catalog), request body up to 256 KB. No php.ini changes. The saved presets file lives in public/_db/ (never served, not in git, kept by the live rsync).
Notes
- Saving from
?tune(and every write ofpresets.php) is for album admins on demo.dphub.net: nginx refuses others with 403 (ops/nginx/depo-demo.conf), and the panel then offers to sign in.
- The copied CSS is a snapshot of the live site on 2026-10-18; if the site header or footer changes, copy the three files again from
front/public/css/(and drop the.ellipsesblock from site.css). - Like the live site, the background keeps animating under "reduce motion" (the fades are slow);
reducedMotion: 'static'stops it.
Suits a site for…
What kind of website would this design fit? Agree with a tag by clicking it, or add your own — a tag can be several words.
No tags yet — be the first.
Comments 0
No comments yet — be the first.