Skip to content
AstroCraft Docs
On this theme

Installation

Finly ships as a complete Astro project, not as an npm package or an integration you register. You clone the repository, install its dependencies and start editing — there is no theme layer between you and the markup, and nothing is hidden inside node_modules. Every component, token, icon and animation is a file in src/ that you own from the first commit.

It runs with no configuration, no API keys and no accounts. pnpm install followed by pnpm dev gives you the whole site — home, product, a 60-connector integrations directory, pricing, ten customer stories, a paginated blog, nine careers adverts, about, contact, three account screens and legal pages — populated with written sample content. Configuration is what you do after you have looked around, not a prerequisite for seeing it work.

Requirements

  • Node.js 22.12.0 or newer. engines.node in package.json pins the floor at >=22.12.0, and the reason is the test runner rather than the language: every check under src/ runs through Node’s --experimental-strip-types, which arrived in 22.6 and became usable without a flag dance in 22.12. Check yours with node -v.
  • pnpm. The lockfile is pnpm-lock.yaml and pnpm-workspace.yaml carries settings that only pnpm reads. corepack enable pnpm is the shortest route if you do not have it.
  • Git, to clone the repository and to keep your own history from the first commit onward.

You do not need a hosting account, an email provider or a domain to run the theme locally. One route — /contact/ — is server-rendered, and it renders perfectly well without an email provider configured; the action returns a readable error instead of a build failure. Everything else is a prerendered file.

Get the code

Clone the repository and drop the upstream history so your project starts with a clean log:

git clone https://github.com/Astro-Craft-Theme/finly.git my-fintech
cd my-fintech
rm -rf .git && git init

If you would rather keep the upstream remote so you can pull theme updates later, skip the rm -rf .git and rename the remote instead:

git remote rename origin upstream
git remote add origin [email protected]:you/my-fintech.git

Keeping upstream is only worth it if you plan to merge theme changes. Because the theme is source you edit directly, a merge after heavy customization is a real merge — most people take the clean-slate route and treat the clone as a starting point.

Install dependencies

pnpm install

The runtime dependency list is ten packages, and the shape of that list is the whole design philosophy of the theme in one place:

"dependencies": {
  "@astrojs/cloudflare": "^14.2.1",
  "@astrojs/mdx": "^7.0.5",
  "@astrojs/sitemap": "^3.7.3",
  "@fontsource-variable/plus-jakarta-sans": "^5.3.0",
  "@tailwindcss/vite": "^4.3.3",
  "astro": "^7.2.0",
  "tailwind-merge": "^3.6.0",
  "tailwind-variants": "^3.3.1",
  "tailwindcss": "^4.3.3"
}

Astro, Tailwind and its two class-composition helpers, one variable font, and three official Astro integrations — MDX, the sitemap and the Cloudflare adapter. sharp sits in devDependencies, where build-time image optimization belongs. There is no UI kit, no animation library, no SEO package, no icon package, no schema package, no RSS package and no CMS. Those are all implemented inside the theme rather than pulled in: the 61 UI primitives, the 91-utility motion catalog, the JSON-LD builders, the 571-icon registry, the hand-rolled RSS feed and the typed config layer are source files in src/. That is why the surface you have to keep up to date stays small, and it is also why customizing any of them means editing a file rather than reading a plugin’s options.

Two settings in pnpm-workspace.yaml are worth knowing about before they surprise you:

  • allowBuilds denies post-install build scripts for esbuild, sharp and workerd. None of the three needs to compile for the project to work — workerd in particular is only the local runtime binary that wrangler dev uses, and neither astro build nor the deployed Worker touches it. If your install prints a notice about ignored build scripts, that is this setting working as designed.
  • minimumReleaseAgeExclude pins the Tailwind package set to the exact versions the theme was built and tested against, including every platform-specific @tailwindcss/oxide-* binary.

Start the dev server

pnpm dev

The site is at http://localhost:4321. Every route is available immediately with sample content in place:

  • / — the home page
  • /product/ and /product/integrations/ — the overview plus a 60-connector directory in five categories
  • /pricing/, /about/, /careers/, /contact/
  • /blog/, /blog/page/2/, /blog/<slug>/, /blog/category/<slug>/, /blog/author/<slug>/ — thirteen posts, five authors, five categories
  • /customers/, /customers/<slug>/, /customers/industry/<slug>/ — ten stories across five industries
  • /login/, /signup/, /forgot-password/ — the three account screens, drawn without site chrome
  • /privacy/ and /terms/ — placeholder legal copy
  • /rss.xml, /robots.txt, /llms.txt, /sitemap-index.xml — all generated, all deriving their absolute URLs from one setting

Twenty-four page routes and three endpoints produce 123 pages: 122 HTML files land in dist/client/ and /contact/ is served on demand. The full map is in Pages & Routing.

The primitive catalog

Before you start building pages, open http://localhost:4321/examples/ui/. It is a development-only catalog rendering all 61 UI primitives in every variant, alongside the motion utilities and the full 571-icon registry, grouped into nine panels — statics, disclosure, overlays, chrome, navigation, form controls, icons, motion and page-level primitives. It is the fastest way to find out what already exists rather than rebuilding it.

The route is gated inside getStaticPaths:

export function getStaticPaths() {
  return import.meta.env.PROD ? [] : [{ params: { catalog: "ui" } }];
}

A production build emits no paths for it, so no HTML ships. You can leave it in place while you work. When you no longer need it, delete src/pages/examples/ and src/components/UiCatalog/ together — Tailwind still scans the catalog’s markup even though it builds no pages, so its demo classes sit in the stylesheet every real page loads.

Configuration and environment

There is no .env file to copy, and no environment variable a local run needs. Two things are configured instead, and only one of them lives outside the repository.

site in astro.config.mjs is the field only you can fill. It feeds the canonical link, og:url, hreflang, the sitemap, robots.txt, llms.txt, rss.xml and the JSON-LD @ids, so one wrong value poisons seven things at once and none of them looks broken in review. It ships pointing at the theme’s own demo deployment:

const SITE = "https://finly.domidex01.workers.dev/";

Change it in the same commit that moves the site. It is a const rather than a literal inside defineConfig because the sitemap’s customPages needs the same origin, and two copies of a URL are two chances to disagree.

Three secrets belong to the contact form, declared in the env.schema block of astro.config.mjs and all optional:

RESEND_API_KEY      // resend.com -> API keys
CONTACT_TO_EMAIL    // where submissions land
CONTACT_FROM_EMAIL  // defaults to Resend's shared sandbox sender

They are read at request time through astro:env/server, never at build, so a fresh clone builds and runs without them — the form renders and, on submit, returns “This form is not available right now” instead of failing a build. On Cloudflare they are Worker secrets (npx wrangler secret put RESEND_API_KEY), never files. Contact Form & Email covers the whole path.

Make it yours

With the site running, these are the first files to edit. All of them are typed, so a mistake fails the build with the offending value named rather than shipping quietly.

  1. src/config/en/siteData.json.ts — brand name, the home page’s title and description, the tagline, the regulatory disclaimer, the legal entity, the sample notice, the author block, sameAs and the default social image. The description is not only the home page’s: it is the site-wide WebSite JSON-LD description on every page and the lead line of /llms.txt.
  2. src/config/en/navData.json.ts — one source for the header’s four mega-menu groups and the footer’s four columns. Every row in it resolves, and a build hook keeps it that way; read Configuration before you extend it.
  3. src/config/siteSettings.json.tslocales, defaultLocale, localeMap, and two switches: useViewTransitions and useAnimations (the master switch for decorative motion). prefers-reduced-motion is honored by a global CSS guard regardless of what useAnimations says; the flag is a design choice, not an accessibility one.
  4. src/config/en/legalData.json.ts — the terms and privacy copy. It is explicitly placeholder text. Have a professional review it; it is not legal advice.
  5. public/og.jpg, public/favicon.svg, public/favicon.ico — the shipped og.jpg is a labelled placeholder, and it doubles as the JSON-LD Organization logo until you pass a real one, so replacing it fixes two things at once.
  6. src/data/ — replace the thirteen posts, five authors and ten customer stories. Each entry is a folder whose name is the URL slug, holding an index.md. Schemas live in src/content.config.ts, so bad frontmatter fails the build with the entry named.

Two fields are empty on purpose and should stay empty until they are true: siteData.sameAs and siteData.author.twitter. Finly is an invented company, and every plausible value for either points at a real stranger’s account. BaseHead renders twitter:creator only when the handle is truthy, and sameAs is omitted from the Organization node entirely when the array is empty, so an unfilled field costs nothing while a wrong one misattributes the site.

Colors, type and spacing are not in that list because they are not in the config layer. They are CSS tokens in src/styles/tailwind-theme.css and src/styles/global.css, and the Colors & Theming and Typography chapters cover them.

Verify your install

pnpm lint && pnpm check && pnpm build && pnpm test
  • pnpm lint runs ESLint, including the Astro JSX accessibility rules.
  • pnpm check runs astro check across .astro and .ts files.
  • pnpm build is the real check. Content-schema errors, config typos and broken references all surface here rather than in the browser — and one of them is unique to this theme: the finly:link-integrity hook scans the emitted HTML and fails the build naming any href that points at a path the build did not produce.
  • pnpm test discovers and runs every scripts/*.test.mjs and every src/**/*.test.ts / *.selfcheck.ts file. There are fifteen today, and the runner walks both trees rather than reading a list, so a check dropped beside new logic is picked up without editing it.

There is also pnpm format, which runs eslint --fix and then Prettier. Class ordering is handled by prettier-plugin-tailwindcss, so let it sort and do not hand-order class lists.

Two things to know before you start building

Light is the default theme, and the device preference is deliberately ignored. BaseHead ships an inline, pre-paint script that reads localStorage("colorTheme"); only a saved "dark" — written by the ThemeToggle primitive — turns dark mode on. A first-time visitor always lands on the light theme the design was built around, whatever their OS is set to. The script stays inline on purpose; moving it into a bundled <script> reintroduces a flash of the wrong theme.

Every link on the site resolves, and the build enforces it. There is no planned-routes list and no redirect table here, because there is nothing to redirect: the footer was trimmed to the pages that exist rather than stubbed out, and finly:link-integrity fails pnpm build the moment a href points somewhere the build did not emit. Add the route before you link it — see Pages & Routing.

Troubleshooting

A renamed content entry keeps 404ing in dev. Astro’s content layer caches entries, and moving or renaming a folder while the dev server runs can leave the old entry in place and the new one missing. Restart the dev server; touching the file will not clear it.

A utility class has no effect in dev. In a long-running dev server, classes used only in newly created files can be missing from the generated stylesheet. Restart before you go looking for a bug in your markup — a pnpm build that renders correctly while dev does not is the tell.

Every image renders as alt text in dev. sharp has stopped resolving in the running dev process. Restart it; pnpm build is unaffected, which is again the tell.

Node version errors on install. The floor is 22.12.0. Older releases fail even if the install itself appears to succeed.

More in Troubleshooting.

NEXT STEPProject Structure