Fortuno Documentation

01 · Overview

Introduction

Everything you need to know before you open your editor — what’s in the box, what it’s built with, and what it expects from your machine.

Welcome

Thanks for picking up Fortuno, a multi-page marketing theme for finance, investment, and consulting businesses, built with Astro. This guide walks through installing the template, understanding how the project is organized, customizing content and styling, and shipping it to production. It’s written for developers who are comfortable with the command line but new to this specific codebase — if you already know Astro well, feel free to skip ahead using the sidebar.

What’s Included

Source files

The full, uncompiled project source — components, pages, styles, and configuration.

Production build

Run npm run build to generate a static dist/ folder you can deploy anywhere. dist/ is generated output and is listed in .gitignore, so it isn’t part of the source.

Images & fonts

78 theme images in public/images/ (WebP photos, SVG icons and logos, PNG favicon) plus the self-hosted Satoshi variable font in public/fonts/. Photos and illustrations are for demo purposes — replace them before launch.

This documentation

A single offline HTML file — open it directly in any browser, no server required.

Features

  • Five fully responsive pages — Home, About, Services, Careers, and Contact — sharing one navbar and footer
  • Animated hero slider and a looping services carousel, built with Swiper and GSAP
  • Scroll-in reveal animations you control with utility classes such as fade-in-200-ms or slide-in-from-bottom-300-ms
  • Accessible tabs, an accordion, a YouTube video modal, logo marquees, and a slide-over mobile menu
  • Per-page SEO: title, description, canonical URL, Open Graph and Twitter/X tags, plus an automatic sitemap
  • Plain CSS with design tokens — no UI framework, no Tailwind — and motion that respects prefers-reduced-motion

Technology Stack

Fortuno is a static Astro site with no UI framework. Everything it depends on:

Astro 7 GSAP 3 Swiper 14 @astrojs/sitemap Vite (via Astro) Plain CSS

Requirements

ToolMinimum versionNotes
Node.js22.12.0 or laterRequired by Astro 7 (set in package.json → engines)
Package managernpm, pnpm, or YarnA package-lock.json is included, so npm installs the exact tested versions
Code editor—VS Code with the Astro extension (recommended in .vscode/extensions.json)
Git2.xOnly required if you plan to version-control your customized copy

Browser Support

The built site targets the last two versions of all evergreen browsers:

Chrome Firefox Safari Edge
Internet Explorer

Internet Explorer 11 is not supported, and no polyfills are included.

02 · Setup

Getting Started

From a downloaded ZIP to a running dev server in five steps.

Installation & Extraction

  1. Download the template ZIP from your purchase confirmation email or account downloads page.
  2. Extract it to a folder on your machine — avoid folder names with spaces or special characters.
  3. Open that folder in your terminal and in your code editor.
bash
# Extract on macOS / Linux
unzip fortuno-astro.zip -d fortuno-astro
cd fortuno-astro

Node.js Setup

Check which version of Node.js is currently active:

bash
node --version
# v22.12.0 or later

If you manage multiple Node versions, tools like nvm or fnm make switching painless:

bash
nvm install 22
nvm use 22

Install Dependencies

From the project root, install packages with your preferred package manager:

npm
npm install
pnpm
pnpm install
yarn
yarn install

This reads package.json and downloads every dependency into a local node_modules/ folder. It only needs to be re-run when dependencies change.

Run the Development Server

npm
npm run dev
pnpm
pnpm dev

This starts Vite’s local dev server with hot module reloading — edits to components, pages, and styles appear in the browser immediately without a manual refresh. By default it’s available at http://localhost:4321; the terminal output will confirm the exact address.

Build for Production & Preview

bash
# Compile an optimized production build into dist/
npm run build

# Serve that build locally to sanity-check it
npm run preview

build bundles and minifies assets, writes static HTML for every page to dist/, and generates sitemap-index.xml. preview serves that exact output locally so you can verify it before deploying — it does not rebuild automatically, so re-run build after further changes.

Which command do I actually need?

Use dev while you’re customizing the template. Use build, then preview, once before you deploy — it catches issues (like a missing import or a component that only breaks when rendered to static HTML) before they reach your live site.

03 · Reference

Project Structure

A tour of the folders you’ll actually touch, and the ones you generally shouldn’t.

PathPurpose
public/Files here are copied to the output root untouched — no optimization or hashing. Fortuno keeps all of its images (public/images/) and the Satoshi font (public/fonts/) here, referenced by root-relative URLs like /images/favicon.png.
src/components/Shared components (Navbar, Footer, Testimonial, TrustedBy, PlayButton, MissionWidget, ArrowIcon) at the top level, and one sub-folder of section components per page.
src/layouts/BaseLayout.astro, the single page shell: <head> and SEO tags, fonts, navbar, footer, and the global scripts. See Layouts.
src/pages/Every file here becomes a route automatically. See Pages for details.
src/scripts/Shared browser scripts: reveal.js (scroll-in animations), animations.js (GSAP helpers), and tabs.js (accessible tabs).
src/styles/global.css imports normalize.css, base-framework.css, fortuno.css, and site.css in that order. See Styling.
Files not shown above

package-lock.json (npm lockfile), .vscode/ (editor recommendations), and .gitignore (ignores dist/, .astro/, node_modules/, and .env). There is no src/assets/, src/data/, or content collection — page content lives directly in the section components.

04 · Reference

Configuration

The files that control how the project builds, and where to set site-wide values.

package.json

Defines dependencies and the scripts you run from the terminal (dev, build, preview). Add your own script here if you introduce a new tool.

jsonpackage.json
{
  "name": "fortuno-astro",
  "type": "module",
  "version": "0.0.1",
  "engines": { "node": ">=22.12.0" },
  "scripts": {
    "dev": "astro dev",
    "build": "astro build",
    "preview": "astro preview",
    "astro": "astro"
  },
  "dependencies": {
    "@astrojs/sitemap": "^3.7.4",
    "astro": "^7.3.2",
    "gsap": "^3.15.0",
    "swiper": "^14.2.0"
  }
}

astro.config.mjs

Controls integrations, the deployed site URL, and build behavior. Fortuno registers only the sitemap integration and uses Astro’s default static output. Set site to your real domain — canonical URLs, Open Graph tags, and the sitemap are all built from it.

javascriptastro.config.mjs
// @ts-check
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';

// Set `site` to your deployed URL so canonical/OG URLs and the sitemap are absolute.
export default defineConfig({
  site: 'https://example.com',
  integrations: [sitemap()],
});

tsconfig.json

Fortuno’s code is plain JavaScript inside .astro files. tsconfig.json only extends Astro’s strict preset so your editor gets accurate hints; it defines no path aliases, so imports use relative paths such as ../components/Navbar.astro.

jsontsconfig.json
{
  "extends": "astro/tsconfigs/strict",
  "include": [".astro/types.d.ts", "**/*"],
  "exclude": ["dist"]
}

Environment Variables (.env)

Fortuno doesn’t read any environment variables, so there’s nothing to set out of the box. If you add values that differ between environments (API URLs, keys) or shouldn’t be committed to Git, put them in a .env file in the project root. Variables must be prefixed PUBLIC_ to be readable in client-side code.

env.env
# Exposed to the browser — never put secrets here
PUBLIC_SITE_URL=https://example.com

# Server-only — safe for secrets, not readable in browser code
API_SECRET_KEY=your_secret_key
Never commit .env

Add .env to .gitignore (it usually is by default). Anything without the PUBLIC_ prefix should stay off the client entirely.

05 · Guide

Pages

How routes are created, and how each page is assembled from section components.

Creating a New Page

Astro uses file-based routing: any .astro or .md file placed in src/pages/ automatically becomes a route matching its file path. Fortuno ships five pages:

text
src/pages/index.astro    →  /
src/pages/about.astro    →  /about
src/pages/service.astro  →  /service
src/pages/careers.astro  →  /careers
src/pages/contact.astro  →  /contact

To add a page, create a new file in src/pages/ using an existing page as a starting point. Every page wraps its sections in BaseLayout and a <main> element, and can reuse any section component:

astrosrc/pages/pricing.astro
---
import BaseLayout from '../layouts/BaseLayout.astro';
import GetInTouch from '../components/home/GetInTouch.astro';
---
<BaseLayout
  title="Pricing"
  description="Plans for every stage of your business."
>
  <main>
    <h1>Pricing</h1>
    <GetInTouch />
  </main>
</BaseLayout>

Add the new page to the links array in src/components/Navbar.astro (and to the footer, if you want it there) so visitors can reach it — see Navigation.

Editing an Existing Page

Page files in src/pages/ are short: they set the page’s title, description, and social image, then list its sections. The actual text and images live in the section components under src/components/<page>/ (for example src/components/home/HomeHero.astro) — open those to change what a page says. Shared pieces such as Testimonial.astro are edited once and update every page that uses them.

Dynamic Routes

Fortuno doesn’t use dynamic routes — all five pages are individual files. If you add something like a blog, files wrapped in square brackets, such as [slug].astro, generate multiple pages from a single template. Astro requires a getStaticPaths() function for these on statically-generated sites:

astrosrc/pages/blog/[slug].astro
---
export async function getStaticPaths() {
  const posts = await import.meta.glob('./posts/*.md');
  return Object.keys(posts).map((path) => ({
    params: { slug: path.split('/').pop().replace('.md', '') },
  }));
}
---

Layouts

Fortuno has a single layout, src/layouts/BaseLayout.astro. It imports the global stylesheet, renders the <head> (SEO tags, favicon, fonts), the navbar and footer, and starts the scroll-reveal and link-underline scripts. Each page’s content is injected at the <slot />. Abridged:

astrosrc/layouts/BaseLayout.astro
---
import '../styles/global.css';
import Navbar from '../components/Navbar.astro';
import Footer from '../components/Footer.astro';

const {
  title = 'Fortuno - Finance & Consulting Astro Theme',
  description = 'Champion of finance industry.',
  image = '/images/Our-Mission-Image_1Our-Mission-Image.webp',
  navDark = false,
} = Astro.props;
---
<html lang="en">
  <head><title>{title}</title> <!-- + meta, canonical, OG/Twitter, fonts --></head>
  <body>
    <Navbar dark={navDark} />
    <slot /> <!-- page content is injected here -->
    <Footer />
  </body>
</html>

Page Metadata & the 404 Page

Pass a title, description, and optional image into BaseLayout on every page for correct browser tabs, search results, and social previews (see also SEO). The Careers page also passes navDark, which switches the navbar to its dark logo and links for the light hero background. Fortuno doesn’t include a 404 page; add a file named 404.astro to src/pages/ and Astro will serve it automatically whenever no route matches.

06 · Guide

Components

The building blocks pages are assembled from, and how data flows into them.

Reusable Components

Components live in src/components/ and encapsulate one piece of UI so it can be reused across pages without copy-pasting markup. Every component in Fortuno is an .astro file — there are no React or other framework components. They fall into two groups:

  • Shared components (top level): Navbar, Footer, Testimonial, TrustedBy (logo marquee), PlayButton (YouTube video modal), MissionWidget, and ArrowIcon.
  • Section components, one folder per page: home/, about/, service/, careers/, and contact/ — for example home/HomeHero.astro or contact/ContactForm.astro.

Props

Props are the inputs a component accepts, similar to HTML attributes. Fortuno’s components are plain JavaScript, so props are read from Astro.props with a default value for each — no TypeScript interfaces. For example, PlayButton:

astrosrc/components/PlayButton.astro
---
// Play button that opens a YouTube video in a modal dialog.
const { videoId = 'r233kDWShkA', label = 'Play video' } = Astro.props;
---

In plain language: videoId is the YouTube video to play and label is the accessible name screen readers announce for the button. Both are optional — leave one out and the default after the = is used. The components that accept props:

ComponentProps (default)
BaseLayouttitle, description, image (social preview image), navDark (false)
Navbardark (false) — dark logo and links for light heroes
PlayButtonvideoId ('r233kDWShkA'), label ('Play video')
MissionWidgettitle ('Our Mission'), text, href ('/about')
TestimonialtrustedBy (true) — show the logo marquee underneath
TrustedByvariant ('white' or 'blue') — edge-gradient color
ArrowIconsize (none, 'small', 'medium', or 'large')

Component Composition

Pages are composed from section components rather than written as one long block of markup. The home page, in full:

astrosrc/pages/index.astro
<BaseLayout
  title="Fortuno - Finance & Consulting Astro Theme"
  description="Champion of finance industry."
  image="/images/Our-Mission-Image_1Our-Mission-Image.webp"
>
  <main>
    <HomeHero />
    <HomeAbout />
    <NumberSection />
    <IndustriesTabs />
    <Features />
    <AccordionSection />
    <Testimonial />
    <GetInTouch />
  </main>
</BaseLayout>

Reorder, remove, or reuse sections by editing that list. Components can also nest: Testimonial renders a PlayButton and, by default, a TrustedBy marquee.

Passing Data to Components

In Astro, props are passed the same way as HTML attributes and read via Astro.props:

astro
---
import PlayButton from '../PlayButton.astro';
import Testimonial from '../Testimonial.astro';
---
<PlayButton videoId="YOUR_YOUTUBE_ID" label="Play company video" />
<Testimonial trustedBy={false} />
Interactivity without a framework

Components render to static HTML. The interactive pieces — sliders, tabs, accordion, mobile menu, video modal — each add a <script> tag inside their own .astro file, which Astro bundles and ships to the browser. They use GSAP and Swiper directly; no React or other UI framework is involved.

07 · Guide

Styling

Where to change colors, type, and spacing without fighting the build.

Global Styles & CSS Variables

Fortuno uses plain CSS. BaseLayout imports src/styles/global.css, which loads four stylesheets in order: normalize.css (reset), base-framework.css (containers, grid, nav, tabs, and button basics), fortuno.css (the theme: colors, typography, and every section), and site.css (the interactive pieces — sliders, accordion, video modal, mobile menu).

Site-wide colors, fonts, and section spacing are defined once as CSS custom properties in the :root block at the top of src/styles/fortuno.css. Change a value there and it updates across the whole site. The main tokens:

csssrc/styles/fortuno.css
:root {
  --fonts--body: "Satoshi Variable", sans-serif;
  --fonts--heading: Outfit, sans-serif;
  --colors--heading: #1a1d39;
  --colors--body: #616377;
  --colors--blue: #0b88e2;
  --colors--dark-blue: #08317e;
  --colors--light-blue: #ecf6ff;
  --colors--green: #00a57d;
  --colors--red: #ff4e44;
  --section-spacing--desktop: 120px;
  --section-spacing--tab: 100px;
  --section-spacing--mobile: 90px;
}

Component Styles

Fortuno keeps its styles in the global stylesheets above rather than in per-component blocks, so look up a component’s class names in fortuno.css or site.css to restyle it. For components you add yourself, Astro supports scoped <style> blocks — CSS written there only applies to that component, so class names never collide across files.

astro
<style>
  .card { color: var(--colors--heading); padding: 2rem; }
</style>

Responsive Design, Typography & Spacing

Styles are desktop-first, with responsive overrides in @media screen and (max-width: …) blocks at 991px (tablet — the navbar switches to the slide-over menu), 767px (landscape phone), and 479px (portrait phone). Headings use Outfit and body text uses Satoshi through the --fonts--* tokens, and vertical section padding comes from the --section-spacing--* tokens. Prefer adjusting these shared values over overriding sizes on individual elements, so the site keeps a consistent rhythm as you edit it.

Avoid editing dist/

The dist/ folder is generated output — any change made there is overwritten on the next build. Always edit files under src/.

08 · Guide

Images & Assets

Where Fortuno keeps its images, and how to swap them.

LocationUse forBehavior
public/images/Every image Fortuno uses — photos, logos, icons, the favicon (favicon.png), and the Apple touch icon (webclip.png)Copied as-is, no processing; referenced as /images/<file>
src/assets/ (not used)Optional: images you want Astro to optimizeOptimized, resized, and content-hashed automatically by the build. Create the folder if you want this.

Replacing Images

The quickest route is to overwrite the file in public/images/ with your own, keeping the same filename. Otherwise, add your file there and update the path in the component. Images are plain <img> tags; keep the srcset/sizes attributes in sync with the new file (or remove them) and write a meaningful alt:

astrosrc/components/home/HomeAbout.astro
<img
  src="/images/Home-About-Image_1Home-About-Image.webp"
  srcset="/images/Home-About-Image_1Home-About-Image.webp 1234w"
  sizes="(max-width: 767px) 79vw, (max-width: 991px) 70vw, 50vw"
  loading="lazy"
  alt="Advisor meeting with a client"
  class="home-about-image"
/>

Repeated images such as hero slides, service icons, and client logos are listed in data arrays at the top of their component — see Content Editing. Social preview images are set per page through BaseLayout’s image prop.

Supported Formats & SVGs

Fortuno ships WebP photos, SVG icons and logos, and a few PNGs (favicon, web clip, the rotating circular badge text). Any format the browser supports works in an <img> tag. Small UI icons (arrows, phone, social links) are inline <svg> markup using currentColor, so they follow the text color; larger illustrations are SVG files referenced as <img> sources.

Image Optimization

Files in public/ are not processed by the build, so compress replacement images yourself before adding them (WebP at a sensible width, as the demo images are). If you’d rather let Astro do it, move an image into src/assets/, import it, and render it with the Image component from astro:assets — it’s then resized and re-encoded at build time.

Rule of thumb

To stay consistent with the rest of the theme, put new images in public/images/ and reference them as /images/<file>. Anything that needs a fixed URL (the favicon, a file linked from an email) must stay in public/.

09 · Guide

Fonts & Icons

Swapping typefaces and icon sets without touching every component.

Google Fonts

Headings use Outfit, loaded from Google Fonts in BaseLayout’s <head>. To change it, replace the stylesheet link with your chosen font’s embed code, then update --fonts--heading in src/styles/fortuno.css:

htmlsrc/layouts/BaseLayout.astro
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
  rel="stylesheet"
  href="https://fonts.googleapis.com/css2?family=Outfit:wght@100..900&display=swap"
/>

Local Fonts

Body text uses Satoshi, self-hosted as a single variable font at public/fonts/Satoshi-Variable.ttf. It’s declared with @font-face at the top of src/styles/fortuno.css and preloaded in BaseLayout. To swap it, add your font file to public/fonts/, update the @font-face rule and the <link rel="preload"> path, then point --fonts--body at the new family:

csssrc/styles/fortuno.css
@font-face {
  font-family: Satoshi Variable;
  src: url('/fonts/Satoshi-Variable.ttf') format("truetype");
  font-weight: 300 900;
  font-style: normal;
  font-display: swap;
}

Icon Libraries

Fortuno doesn’t use an icon library. Icons come in two forms: small UI icons (the phone, email, and social icons, slider arrows, the menu close button) are inline <svg> markup inside the components that use them, and the animated “Learn More” arrow is its own component, src/components/ArrowIcon.astro. Larger illustrative icons, such as the service card icons, are SVG files in public/images/.

Replacing & Adding Icons

To replace an inline icon, paste your SVG over the existing <svg> element, keep its width/height, and use fill="currentColor" or stroke="currentColor" so it keeps following the link’s color and hover state. For file-based icons, overwrite the SVG in public/images/ or add a new file and update the icon path in the component’s data array (for example, the services array in src/components/home/HomeAbout.astro).

10 · Beginner Friendly

Content Editing

The fastest, lowest-risk way to make the site say what you want it to say.

New to code?

Everything in this section is plain text or attribute changes — no logic to break. Save the file, and your dev server (from Getting Started) will refresh the browser automatically so you can see the change right away.

Headings, Paragraphs & Buttons

Text lives in the section components, not in the page files. Find the section under src/components/<page>/ (for example home/HomeAbout.astro for the home page’s “Welcome” block), locate the text between the tags, and edit it directly. Buttons are ordinary links styled with classes:

astrosrc/components/home/HomeAbout.astro
<!-- before -->
<h2 class="h2">Welcome to Fortuno Finance Company</h2>
<a href="/about" class="button-primary large w-button">Learn More</a>

<!-- after -->
<h2 class="h2">Welcome to Riverside Wealth Partners</h2>
<a href="/contact" class="button-primary large w-button">Book a call</a>

Header links are the links array in src/components/Navbar.astro; footer link columns are written directly in src/components/Footer.astro. Both components are shared by every page, so each change is made once. See Navigation for details.

Cards, Testimonials & Pricing

Repeated items are driven by a data array in the component’s frontmatter (between the --- lines), so adding, removing, or editing an item is a matter of editing the list. The home page’s services carousel, for example:

javascriptsrc/components/home/HomeAbout.astro
const services = [
  {
    href: '/service#Finance-Planning',
    icon: '/images/Banking-Loans-and-Services.svg',
    tag: 'Financial Planning',
    tagColor: 'bg-color-blue-light',
    title: 'Banking Loans and Services',
    text: 'Providing banking products and services such as savings accounts, loans, credit cards, and investment opportunities.',
  },
  // …four more services
];

The other data arrays: slides in home/HomeHero.astro (hero slides), values in about/CoreValues.astro (the rotating core values), rowOne/rowTwo in TrustedBy.astro (client logos), and links in Navbar.astro. Everything else — testimonials, team members, open positions, FAQs — is written directly in the section’s markup.

Services carousel

The carousel renders the services list twice so its loop always has enough cards to fill the screen. Edit the list itself; the duplication is automatic.

Blog Content & Contact Information

Fortuno doesn’t include a blog. Contact details are written directly into the markup in three components, so update each of them:

  • src/components/Navbar.astro — header phone number (1234-567-890).
  • src/components/Footer.astro — consultation phone number and email (hello@example.com), plus the “Connect” social links.
  • src/components/contact/ContactForm.astro — address and map link, phone (1800-123-1234), emails (hello@example.com, help@example.com), and social icons.

All people, companies, phone numbers, and addresses in the demo content are placeholders, and every email uses example.com.

12 · Guide

Forms

What ships out of the box, and what still needs a backend.

Forms need somewhere to go

Fortuno’s only form is the enquiry form on the Contact page, and it isn’t connected to any service. Out of the box it validates the fields, then hides itself and shows a “Thank you” message — nothing is sent anywhere. To receive submissions you need a backend endpoint or a third-party form service.

Contact Forms

The form lives in src/components/contact/ContactForm.astro and collects first and last name, phone, email, profession, the service needed, and a message. To make it live, add an action attribute pointing at your endpoint and change method to post. The component’s script only fakes the success message when the form has no action, so once one is set the browser submits to it normally:

astrosrc/components/contact/ContactForm.astro
<!-- before -->
<form id="contact-form" name="contact-form" method="get" class="contact-form" data-contact-form>

<!-- after -->
<form id="contact-form" name="contact-form" method="post"
  action="https://your-form-endpoint.example" class="contact-form" data-contact-form>

The two dropdowns (“Your Profession” and “Need service for”) contain demo options (Option One to Option Three); replace them with your own <option> values.

Newsletter Forms

Fortuno doesn’t include a newsletter form. If you add one, the same approach applies: point its action at your email provider’s signup endpoint or embed code.

Form Validation

Validation uses standard HTML attributes, so the browser checks fields before submitting and gives immediate feedback without a round trip to a server. First name, phone, email, and message are required; the email field uses type="email", the phone field type="tel"; and every field has a maxlength. There’s no custom validation script.

Third-Party Form Services

If you’d rather not run your own backend, services like Formspree, Getform, Basin, or Netlify Forms accept form submissions directly from static HTML and forward them to your email — typically a one-line change to the form’s action attribute, as shown above.

13 · Guide

API & Data

Fortuno doesn’t fetch data from any API — this section only applies if you add an external data source.

No API out of the box

Every page is static: all content is written in the components or in the data arrays at the top of them (see Content Editing). No API URLs, keys, or environment variables are needed. The patterns below are a starting point if you later connect a CMS or API.

API Configuration

API URLs and keys are read from environment variables (see Configuration) rather than hard-coded, so the same code can point at a staging or production API depending on environment:

env.env
PUBLIC_API_URL=https://example.com/api
PUBLIC_API_KEY=your_api_key
Never expose real credentials

The values above are placeholders. Keep real API keys out of version control, and prefer server-only variables (without the PUBLIC_ prefix) for anything sensitive.

Fetch Requests

typescript
const res = await fetch(`${import.meta.env.PUBLIC_API_URL}/products`, {
  headers: { Authorization: `Bearer ${import.meta.env.PUBLIC_API_KEY}` },
});
const data = await res.json();

Data Structures

Fortuno defines no API data shapes. The closest equivalents are the frontmatter data arrays: services in home/HomeAbout.astro uses the fields href, icon, tag, tagColor, title, and text, and slides in home/HomeHero.astro uses tag, title, tags, image, and width. If you move content to an API or CMS, return data in the same shape and those components will render it unchanged.

Error Handling

typescript
try {
  const res = await fetch(apiUrl);
  if (!res.ok) throw new Error(`Request failed: ${res.status}`);
  const data = await res.json();
} catch (err) {
  // show a fallback UI state instead of a blank page
  console.error(err);
}
14 · Guide

SEO

Per-page metadata, social previews, and the machine-readable files search engines expect.

Page Title & Meta Description

Pass a unique title and description into BaseLayout at the top of every page — these drive both the browser tab and the snippet shown in search results. image sets the social preview image:

astrosrc/pages/service.astro
<BaseLayout
  title="Service"
  description="Finance and business consulting agency"
  image="/images/Our-Mission-Image-1_1Our-Mission-Image-1.webp"
>

The demo titles and descriptions are short placeholders (“Service”, “Careers”, “Contact”) — rewrite them for your business before launch.

Canonical URL, Open Graph & Twitter/X Cards

Already set up in BaseLayout’s <head>, using the site value from astro.config.mjs to build absolute URLs. You don’t need to edit this — just set site and pass the page props:

astrosrc/layouts/BaseLayout.astro
---
const canonical = new URL(Astro.url.pathname, Astro.site ?? Astro.url);
const ogImage = new URL(image, Astro.site ?? Astro.url);
---
<link rel="canonical" href={canonical} />
<meta property="og:type" content="website" />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:image" content={ogImage} />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={ogImage} />

Sitemap & Robots.txt

Fortuno includes Astro’s official sitemap integration (@astrojs/sitemap), which generates sitemap-index.xml automatically at build time from the site value. No robots.txt is included; to add one, create public/robots.txt pointing at the sitemap on your domain:

textpublic/robots.txt
User-agent: *
Allow: /
Sitemap: https://example.com/sitemap-index.xml

Structured Data & Semantic HTML

Use landmark elements (<header>, <nav>, <main>, <article>) and a single <h1> per page so both search engines and screen readers can parse the page’s structure. Every Fortuno page wraps its sections in <main>, and the navbar is a labelled <nav>. No JSON-LD structured data is included; add it to BaseLayout’s <head> for rich results (e.g. Organization or FinancialService schema) if it suits your content.

15 · Guide

Deployment

Platform-by-platform steps. Confirm your rendering mode first — it changes the build output you deploy.

Static vs. SSR — check this first

Fortuno is a static Astro build (the default — no adapter is installed). It produces plain HTML/CSS/JS in dist/ that any static host can serve, so follow the static instructions below. Hosts that build your site for you must use Node.js 22.12 or later, as Astro 7 won’t build on older versions.

Vercel

  1. Push the project to a GitHub, GitLab, or Bitbucket repository.
  2. In Vercel, choose Add New → Project and import that repository.
  3. Build command: npm run build · Output directory: dist (Astro static) — Vercel’s Astro preset detects this automatically in most cases.
  4. Fortuno needs no environment variables. If you’ve added some, set them under Project Settings → Environment Variables, and make sure the project’s Node.js version is 22.x.
  5. Click Deploy.

Netlify

tomlnetlify.toml
[build]
  command = "npm run build"
  publish = "dist"

[build.environment]
  NODE_VERSION = "22"

Fortuno doesn’t ship a netlify.toml; add the file above to the project root, or enter the same settings in the dashboard. Connect the repository in Netlify, confirm the build settings, add any environment variables you’ve introduced under Site configuration → Environment variables, and deploy.

Cloudflare Pages

Connect the repository, set the build command to npm run build and the output directory to dist, and set a NODE_VERSION environment variable of 22. Fortuno is static, so no adapter is needed.

GitHub Pages

Set site and base in astro.config.mjs to match your repository URL, then build and publish the dist/ folder to the gh-pages branch (via the official astro build + a deploy action, or manually). GitHub Pages only serves static output — it cannot run an SSR adapter.

Traditional Hosting

Run npm run build locally, then upload the contents of dist/ to your host’s public web root via FTP/SFTP or your host’s file manager. Because Fortuno is fully static, any plain shared host can serve it — no Node.js process is needed on the server.

16 · Guide

Build & Production

What happens when you run build, and a checklist before you ship.

bash
npm run build     # bundle, write dist/, and generate the sitemap
npm run preview   # serve dist/ locally, exactly as it will run in production

Build Output

The build writes one static HTML file per page, hashed CSS/JS bundles, sitemap-index.xml, and a copy of everything in public/ to dist/. This folder is disposable and regenerated by every build; Fortuno’s .gitignore already keeps it out of Git.

Environment Variables in Production

Fortuno uses none by default. If you add some, remember that variables from your local .env are not deployed automatically — each hosting platform requires you to set them again in its dashboard (see Deployment). A missing production variable is one of the most common causes of a build that works locally but fails, or behaves unexpectedly, once deployed.

Production Checklist

  • Run npm run build locally and confirm it completes with no errors.
  • Run npm run preview and click through the main pages.
  • Replace https://example.com as the site URL in astro.config.mjs with your real domain.
  • Give the contact form a real action endpoint (see Forms).
  • Replace the placeholder phone numbers, example.com emails, address, and social links (see Content Editing).
  • Swap the favicon (public/images/favicon.png), Apple touch icon (webclip.png), demo photos, and each page’s title, description, and social image for your own.
  • Point the PlayButton videos at your own YouTube IDs.
  • Set any environment variables you’ve added in your hosting platform’s dashboard.
17 · Reference

Troubleshooting

The most common problems, in the order you’re likely to hit them.

npm install fails

Cause
Node.js older than 22.12 (Astro 7’s minimum), a corrupted local cache, or a stale lockfile from a different package manager.
Solution
Confirm node --version meets the requirement in Requirements, then delete node_modules/ and reinstall with npm ci, which installs exactly the versions in the included package-lock.json.

Port already in use

Cause
Another process (often a previous dev server that didn’t shut down cleanly) is already listening on the default port.
Solution
Stop the other process, or start this one on a different port: npm run dev -- --port 4322.

Module not found

Cause
A missing dependency, or a typo in a relative import path — often after moving a component into or out of a sub-folder such as src/components/home/.
Solution
Re-run npm install; check the import path casing matches the file exactly, and that the number of ../ segments matches the file’s new location. Fortuno has no path aliases.

Images not loading

Cause
The file isn’t in public/images/, the path is missing its leading /images/, or the filename’s capitalization doesn’t match — which works on Windows and macOS but breaks on Linux hosts.
Solution
Review Images & Assets — reference images as /images/<exact-filename>, and update any srcset entry alongside the src.

Styles not loading

Cause
A new page doesn’t render inside BaseLayout (which imports the stylesheets), or an edit went into the wrong stylesheet and is overridden by a later one.
Solution
Wrap every page in BaseLayout. Stylesheets load in the order normalize.css → base-framework.css → fortuno.css → site.css, so a rule in a later file wins; check the matching @media block too, since responsive overrides replace desktop values.

Sections stay invisible or animations don’t play

Cause
Elements with reveal classes (fade-in-*, slide-in-from-*) start hidden until src/scripts/reveal.js animates them in. If a JavaScript error stops the page’s scripts, they never appear.
Solution
Open the browser console and fix the first error — often a script looking for markup that was deleted or renamed (a slider’s data-* hooks, for example). Keep the data- attributes when editing interactive components.

Build fails (but dev server works)

Cause
The dev server renders pages on demand, while build renders every page up front — an error in a page you haven’t opened in dev only surfaces during the build.
Solution
Read the full terminal output for the first error (later errors are often side effects of it); fix issues top to bottom and re-run.

Environment variables not working

Cause
Only applies if you’ve added variables (Fortuno uses none): missing the PUBLIC_ prefix for a client-side value, or the dev server wasn’t restarted after editing .env.
Solution
Rename the variable with the PUBLIC_ prefix if it’s used in browser code, then stop and restart npm run dev — env changes aren’t hot-reloaded.

Deployment problems

Cause
The host builds with a Node.js version older than 22.12, the output directory isn’t set to dist, or environment variables you added exist locally but not in the platform’s dashboard.
Solution
Set the host’s Node version to 22, then re-check the build command and output folder against Deployment for your platform.
18 · Reference

FAQ

Quick answers to the questions we hear most.

How do I install the template?

Extract the ZIP, run your package manager’s install command, then start the dev server. The full walkthrough is in Getting Started.

Which Node.js version should I use?

Node.js 22.12 or later, which Astro 7 requires — see Requirements.

Do I need to know TypeScript or React?

No. Fortuno is written in plain JavaScript inside .astro files, with no React or other UI framework. tsconfig.json only extends Astro’s preset to improve editor hints.

How do I change colors?

Update the CSS custom properties in the :root block at the top of src/styles/fortuno.css, such as --colors--blue and --colors--heading — see Styling.

How do I change fonts?

Swap the Google Fonts link (Outfit) or the self-hosted Satoshi file, then update --fonts--heading or --fonts--body — see Fonts & Icons.

How do I replace images?

Overwrite the file in public/images/ or update the path in the component — see Images & Assets.

How do I add a new page?

Add a file to src/pages/ that renders inside BaseLayout; the route is created automatically. Then add it to the links array in Navbar.astro — see Pages.

How do I deploy the template?

Platform-specific steps for Vercel, Netlify, Cloudflare Pages, GitHub Pages, and traditional hosts are in Deployment.

Can I use the template commercially?

Theme code is provided under the terms of your purchase licence. Photos and illustrations are for demo purposes only — replace them with your own before launch. [Link to the full license text and state standard vs. extended terms.]

Where can I get support?

See the Support section for contact details and what to include in a request.

19 · Reference

Changelog

Every notable change, newest first. Add a new entry above the last one for each release.

Version 0.0.1
  • AddedInitial release: Home, About, Services, Careers, and Contact pages built with Astro 7, GSAP, and Swiper.
Keeping this current

Copy the markup for one entry above, update the version number, date, and bullet list, and place it at the top of this section for each new release.

20 · Reference

Support

Stuck on something this guide didn’t cover? Here’s how to reach us.

Documentation

Most questions are answered somewhere in this guide — try the search (Ctrl K) before reaching out.

Back to top

Contact support

Email hello@rnnstudio.com or reach us through our contact form.

Contact support

Support hours

We’re based in India and available Monday–Friday, 10am–7pm IST. Expect a response within 24 hours.

What to Include in a Support Request

The fastest way to get a useful answer is to include the details below in your first message:

text
When contacting support, please include:

- Template name and version
- Browser (and version)
- Operating system
- Node.js version (node --version)
- The exact error message
- Steps to reproduce the problem