Paytime Documentation
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 Paytime. 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 script
Run npm run build to generate an optimized, deployable dist/ folder — it isn’t pre-built in the source download.
Image, video & font credits
Full attribution for the Freepik/Unsplash/Pexels imagery and the Outfit and Satoshi typefaces lives on the bundled License page.
This documentation
A single offline HTML file — open it directly in any browser, no server required.
Features
- A full fintech/payments landing page — hero, feature highlights, an app-tour tab section, a testimonial carousel, tabbed monthly/yearly pricing, and an FAQ accordion, all composed in
src/pages/index.astro - Smooth, GSAP-powered interactions: an animated FAQ accordion, animated tab panels, a pricing toggle, and a slide-in mobile navigation drawer
- A dedicated components/style showcase page at
/components, plus License, Changelog, and Style Guide utility pages under/template-info/ - Self-hosted Satoshi font files and the Outfit Google Font, already wired up with
@font-facedeclarations and a<link>tag - SEO defaults on every page — canonical URL, Open Graph and Twitter card meta tags, and an auto-generated sitemap via
@astrojs/sitemap
Technology Stack
Paytime is built with:
No React, TypeScript, or Tailwind CSS — components are plain .astro files, styling is hand-written CSS, and interactivity is small vanilla-JS modules under src/scripts/.
Requirements
| Tool | Minimum version | Notes |
|---|---|---|
| Node.js | 22.12.0 or later | Matches the engines.node requirement in package.json |
| Package manager | npm 9+, pnpm 8+, or Yarn 1.22+ | Use whichever you prefer; examples below cover all three |
| Code editor | — | VS Code with the Astro and ESLint extensions is a comfortable default |
| Git | 2.x | Only required if you plan to version-control your customized copy |
Browser Support
The built site targets the last two versions of all evergreen browsers:
Internet Explorer 11 is not supported. No additional polyfills are included.
Getting Started
From a downloaded ZIP to a running dev server in five steps.
Installation & Extraction
- Download the template ZIP from your purchase confirmation email or account downloads page.
- Extract it to a folder on your machine — avoid folder names with spaces or special characters.
- Open that folder in your terminal and in your code editor.
# Extract on macOS / Linux
unzip paytime-astro.zip -d paytime-astro
cd paytime-astro
Node.js Setup
Check which version of Node.js is currently active:
node --version
# v22.12.0 or later
If you manage multiple Node versions, tools like nvm or fnm make switching painless:
nvm install 22
nvm use 22
Install Dependencies
From the project root, install packages with your preferred package manager:
npm install
pnpm install
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 run dev
pnpm dev
This starts Astro’s local dev server (powered by Vite) 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
# Compile an optimized production build into dist/
npm run build
# Serve that build locally to sanity-check it
npm run preview
build type-checks the project, bundles and minifies assets, and writes static output to dist/. 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.
Use dev while you’re customizing the template. Use build, then preview, once before you deploy — it catches issues (like a broken import or a missing file) that the dev server tolerates but production won’t.
Project Structure
A tour of the folders you’ll actually touch, and the ones you generally shouldn’t.
| Path | Purpose |
|---|---|
public/ | Files here are copied to the output root untouched — no optimization or hashing. Holds images/ (icons, screenshots, favicon), fonts/ (self-hosted Satoshi .otf files), and videos/ (the USP section’s background clip). |
src/components/ | One .astro component per page section — Navbar, Hero, AppFeatures, USP, AppPointsTabs, ReviewSlider, Pricing, FAQ, Footer, ComponentsShowcase. |
src/layouts/ | Layout.astro — the single shared page shell: global <head>/meta/SEO tags and global stylesheet imports. Every page renders through it. |
src/pages/ | Every file here becomes a route automatically. See Pages for details. |
src/scripts/ | Small vanilla-JS modules (accordion.js, tabs.js, smooth-scroll.js, nav-menu.js), several using GSAP, imported directly into a component’s <script> tag. |
src/styles/ | normalize.css, webflow-base.css (layout utility classes from the original Webflow export), and theme.css (color/type tokens and every component’s styles). See Styling. |
_starter/_raw_html/ holds the original Webflow HTML/CSS export this template was converted from. It’s kept for reference only — the live site is built entirely from src/ and doesn’t read from this folder.
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.
{
"name": "paytime-astro",
"version": "1.0.0",
"engines": { "node": ">=22.12.0" },
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview"
}
}
astro.config.mjs
Controls integrations, the deployed site URL, and build behavior. Paytime registers only the official sitemap integration — there’s no React, Tailwind, or other framework integration to configure.
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';
export default defineConfig({
site: 'https://example.com', // used to build absolute URLs for SEO tags and the sitemap
integrations: [sitemap()],
});
The template ships with site: 'https://example.com' as a placeholder. Replace it with your real production domain, or canonical URLs, Open Graph tags, and the generated sitemap will all point at the wrong address.
tsconfig.json
Paytime uses Astro’s default strict preset as-is — there are no custom path aliases configured, so imports use relative paths (e.g. ../../layouts/Layout.astro).
{
"extends": "astro/tsconfigs/strict",
"include": [".astro/types.d.ts", "**/*"],
"exclude": ["dist"]
}
Environment Variables (.env)
Paytime doesn’t read any environment variables out of the box — there’s no .env file and no API keys to configure. If you add a service that needs one (see API & Data), create a .env file in the project root. Variables must be prefixed PUBLIC_ to be readable in client-side code.
# 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
Add .env to .gitignore (it usually is by default). Anything without the PUBLIC_ prefix should stay off the client entirely.
Pages
How routes are created, and how each page assembles its 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 (a .tsx page would additionally require adding the @astrojs/react integration, which this template doesn’t include).
src/pages/index.astro → /
src/pages/about.astro → /about
src/pages/blog/index.astro → /blog
src/pages/blog/[slug].astro → /blog/:slug (dynamic)
To add a page, create a new file in src/pages/ using the layout and structure of an existing, similar page as a starting point — e.g. src/pages/template-info/license.astro:
---
import Layout from '../layouts/Layout.astro';
---
<Layout title="Services - Paytime" description="What we offer.">
<h1>Our Services</h1>
</Layout>
Editing an Existing Page
Open the relevant file under src/pages/ and edit the markup directly. Anything imported from src/components/ lives elsewhere — edit the component file itself to change content that repeats across multiple pages (like a shared call-to-action block).
Dynamic Routes
Files wrapped in square brackets, such as [slug].astro, generate multiple pages from a single template — commonly used for blog posts or product pages. Astro requires a getStaticPaths() function for these on statically-generated sites. Paytime doesn’t currently ship any dynamic routes (every route under src/pages/ is a fixed, single file), but you can add one the same way in any Astro project:
---
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
Paytime has a single shared layout, src/layouts/Layout.astro, that wraps every page — it imports the three global stylesheets and sets up all SEO/meta tags, then renders page content through a <slot />. Individual pages import their own Navbar and Footer components rather than the layout hard-coding them, so each page controls its own header/footer variant:
---
import "../styles/normalize.css";
import "../styles/webflow-base.css";
import "../styles/theme.css";
const {
title = "Paytime - Astro website template",
description = "Fastest way to make payment anywhere.",
noindex = false,
} = Astro.props;
---
<html lang="en">
<head><title>{title}</title><!-- + SEO meta tags --></head>
<body class="main-body">
<slot /> <!-- page supplies its own Navbar / Footer -->
</body>
</html>
Page Metadata & the 404 Page
Pass title and description props into <Layout> on every page for correct browser tabs and search results (see also SEO); pass noindex to keep a utility page like License or Changelog out of search results. src/pages/404.astro is served automatically whenever no route matches.
Components
The building blocks pages are assembled from, and how data flows into them.
Reusable Components
Components live in src/components/, one per page section — Hero.astro, AppFeatures.astro, USP.astro, AppPointsTabs.astro, ReviewSlider.astro, Pricing.astro, FAQ.astro, Navbar.astro, Footer.astro, and ComponentsShowcase.astro. Every component is a plain .astro file — there are no .tsx/React components in this template.
Props
Props are the inputs a component accepts, similar to HTML attributes. Paytime doesn’t use TypeScript interface declarations for them — components just destructure Astro.props with a plain default value, which is what most of this template’s components (Navbar, Footer) do for their single page prop:
---
const { page = "home" } = Astro.props;
---
In plain language: page is optional, and defaults to "home" when the caller doesn’t pass it — used to mark which nav link is aria-current on each page (e.g. <Navbar page="components" /> on /components).
Component Composition
Most sections build their repeating markup by mapping over a small array defined right in the component’s frontmatter, rather than hand-writing each card:
---
const features = [
{ icon: "/images/Billing.svg", title: "Billing", text: "..." },
{ icon: "/images/Invoice.svg", title: "Invoice", text: "..." },
];
---
{features.map((feature) => (
<div class="feature-block">
<h3>{feature.title}</h3>
</div>
))}
Passing Data to Components
In Astro, props are passed the same way as HTML attributes and read via Astro.props. Every page in Paytime passes its own Navbar/Footer a page value so the correct nav link is highlighted:
---
import Navbar from '../components/Navbar.astro';
---
<Navbar page="components" />
Styling
Where to change colors, type, and spacing without fighting the build.
Global Styles & CSS Variables
Color palette and heading font are defined once as CSS custom properties at the top of src/styles/theme.css and referenced everywhere else. Change a value here and it updates across the whole site:
:root {
--primary: #502ff5;
--light-low: #f3f1ff;
--heading-color: #0f0840;
--body: #54506f;
--white: white;
--orange: #ffb459;
}
Component Styles
Paytime doesn’t use Astro’s scoped <style> blocks. All styling instead lives in three global stylesheets imported once by Layout.astro — normalize.css (browser reset), webflow-base.css (layout utility classes carried over from the original Webflow export), and theme.css (color/type tokens plus every component’s actual styles, keyed by class name, e.g. .pricing-card, .faq-item). To restyle a section, find its class in the markup and edit the matching rule in theme.css.
Responsive Design, Typography & Spacing
Layout switches to a mobile drawer nav and stacked sections at 991px, with further type-size and spacing adjustments at 767px and 479px — all as plain @media (max-width: …) blocks in theme.css. Body copy uses the Outfit Google Font; the self-hosted Satoshi font is used for several heading/UI classes (see Fonts & Icons).
The dist/ folder is generated output — any change made there is overwritten on the next build. Always edit files under src/.
Images & Assets
Every image lives in one place, referenced as a plain URL.
| Location | Use for | Behavior |
|---|---|---|
public/images/ | All template imagery — hero art, icons, screenshots, the favicon | Copied as-is at a fixed URL; no build-time processing (Paytime doesn’t use astro:assets’s <Image> component or a src/assets/ folder) |
public/videos/ | The USP section’s background video (.mp4/.webm) and its poster image | Copied as-is |
Replacing Images
Swap the file in public/images/ in place (keeping the same filename), or add a new file and update the src path in the component that references it:
<img
class="hero-image"
src="/images/phone.webp"
alt="Phone frame showing the Paytime app"
srcset="/images/phone-p-500.png 500w, /images/phone.webp 757w"
loading="lazy"
/>
Supported Formats & SVGs
The template ships a mix of .webp photography (with a smaller .png fallback in srcset for narrow viewports) and .svg icons, referenced directly as plain <img> sources. If you add a new photo, exporting both a full-size .webp and a smaller fallback keeps the existing responsive pattern consistent.
Image Optimization
There is no build-time image pipeline here — every image is served exactly as it sits in public/images/. Responsive loading instead comes from hand-written srcset/sizes attributes pointing at pre-exported smaller variants (e.g. phone-p-500.png alongside phone.webp). Compress and resize a replacement image yourself before adding it, and export a smaller variant if you want the same responsive behavior.
Every image in this template goes in public/images/ (or public/videos/ for video) and is referenced by its root-relative URL — e.g. /images/logo.svg. There is no separate optimized-assets folder to choose between.
Fonts & Icons
Swapping typefaces and icon sets without touching every component.
Google Fonts
The Outfit font is loaded from Google Fonts via a <link> tag in the shared layout’s <head>. Replace it with your chosen font’s embed code, then update the font-family on body in theme.css:
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Outfit:wght@100;200;300;400;500;600;700;800;900&display=swap"
rel="stylesheet"
/>
Local Fonts
The Satoshi family is self-hosted — five weights of .otf files live in public/fonts/ and are declared with @font-face at the top of src/styles/theme.css, pointing at the root-relative file path:
@font-face {
font-family: Satoshi;
src: url('/fonts/Satoshi-Bold.otf') format("opentype");
font-weight: 700;
font-style: normal;
font-display: swap;
}
Icon Libraries
Paytime doesn’t use an icon component library or sprite sheet. Every icon is an individual .svg file in public/images/ (e.g. check.svg, down-Arrow.svg, the payment-provider marks), referenced directly as a plain <img> source.
Replacing & Adding Icons
Swap the SVG file in public/images/ in place (keeping the filename), or add a new SVG there and point a component’s src at it — there’s no import step or icon registry to update. A few icons are inlined directly as <svg> markup in components (e.g. the footer’s social links in Footer.astro) so they can inherit color via currentColor.
Content Editing
The fastest, lowest-risk way to make the site say what you want it to say.
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
Find the relevant component in src/components/ (page copy lives in the component, not the page file — see Pages), locate the text between the tags, and edit it directly:
<!-- before -->
<h1 class="display-title semi-bold">Fastest way to make payment anywhere.</h1>
<!-- after -->
<h1 class="display-title semi-bold">Get paid in seconds, anywhere.</h1>
Navigation & Footer
Menu links live directly in Navbar.astro’s links array; footer copy and social links live directly in Footer.astro — there’s no separate src/data/ file to find. See Navigation for the full pattern.
Cards, Testimonials & Pricing
Repeating content blocks are driven by a plain array declared right in the component’s frontmatter, so adding or removing an item is a matter of editing that list:
const reviews = [
{ image: "/images/IMG-2.webp", name: "Smith Grey" },
{ image: "/images/IMG.webp", name: "Smith Grey" },
];
Pricing tiers follow the same pattern in Pricing.astro (a plans.monthly / plans.yearly object) and FAQ questions in FAQ.astro (a columnOne / columnTwo array).
Blog Content & Contact Information
Paytime doesn’t include a blog or a contact page. The only contact-adjacent content is the footer’s social links (LinkedIn, Facebook, Twitter/X — currently placeholder URLs) and Play Store link in Footer.astro and Hero.astro; update the hrefs there to point at your real accounts and app listing.
Forms
Paytime doesn’t ship any forms.
There is no <form> anywhere in this template — every call to action (“Get Started”, “Play Store”) is a plain link. If your build needs a contact or signup form, you’ll be adding one from scratch rather than wiring up an existing component.
Contact Forms
Not included. If you add one, a plain HTML <form> with a submit handler is the simplest fit for this template’s vanilla-JS approach (see Third-Party Form Services below for a no-backend option):
<form action="[Replace with your form endpoint]" method="POST">
<input type="email" name="email" required />
<button type="submit">Submit</button>
</form>
Newsletter Forms
Not included, and not pre-wired to any email provider (Mailchimp, ConvertKit, etc.). Add the provider’s own embed form or hand-roll a form and call their API.
Form Validation
N/A — with no forms in the template, there’s no existing validation to be aware of. If you add a form, standard HTML attributes (required, type="email") cover most cases without writing JavaScript.
Third-Party Form Services
If you’d rather not run your own backend, services like Formspree, Getform, or Basin accept form submissions directly from static HTML and forward them to your email — typically just pointing a form’s action attribute at their endpoint.
API & Data
Paytime doesn’t fetch data from any external source.
Every number, price, name, and review in this template is a hard-coded value in a component’s frontmatter array (see Content Editing) — there is no fetch() call, API client, or CMS integration anywhere in src/.
API Configuration
N/A. If you wire up a real backend or CMS, read its URL and keys from environment variables rather than hard-coding them (see Configuration):
PUBLIC_API_URL=https://example.com/api
PUBLIC_API_KEY=your_api_key
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
N/A today. If you add one (e.g. to pull live pricing or reviews), a typical call in an Astro component’s frontmatter looks like:
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
N/A — every “data structure” in this template is just a plain array of object literals (e.g. Pricing.astro’s plans, ReviewSlider.astro’s reviews) with no TypeScript type declared for their shape.
Error Handling
N/A — with no network requests, there’s nothing to handle errors for. If you add a fetch() call, wrap it so a failed request doesn’t leave a blank section:
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);
}
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 <Layout> on every page — these drive both the browser tab and the snippet shown in search results:
<Layout
title="Components - Paytime"
description="Slightly domed and divided by arches into stiff"
>
Canonical URL, Open Graph & Twitter/X Cards
Set inside Layout.astro’s <head>, using the site value from astro.config.mjs to build absolute URLs. The Open Graph/Twitter image defaults to /images/love-paytime.webp via the layout’s ogImage prop, and can be overridden per page:
<link rel="canonical" href={canonicalURL} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:image" content={ogImageURL} />
<meta name="twitter:card" content="summary_large_image" />
Sitemap & Robots.txt
The official @astrojs/sitemap integration is already registered in astro.config.mjs and generates sitemap-index.xml automatically at build time once the site value is set to your real domain. There’s no robots.txt in public/ yet — add one pointing at the generated sitemap:
User-agent: *
Allow: /
Sitemap: https://example.com/sitemap-index.xml
Structured Data & Semantic HTML
Landmark elements are already in place — each page section is a <section>, the nav bar is a <nav>, and the home page’s single <h1> lives in Hero.astro. There is no JSON-LD structured data in the layout; add it there for rich results (e.g. Organization schema) if you need it.
Deployment
Platform-by-platform steps. Confirm your rendering mode first — it changes the build output you deploy.
There’s no adapter registered in astro.config.mjs, so npm run build always produces plain static HTML/CSS/JS in dist/ — any static host works, and none of the SSR-specific notes below apply to this template.
Vercel
- Push the project to a GitHub, GitLab, or Bitbucket repository.
- In Vercel, choose Add New → Project and import that repository.
- Build command:
npm run build· Output directory:dist(Astro static) — Vercel’s Astro preset detects this automatically in most cases. - Add any environment variables from your
.envfile under Project Settings → Environment Variables. - Click Deploy.
Netlify
[build]
command = "npm run build"
publish = "dist"
Connect the repository in the Netlify dashboard, confirm these build settings, add environment variables 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. For SSR Astro sites, use the official @astrojs/cloudflare adapter instead of the static preset.
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
Upload the contents of dist/ (after npm run build) to your host’s public web root via FTP/SFTP or your host’s file manager. Since Paytime builds fully static, any plain web host works — no Node process needs to run in production.
Build & Production
What happens when you run build, and a checklist before you ship.
npm run build # type-check, bundle, and write dist/
npm run preview # serve dist/ locally, exactly as it will run in production
Build Output
The build writes static HTML and hashed CSS/JS bundles to dist/. This folder is disposable and regenerated by every build — it’s already excluded from Git via .gitignore.
Environment Variables in Production
N/A for Paytime as shipped — there’s no .env file or environment variable to set (see Configuration). If you add one later, remember each hosting platform requires you to set it again in its own dashboard; a missing production variable is a common cause of a build that works locally but misbehaves once deployed.
Production Checklist
- Run
npm run buildlocally and confirm it completes with no errors. - Run
npm run previewand click through the main pages. - Confirm the
siteURL inastro.config.mjsmatches your real domain (it ships ashttps://example.com). - Update the placeholder social links in
Footer.astroand the Play Store link inHero.astro/Footer.astro. - Verify favicon, Open Graph image, and meta descriptions are your own, not the template defaults.
Troubleshooting
The most common problems, in the order you’re likely to hit them.
npm install fails
- Cause
- Node.js version too old, a corrupted local cache, or a stale lockfile from a different package manager.
- Solution
- Confirm
node --versionmeets the requirement in Requirements, then runrm -rf node_modules package-lock.json && npm install.
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/casing mismatch in a relative import path (this template has no path aliases configured in
tsconfig.json).
- Solution
- Re-run
npm install; check the relative import path (e.g.../../layouts/Layout.astro) matches the file’s real location and casing exactly.
Images not loading
- Cause
- An incorrect path in an
<img src>. All images in this template live inpublic/images/(orpublic/videos/), referenced by root-relative URL — there’s nosrc/assets/import step to get wrong.
- Solution
- Review Images & Assets — confirm the file exists under
public/images/and thesrcmatches its filename exactly, including case.
Styles not loading
- Cause
- One of the three global stylesheets isn’t imported into
Layout.astro, or the class name in your markup doesn’t match the selector intheme.css.
- Solution
- Confirm
normalize.css,webflow-base.css, andtheme.cssare all imported at the top ofLayout.astro; searchtheme.cssfor the exact class name you expect to apply.
TypeScript / build type errors
- Cause
- Paytime has no
.tsxcomponents or declared propinterfaces, so this is rare — it’s usually a plain syntax mistake in a component’s frontmatter (between the---fences) surfacing under Astro’sstricttsconfig preset.
- Solution
- Read the error’s file and line number and check the frontmatter syntax there — a missing comma, an unclosed brace, or a variable used before it’s defined are the most common culprits.
Build fails (but dev server works)
- Cause
- The dev server is more forgiving than
build, which fully type-checks the project — an issue tolerated in dev can fail 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
- Paytime doesn’t read any
.envvariables out of the box, so this only applies once you’ve added your own (see Configuration). The usual cause is a missingPUBLIC_prefix for a client-side value, or not restarting the dev server after editing.env.
- Solution
- Rename the variable with the
PUBLIC_prefix if it’s used in browser code, then stop and restartnpm run dev— env changes aren’t hot-reloaded.
Deployment problems
- Cause
- Wrong output directory configured on the host, or environment variables set locally but not in the platform’s dashboard.
- Solution
- Re-check the build command and output folder against Deployment for your platform, and confirm every variable from
.envis duplicated there.
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 22.12.0 or later — see Requirements. This matches the engines.node field in package.json.
Does this template use TypeScript or React?
No — every component is a plain .astro file with vanilla-JS interactivity (some of it GSAP-powered). tsconfig.json is present only because Astro projects ship one by default; see Technology Stack.
How do I change colors?
Update the CSS custom properties at the top of src/styles/theme.css — see Styling.
How do I change fonts?
Swap the Google Fonts <link> in Layout.astro (for Outfit) or the @font-face files in public/fonts/ (for Satoshi) — see Fonts & Icons.
How do I replace images?
Swap the file in public/images/ or update the src path that points to it — see Images & Assets.
How do I add a new page?
Add a file to src/pages/; the route is created automatically — 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?
[State your license terms here — e.g. standard vs. extended license — and link to the full license text.]
Where can I get support?
See the Support section for contact details and what to include in a request.
Changelog
Every notable change, newest first. Add a new entry above the last one for each release.
- AddedInitial release.
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.
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 topSupport 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:
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