Editing the site — Tustel HTML
Every page of Tustel is a plain HTML file that you edit in a code editor. This guide shows where everything is, and how to add a project, a post or a page.
Open it
Section titled “Open it”Double-click index.html: the site opens in your browser and every link works, straight from the folder. To see it
exactly as a host serves it (and to test the form), run a small local server from the folder:
npx serve .npm start runs the same command. Then edit the files in a code editor and reload the browser to see the change.
What is where
Section titled “What is where”index.html, about.html, portfolio.html, blog.html, contact.html404.html shown for addresses that don't existstyle-guide.html every component with its name (noindex; delete it if you don't want it)portfolio/*.html one page per projectblog/*.html one page per postassets/css/style.css the stylesheet (generated — see design.md)assets/js/main.js the site's scripts (you rarely need to touch it)assets/js/config.js your settings: form endpointassets/images/ photos, your portrait, the client logos, the logo as filesassets/fonts/ Intericon.svg, apple-icon.png, opengraph-image.pngsitemap.xml, robots.txtsrc/css/style.css the stylesheet's source: colours, breakpoints, fontsportfolio.html is the page the menu calls “Works”.
Find the words on the page and change them in the HTML. Keep the tags and classes around them, because they carry the layout. A heading looks like this:
<h2 class="text-[32px] md:text-[36px] lg:text-[42px] leading-[1.2] font-medium tracking-[-0.03em] [font-variation-settings:'opsz'_32] md:max-w-[420px]">Selected work from recent projects.</h2>Change Selected work from recent projects., leave the class. Apostrophes and ampersands are often written as
' and & (Let's work together, Form & Field), and the demo also uses the typographic ’
(I’d love to hear about it); typing ' works too, & should stay &. When you search for a sentence, search
for a part without them.
Button labels are written three times: once to size the button (class="opacity-0", the copy screen readers read) and
twice in the copy that rolls up on hover (aria-hidden="true"). The project titles on their cards work the same way.
Change all three:
<span class="opacity-0">Book a call</span><span aria-hidden="true" …><span …>Book a call</span><span …>Book a call</span></span>Text that appears on load
Section titled “Text that appears on load”Some texts appear as the page loads: the Home hero letter by letter, page titles word by word (the About hero, Works,
Blog, Contact, every project and post), labels and introductions line by line. Each is written twice: once whole, for
screen readers and search engines (class="sr-only"), and once split into one <span> per letter or word for the
effect (aria-hidden="true"):
<h1 …> <span class="sr-only">Made with intention.</span ><span aria-hidden="true"><span class="inline-block" data-appear="word" data-delay="0" style="…">Made</span> </span ><span aria-hidden="true"><span class="inline-block" data-appear="word" data-delay="0.05" style="…">with</span> </span ><span aria-hidden="true"><span class="inline-block" data-appear="word" data-delay="0.1" style="…">intention.</span></span></h1>To change one, write the new text in the sr-only span, then in the split copy: one pair of spans per word, each word
starting 0.05 seconds after the one before it (data-delay). In the Home hero, each word holds one span per letter
(data-appear="letter"), 0.05 seconds apart as well. Paragraphs that appear line by line carry data-appear="lines"
and one <span data-word="true"> per word, without delays: the script finds the lines by itself.
To drop the effect, replace both copies with the plain text, <h1 class="…">Made with intention.</h1>, and remove
data-appear="lines" from a paragraph.
Text that repeats on every page
Section titled “Text that repeats on every page”The header, the footer, your links and your contact details are copied into many pages. Change them once for all files
with your editor’s Find in Files / Replace in Files (VS Code: Ctrl/Cmd + Shift + H):
| Replace | With |
|---|---|
https://tustel-html-erapee.vercel.app |
Your domain, e.g. https://www.yourname.com (canonical links, share cards, sitemap.xml, robots.txt) |
https://cal.com/ |
Your booking page (Cal.com, Calendly…): the “Book a call” buttons in the header, the phone menu, the Home and About heroes, the photo band and “Let’s work together” |
hello@example.com |
Your e-mail (“Let’s work together” on Home and every project page; in the mailto: link and three times as text) |
+1 (415) 123-4567 and tel:+14151234567 |
Your phone, as shown and as dialled (same places) |
California, USA, Within 24 hours |
Your location and response time (same places) |
https://behance.net, https://dribbble.com, https://instagram.com, https://youtube.com |
Your profiles (the Home and About heroes, the footer); change the link texts (Behance, …) too |
aria-label="Alex Carter" |
Your name: the name of the logo link for screen readers, four times per page |
Available worldwide · © <span data-current-year>2026</span> Alex Carter |
Your own footer note; keep the <span data-current-year> for the year |
| Tustel in <title> and share tags |
| Your Name (the Home title, Tustel - Portfolio for Photographers & Creative Designers, has no suffix) |
content="Tustel" |
Your site’s name (application-name and og:site_name) |
Tustel — photographer and creative designer portfolio template |
A description of your share image (og:image:alt, twitter:image:alt) |
Include the .html, .xml and .txt files. Review each change before replacing all: “Alex” and “Tustel” also appear
in text you may want to rewrite rather than replace (your name, the Home title and
description). The year in the footer updates itself (data-current-year). The Contact page shows only the form: your
e-mail and phone appear in “Let’s work together”.
The logo is an <svg> drawing in the header and the footer of every page; see
Making it look like your brand.
Sections that repeat on several pages
Section titled “Sections that repeat on several pages”Some sections are copied into several pages. Change them in every copy (find and replace in files works for text):
| Section | Pages |
|---|---|
| Header and footer | Every page |
| The photo band (“Creating Visual Stories That Inspire”) | index.html, about.html |
| The counters (“80+ Years Experience”, …) | index.html, about.html |
| “Let’s work together”, with your contact details | index.html and every page in portfolio/ |
| “From the journal” (three posts and “View all articles”) | index.html and every page in blog/ |
| “Other Projects” (six projects) | Every page in portfolio/ |
| The social links of the hero | index.html, about.html |
Your name
Section titled “Your name”The demo is the portfolio of Alex Carter. The name appears in:
- the Home hero (“Hello, I’m” / “Alex Carter”, letter by letter) and the About hero (word by word), see text that appears on load;
- the logo drawing and the logo link’s
aria-label(Making it look like your brand); - the footer note of every page;
- the descriptions of About, Works, Blog and Contact (
description,og:description,twitter:description); - the descriptions (
alt) of the two “About me” photos on Home; - the testimonials (“Working with Alex…”).
Search the folder for “Alex” to find them all. Your role (“Photographer & Creative Designer Based in California”) is in
the Home and About heroes, and your portrait is assets/images/portrait-alex-carter.jpg (the Home hero card and the
About hero).
Page titles and descriptions
Section titled “Page titles and descriptions”Each page’s <head> holds what search engines and share cards show:
<title>About | Tustel</title><meta name="description" content="…" /><link rel="canonical" href="https://yourdomain.com/about.html" /><meta property="og:title" content="About | Tustel" /><meta property="og:url" content="https://yourdomain.com/about.html" /><meta property="og:description" content="…" /><meta property="og:image" content="https://yourdomain.com/opengraph-image.png" /><meta name="twitter:title" content="About | Tustel" /><meta name="twitter:description" content="…" /><meta name="twitter:image" content="https://yourdomain.com/opengraph-image.png" />Keep these in step:
- The title, the
og:and thetwitter:versions say the same thing. - The canonical link and
og:urlare the page’s own address (Home’s is the root,https://yourdomain.com/). - A description of 80–160 characters shows in full in search results, and so does a title of up to 60 characters
(drop the
| Tustelsuffix when a title is longer, as four of the demo posts do). - Home’s title and description describe the template: write them for your work.
- Project and post pages use their own photo as
og:imageandtwitter:image(https://yourdomain.com/assets/images/<file>), with their title asog:image:alt. Posts are shared as articles, with their date inarticle:published_time.
Images
Section titled “Images”assets/images/ holds every photo. The easiest change is to replace a file with yours under the same name: every
page that shows it updates. The download ships with grey placeholders that state the size each image was designed for
(for example 2400 × 1600).
To use a new file instead, change the src: <img src="assets/images/my-photo.jpg" …>. In pages inside a folder
(portfolio/…, blog/…), the path starts with ../: src="../assets/images/my-photo.jpg". In 404.html it starts
at the site’s root: src="/assets/images/…".
Photos in a fixed frame are cropped to fill it, so a photo of another shape still fits: the Home slideshow, the photo band, the 404 photo, “About me”, “How I work”, “Let’s work together”, the services, the portraits and the post cards (about 1.41 : 1).
Photos that set their own shape are project covers, gallery photos and the photo at the top of a post. Their shape is written in the HTML next to the image, so when the new photo has another shape, write its width and height there too, or it is cropped to the old shape:
| Where | What to change |
|---|---|
| A project card (Home, Works, “Other Projects”) | aspect-ratio: 2400 / 3600 twice (the photo shows sharp over a blurred copy of itself), and width and height on both <img> |
| The List view on Home (desktop) | aspect-ratio on the photo’s link (data-portfolio-image), and width and height on its <img> |
| The cover of a project page, the photo of a post | The number in height: min(100vh, calc(100cqw / 1.5)), which is the width divided by the height (1.5 for 2400 × 1600), and width and height on the <img> |
| A gallery photo | aspect-ratio: 1200 / 800, and width and height on the <img> |
A portrait cover makes a tall card, and the cards of a row line up at the top. The cover of a project page and the photo of a post are at most one screen tall (cropped beyond). A project’s cover is also on its cards in other pages: search the folder for its file name to change every one.
Use photos at least as large as the demo’s, which the placeholders show:
| Photos | Demo size |
|---|---|
| The Home slideshow | 2400 px wide, landscape (they fill the screen, cropped) |
| The photo band (Home, About) and the 404 photo | 2400 × 3600, portrait (they fill the screen, cropped) |
| Project covers | 2400 px wide, any proportion |
| Project gallery photos | 1200 px wide, any proportion |
| Post photos | 2400 px wide |
| “Let’s work together” (Home, project pages) | 1200 × 1600, portrait |
| “How I work” on About | 1200 × 1800, portrait |
| “About me” on Home | 1000 × 750 and 600 × 399 |
| Service photos | 800 px wide (shown 300 × 200) |
| Your portrait (the Home hero card, the About hero) | 300 × 300 |
| Testimonial portraits | 200 × 200 |
A few files are used in more than one place: your portrait, band.jpg (Home and About), contact-cta.jpg (“Let’s
work together” on Home and every project page), and every project cover and post photo (their page and their cards).
Replacing such a file changes every place; to show another photo in one of them, use a new file there.
Use .jpg for photos and keep files small; compress them with Squoosh or
TinyPNG. Write an alt text for images that carry meaning; leave it empty for decorative ones
(written alt or alt="").
Client logos
Section titled “Client logos”The ticker under the Home hero (“Trusted by creative brands worldwide”) shows seven sample logos,
assets/images/client-*.svg, 25 px tall at their own width. Replace the files with your clients’ logos (or change the
src, for a PNG), the alt with each client’s name, and the width and height with the logo’s size at 25 px tall
(width="62" height="25"): they keep its space while it loads. The row is written three times inside the ticker
(data-ticker-copy="0", "1" and "2") so that it loops without a gap: make the same change in all three. If you
change the line above the logos, change the aria-label of the box around the ticker too.
To drop the section, delete the <section> that holds “Trusted by creative brands worldwide”. It also tells the solid
header on Home when to appear (data-header-reveal): add that attribute to the next <section> (“About me”), or the
header that comes back as you scroll up never shows on Home (Making it look like your brand).
Pages link to each other as about.html, portfolio.html, portfolio/<slug>.html; from inside a folder, add ../
(../contact.html). Keep the .html: it’s what lets the site work from any host and from disk. 404.html is the
exception: its links start at the site’s root (/contact.html), because hosts show it at any address.
Links that start with https:// (the booking link, the social links) open in a new tab (target="_blank"); mailto:
and tel: links open the visitor’s mail app or phone.
The counters
Section titled “The counters”Home and About show four counters (“80+ Years Experience”, “120+ Projects Completed”, “45+ Happy Clients”, “18 Awards
Received”). Each number counts up by one every 5 ms, from data-from to data-counter, when it scrolls into view:
<span data-counter="120" data-from="40" class="…">40</span><span class="…">+</span>Change the numbers in index.html and about.html, and write the starting number as the text too: it is what shows
before the count starts. The + is the span after it; delete that span for no suffix, as for the awards. Write whole
numbers, and keep the distance between data-from and data-counter to a few hundred (a counter to 5000 from 0 would
count for 25 seconds).
The Home hero
Section titled “The Home hero”- The slideshow shows three photos (
hero-1.jpgtohero-3.jpg), a new one every 5 seconds. Its track holds the three slides and then a copy of the first, which lets it loop: replacehero-1.jpgin both, and keepdata-count="3"on thedata-slideshowelement equal to the number of photos without the copy. To add a photo, copy the second slide (it carriesaria-hidden="true" inert), paste it before the last one and raisedata-count. - The card (“I specialize in”, with your portrait) scrolls five specialities upwards. They are written four times:
twice in the card and twice in the faded lines above it (
data-ticker-copy="0"and"1"of each of the two tickers). Change all four, in the same order. - The texts appear letter by letter (text that appears on load); the buttons, the card and the social links rise into place after them.
Services and testimonials
Section titled “Services and testimonials”- The services (“What I Do” on Home): pointing at a service on a desktop (or tapping it on a tablet) shows its
title, text and photo beside the list; on phones, the chosen service opens under its name. Each service is written
twice: in the list, as a button (
01 — Photography) followed by the panel phones open (id="services-0"), and beside the list, in adata-service-detailsblock. The first is chosen when the page loads: its button is orange (style="color: #eb4b3d; opacity: 1",aria-expanded="true") and its panel open (style="height: auto"); the others are faded (style="color: #000000; opacity: 0.3"), their panels closed (style="display: none; height: 0px") and their detailshidden. To add a service, copy the last<li>of the list and the lastdata-service-detailsblock, paste each after its original, and edit both: the number and name on the button (“06 — Retouching”), itsdata-serviceandaria-controls(5,services-5), the panel’sid(services-5), and the title, text and photo in both copies. - The testimonials (“What clients say”): a slideshow like the hero’s, with a quote, a round portrait, a name and a
role per slide, then a copy of the first slide so that it loops. It moves on every 8 seconds, and the arrows step
through it. To add one, copy a slide that is not the first (it carries
aria-hidden="true" inert), paste it before the last slide, edit it and raisedata-countby one. When you change the first testimonial, change its copy at the end too.
Edit the text and keep these attributes: the site script relies on them.
The portfolio on Home
Section titled “The portfolio on Home”“My Portfolio” on Home shows the first six projects on desktops and four on tablets and phones (the fifth and sixth
cards carry class="hidden lg:block"). On desktops, “Catalog” and “List” switch between the cards and a list of
titles: pointing at a title shows its photo, category and summary. The List view is three lists in the same order,
after the cards:
- the photos (
data-portfolio-image, one link each); - the titles (
data-portfolio-row); - the details (
data-portfolio-details: the category and the summary).
The first project is the active one: its row has style="opacity: 1; color: #eb4b3d", and its photo and details have
no hidden; the others carry hidden and their rows style="opacity: 0.3; color: #000000". To change which
projects Home shows, change the card and its three List view entries together.
Portfolio and Blog lists
Section titled “Portfolio and Blog lists”Works (portfolio.html) and the Blog hold every project or post, but show six on desktops and four on tablets and
phones; more appear each time the visitor scrolls to the spinner under the list. The list is
<ul data-paged-list data-page-size="6" data-small-page-size="4">: the first four cards are <li class>, the fifth and
sixth <li class="max-lg:hidden">, the others <li class="max-lg:hidden lg:hidden">. Keep that pattern when you add
or remove cards (the script also recounts them when the page loads). To show more at a time, change the two numbers
and the classes with them. Every card is in the page’s HTML, so search engines find them all.
The lists keep the order of the HTML: the Blog doesn’t sort posts by date, so put a new post where it should show.
Adding a project
Section titled “Adding a project”A project is a page plus its cards in the lists:
-
The page. Copy an existing one, e.g.
portfolio/aurora-coffee.html→portfolio/lumen-studio.html. Use lower-case words joined by-for the file name; it becomes the address. Edit:- the title (text that appears on load) and the four details under it (Client, Category, Year, Timeline);
- the cover: its
src,altand size (images); - “Project Description” (one
<p>per paragraph), “Project Details” (Industry, Deliverables, Timeline, Scope) and “The Challenge”; - the two galleries: each has two columns of photos, the first half of its photos on the left and the rest on the right; copy a photo’s block to add one, and give each photo its size;
- the
<head>: title, description, canonical,og:url, and the cover asog:imageandtwitter:image.
“Other Projects” and “Let’s work together” stay as they are.
-
Works. Copy a card (
<li>) inportfolio.htmland paste it where the project belongs. Edit its link, its photo (src,width,heightandaspect-ratio, twice each), its title (three times) and its category, and keep the classes of the cards in their pattern (the lists). -
Home, if the project should be among the first six: add its card to the grid and its photo, title and details at the same place in the three lists of the List view (the portfolio on Home), and remove the sixth project from each, so that six remain. The fifth and sixth cards of the grid keep
class="hidden lg:block". -
Other Projects. Each project page lists six other projects at its end. Copy a card there in the pages where the new project should appear.
-
The sitemap. Add a line to
sitemap.xml:<url><loc>https://yourdomain.com/portfolio/lumen-studio.html</loc></url>
Adding a post
Section titled “Adding a post”-
The page. Copy a page in
blog/, e.g.blog/the-power-of-a-strong-brand-foundation.html→blog/my-new-post.html. Edit the category, the title and the excerpt (text that appears on load), the photo (srcand size, images), the text, and the<head>, with the post’s date inarticle:published_timeand its photo asog:imageandtwitter:image. The text is plain HTML: paragraphs are<p class="mt-5 first:mt-0">, headings<h2 class="… mt-10 first:mt-0">and lists<ul class="mt-5 pl-5 first:mt-0 [list-style-type:disc]">, for the space above them;<em>sets a word in italics,<br />starts a new line inside a paragraph. The page itself shows no date: the cards do. -
The Blog. Copy a card in
blog.htmland paste it where the post belongs. Edit its link, photo, date (the<time>element’sdatetimeand its text,Oct 6, 2026), category and title, and keep the classes of the cards in their pattern (the lists). -
“From the journal”. Home shows the first three posts of the Blog, and every post the first three others. Copy a card there for the new post to appear, and remove one so that three remain.
-
The sitemap. Add a line with the post’s date:
<url><loc>https://yourdomain.com/blog/my-new-post.html</loc><lastmod>2026-10-06</lastmod></url>
To remove a project or a post, do the reverse: delete the page, its cards, any link to it and its line in
sitemap.xml. Search the folder for the file name to catch any link left behind.
Adding a page
Section titled “Adding a page”- Copy
about.htmland rename it, e.g.services.html. About opens without a photo, so it has the solid header; a page whose first section carriesdata-header-covergets the header over the photo, like Home (Making it look like your brand). - Replace the sections inside
<main>with the ones you want. Every section in the template is a block you can copy from its page (or fromstyle-guide.html) and paste between<main>and</main>. Without a photo at the top, the first section needs room for the header, like the first section of Works, Blog or Contact (pt-[110px] md:pt-[130px] lg:pt-[150px]). - Update the
<head>(title, description, canonical,og:url, and theog:andtwitter:titles and descriptions). - The copy marks About as the current page: remove
aria-current="page"from its six About links (the header has three bars, and each has a menu for desktops and one for phones). - Link to it: in each of the six menus, copy the
<li>of a neighbouring link and change itshrefand its text. The header is the same in every page of a folder apart from thosearia-currentmarks, so once one page is done, copy everything from<headerto<main>into the others and mark each page’s own links again (pages inportfolio/andblog/mark none, and404.htmlwrites its links from the root,/services.html). Add the page tositemap.xml.
Removing a page
Section titled “Removing a page”Delete the file, remove its links from the six menus of every page and its line from sitemap.xml. Search the folder
for the file name to catch any link left behind: buttons link to pages too (“View my works”, “More about me”, “View
all articles”).
The style guide
Section titled “The style guide”style-guide.html shows every component with its name, which is handy for copying a button or a card. It’s hidden from
search engines. Delete it before publishing if you don’t want it online; its sample form never sends anything.