Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion TEMPLATES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Templates

Catalog of 51 templates from [templates.json](templates.json).
Catalog of 52 templates from [templates.json](templates.json).

| Template | Thumbnail | Live demo | Tech stack |
| --- | --- | --- | --- |
Expand Down Expand Up @@ -55,3 +55,4 @@ Catalog of 51 templates from [templates.json](templates.json).
| [The Rooms](templates/the-rooms/) | <a href="https://github.com/hostinger/hostinger-templates/blob/main/templates/the-rooms/preview/the-rooms-thumbnail.png?raw=true"><img src="https://raw.githubusercontent.com/hostinger/hostinger-templates/main/templates/the-rooms/preview/the-rooms-thumbnail-480.webp" width="180" alt="The Rooms thumbnail"></a> · [Full preview](https://github.com/hostinger/hostinger-templates/blob/main/templates/the-rooms/preview/the-rooms-homepage.png?raw=true) | [Open demo](https://the-rooms.hostingertemplates.com) | Nuxt 3 (Vue 3), Nitro server rendering |
| [Model](templates/model/) | <a href="https://github.com/hostinger/hostinger-templates/blob/main/templates/model/preview/model-thumbnail.png?raw=true"><img src="https://raw.githubusercontent.com/hostinger/hostinger-templates/main/templates/model/preview/model-thumbnail-480.webp" width="180" alt="Model thumbnail"></a> · [Full preview](https://github.com/hostinger/hostinger-templates/blob/main/templates/model/preview/model-homepage.png?raw=true) | [Open demo](https://model.hostingertemplates.com) | Next.js 16 App Router, React |
| [Route Library Halloween](templates/route-library-halloween/) | <a href="https://github.com/hostinger/hostinger-templates/blob/main/templates/route-library-halloween/preview/route-library-halloween-thumbnail.png?raw=true"><img src="https://raw.githubusercontent.com/hostinger/hostinger-templates/main/templates/route-library-halloween/preview/route-library-halloween-thumbnail-480.webp" width="180" alt="Route Library Halloween thumbnail"></a> · [Full preview](https://github.com/hostinger/hostinger-templates/blob/main/templates/route-library-halloween/preview/route-library-halloween-homepage.png?raw=true) | [Open demo](https://route-library-halloween.hostingertemplates.com) | Express 5 with server-rendered EJS views |
| [Walkies](templates/walkies/) | <a href="https://github.com/hostinger/hostinger-templates/blob/main/templates/walkies/preview/walkies-thumbnail.png?raw=true"><img src="https://raw.githubusercontent.com/hostinger/hostinger-templates/main/templates/walkies/preview/walkies-thumbnail-480.webp" width="180" alt="Walkies thumbnail"></a> · [Full preview](https://github.com/hostinger/hostinger-templates/blob/main/templates/walkies/preview/walkies-homepage.png?raw=true) | [Open demo](https://walkies.hostingertemplates.com) | React, React Router, Vite |
115 changes: 115 additions & 0 deletions templates.json
Original file line number Diff line number Diff line change
Expand Up @@ -6000,6 +6000,121 @@
"outputDirectory": "",
"entryFile": "dist/server.js"
}
},
{
"id": "walkies",
"name": "Walkies",
"summary": "A dog walking service site with a walk-area map and a slot-based booking flow.",
"description": "Walkies is a website for an independent dog walker or small walking team. It presents the service on a warm landing page, lists every walk area beside an illustrated map with lead-policy filters, and lets owners book by picking an area, a day, and an available time slot before confirming with their dog's details. Availability is deterministic sample data, so the demo works without a backend.",
"bucket": "Non-technical",
"categories": [
"Business"
],
"whoItsFor": "A dog walker",
"demoUrl": "https://walkies.hostingertemplates.com",
"classification": {
"categories": [
"local-business",
"pet-services",
"dog-walking"
],
"useCases": [
"booking",
"slots",
"areas"
],
"frameworks": [
"react",
"react-router",
"vite"
]
},
"features": [
{
"id": "walk-area-map",
"name": "Walk area map",
"description": "Illustrated map with numbered pins linked to area cards, plus an all, off-lead, and on-lead filter."
},
{
"id": "slot-based-booking",
"name": "Slot-based booking flow",
"description": "Pick a walk area, a date in the next 10 days, and a time slot showing spaces left, full, or booked by you."
},
{
"id": "validated-booking-details",
"name": "Validated booking details",
"description": "Owner and dog details form with inline, accessible validation, a live booking summary, and a confirmation reference."
},
{
"id": "service-landing-page",
"name": "Service landing page",
"description": "Hero, stats, how-it-works steps, featured walk areas, owner testimonials, FAQ, and a call-to-action band."
}
],
"technology": {
"languages": [
"TypeScript"
],
"frameworks": [
"React",
"Vite"
],
"styling": [
"Hand-written CSS (design tokens, section styles, responsive rules)"
],
"data": [
"Shareable URL and query-parameter state",
"Typed TypeScript content and configuration",
"No database or application backend required"
],
"deployment": [
"Static production output in dist/"
]
},
"compatibility": {
"runtimes": [
{
"name": "Node.js",
"versions": [
"22+"
]
}
]
},
"media": {
"thumbnail": {
"path": "templates/walkies/preview/walkies-thumbnail.png",
"url": "https://github.com/hostinger/hostinger-templates/blob/main/templates/walkies/preview/walkies-thumbnail.png?raw=true",
"source": "viewport",
"width": 1440,
"height": 900,
"aspectRatio": "16:10",
"variants": [
{
"width": 480,
"path": "templates/walkies/preview/walkies-thumbnail-480.webp"
},
{
"width": 960,
"path": "templates/walkies/preview/walkies-thumbnail-960.webp"
}
]
},
"preview": {
"path": "templates/walkies/preview/walkies-homepage.png",
"url": "https://github.com/hostinger/hostinger-templates/blob/main/templates/walkies/preview/walkies-homepage.png?raw=true",
"source": "fullPage",
"width": 1440,
"height": 3870
}
},
"searchTerms": [
"dog walker website",
"dog walking booking",
"pet services template",
"walk slot booking",
"dog walk areas map"
]
}
]
}
5 changes: 5 additions & 0 deletions templates/walkies/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
dist
.env
.env.*
*.tsbuildinfo
21 changes: 21 additions & 0 deletions templates/walkies/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Walkies contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
162 changes: 162 additions & 0 deletions templates/walkies/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# Walkies

A dog walker website with a walk-area map and a slot-based booking flow: pick an area, a day, and a time slot, then confirm the walk.

## Overview

Walkies is a small-group dog walking service site. The landing page introduces the service, shows how booking works, features favourite walk areas, and answers common questions. The walk areas page lists every area next to an illustrated map with numbered pins, and lets visitors filter by off-lead or on-lead walks.

The booking page walks through four steps: choose a walk area, choose a date within the next 10 days, pick an available time slot, and enter owner and dog details. Each area runs only on certain days and has fixed slot times and a maximum group size. Spaces left per slot come from deterministic sample data, so the same area, day, and time always show the same availability.

Confirming a booking shows a reference number and marks the slot as yours. Bookings are held in memory in the browser tab and clear on reload. There is no backend, no payment, and nothing is sent anywhere — the summary also offers a pre-filled email enquiry link.

## Features

- Landing page with hero, quick stats, three-step how-it-works, featured walk areas, owner testimonials, FAQ, and a call-to-action band.
- Walk areas page with an illustrated map, numbered pins linked to area cards, and an all / off-lead / on-lead filter.
- Area cards with terrain badge, neighbourhood, walk days, duration, lead policy, group size, price, and a direct "Book this walk" link.
- Booking flow: area radios, a 10-day date strip that greys out days an area does not run, and time-slot tickets showing spaces left, full, or booked by you.
- Owner and dog details form with inline validation, accessible error messages, and a live booking summary.
- Confirmation view with a booking reference, focus moved to the heading for screen readers, and a "Book another walk" action.
- Deep links: `/book?area=<area-id>` preselects an area; `/areas` and `/book` load directly on static hosts.
- Self-hosted Fraunces and DM Sans variable fonts, an inline SVG dog illustration, and no external requests.

## Tech stack

- **Language:** TypeScript
- **Framework:** React 19
- **Routing:** React Router
- **Build tool:** Vite
- **Styling:** Hand-written CSS (design tokens, section styles, responsive rules)

## Getting started

### Prerequisites

- Node.js 22 or newer
- npm

### Installation

```bash
npm install
```

### Development

```bash
npm run dev
```

Open the local URL printed by the development server.

## Available scripts

- `npm run dev` — start the local development server
- `npm run build` — type-check and create a production build
- `npm run lint` — run ESLint
- `npm run preview` — preview the production build locally

## Project structure

```text
walkies/
├── index.html
├── preview/
├── src/
│ ├── components/
│ │ ├── booking/
│ │ │ ├── AreaPicker.tsx
│ │ │ ├── BookingConfirmation.tsx
│ │ │ ├── BookingSummary.tsx
│ │ │ ├── DatePicker.tsx
│ │ │ ├── DetailsFields.tsx
│ │ │ └── SlotPicker.tsx
│ │ ├── AreaCard.tsx
│ │ ├── AreaFacts.tsx
│ │ ├── AreaMap.tsx
│ │ ├── FaqSection.tsx
│ │ ├── Footer.tsx
│ │ ├── Header.tsx
│ │ ├── Layout.tsx
│ │ ├── LeadFilter.tsx
│ │ ├── SectionHeading.tsx
│ │ └── TerrainBadge.tsx
│ ├── constants/
│ │ ├── areas.ts
│ │ ├── booking.ts
│ │ ├── routes.ts
│ │ └── site.ts
│ ├── icons/
│ │ ├── AreaMapArt.tsx
│ │ ├── DogIllustration.tsx
│ │ └── index.tsx
│ ├── lib/
│ │ ├── areas.ts
│ │ ├── booking.ts
│ │ ├── format.ts
│ │ ├── hash.ts
│ │ └── schedule.ts
│ ├── pages/
│ │ ├── AreasPage.tsx
│ │ ├── BookingPage.tsx
│ │ └── HomePage.tsx
│ ├── styles/
│ │ ├── foundation.css
│ │ ├── responsive.css
│ │ └── sections.css
│ ├── types/
│ │ └── content.ts
│ ├── App.tsx
│ ├── main.tsx
│ └── vite-env.d.ts
├── eslint.config.js
├── package.json
├── tsconfig.json
└── vite.config.ts
```

## Personalizing

### Content and business data

- `src/constants/site.ts` — brand name, contact email and phone, locale and currency, navigation, and all landing page copy (hero, stats, steps, testimonials, FAQ, call to action, footer).
- `src/constants/areas.ts` — the walk areas: name, neighbourhood, terrain, lead policy, summary, duration, price, group size, walker, highlights, walk days (0 = Sunday), slot times, and map pin position (percentages).
- `src/constants/booking.ts` — booking page copy, validation messages, the booking window (10 days from tomorrow), the reference prefix, and the notes length limit.

### Branding and styles

- `src/styles/foundation.css` — colour palette, terrain and map colours, fonts, radii, shadows, buttons, and chips (all CSS custom properties).
- `src/styles/sections.css` — per-section styles from header to footer, including the map, booking steps, and slot tickets.
- `src/styles/responsive.css` — breakpoints at 960px, 640px, and 380px.
- `src/main.tsx` — the self-hosted font imports; swap the `@fontsource-variable/*` packages to change typefaces.
- `index.html` — page title, meta description, theme colour, and the inline SVG favicon.

### Images

There are no raster images. The hero dog and the walk-area map are original inline SVG components in `src/icons/` (`DogIllustration.tsx`, `AreaMapArt.tsx`), and small UI icons live in `src/icons/index.tsx`. Edit or replace them there; the map art uses a 1000×700 viewBox, and pin positions in `src/constants/areas.ts` are percentages of that box.

### Routes and features

- Routes are defined in `src/constants/routes.ts` and wired in `src/App.tsx` (home, walk areas, booking). Unknown paths redirect home.
- `vite.config.ts` copies `index.html` into `dist/areas/` and `dist/book/` after the build, so direct visits work on static hosts. Add new routes to `STATIC_ROUTE_PATHS`.
- Slot availability is sample data from `src/lib/schedule.ts` (`getSampleBookedDogs`). Replace it with a real diary or booking API to take live bookings.
- Confirmed bookings live in `App.tsx` state; `src/lib/booking.ts` holds validation, the reference generator, and the email enquiry link.

### Environment variables

This project does not require environment variables.

## Production build

```bash
npm run build
npm run preview
```

Production files are written to `dist/`.

## Screenshots

- Thumbnail: `preview/walkies-thumbnail.png`
- Full page: `preview/walkies-homepage.png`
22 changes: 22 additions & 0 deletions templates/walkies/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import js from '@eslint/js';
import globals from 'globals';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
import tseslint from 'typescript-eslint';

export default tseslint.config(
{ ignores: ['dist', 'preview'] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ['**/*.{ts,tsx}'],
languageOptions: { ecmaVersion: 2022, globals: globals.browser },
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
},
},
);
21 changes: 21 additions & 0 deletions templates/walkies/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!doctype html>
<html lang="en-GB">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="description"
content="Small-group dog walks around Ashdown. Browse six mapped walk areas, pick a day and a pick-up slot, and book a walk for your dog."
/>
<meta name="theme-color" content="#2f5d3a" />
<link
rel="icon"
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='8' fill='%232f5d3a'/%3E%3Cg fill='%23fbf4e6'%3E%3Cellipse cx='9' cy='13' rx='2.4' ry='3'/%3E%3Cellipse cx='13.5' cy='8.5' rx='2.4' ry='3'/%3E%3Cellipse cx='18.5' cy='8.5' rx='2.4' ry='3'/%3E%3Cellipse cx='23' cy='13' rx='2.4' ry='3'/%3E%3Cpath d='M16 15c-3.4 0-6.6 4-6.6 6.8 0 2 1.6 3.2 3.4 3.2 1.3 0 2.1-.7 3.2-.7s1.9.7 3.2.7c1.8 0 3.4-1.2 3.4-3.2 0-2.8-3.2-6.8-6.6-6.8Z'/%3E%3C/g%3E%3C/svg%3E"
/>
<title>Walkies — small-group dog walks you can book by the slot</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Loading
Loading