Prodesk 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 Prodesk, a clean, animated marketing site template for CRM and SaaS products, built with Astro. It includes a home page, three feature pages, a pricing page with a plan comparison table and FAQ, login and signup screens, and template-info pages (style guide, license, changelog). 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 (it’s listed in .gitignore) and is not part of the source files.
Design assets
All illustrations, dashboard screenshots (AVIF), SVG icons, brand logos and background patterns in public/images/, plus the self-hosted Satoshi variable font in public/fonts/. No Figma or other design source files are included.
This documentation
A single offline HTML file — open it directly in any browser, no server required.
Features
- Fully responsive pages: home, three feature pages (Automation, Management, Analytics), pricing, login, signup, plus style guide, license and changelog pages
- Feature pages generated from a single data file (
src/data/features.js) — add an entry, get a new page at/features/<slug> - GSAP + ScrollTrigger animations driven by plain CSS classes: scroll reveals, floating illustrations, magnetic buttons and hover effects — all disabled automatically for visitors who prefer reduced motion
- Swiper-powered sales-performance slider, accessible tabs, a monthly/yearly pricing toggle and an FAQ accordion
- Plan comparison table and three pricing plans on the pricing page
- Canonical, Open Graph and Twitter/X meta tags on every page, and an auto-generated sitemap via
@astrojs/sitemap - Plain CSS and JavaScript — no UI framework, no Tailwind, no TypeScript to learn
Technology Stack
Prodesk is a static Astro site with no UI framework. Styling is plain CSS and all scripts are plain JavaScript.
Requirements
| Tool | Minimum version | Notes |
|---|---|---|
| Node.js | 22.12.0 or later | Required by Astro 7 and declared in package.json under engines |
| Package manager | npm 10+ (ships with Node 22), pnpm, or Yarn | The template ships an npm package-lock.json; pnpm and Yarn also work |
| Code editor | — | VS Code with the Astro extension (recommended by the bundled .vscode/extensions.json) 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, and the template ships no polyfills.
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 prodesk-astro-package.zip
cd prodesk-astro-package/prodesk-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 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
# Compile an optimized production build into dist/
npm run build
# Serve that build locally to sanity-check it
npm run preview
build renders every page to static HTML, bundles and minifies CSS and JavaScript, generates sitemap-index.xml, and writes the 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 missing imports or a broken getStaticPaths() entry in src/data/features.js) that the dev server only surfaces when you visit the affected page.
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. In Prodesk this holds every image (public/images/), the Satoshi font (public/fonts/) and the favicons; they are referenced by root-relative URLs such as /images/logo.svg. |
src/components/ | Reusable UI shared across pages (Navbar, Footer, Button, Tag, SectionHeading, CircularCta, Reviews, SinglePricing, PricingTabs, AuthPage), plus page-specific sections grouped in home/, features/ and pricing/. |
src/layouts/ | BaseLayout.astro defines the common page shell — <head> and SEO tags, navbar, footer and the animation script. UtilityLayout.astro wraps it for the template-info pages. |
src/pages/ | Every file here becomes a route automatically. See Pages for details. |
src/scripts/ | animations.js runs the site-wide GSAP scroll animations; tabs.js exports the shared accessible-tabs helper used by the home page tabs and the pricing toggle. |
src/styles/ | base-framework.css (base/reset and layout utilities), prodesk.css (the theme, including the CSS custom properties) and global.css (small additions such as focus styles). See Styling. |
src/data/ | features.js holds the content for the three feature pages, kept separate from markup so it’s easy to edit without touching Astro templates. |
The project root also contains package-lock.json, .gitignore and a .vscode/ folder recommending the Astro extension. There is no src/assets/ or src/content/ folder, no .env file, and no Tailwind or other CSS tooling config.
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": "prodesk-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.5",
"gsap": "^3.15.0",
"swiper": "^14.3.0"
}
}
astro.config.mjs
Controls integrations, the deployed site URL, and build behavior. Prodesk registers only the sitemap integration, and excludes the /template-info/ pages from the sitemap. Set site to your real domain before deploying — it’s used for canonical URLs, Open Graph image URLs and the sitemap.
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';
export default defineConfig({
// Replace with your production URL — used for the sitemap and canonical/OG URLs.
site: 'https://example.com',
integrations: [
sitemap({
filter: (page) => !page.includes('/template-info/'),
}),
],
});
tsconfig.json
Prodesk is written in plain JavaScript, so this file only extends Astro’s default config to give your editor IntelliSense for .astro files. No path aliases are defined — imports use relative paths such as ../components/Button.astro.
{
"extends": "astro/tsconfigs/strict",
"include": [".astro/types.d.ts", "**/*"],
"exclude": ["dist"]
}
Environment Variables (.env)
Prodesk doesn’t read any environment variables out of the box. If you add an integration that needs one (a form endpoint, an analytics key), create a .env file in the project root for values that differ between environments or shouldn’t be committed to Git. 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
.env and .env.production are already listed in the template’s .gitignore. Anything without the PUBLIC_ prefix should stay off the client entirely.
Pages
How routes are created, and how Prodesk’s pages are put together.
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. Prodesk ships these routes:
src/pages/index.astro → /
src/pages/pricing.astro → /pricing
src/pages/login.astro → /login
src/pages/signup.astro → /signup
src/pages/features/[slug].astro → /features/automation, /features/management, /features/analytics
src/pages/template-info/style-guide.astro → /template-info/style-guide
src/pages/template-info/license.astro → /template-info/license
src/pages/template-info/changelog.astro → /template-info/changelog
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. Pages are composed from section components inside a <main> element:
---
import BaseLayout from '../layouts/BaseLayout.astro';
import Reviews from '../components/Reviews.astro';
import SinglePricing from '../components/SinglePricing.astro';
---
<BaseLayout title="About — Prodesk" description="Who we are and what we build.">
<main>
<Reviews />
<SinglePricing />
</main>
</BaseLayout>
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. Astro requires a getStaticPaths() function for these on statically-generated sites. Prodesk’s feature pages are built this way — one page per entry in src/data/features.js:
---
import { features } from '../../data/features.js';
export function getStaticPaths() {
return features.map((feature) => ({ params: { slug: feature.slug }, props: { feature } }));
}
const { feature } = Astro.props;
---
To add a fourth feature page, copy an existing entry in features.js and give it a new slug; remember to add a matching link to featureLinks in Navbar.astro and to the footer columns (see Navigation).
Layouts
Layouts (in src/layouts/) wrap page content with shared structure — the <html> shell, <head> metadata, navbar, and footer. Every page renders inside BaseLayout via a <slot /> (simplified here):
---
import '../styles/base-framework.css';
import '../styles/prodesk.css';
import '../styles/global.css';
import Navbar from '../components/Navbar.astro';
import Footer from '../components/Footer.astro';
const {
title,
description,
ogImage = '/images/home-hero-image.svg',
noindex = false,
showFooter = true,
} = Astro.props;
---
<html lang="en">
<head><title>{title}</title> <!-- + meta, canonical, OG and font tags --></head>
<body>
<slot name="navbar"><Navbar /></slot>
<slot /> <!-- page content is injected here -->
{showFooter && <Footer />}
</body>
</html>
UtilityLayout.astro builds on BaseLayout for the template-info pages: it takes title, heading and intro props, renders a page heading block, and marks the page noindex.
Page Metadata & the 404 Page
Pass a title and description into BaseLayout on every page for correct browser tabs and search results (see also SEO). Use showFooter={false} to hide the footer (as the login and signup pages do) and noindex to keep a page out of search engines. Prodesk does not ship a custom 404 page; create a file named 404.astro in src/pages/ and Astro will serve it 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/ and encapsulate one piece of UI — a button, a pricing card, a navigation bar — so it can be reused across pages without copy-pasting markup. Every component in Prodesk is an .astro file. Shared pieces sit at the top level (Button, Tag, SectionHeading, CircularCta, Navbar, Footer, Reviews, SinglePricing, PricingTabs, AuthPage); page sections are grouped in home/ (HomeHero, AutomationTabs, ProcessManagement, AnalyticsAccordion, Performance, Security), features/ (FeatureHero, FeatureImages, AutomatingRoutine, CrmAnalytics, Integration) and pricing/ (PricingHero, PlanCard, Compare, Faq).
Props & Prop Comments
Props are the inputs a component accepts, similar to HTML attributes. Prodesk doesn’t use TypeScript interfaces; instead each shared component documents its props in a JSDoc comment at the top of its frontmatter and gives optional props a default value. Here is the real Button component (hover animation script omitted):
---
/**
* @prop href
* @prop variant 'primary' | 'secondary' | 'tertiary'
* @prop size 'regular' | 'small'
* @prop icon optional image path shown before the label
*/
const { href, variant = 'primary', size = 'regular', icon, class: className, ...rest } = Astro.props;
const small = size === 'small';
---
<a href={href} class:list={['button', variant !== 'primary' && `is-${variant}`, className]} {...rest}>
<div class:list={['button-size-controller', small && 'is-small']}>
{icon && <img src={icon} alt="" class="button-icon" />}
<div class:list={['button-text', small && 'is-small']}><slot /></div>
</div>
</a>
In plain language: href is the link target; variant picks one of three button styles and defaults to primary; size is regular unless you pass small; icon is optional. The button label isn’t a prop — it’s whatever you place between the tags, passed through the <slot />.
Component Composition
Larger sections are composed from smaller components rather than written as one long block of markup. For example, SectionHeading combines a Tag and a CircularCta, and the home page is just a list of section components:
<main>
<HomeHero />
<AutomationTabs />
<ProcessManagement />
<AnalyticsAccordion />
<Performance />
<Security />
<Reviews />
<SinglePricing />
</main>
Passing Data to Components
In Astro, props are passed the same way as HTML attributes and read via Astro.props:
---
import SectionHeading from '../SectionHeading.astro';
---
<SectionHeading class="fade-in-100ms" tag="INTEGRATION" title="Easy Integration with your favorite tools" />
Prodesk has no React or other UI framework. Interactive pieces — the mobile menu, the Features dropdown, tabs, the pricing toggle, the FAQ accordion and the Swiper slider — are small <script> blocks inside the relevant .astro component, which Astro bundles automatically.
Styling
Where to change colors, type, and spacing without fighting the build.
Global Styles & CSS Variables
Prodesk is styled with plain CSS in three stylesheets, all imported (in this order) by BaseLayout.astro: base-framework.css (base/reset and layout utilities), prodesk.css (the theme) and global.css (small additions such as focus outlines). Site-wide values — color palette, font families, section spacing — are defined once as CSS custom properties at the top of src/styles/prodesk.css and referenced everywhere else. Change a value here and it updates across the whole site.
:root {
--fonts--body: "Satoshi Variable", Verdana, sans-serif;
--fonts--heading: Onest, sans-serif;
--text-color--body: var(--colors--gray);
--text-color--heading: var(--colors--indigo);
--colors--green: #00b172; /* brand accent */
--colors--indigo: #2b2b46; /* headings */
--colors--gray: #6b6e88; /* body text */
--colors--light-green: #f3fcf9;
--colors--light-pink: #ffedfb;
--colors--light-purple: #f4f1ff;
--colors--light-yellow: #fffced;
--colors--light-blue: #f1fdff;
--colors--light-orange: #fff3ed;
--_spacing---section-spacing: 150px;
/* …plus white, black and font-weight tokens */
}
Component Styles
Most of Prodesk’s component styling lives as class rules in prodesk.css, so components mainly apply class names. A few components (Navbar, home/Performance, pricing/Faq) add their own <style is:global> block for behavior specific to them. For new components you can also use Astro’s scoped <style> blocks — CSS written there only applies to that component, so class names never collide across files.
<style>
.card { padding: 24px; border-radius: 16px; background: var(--colors--light-green); }
</style>
Responsive Design, Typography & Spacing
The type scale (h1–h6 sizes and line heights) and responsive overrides are defined in prodesk.css, which uses three max-width breakpoints: 991px (tablet), 767px (mobile landscape) and 479px (mobile portrait). Prefer adjusting these shared rules and the :root tokens over overriding sizes on individual elements, so the site keeps a consistent rhythm as you edit it. The /template-info/style-guide page shows the typography, buttons and special classes in one place.
Animation Classes
Scroll animations are applied by class name and run by src/scripts/animations.js (GSAP + ScrollTrigger), so you can animate any element without writing JavaScript:
slide-in-from-bottom-100ms…slide-in-from-bottom-800ms(also-from-left-/-from-right-) — slide and fade in when scrolled into view, after the given delay.fade-in-100ms…fade-in-800ms— fade in when scrolled into view.movement-loop-top-to-bottom/movement-loop-bottom-to-top— float gently up and down forever.move-from-bottom-to-top/move-from-top-to-bottom— travel and rotate into place as you scroll; must be placed inside afloating-animation-triggersection (desktop only unless the section hasdata-float-all).
All animations are skipped automatically for visitors who have “reduce motion” enabled in their operating system.
The dist/ folder is generated output — any change made there is overwritten on the next build. Always edit files under src/.
Images & Assets
Two homes for static files, and when to use each.
| Location | Use for | Behavior |
|---|---|---|
public/ | Where Prodesk keeps all of its images (public/images/), the Satoshi font (public/fonts/) and the favicons | Copied as-is, no processing; referenced by root-relative URLs like /images/logo.svg |
src/assets/ | Not used by the template, but available if you want Astro to optimize new images you add | Optimized, resized, and content-hashed automatically by the build |
Replacing Images
The easiest way is to swap the file in public/images/ while keeping the same filename. Otherwise, update the path where the image is used — in a component’s <img> tag, or in src/data/features.js for the feature-page images:
<img
src="/images/analytics-image.avif"
srcset="/images/analytics-image-p-500.avif 500w, /images/analytics-image.avif 1345w"
alt="Analytics dashboard"
class="full-size-image object-fit-contain"
/>
Some images have smaller -p-500 / -p-800 variants listed in a srcset; when you replace the main image, replace or remove those variants too so smaller screens don’t keep showing the old picture.
Supported Formats & SVGs
Photos and dashboard screenshots ship as AVIF; illustrations, icons, logos and background patterns ship as SVG. Any web format (JPEG, PNG, WebP, AVIF, GIF, SVG) works in an <img> tag. A handful of icons that need to inherit color via currentColor (the footer social icons and the CTA arrows) are written as inline <svg> markup directly in their components.
Image Optimization
Because the template’s images live in public/, the build does not resize or re-encode them — compress new images (for example to AVIF or WebP) before adding them. If you’d rather let Astro handle it, place new images in src/assets/ and render them with the Image component from astro:assets; they will then be resized and re-encoded at build time based on the width/height you specify.
To match the rest of the template, put new images in public/images/ and reference them as /images/your-file.avif. Use src/assets/ only for new images you want the build to optimize automatically.
Fonts & Icons
Swapping typefaces and icon sets without touching every component.
Google Fonts
Prodesk uses two typefaces: Onest for headings (from Google Fonts) and Satoshi for body text (self-hosted, see below). The Onest <link> tag lives in BaseLayout.astro’s <head>. To change the heading font, replace it with your chosen font’s embed code, then update --fonts--heading in src/styles/prodesk.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=Onest:wght@100..900&display=swap" rel="stylesheet" />
Local Fonts
The Satoshi variable font is self-hosted at public/fonts/Satoshi-Variable.ttf, declared with @font-face near the end of src/styles/prodesk.css, and preloaded in BaseLayout.astro. To swap it, drop your font file into public/fonts/, update the @font-face rule and the preload <link>, then change --fonts--body:
@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
Prodesk doesn’t use an icon library or package. Icons are individual SVG files in public/images/ (for example nav-book-open.svg, pricing-check.svg, check-mark.svg) used through <img> tags, plus a few inline <svg> icons written directly in Footer.astro (social links), CircularCta.astro and Navbar.astro (arrows). The dropdown caret in the navbar comes from a tiny icon font embedded in base-framework.css.
Replacing & Adding Icons
To replace an icon, overwrite its SVG file in public/images/ (keeping the filename) or point the src/icon value at a new file — for example the icon prop on Button or Tag, or the icon fields in featureLinks (Navbar.astro) and src/data/features.js. Inline SVG icons use fill="currentColor", so they pick up the surrounding text color; paste new SVG markup in place of the existing <svg> to change one.
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
Page files in src/pages/ mostly just list section components, so the text you see on screen lives in the section components themselves — for example the home hero in src/components/home/HomeHero.astro or the pricing banner in src/components/SinglePricing.astro. Locate the text between the tags and edit it directly:
<!-- before -->
<h2 class="h1">Unlimited Scope with low pricing</h2>
<p class="paragraph-large">Choose the plan that's right for your brand</p>
<Button href="/signup">Free Trial - Try for a month</Button>
<!-- after -->
<h2 class="h1">Simple pricing for growing teams</h2>
<p class="paragraph-large">Start free and upgrade when you're ready</p>
<Button href="/signup">Start your 30-day trial</Button>
Page titles and meta descriptions are the title and description props on BaseLayout at the top of each page file (see SEO).
Navigation & Footer
Menu links are kept as arrays at the top of src/components/Navbar.astro (the Features dropdown) and src/components/Footer.astro (the four footer link columns), so you edit each label and URL once rather than hunting through every page. See Navigation for the full pattern.
Cards, Testimonials & Pricing
Repeating content blocks are driven by a data array rather than hand-written per card, so adding or removing an item is a matter of editing the list. The testimonials are an array at the top of src/components/Reviews.astro:
const reviews = [
{
title: '“Saves me time”',
color: 'purple', // card background
quote: 'purple', // quote-mark icon color
text: "Its support for various payment methods…",
name: 'Kevin Douglas',
avatar: '/images/reviewer-image-1.avif',
animation: 'slide-in-from-bottom-400ms',
},
// …
];
Other editable content follows the same pattern:
- Feature pages — titles, intros, images and section blocks for Automation, Management and Analytics are entries in
src/data/features.js. - Pricing plans — plan names and monthly/yearly prices (Starter, Economy, Deluxe) are the
plansarray insrc/components/pricing/PricingHero.astro; each card’s feature list is thefeaturesarray insrc/components/pricing/PlanCard.astro; the “Starting at” monthly/yearly price is insrc/components/SinglePricing.astro. - Plan comparison table — the
groups,rowsand per-planvaluesarrays insrc/components/pricing/Compare.astro(true/falserender as a check or a dash; a string is shown as text). The table has its ownplansarray with names and prices, separate from the pricing cards — update both if you change a price. - FAQ — the
questionsarray andanswertext at the top ofsrc/components/pricing/Faq.astro.
Blog Content & Contact Information
Prodesk has no blog and no contact page, and there is no central site-config file. The brand details to update live in these components: the logo (/images/logo.svg) and links in Navbar.astro; the social links (Facebook, X, Skype — currently pointing at each network’s homepage) and the “© Prodesk” line in Footer.astro; the copyright line and “Continue with Google” link in AuthPage.astro; and the — Prodesk suffix in each page’s title prop.
Forms
What ships out of the box, and what still needs a backend.
The only forms in Prodesk are the login and signup forms, and they are front-end only: no backend, auth provider or third-party service is wired up. Submitting either form just hides it and shows a “Thank you! Your submission has been received!” message. Connect them to your auth provider or API before going live.
Contact Forms
Prodesk has no contact form. The login (/login) and signup (/signup) pages share one component, src/components/AuthPage.astro, which renders a name + email form (the mode prop switches between "login" and "signup"). Its demo submit handler is in the component’s <script> block — replace it with a call to your endpoint:
// Demo only: no backend is wired up, so show the success message instead of submitting.
document.querySelectorAll('[data-auth-form]').forEach((form) => {
form.addEventListener('submit', async (event) => {
event.preventDefault();
await fetch('[Replace with your form endpoint]', { // add this line
method: 'POST',
body: new FormData(form),
});
const done = form.parentElement.querySelector('.w-form-done');
form.style.display = 'none';
done.style.display = 'block';
done.focus();
});
});
The “Continue with Google” button on the same screen is a plain link to https://google.com; point it at your provider’s OAuth URL or remove it.
Newsletter Forms
Prodesk has no newsletter form and is not pre-wired for any email provider. If you add one, the same approach applies: point the form’s action at your provider’s embed endpoint (Mailchimp, ConvertKit, etc.) or post to it from a submit handler.
Form Validation
The login and signup forms rely on the browser’s built-in validation: both fields are required, the email field uses type="email", and both are capped with maxlength="256". This gives users immediate feedback without a round trip to a server; always validate again on your backend once you connect one.
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 a one-line change to the form’s action attribute.
API & Data
Only relevant if your template fetches data from an external source — skip this section otherwise.
The template makes no API calls and reads no environment variables. All content is static: it lives in the components themselves and in src/data/features.js, and is rendered to HTML at build time. The guidance below applies only if you connect your own API later.
API Configuration
If you add an API, read its URLs and keys from environment variables (see Configuration) rather than hard-coded, so the same code can point at a staging or production API depending on environment:
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
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
The only structured data file is src/data/features.js, which exports a features array — one object per feature page. If you later load this content from an API or CMS instead, return objects with the same fields so src/pages/features/[slug].astro keeps working:
{
slug: 'automation', // URL: /features/automation
title: 'Automation', // page <title> prefix
description: '…', // meta description
tag: { label: 'Automation', icon: '/images/book-open.svg' },
heading: 'Build your sales team to success',
intro: '…',
hero: { wrapperClass, images: [{ src, srcset?, alt, class }], spacer },
floatAllBreakpoints: true, // optional: animate floating hero images on mobile too
blocks: ['Sales automation with security', /* … */],
routine: { title, wrapperClass, images },
crm: { tag: 'SALES PERFORMANCE', animate: true },
}
Error Handling
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 BaseLayout on every page — these drive both the browser tab and the snippet shown in search results:
<BaseLayout title="Flexible pricing — Prodesk" description="Choose the best plan for your team.">
Feature pages take their title and description from src/data/features.js. BaseLayout also accepts ogImage (a path for the social preview image, defaulting to /images/home-hero-image.svg) and noindex (used by the template-info pages).
Canonical URL, Open Graph & Twitter/X Cards
Already set up inside BaseLayout.astro’s <head>, using the site value from astro.config.mjs to build absolute URLs — so make sure site is your real domain:
---
const canonical = new URL(Astro.url.pathname, Astro.site);
const ogImageUrl = new URL(ogImage, Astro.site);
---
<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={ogImageUrl} />
<meta name="twitter:card" content="summary_large_image" />
<!-- + twitter:title, twitter:description, twitter:image -->
Social platforms generally don’t render SVG preview images, so consider adding a 1200×630 JPG or PNG to public/images/ and passing it as ogImage.
Sitemap & Robots.txt
Prodesk uses Astro’s official sitemap integration, which generates sitemap-index.xml automatically at build time from the site value (the /template-info/ pages are filtered out), and BaseLayout links to it from every page. The template does not ship a robots.txt; to control crawler access, add one to public/ pointing to the sitemap:
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. Add JSON-LD structured data in the layout’s <head> for rich results (e.g. Organization or SoftwareApplication schema) where relevant to your content. Prodesk’s pages already use a single <h1> and a <main> landmark; it does not ship any JSON-LD, so add your own in BaseLayout.astro if you want rich results.
Deployment
Platform-by-platform steps. Confirm your rendering mode first — it changes the build output you deploy.
A static Astro build (the default) produces plain HTML/CSS/JS in dist/ that any static host can serve. An Astro site using server-side rendering (SSR via an adapter) and a React/Vite single-page app both need a Node-capable host or the platform’s matching adapter. Using the wrong instructions for your rendering mode is the most common deployment mistake. Prodesk is a fully static build with no adapter, so the static instructions below apply.
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
For a static build, upload the contents of dist/ to your host’s public web root via FTP/SFTP or your host’s file manager. For an SSR build or a React/Vite app that needs a Node process, the host must support running node continuously (a VPS or a Node-compatible host) — plain shared hosting without Node support cannot run it.
Build & Production
What happens when you run build, and a checklist before you ship.
npm run build # render pages, bundle, and write dist/
npm run preview # serve dist/ locally, exactly as it will run in production
Build Output
The build writes static HTML for every route, hashed CSS/JS bundles (including GSAP and Swiper), sitemap-index.xml, and a copy of everything in public/ to dist/. This folder is disposable and regenerated by every build — the template’s .gitignore already keeps it out of Git.
Environment Variables in Production
Prodesk needs no environment variables as shipped. If you add some, note 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 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. - If you added a
.envfile, set every variable from it in your hosting platform’s dashboard. - Connect the login and signup forms in
AuthPage.astroto a real endpoint, or remove them — as shipped they only show a demo success message. - Replace the placeholder footer social links and the “Continue with Google” link with your own URLs.
- 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 (for example
gsaporswiper), or a typo in a relative import path — often after moving a component into or out of a subfolder likehome/orpricing/.
- Solution
- Re-run
npm install; check the import path’s../depth and casing match the file exactly (the template uses relative paths, not aliases).
Images not loading
- Cause
- A path that includes
public/, a filename typo or case mismatch, or an image placed insrc/assets/but referenced with apublic/-style absolute path.
- Solution
- Review Images & Assets — files in
public/images/are referenced as/images/logo.svg(withoutpublic); images insrc/assets/need animportstatement.
Styles not loading
- Cause
- A new page doesn’t render inside
BaseLayout, or the stylesheet imports were removed or reordered.
- Solution
- Wrap every page in
<BaseLayout>; confirmBaseLayout.astrostill importsbase-framework.css,prodesk.cssandglobal.css, in that order.
Content invisible or animations not playing
- Cause
- Elements with a
slide-in-from-…orfade-in-…class start hidden untilanimations.jsreveals them; if that script doesn’t run (a page not usingBaseLayout, or a JavaScript error earlier on the page), they stay invisible. A malformed class such asfade-in-200(missingms) is still hidden by the CSS but never matched by the script, so that element stays invisible too.
- Solution
- Render the page inside
BaseLayout, check the browser console for errors, and use the exact class names listed in Animation Classes. Animations are intentionally off when the OS “reduce motion” setting is on.
Build fails (but dev server works)
- Cause
- The dev server only renders the pages you visit, while
buildrenders every route — including all feature pages fromfeatures.js— so an error on a page you didn’t open 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
- Only relevant if you’ve added a
.envfile (the template uses none). Missing thePUBLIC_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 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, as required by Astro 7 and declared in package.json — see Requirements. The current Node 22 or newer LTS release is a safe default.
Can I use JavaScript instead of TypeScript?
Prodesk is already plain JavaScript — there are no .ts files to convert. If you prefer TypeScript, Astro supports it out of the box: add .ts files or a typed Props interface in a component’s frontmatter, and the existing tsconfig.json already extends Astro’s strict preset.
How do I change colors?
Update the CSS custom properties at the top of src/styles/prodesk.css — --colors--green is the brand accent, --colors--indigo the heading color, --colors--gray the body text. See Styling.
How do I change fonts?
Swap the Onest Google Fonts link 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/ with the same name, or update the path in the component or in src/data/features.js — see Images & Assets.
How do I add a new page?
Add a file to src/pages/; the route is created automatically. For another feature page, add an entry to src/data/features.js instead — 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?
The template’s /template-info/license page lists the bundled asset licenses: images from Unsplash and Pexels, 3D illustrations by Aurielaki under CC BY 4.0, and the Onest (Google Fonts) and Satoshi (Fontshare) fonts under their own licenses. [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