平板全屏 kiosk 模式,锁定视口、无滚动,并带闲置自动重置
flight-kiosk-widget — Next.js 企业官网模板
作者 tovrr
面向实体店铺的自助机票预订终端模板,基于 Next.js 构建,通过 Travelpayouts 联盟链接赚取佣金,支持平板全屏 kiosk 模式与网站嵌入。
看看你的网站会是什么样
浏览真实页面截图,比较内容排版与手机效果。点击下方缩略图切换,放大查看整页细节。
全部页面与视图 2
截图用于了解视觉与布局,交互效果请以实际项目为准。
值得关注的模板亮点
从已有项目资料中,快速了解它的特点。
通过 URL 中的 ?ref= 参数按店铺追踪,佣金由 Travelpayouts 联盟计划结算
提供 /embed 路由与 embed.js,可用一行 script 标签嵌入现有网站
断网时显示重试卡片,service worker 缓存应用外壳,屏幕保持常亮
品牌名、颜色、语言、货币、闲置时间等均通过环境变量配置
内置英语、法语、荷兰语,支持 PWA 安装
模板详细介绍
这是一个面向实体店铺的自助机票预订终端(kiosk)模板。顾客在平板或 iPad 上全屏搜索、比价并跳转到合作方完成预订,店铺通过 URL 中的 ?ref= 参数被追踪,佣金由 Travelpayouts 联盟计划结算。项目本身不处理支付,也不收集姓名、邮箱等个人数据,仅在 localStorage 中保存店铺 ref 代码用于归因。
模板通过环境变量完成品牌名、颜色、语言、货币、闲置重置时间等配置,无需改动代码。除全屏 kiosk 外,还提供 /embed 路由与 embed.js,可用一行 script 标签把搜索组件嵌入任意网站。内置英语、法语、荷兰语三种语言,并支持 PWA 安装。
使用前需要自行注册 Travelpayouts 账号,获取 marker 与 Flights Search Form 的 trs 标识,并填入环境变量。由于 NEXT_PUBLIC_* 变量在构建时写入客户端包,修改后需要重新部署。
适合你的项目吗?
适用场景
- 实体店铺在平板或 iPad 上放置全屏机票搜索终端,顾客自助查询并跳转预订
- 把机票搜索组件以 iframe 形式嵌入已有网站,按店铺或渠道追踪转化
- 需要按不同店铺或子渠道区分佣金来源的联盟营销场景
- 在店内网络不稳定时仍希望展示可重试的搜索入口
适合人群
- 拥有实体门店并希望增加机票预订佣金收入的商家
- 已注册或计划注册 Travelpayouts 的联盟营销人员
- 需要快速部署品牌化机票搜索终端、不想从零开发的前端开发者
- 希望把机票搜索嵌入现有网站并保留渠道追踪的运营方
上手与定制指南
结合仓库当前版本的说明,按下面的资料检查内容、配置与运行要求。
- 1
需先注册 Travelpayouts 账号,获取 marker 与 Flights Search Form 的 trs,并填入对应环境变量
- 2
NEXT_PUBLIC_* 变量在构建时写入客户端包,修改后需重新部署并关闭构建缓存
- 3
本地开发可复制 .env.example 为 .env.local,运行 npm install 与 npm run dev
- 4
Travelpayouts 组件脚本从 tpwidg.com 加载,网络受限时会显示离线回退
- 5
演示中的搜索组件为模拟内容,生产环境会替换为真实的 Travelpayouts 表单
授权与来源资料
使用条件与限制
免费使用 · 保留许可声明本次收录的是公开仓库中采用 MIT 许可的免费版本;免费范围为该版本代码,不代表外部服务或第三方素材免费。
使用时需要遵守
- 允许免费使用、修改、商用和分发该版本代码。
- 分发代码副本或实质性部分时,保留原作者版权声明和完整 MIT 许可声明。
- 代码按现状提供;担保与责任限制以原许可证及适用法律为准。
额外费用与待核对事项
- 使用前必须注册 Travelpayouts 账号,并获取 marker 与 Flights Search Form 的 trs 标识填入环境变量,否则无法正常展示搜索组件。
- 必须提供 Travelpayouts 的 partner marker 与 trs 等凭据,属于外部服务依赖,非纯本地即可运行。
- 搜索组件脚本从第三方域名 tpwidg.com 加载,网络受限或被屏蔽时会显示离线回退,无法正常搜索。
- NEXT_PUBLIC_* 变量在构建时写入客户端包,修改后必须重新部署并关闭构建缓存,无法运行时热更新。
- README 中的 Travelpayouts 注册链接带有维护者的推荐 marker,通过该链接注册会为维护者带来推荐收益(不影响用户佣金)。
- 演示图片、字体、图标及其他第三方素材需按各自许可核对,不能仅凭代码的 MIT 许可判断。
- 域名、托管、数据库、支付或 AI 等外部服务可能另外收费。
查看原文依据
Permission is hereby granted, free of charge
许可证原文
Create a free Travelpayouts account
README 原文
your **marker / Partner ID** → `NEXT_PUBLIC_TRAVELPAYOUTS_MARKER`
README 原文
The Travelpayouts widget loads its script from `tpwidg.com`
README 原文
changing them later requires a redeploy
README 原文
https://github.com/tovrr/flight-kiosk-widget/blob/main/LICENSEhttps://github.com/tovrr/flight-kiosk-widget/blob/main/README.mdthe Travelpayouts sign-up link above carries the > maintainer's *refer-a-partner* marker
README 原文
DeepSeek 根据仓库许可证和 README 整理 ·2026-10-02。结果仅覆盖已读取资料,依赖、图片、字体及后续条款变更以各自原文为准。
项目核对记录与介绍依据
模板资料
- 来源平台
- GitHub
- 资料与维护参考分
- 资料较完整 · 80 / 100
- 技术栈
- Next.js · React
- 网站类型
- 企业官网
这个分数如何计算
本站按许可资料(最高30分)、演示链接(12分)、预览图(10分)、Star数(15分)、记录的维护时间(15分)、描述完整度(8分)、功能记录(5分)和分类资料(5分)计算。它不是代码、安全或性能测试,也不是 Google 评分;有链接不代表已实测可用。
这个项目需要核对什么
- 记录的仓库更新时间
- 2026-09-13
- 截图检查日期
- 2026-10-02
已收录演示链接。请用你的内容与屏幕尺寸检查;有演示不代表表单、认证或支付已经可用。
目录记录的主要技术栈是 Next.js。请通过依赖清单和锁文件核对实际版本与托管要求。这些说明基于收录资料,不代表代码审计或部署实测。
查看具体选型方法 →介绍的制作与核对状态
介绍由 AI 辅助整理目录与仓库资料。仓库作者不等于这篇介绍的审核者。
已完成服务器许可规则与 AI 来源核对;未经过人工编辑审核。
查看当时使用的来源资料
SHA-256: 4c974969f0c072d604c597ec41ac966d990c5ca04a0825aaaeca7f6b5188131c
2026-10-02T07:24:14.143Z
来源文件 / 仓库# Flight Kiosk Widget
<p align="center">
<a href="https://vercel.com/new/clone?repository-url=https://github.com/tovrr/flight-kiosk-widget">
<img src="https://vercel.com/button" alt="Deploy with Vercel" height="34">
</a>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-black.svg" alt="MIT License"></a>
<img src="https://img.shields.io/badge/Next.js-16-black?logo=nextdotjs&logoColor=white" alt="Next.js 16">
<img src="https://img.shields.io/badge/Travelpayouts-affiliate-ffe800?labelColor=0a0a0a" alt="Travelpayouts affiliate">
</p>
A self-service **flight-booking kiosk** for physical shops — designed to run
fullscreen on a tablet/iPad in kiosk mode. A customer searches for a flight,
compares prices, and books, while the partner shop is tracked via a `?ref=`
in the URL. Monetisation is
**[Travelpayouts](https://www.travelpayouts.com/?marker=749997) affiliate**
(you earn a commission on every booking).
Fork it, plug in your own Travelpayouts IDs, set a brand, and deploy — no code
changes required. Everything is configured through environment variables.

<p align="center"><em>Booking screen · the attract screen shown between customers 👇</em></p>

> The widget above is rendered from a mock in this demo; in production the real
> Travelpayouts flight-search form loads in its place.
---
## 💸 Deploy your own & earn — in 5 minutes
> 🏗️ Built by [**DevForge Systems**](https://devforge.systems) — enterprise software development, from build to deploy.
Every flight booked through your kiosk pays **you** an affiliate commission via
Travelpayouts. This template is the fastest way to get a branded,
production-ready booking kiosk (or an embeddable widget) live — **no code, just
environment variables**.
<p align="center">
<a href="https://vercel.com/new/clone?repository-url=https://github.com/tovrr/flight-kiosk-widget">
<img src="https://vercel.com/button" alt="Deploy with Vercel" height="34">
</a>
</p>
1. **[Create a free Travelpayouts account](https://www.travelpayouts.com/?marker=749997)** and grab your marker + a Flights Search Form `trs`.
2. **Deploy** (one click above), paste those two values as env vars.
3. **Put a tablet in a shop** — or drop the `<script>` on any site — and earn on every booking. You keep **100 % of the affiliate commission**.
> **Transparency:** the Travelpayouts sign-up link above carries the
> maintainer's *refer-a-partner* marker. It costs you **nothing** and does **not**
> reduce your commissions — Travelpayouts simply shares a small slice of *their*
> own margin with the referrer. Prefer not to? Just sign up directly at
> [travelpayouts.com](https://www.travelpayouts.com/). Either way, the code is
> yours under MIT.
---
## Features
- **Kiosk mode** — fullscreen, no scroll, locked viewport, tablet-first.
- **Attract screen** ("Touch to start") + **idle reset** between customers.
- **Travelpayouts flight-search widget** with per-shop tracking (`shmarker`),
no Aviasales logo / "Powered by".
- **Offline fallback** — a clean "service unavailable / retry" card when the
in-store wifi drops, instead of an empty frame.
- **Mobile-continuity QR** — the customer scans it to finish on their phone,
keeping the shop `?ref=` intact.
- **Optional "Popular flights"** button to your results / White Label page.
- **Embeddable** on any website with a one-line `<script>` (`/embed` + `embed.js`).
- Fully **rebrandable** (name + colours) via env vars, **installable PWA**.
- **Resilient by design** — service worker caches the app shell (reloads offline
if the wifi drops), self-healing error screen, and the screen stays awake.
- **Built-in languages** (EN / FR / NL) via `NEXT_PUBLIC_LOCALE`.
---
## How the affiliate model works
1. A shop's kiosk URL carries its name: `https://your-app.com/?ref=shop-name`.
2. That `ref` is stored and folded into the Travelpayouts marker as
`MARKER.shop-name` (`shmarker`), so every booking is traced to the shop.
3. The customer searches → is redirected to the results page → books with the
seller. **Travelpayouts pays you the commission** (marker), and you know
which shop drove it (sub-marker).
---
## Deploy your own
### 1. Get a Travelpayouts account
Sign up at [travelpayouts.com](https://www.travelpayouts.com/?marker=749997).
From the dashboard you need:
- your **marker / Partner ID** → `NEXT_PUBLIC_TRAVELPAYOUTS_MARKER`
- a **"Flights Search Form"** widget → copy its **`trs`** →
`NEXT_PUBLIC_TP_TRS`
- *(optional)* the **Drive** domain-verification script URL →
`NEXT_PUBLIC_TP_DRIVE_SRC`
- *(optional)* a **White Label** domain for branded results →
`NEXT_PUBLIC_TP_SEARCH_URL` / `NEXT_PUBLIC_RESULTS_URL`
### 2. One-click deploy (Vercel)
[](https://vercel.com/new/clone?repository-url=https://github.com/tovrr/flight-kiosk-widget)
Set the environment variables (see below) during the import, then deploy.
Because `NEXT_PUBLIC_*` values are baked in at build time, **changing them
later requires a redeploy** (uncheck "Use existing Build Cache").
### 3. Point your kiosk at it
Open the deployed URL with a shop ref, e.g.
`https://your-app.com/?ref=shop-name`, and put the tablet in guided-access /
kiosk mode.
---
## Embed on an existing website
Besides the full-screen kiosk, the search widget can be dropped into any
website with **one line** — like a Calendly/Typeform embed:
```html
<script src="https://your-app.com/embed.js" data-ref="your-shop" async></script>
```
- Injects a responsive `<iframe>` of the flight-search widget right where the
script is placed (or into `data-target="#some-element"`).
- Auto-resizes to its content height, transparent background to blend in.
- Tracked by `data-ref` (same `?ref=` → marker model as the kiosk).
The widget lives at `/embed?ref=...` and is the only route allowed to be framed
by third-party sites (every other route stays `X-Frame-Options: SAMEORIGIN`).
---
## Environment variables
| Variable | Required | Default | Role |
| --- | :---: | --- | --- |
| `NEXT_PUBLIC_TRAVELPAYOUTS_MARKER` | ✅ | `000000` | Your partner marker (base of `shmarker`). Placeholder = no attribution. |
| `NEXT_PUBLIC_TP_TRS` | ✅ | — | Tracking source id of your Flights Search Form widget. |
| `NEXT_PUBLIC_TP_DRIVE_SRC` | | — | Drive domain-verification script URL (injected only if set). |
| `NEXT_PUBLIC_TP_SEARCH_URL` | | — | Host (no protocol) where results open, e.g. your White Label. |
| `NEXT_PUBLIC_SHOW_HOTELS` | | `false` | Show the "also search hotels" checkbox in the flight widget. |
| `NEXT_PUBLIC_BRAND_PREFIX` | | `Flight` | Brand name, first tone (foreground). |
| `NEXT_PUBLIC_BRAND_SUFFIX` | | `Kiosk` | Brand name, second tone (accent). |
| `NEXT_PUBLIC_COLOR_PRIMARY` | | `#0A0A0A` | Widget primary colour. |
| `NEXT_PUBLIC_COLOR_ACCENT` | | `#FFE800` | Widget accent colour. |
| `NEXT_PUBLIC_SITE_URL` | | current origin | Canonical URL for the mobile-continue QR. |
| `NEXT_PUBLIC_RESULTS_URL` | | — | Full URL for the "Popular flights" button (hidden if empty). |
| `NEXT_PUBLIC_LOCALE` | | `en` | Widget / page language. |
| `NEXT_PUBLIC_CURRENCY` | | `usd` | Widget currency. |
| `NEXT_PUBLIC_IDLE_TIMEOUT_MS` | | `90000` | Idle delay before the kiosk resets. |
> ⚠️ These are **identifiers, not secrets** — they ship in the client bundle by
> design. **Never** put a Travelpayouts API token in a `NEXT_PUBLIC_*` variable.
---
## Local development
```bash
cp .env.example .env.local # fill in your values
npm install
npm run dev # http://localhost:3000/?ref=demo-shop
npm run lint # ESLint (next/core-web-vitals)
npm test # unit tests (Vitest)
```
The Travelpayouts widget loads its script from `tpwidg.com`; if your network
blocks it you'll see the offline fallback — that's expected locally.
## Customisation
- **Name / colours** → env vars above. To also restyle the app chrome (not just
the widget), edit the two colours in `app/globals.css` (Tailwind v4 `@theme`
is static, so it can't read env at runtime).
- **Language** → set `NEXT_PUBLIC_LOCALE` (`en`, `fr`, `nl` built in). Add a
locale by extending the dictionary in `lib/i18n.js`; the widget follows the
same variable.
- **Icon** → replace `app/icon.svg` (also used as the PWA icon).
## Data & privacy
This app is a thin, brand-able shell around Travelpayouts — it runs almost no
logic of its own, and **collects no personal data**.
- **What it stores:** only the `?ref=` shop code, in `localStorage`, to keep
per-shop attribution across a reload. No names, emails, accounts, or payment
data — ever. No first-party tracking cookies.
- **What flows where:** the search widget and the results page are both hosted
by **Travelpayouts**. When a visitor searches, only the **search query**
(route, dates, passengers) and your **marker** are passed — via the URL — to
the results page. There is no shared backend and no database.
- **Payments** happen on the airline/OTA's own checkout, never here, so there is
no card handling or PCI scope.
- **Isolation:** every deployment uses its own marker/White Label (its own env
vars). One fork can never read another's traffic or bookings.
- **`NEXT_PUBLIC_*` values are identifiers, not secrets** — they ship in the
client bundle by design. Never put an API token in one.
Add your own privacy notice if your jurisdiction requires one; the third-party
Travelpayouts scripts have their own policy.
## Stack
Next.js 16 (App Router) · React 19 · Tailwind CSS 4 · `react-qr-code` ·
`lucide-react` · Node 22.
## License
[MIT](LICENSE) — do whatever you want, no warranty.
看看同类模板
对比同技术栈与用途的模板,找到更适合的视觉与内容结构。

SaaS-Boilerplate
🚀🎉📚 SaaS Boilerplate built with Next.js + Tailwind CSS + Shadcn UI + TypeScript. ⚡️ Full-stack React applic…
Next.js · SaaS

Next-JS-Landing-Page-Starter-Template
🚀 Free NextJS Landing Page Template written in Tailwind CSS 3 and TypeScript ⚡️ Made with developer experienc…
Next.js · 企业官网

next-saas-starter
⚡️ Free Next.js responsive landing page template for SaaS products made using JAMStack architecture.
Next.js · SaaS

startup-nextjs
Startup is free Next.js template for SaaS startups comes with all the essential pages, components, and section…
Next.js · SaaS

shadcn-landing-page
New design 🎉 Nextjs + Shadcn + TypeScript + Tailwind. Landing page template ease-to-use
Next.js · 企业官网

shadcn-dashboard-landing-template
Accelerate your development with a sleek, open-source admin dashboard and landing page built on Vite-React, Ne…
Next.js · 后台
