AstroStarter

craftline-astro-theme — Astro Starter Template

By formgong

A free Astro theme for plumbers and other local service businesses, featuring a scroll-driven narrative homepage, a CSS 3D house scene, and a quote form powered by Formgong.

Explore the design

Compare the page layouts and mobile experience. Open any screenshot for a closer look.

3 previews
Desktop homepage1 / 3
Desktop captureTop of page

Actual screenshot captured by the server browser.

All pages & views 3

Screenshots show visual appearance; interactive behavior may differ.

Recorded 2026-10-08View source

What stands out

A quick read of the recorded project description.

01

The homepage scroll narrative is implemented with CSS scroll-driven animations, including a fixed-view CSS 3D house cutaway, with no animation library or WebGL.

02

The quote form only shows success when the Formgong backend returns success: true; errors and network failures display error messages, and it can still submit without JavaScript.

03

Brand information, contact details, service areas, business hours, social links, accent color, and form keys are centralized in a single file, src/config.ts.

04

Services, testimonials, and FAQs are managed by Markdown and JSON content files; service cards can configure line animation types.

05

A dark navigation base paired with a single accent color; service cards are solid accent blocks, and all text color pairs meet AA contrast.

06

Static pages, one self-hosted variable font, and two small scripts, with prefers-reduced-motion handled.

Template Details

Craftline is a free theme built with Astro for local service businesses such as plumbers, electricians, cleaners, handymen, and contractors. The demo site fictionalizes Northside Plumbing & Heating, a plumbing company; all phone numbers, email addresses, and links are sample content. The theme centers on a scroll-driven narrative on the homepage: from a late-night leak, submitting a form on a phone, a van departing, a fixed quote, to the floor drying out, accompanied by a fixed three-quarter-view CSS 3D house cutaway showing the kitchen, pipes, and boiler. All animations are driven by CSS scroll, with no animation library, WebGL, or JavaScript. The quote form submits to a Formgong hosted backend and only shows a success state when the backend returns success: true; without JavaScript, it still submits as a normal HTML form. Brand information, contact details, service areas, business hours, social links, accent color, and form keys are centralized in a single file, src/config.ts. Services, testimonials, and FAQs are managed by Markdown and JSON content files. The theme uses a dark navigation base, light display type, and a single accent color; service cards are solid accent blocks with small line animations. The build toolchain is Astro, Tailwind CSS, and TypeScript, requiring Node 22.12 or newer.

AstroStarter

Is it right for your project?

Use Cases

  • Building a local service showcase website for plumbers, electricians, cleaners, handymen, or contractors.
  • Needing an industry theme homepage with a scroll narrative and a 3D house scene.
  • Wanting to collect quote requests through a hosted form backend without faking submission success.
  • Needing to quickly replace sample content after centralizing brand information, service content, and contact details.
  • Ensuring forms and content remain accessible in environments without JavaScript or with reduced motion.

Suitable For

  • Local service businesses such as plumbers, electricians, cleaners, handymen, and contractors.
  • Sites that accept using Formgong or a compatible hosted backend that accepts standard form POST to receive quotes.
  • Developers using Astro who need static output, content file management, and centralized configuration.
  • Websites that need a dark interface, a single accent color, and accessible forms.

Getting started & customization

Use these recorded setup notes alongside the repository instructions for your chosen version.

  1. 1

    Requires Node 22.12 or newer; use npm create astro or clone the repository, then run npm install and npm run dev.

  2. 2

    Replace sample content in src/config.ts, including name, phone, address, service areas, business hours, social links, accent color, and form keys.

  3. 3

    Create a free form on Formgong to obtain an access key starting with fk_, and configure it via PUBLIC_FORMGONG_ACCESS_KEY in .env or in src/config.ts.

  4. 4

    Set url in src/config.ts to the real domain, and replace the logo, favicon, og.png, and apple-touch-icon.png.

  5. 5

    Third-party assets such as demo images, fonts, and icons must be checked against their respective licenses; external services such as domains and hosting may incur additional charges.

Read repository instructions

License & source material

Usage conditions & limitations

Free to use · keep license notice

This entry covers the free version under the MIT license in the public repository; the free scope is the code of that version and does not mean external services or third-party assets are free.

Must comply with when using

  • Free use, modification, commercial use, and distribution of this version's code are permitted.
  • When distributing copies or substantial portions of the code, retain the original author's copyright notice and the full MIT license notice.
  • The code is provided as is; warranties and limitations of liability are governed by the original license and applicable law.

Additional costs & items to verify

  • Demo images, fonts, icons, and other third-party assets must be checked against their respective licenses and cannot be judged solely by the code's MIT license.
  • External services such as domains, hosting, databases, payments, or AI may incur additional charges.
  • The quote form by default relies on the Formgong hosted form backend and requires an external service to receive submissions.
  • Using the form feature requires registering with Formgong and creating a form, which means an external account is needed.
  • A Formgong access key starting with fk_ must be obtained and configured for the form to work.
  • Formgong's free plan covers only 300 submissions per month; exceeding this may require a paid upgrade.
  • If not using Formgong, you must switch to another backend service that accepts standard form POST.
  • When deploying to Vercel or Netlify, the access key must be configured in the build environment variables; the key is read at build time.
  • When using the Cloudflare deploy button, the key is stored as a Worker secret and injected into the form by worker.js on each page request.
View Original Text Basis

Permission is hereby granted, free of charge

Original License Text

The quote form posts to [Formgong](https://formgong.com), a hosted form backend, so you don't need a server.

Original README

Create a free form at [formgong.com/new](https://formgong.com/new?name=Website%20quote%20form) (or from the dashboard if you already have an account).

Original README

Copy the form's access key. It starts with `fk_` and is public by design: it only lets visitors send submissions to that one form.

Original README

The free plan covers 300 submissions a month.

Original README

**Using another form backend.** Any service that accepts a standard form `POST` works.

Original README

On Vercel or Netlify, set `PUBLIC_FORMGONG_ACCESS_KEY` in the project's build environment variables: the key is read at build time.

Original README

The Deploy to Cloudflare button stores it as a Worker secret instead, and `worker.js` puts it into the form as each page is served.

Original README
https://github.com/formgong/craftline-astro-theme/blob/main/LICENSEhttps://github.com/formgong/craftline-astro-theme/blob/main/README.md

Compiled by DeepSeek based on repository license and README ·2026-10-08. Results only cover the materials read; dependencies, images, fonts, and subsequent term changes are subject to their respective original texts.

Project checks & description sources

Template Information

Source platforms
GitHub
Documentation and maintenance reference score
More documented · 80 / 100
Technologies
Astro
Website type
Starter
How this score is calculated

Our heuristic uses license records (up to 30), a demo link (12), a preview (10), stars (15), recorded maintenance (15), description completeness (8), feature records (5) and classification data (5). It is not a code, security or performance test, or a Google score. A link does not establish tested functionality.

What to verify for this project

Repository update recorded
2026-10-08
Screenshot last checked
2026-10-08

A demo link is listed. Check it with your own content and viewport sizes; its presence does not confirm that forms, authentication or payments work.

The catalog identifies Astro as the primary stack. Check the actual dependency manifest and lockfile for versions and hosting requirements. These notes use recorded metadata, not a code audit or a deployment test.

Use a selection guide →

How this description was prepared

AI-assisted description based on catalog records and repository material. Repository authors are not automatically the reviewers of this description.

Review declaration: [email protected] · 2026-10-09

Inspect the recorded source material

SHA-256: a4a47c4c5b941387d0b227279b6afed5e10f1ec2e2a9ce332cbd5779a05dd3d7

2026-10-08T22:09:52.378Z

Source file / repository
# Craftline

A free Astro theme for local service businesses: plumbers, electricians, cleaners, handymen and contractors.

**Live demo:** https://craftline.formgong.com · **No build step?** Download `craftline-html.zip` from the [latest release](https://github.com/formgong/craftline-astro-theme/releases/latest): plain HTML files, replace `fk_your_access_key` and `https://example.com` with your own and upload them anywhere.

[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/formgong/craftline-astro-theme) [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fformgong%2Fcraftline-astro-theme&project-name=craftline&repository-name=craftline&env=PUBLIC_FORMGONG_ACCESS_KEY&envDescription=Your%20Formgong%20access%20key%20%28fk_...%29.%20Create%20a%20free%20form%20to%20get%20one.&envLink=https%3A%2F%2Fformgong.com%2Fnew%3Fname%3Dcraftline)

Each button copies the theme to your GitHub, builds it and asks for one value: your Formgong access key (`fk_…`), free at https://formgong.com/new. The form works from the first deploy. Then set `url` in `src/config.ts` to your domain.

The demo business is **Northside Plumbing & Heating**, a fictional plumber in the fictional town of Fernhollow. Everything you see is sample content: phone numbers use the 555-01xx range reserved for fiction, and every email and link uses `example.com`.

- **One file to rebrand.** Name, phone, address, service areas, hours, social links, accent color and the form key live in `src/config.ts`.
- **A home page that tells a story.** The hero picture is the first frame of a scroll story: a leak at 11:40 pm, a form sent from a phone, a van on the way, a fixed price, a dry floor. The house is a real CSS 3D object, seen at a fixed three-quarter angle, with a cutaway front wall where the leak and the repair happen. Everything is driven by CSS (scroll-driven animations). No animation library, no WebGL, no JavaScript.
- **A quote form that never fakes success.** It shows "Request received" only when the form backend answers `success: true`. Errors and lost connections show an error. Without JavaScript it still works as a plain HTML form.
- **Dark, light type, one loud accent.** A navy ground, large light-weight display type with the key words in the accent, solid accent service cards with small line animations that explain each service, stat counters, a large quote panel, and an ambient pipe network behind the hero.
- **Fast and accessible.** Static pages, one self-hosted variable font, two tiny scripts (the form and closing the mobile menu). Labels on every field, visible focus, AA contrast on every text color pair, `prefers-reduced-motion` respected.

Built with Astro 7, Tailwind CSS 4 and TypeScript.

## Quick start

```sh
npm create astro@latest -- --template formgong/craftline-astro-theme
cd your-project
npm run dev
```

Or clone the repository and run `npm install`, then `npm run dev`. Node 22.12 or newer is required.

| Command           | What it does                                   |
| ----------------- | ---------------------------------------------- |
| `npm run dev`     | Local dev server at `http://localhost:4321`    |
| `npm run build`   | Static site in `dist/`                         |
| `npm run preview` | Serve the built site locally                   |
| `npm run check`   | Type-check `.astro` and `.ts` files            |

## Rebrand it

Open `src/config.ts`. The main fields:

| Field                         | Used for                                                                     |
| ----------------------------- | ---------------------------------------------------------------------------- |
| `name`, `shortName`, `tagline`, `description` | Header, footer, page titles, meta description, JSON-LD       |
| `url`                         | Canonical URLs, Open Graph, sitemap, robots.txt and the form's redirect      |
| `schemaType`                  | schema.org type: `Plumber`, `Electrician`, `HVACBusiness`, `RoofingContractor`, `GeneralContractor` or `LocalBusiness` |
| `phone`, `emergencyPhone`, `email`, `address` | Click-to-call buttons, contact page, footer, JSON-LD          |
| `serviceAreas`                | Service area list and map (the first eight get a pin), JSON-LD `areaServed`  |
| `hours`, `hoursNote`          | Contact page, footer, JSON-LD opening hours                                  |
| `social`                      | Footer icons. Real profile URLs are also added to JSON-LD `sameAs`           |
| `trust`                       | License number, years, rating, response time, call-out fee. Sample values: replace them, then clear `trust.note` |
| `theme.accent`, `theme.accentText` | The one accent color (highlighted words, buttons, service cards) and the text color on accent fills (keep 4.5:1 contrast) |
| `formgong`                    | Fallback access key, endpoint and email subject for the quote form           |

Replace the logo in `src/components/Logo.astro` and `public/favicon.svg`, and regenerate `public/og.png` (1200×630) and `public/apple-touch-icon.png` (180×180).

The JSON-LD block deliberately has no star rating: search engines ignore ratings a business publishes about itself.

## Set up the form

The quote form posts to [Formgong](https://formgong.com), a hosted form backend, so you don't need a server.

1. Create a free form at [formgong.com/new](https://formgong.com/new?name=Website%20quote%20form) (or from the dashboard if you already have an account).
2. Copy the form's access key. It starts with `fk_` and is public by design: it only lets visitors send submissions to that one form.
3. Add it to a `.env` file in the project root:

   ```sh
   PUBLIC_FORMGONG_ACCESS_KEY=fk_your_access_key
   ```

   or set `formgong.accessKey` in `src/config.ts`. While the placeholder key is in use, the dev server shows a reminder above the form.
4. Set `url` in `src/config.ts` to your real domain. Visitors without JavaScript are redirected to `/thanks/` on that domain.

Submissions arrive by email and, if you connect it, in Telegram. The free plan covers 300 submissions a month.

**How the form behaves**

- Without JavaScript: a normal `POST` to `https://formgong.com/submit`. The hidden `_redirect` field sends the visitor to `/thanks/` afterwards.
- With JavaScript: the same fields are sent with `fetch` and `Accept: application/json`. The button is disabled while sending. The success state, with its checkmark animation, appears only when the JSON response has `success === true`. Any other response shows the server's `message`. A network failure shows an error and the phone number.
- The hidden `botcheck` field is a spam honeypot. Keep it empty and keep it in the markup.

**Using another form backend.** Any service that accepts a standard form `POST` works. Set `PUBLIC_FORMGONG_ENDPOINT` (or `formgong.endpoint`) to its URL and rename the hidden fields to what that service expects. If its JSON response is shaped differently, change the single `reply?.success === true` check in `src/components/QuoteForm.astro`.

## Edit the content

- **Services:** one Markdown file per service in `src/content/services/`. Frontmatter: `title`, `summary`, `order`, `priceFrom`, `priceNote`, `duration`, `included` (list), `featured` (adds the emergency number to the card) and `art`, the card's line animation: `pulse`, `sonar`, `drain`, `bars`, `wave` or `drip` (see `src/components/ServiceArt.astro`). The body is the service page.
- **Headings:** wrap key words in asterisks to show them in the accent, for example `title="What we fix, and what it *usually costs*"` (section headings, page headers and the quote section).
- **Testimonials:** `src/content/testimonials.json`. Each review can point to a service by its file name. The demo reviews are samples and are labeled as such on the page.
- **FAQ:** `src/content/faq.json`.
- **Page copy:** the home page story captions are in `src/components/story/StoryHero.astro`; the hero headline and bullets in `src/pages/index.astro`.

Some sample figures appear in copy as well as in the config (the $129 call-out in the FAQ, the $149 repair in the story). Search for `$` when you change prices.

## The home page story

Four files:

- `src/components/story/StoryHero.astro`: hero text and the six chapter captions.
- `src/components/story/StoryScene.astro`: three stacked layers that share one coordinate system: the sky and road (SVG), the house (below), and the cards, phone and van in front of it (SVG).
- `src/components/story/House3D.astro`: the house as a CSS 3D box (`transform-style: preserve-3d`): four walls, floor, a two-plane roof and a chimney. The front wall is the cutaway with the kitchen, pipes and boiler that the story animates.
- `src/styles/story.css`: layout, the 3D geometry and the timelines.

The scene is a 1200×600 canvas anchored to the right edge. The frame is a size container, and one canvas unit is `--u = max(100cqw / 1200, 100cqh / 600)` pixels, so the SVG layers and the 3D house line up exactly at any frame size. On wide layouts the unit is capped so the house stays in the right half.

The house itself never moves. It sits at one fixed three-quarter angle (the cutaway faces you, the left wall and the roof show), and only the things inside the cutaway and the cards around it animate. An earlier version turned the house with the scroll; on a pinned stage that read as the house jumping, so the 3D wrappers now have no animations at all.

Each caption block declares a named view timeline (`--ch1` … `--ch6`) and the story wrapper shares them with `timeline-scope`. Every animated part of the scene follows exactly one chapter, with `animation-range` set per layout. When something has to appear in one chapter and leave in a later one, it sits inside two nested groups with one animation each. On desktop the scene is pinned next to the captions; on phones it is pinned at the top (about 55% of the screen) and the captions scroll underneath.

Browsers without scroll-driven animations or `timeline-scope`, and visitors who prefer reduced motion, get a static version: a front-facing house that doesn't move, and a small picture next to each caption. Nothing is hidden. The scroll version was checked in Chrome and in WebKit (Playwright's WebKit 27.2, via a recorded video: its screenshot path flattens every 3D transform, even a plain test cube).

To adapt the story to another trade, rewrite the captions and redraw the parts of the scene you need, or replace `StoryHero` with a plain hero in `src/pages/index.astro`.

Two CSS details that keep it working:

- Scroll-driven rules use longhand properties (`animation-name`, `animation-timeline`, …). A minifier can merge a shorthand and `animation-timeline` into one declaration that Chrome rejects.
- Wrappers around revealed content use `overflow: clip`, not `overflow: hidden`. `overflow: hidden` creates a scroll container, and a view timeline inside it would track that box instead of the page.

## Look

Dark first: navy ground (`--c-bg`), near-white type, one accent from `theme.accent`. Display type is Urbanist at a light weight; the key words of each heading take the accent and a thin accent rule follows the lead. Service cards are solid accent blocks with dark type. Colors are tokens at the top of `src/styles/global.css`.

## Motion

All motion is CSS and SVG. Page-to-page transitions use native cross-document View Transitions (`@view-transition`), so there is no client router. Sections fade in with `animation-timeline: view()` where supported. The stat numbers count up once as they scroll in (a registered integer property printed with `counter()`; screen readers get the plain number). The pipe network behind the hero (`src/components/story/PipeNetwork.astro`) is generated at build time from a fixed seed, with slow water pulses along some runs. Hover effects move only `transform` and `opacity`. With `prefers-reduced-motion: reduce` there are no transitions, reveals, counters or ambient animations: everything shows its final state.

## Project structure

```text
src/
├── components/
│   ├── story/          StoryHero, StoryScene (SVG layers), House3D (CSS 3D house), PipeNetwork, StoryVignette (static fallback pictures)
│   ├── sections/       Stats, services grid, quote panel, how it works, areas, reviews, FAQ, quote section
│   ├── illustrations/  Van, map placeholder
│   ├── QuoteForm.astro The form and its script
│   ├── Head.astro      Meta tags, Open Graph, JSON-LD
│   ├── Header.astro, Footer.astro, Logo.astro, Icon.astro, icons.ts
│   └── PageHeader.astro, SectionHeading.astro, Highlight.astro, ServiceCard.astro, ServiceArt.astro
├── content/            services/*.md, testimonials.json, faq.json
├── layouts/            BaseLayout.astro
├── lib/schema.ts       JSON-LD built from the config
├── pages/              index, about, contact, thanks, 404, services/, robots.txt.ts
├── styles/             global.css (tokens, components, motion), story.css
├── config.ts           Everything you rebrand
└── content.config.ts   Collection schemas
public/                 favicon.svg, og.png, apple-touch-icon.png
```

## Deploy

`npm run build` produces a static site in `dist/` that any static host can serve. On Vercel or Netlify, set `PUBLIC_FORMGONG_ACCESS_KEY` in the project's build environment variables: the key is read at build time. The Deploy to Cloudflare button stores it as a Worker secret instead, and `worker.js` puts it into the form as each page is served. Set `url` in `src/config.ts` first so canonical links, the sitemap and the form redirect point at your domain.

## License

MIT, see `LICENSE`. The illustrations and icons were drawn for this theme and are covered by the same license. The font is Urbanist, licensed under the SIL Open Font License 1.1 and installed from `@fontsource-variable/urbanist`.
Report a correction

Explore similar templates

Compare previews and descriptions within the same stack and category.