Template

Instructions. How to make Tessel yours.

Where every animation lives, how the isometric art is drawn, and what to change first when you build your own site on this template.

19 script blocksG1 to G19
3 CMS collectionsBlog, Jobs, Integrations
0 imagesAll art drawn in code
01 Guide

How to edit GSAP animations

All motion and drawing is GSAP code in two places. The shared script sits in public/assets/js/tessel.js. Drawings that exist on one page only sit in that page's Page settings → Custom code → Before </body>: Home 01 (G3 to G6, G8, G9), Home 02 (G13, the comparison scenes and stairs of G14, G16), Home 03 (G17) and Product (G16). Each block starts with a comment header such as /* G6 feature illustrations */.

GSAP 3.15 with the ScrollTrigger and SplitText plugins comes from npm (src/components/CustomCode.astro). The site head code (src/custom-code/site-head.html) holds three things: a short script that hides the page until the motion script is ready (the page always appears after 3 seconds), the hover and open state styles (is-hover, is-open, is-current and friends, kept in code next to the motion script), and the nav menu script. The Tessel script sits in the footer code and runs after GSAP. Every timer, frame loop and in-view check runs through GSAP, so the template ships no other animation code.

Every block looks for its own element first, so a page without #stackSvg simply skips G5. Page blocks register with window.Tessel.inits and run once the page is parsed.

The script blocks

G0

Element bridge

Lets the plain markup behave like the design: adds a canvas inside every data-canvas block, copies state classes such as is-open onto children marked data-mirror, adds is-hover to children of data-hover elements, drives button and card depth, and runs the small loops (blinking dot, logo marquee, flow dots).

Targets [data-canvas], [data-mirror], [data-hover], [data-press], [data-loop]

Variables --btn-d (6 px rest, 2 px hover, 0 pressed), --slab-d (0 to 8 px)

G1

Key variables

Shared settings for every other block. Animates nothing. Reads colors from the CSS variables on the root element once on load, and defines the GSAP timing helpers every block uses: every (repeating timer), later (gsap.delayedCall), watch (ScrollTrigger in-view check) and frames (gsap.ticker loop).

Targets :root CSS variables

Variables REDUCED, C30, COL { ink, top, l, r, aTop, a, aSide, paper }, rng(seed)

G2

Iso SVG helpers

The drawing functions used by every SVG illustration. Animates nothing on its own.

Targets any SVG drawn by a later block

Variables iso(x, y, z, s, ox, oy), box({ x, y, z, w, d, h, cls }, s, ox, oy), boxes(list, s, ox, oy), label(x, y, text)

G3

Isometric canvas field

A grid of tiles on a canvas that drops in, then lifts toward the cursor. Used by the CTA builder in G9.

Targets the canvas passed in by G9

Variables N, seed, gap, hFrac, cy, span, cx, lift, radius, height()

G4

Home 01 hero monolith

A 4×4×4 block that builds itself on load and opens toward the cursor, with layer tags that follow it. Also runs the live run counter.

Targets #heroCanvasB, #heroTagsB .hero_ltag, #heroStage, #runs

Variables N = 4, AGENT_LAYER = 2, scale s, origin ox / oy, runs = 1284092

G5

Stack layers

Four exploded layers that spread apart and light up one by one as you scroll past the stack list.

Targets #stackSvg, #stackList, .stack_item

Variables s = 30, ox = 300, oy = 360, content (blocks per layer), names, setGap(2.6)

G6

Feature illustrations

Six small scenes on Home 01: floating versions, a runner moving along a path, a caged agent, an approval pulse, prod versus draft, and region tiles that light up.

Targets #f1 to #f6

Variables s, ox, oy in each function, runner duration 4.2 s, region interval 1100 ms

G7

Blueprint cities

Draws a seeded 4×4 city of blocks. Static. The number decides the layout.

Targets svg[data-city]

Variables n = 4, s = 26, ox = 120, oy = 82

G8

Night chart

An isometric bar chart of monthly runs. The bars rise when the chart scrolls into view.

Targets #chartSvg

Variables DATA (month, value), max = 2.1, Hmax = 8, step = 1.3

G9

CTA builder

Click a tile to stack a block on it, shift-click to remove one. Counts the blocks placed.

Targets #buildCanvas, #buildCount, #buildClear

Variables N = 8, seed (starting stacks), maximum of 4 blocks per tile

G10

Nav and FAQ

Opens and closes the mobile menu and the FAQ accordion, and wraps the statement in word spans for the scroll effect. The page menu itself (Homes, Product, Company, Resources) is built by the nav menu script in src/custom-code/site-head.html: on desktop one white block morphs between groups and lifts on blue faces, below 992px the groups become rows in the menu panel. Edit the pages, titles and icons in its G list; the Navbar links in the markup stay as the fallback and are hidden once it runs.

Targets #nav, #navToggle, #navPanel, .faq_q, .faq_item, #statement

Variables is-open class on .nav and .faq_item

G11

GSAP motion

Every scroll and entrance effect: hero intro, heading lines, reveals, card rows, counters, the statement scrub, stack spacing, chart rise, Home 02 cells, stairs and inspector bars.

Targets [data-hero], [data-fade], [data-split], [data-reveal], [data-cards], [data-count]

Variables duration .9 to 1.1 s, ease "expo.out", start "top 88%", stagger .08 s

G12

Footer

The voxel wordmark that drops in and lifts under the cursor, the Rotterdam clock, the region latency bars and the newsletter form.

Targets #voxelCanvas, #clock, #regions, #newsForm

Variables GLYPHS (letters of the wordmark), timeZone "Europe/Amsterdam", baseMs = [41, 38, 52]

G13

Home 02 assembly line

Packets travel from two sources through the agent tower to two outputs. Station tags count the runs.

Targets #lineCanvas, #lineTags .h2tag[data-st]

Variables ST (stations: cell, h, side, n), FEED, SPINE, OUT, packet speed 2.6

G14

Small iso icons and scenes

Draws every data-iso icon and data-chip tile, plus the Home 02 before and after scenes and the stairs.

Targets svg[data-iso], svg[data-chip], #cmpBefore, #cmpAfter, #h2stairs

Variables sets (one entry per kind), s = 14, ox = 60, oy = 22, chip s = 22, stairs n = 16

G15

Tabs

Switches the Home 02 use-case tabs and the Pricing 03 plan tabs on click. Each tab and its pane share a data-w-tab value.

Targets .tabset, .tabset_link, .tabset_pane, data-w-tab

Variables is-current (tab), is-active (pane)

G16

Run inspector

Select a step in the Home 02 trace to show its type, timing and payload.

Targets #inspector .insp_row[data-step], [data-f]

Variables INSPECT (one entry per step), default step "agent"

G17

Home 03 art

The floating hero cube, the three principle glyphs, the exploded anatomy drawing with its callouts, the signup form and the CTA cube.

Targets #h3obj, svg[data-glyph], #h3anat, #h3Form, #h3ctaCube

Variables hero s = 34, glyph s = 16, anatomy layers and gap = 3.6

G18

Forms

Not needed. Every form has its own success and error states.

G19

Filters

Filter buttons show and hide list items by category.

Targets [data-filters], [data-filter], [data-filter-list], [data-cat]

Variables data-filter="all" shows every item

G20

Overview thumbnails

Hovering a page card on the Overview scrolls its screenshot from top to bottom.

Targets [data-shot] cards with an image

Variables data-shot="6" sets the scroll time in seconds

G21

CMS helpers

Turns plain-text CMS fields into the designed lists on the integration page and builds the blog post contents from its H2 headings.

Targets [data-lines] (Name | Type per line), [data-steps] (Step | Tag | Time per line), [data-toc]

Variables data-count-label on the label above a list adds its count

Data attributes

Motion and art are switched on with attributes, so you never need to write JavaScript. Add them to the elements in the section components (src/components/sections/).

data-hero

On the hero wrapper. Its data-fade children fade up in sequence on load.

data-fade

On a child of data-hero. Rises 18 px and fades in, 0.9 s, 0.08 s apart.

data-split

On a heading. Splits it into lines that slide up. The H1 of a hero plays on load, every other heading plays when it scrolls into view.

data-reveal

On a single element. Rises 20 px and fades in when it reaches the bottom 10% of the screen. One per section is enough.

data-cards

On a grid. Each direct child rises 36 px in turn.

data-count="146"

Counts up from zero to the value when visible. Add data-decimals="1" for decimal places, data-suffix=" ms" for a unit and data-comma="1" for thousands separators. Keep the final number as the element's text, so it reads correctly without the script.

data-iso="cube"

On an empty SVG with viewBox 0 0 120 90. Kinds: cube, stack, tower, plinth, pair, tiles, teams, runs, connectors, regions.

data-glyph="typed"

On an empty SVG with viewBox 0 0 112 80. Kinds: typed, traced, approved.

data-chip="PG"

On an empty SVG with viewBox 0 0 160 110. Prints 2 to 4 letters on a tile. Add data-accent for the blue tile.

data-city="23"

On an empty SVG with viewBox 0 0 240 240. Any number draws a different city.

data-filters="#list"

On the filter bar. Its buttons carry data-filter, the list carries data-filter-list and each item carries data-cat with one or more categories.

data-hover / data-mirror

data-hover on a card or button adds is-hover to its children marked data-mirror="is-hover". The hover looks (the card lifting onto its blue side faces, arrows nudging) are written in the site head code (src/custom-code/site-head.html), next to the other state styles. Edit them there.

Remove an animation

To turn off one effect, delete its attribute. The element then simply appears in place. To remove a whole feature, delete its block from the footer code or from the page's custom code. Keep G0, G1, G2 and G10, because the other blocks use their helpers and G10 runs the mobile menu.

Reduced motion

When a visitor's system asks for reduced motion, REDUCED in G1 is true. GSAP effects are skipped, canvases draw one still frame, ticking counters stop, and the small loops in G0, such as the logo marquee and the flow dots, do not start. Nothing is hidden. Every element is shown in its final state.

Editing the isometric art

Every small drawing is an SVG built from two helpers in G2. iso(x, y, z, s, ox, oy) turns a point on the grid into screen coordinates at 30°. box({ x, y, z, w, d, h, cls }, s, ox, oy) returns one block as three polygons for its top, left and right faces.

  • x, y place the block on the floor and z lifts it, in grid units.
  • w, d, h are its width, depth and height.
  • s is the size of one grid unit in pixels, and ox, oy move the whole drawing inside its viewBox.

To change a data-iso drawing, edit its line in the sets object in G14. The tower, for example, is a thin plinth plus one block with h: 2.4. Raise that number for a taller tower.

Colors

Faces are painted by the script with the color Variables. Tops use --face-top, sides use --face-l and --face-r, and edges use --ink. Add cls: 'is-accent' to a block to paint it in the three accent shades. Other classes are is-ghost for a light outline, is-wire for a dashed frame and is-night for dark sections.

The canvas scenes (the Home 01 hero, the Home 02 line, the CTA builder and the footer wordmark) read the same variables once on load through COL in G1.

Keep one accent block per view. It is where the eye should land.

Fonts

  • Fraunces for headings, statements and numbers. Weights 300 to 500, optical size 72.
  • Inter Tight for body text, buttons and navigation. Weights 400 to 700.
  • Martian Mono for labels, tags and eyebrows. Weights 300 to 600 at a narrow width.

All three are self-hosted with the theme (src/styles/fonts.ts and public/assets/fonts), with Inter Tight on the Body (All Pages) tag. The type classes in the style guide set the other two.

Colors and variables

Every color is a variable. Change it once and the pages, buttons and drawings follow.

  • --paper, --paper-2 for backgrounds.
  • --ink, --ink-2, --muted for text, from strongest to quietest.
  • --line, --line-2 for hairlines and outlines.
  • --accent, --accent-top, --accent-side for the one cobalt block. Change all three together, lightest on top and darkest on the side.
  • --face-top, --face-l, --face-r for the faces of every block.
  • --night and the other night tokens for the dark section.

They are CSS variables at the top of src/styles/template.css (Paper, Ink, Accent and so on). Edit a value and the classes, the SVG drawings and the canvas scenes all follow, because G1 reads each Variable by its CSS name, for example --_colors---accent. If you rename a Variable, update its name in COL and SKIN at the top of G1.

CMS collections

Three collections feed the list pages. Every item in a list links to its collection's template page, so you never build a page per item.

Blog Posts

Listed on Blog, template Blog post. Fields: name, slug, topic (Engineering, Operations, Product, Customers), summary (up to 140 characters), published date, author name, author role, read time, cover seed (the number for data-city) and body (Rich Text).

Jobs

Listed on Careers, template Job detail. Fields: name, slug, department (Engineering, Design, Go-to-market), location, type, salary range, summary and body (Rich Text).

Integrations

Listed on Integrations, template Integration detail. Fields: name, slug, code (2 to 4 letters for data-chip), category (Database, Payments, CRM, Messaging, Identity, Warehouse), sync mode, latency, setup time, capabilities, summary, intro, triggers and actions (one per line, Name | Type), setup steps (one per line, Step | Tag | Time) and body (Rich Text).

To bind art to the CMS, add a custom attribute to the SVG and pick the field as its value, for example data-city from cover seed or data-chip from code.

Forms

The contact, newsletter and demo forms show the design's success message. To receive submissions, set each form's action to your form service (see README, Forms).

Each form has Success and Error messages. Edit their text in the form's section component.

Utility pages

404 shows the navigation without the footer. Edit it under Pages → Utility pages → 404.

Password shows no navigation or footer. Edit it under Pages → Utility pages → Password, and turn on protection for the whole site or for single pages in their settings.

Support

For questions about the template, or if something does not work as described here, email hello@example.com with your site's read-only link. We reply within two working days.