JOURNAL · Apr 26, 2026 · 5 MIN READ

LINE booking systems done right: a LIFF in-app web engineering guide

Shops want customers to book via LINE, but if you tell them 'click this link to leave LINE and fill out a form,' they won't. LIFF (LINE Front-end Framework) embeds your booking page inside LINE itself. Here's how to build it without falling into the typical traps.

"I want a LINE-based booking system" — third-most-common request from salons, clinics, massage studios, and cafes (especially in Taiwan and Japan, where LINE is the dominant messaging app).

But most implementations get it wrong. The classic broken version:

  1. Owner sets up a LINE rich menu: "Book here" → opens a browser
  2. Customer is dropped into a separate website
  3. Customer has to log in, re-enter name / phone / LINE ID
  4. After booking, customer has to remember to message the shop back
  5. Customer never uses it twice

That funnel leaks 60-70%. The actually-usable version embeds the entire booking flow inside LINE — and that's what LIFF (LINE Front-end Framework) is for.

This post walks through how LIFF works, where it gets tricky, when to use it, and when to skip it.

What's LIFF? (60-second version)

LIFF is LINE's mechanism to embed a web app inside the LINE in-app browser. From the user's view:

  • Tap a link inside a LINE message → page opens inside LINE (not Safari / Chrome)
  • Your web page can read the user's LINE name, avatar, and user ID without a login flow
  • After filling out a form, users can share the result back into the chat
  • The whole thing never feels like leaving LINE

From an engineering view: it's a normal web app (React / Next.js / Vue, whatever) plus the LIFF SDK to access LINE-specific APIs.

A typical LIFF booking flow

I've shipped a few LIFF booking systems. The flow usually looks like:

1. Customer taps [Book Now] in the LINE rich menu
   ↓
2. LIFF opens, auto-pulls customer's LINE profile
   ↓
3. UI shows "Hi Mary — what date are you booking?" (name pre-filled)
   ↓
4. Customer picks date / time / service
   ↓
5. Confirmation page shows total, shop location
   ↓
6. Submit → write to DB + trigger webhook
   ↓
7. LINE auto-sends "Booking confirmed: 6/15 14:00 Haircut"
   ↓
8. 24-hour reminder fires automatically

Key difference: the customer never leaves LINE during the entire flow. Conversion is 3-5× higher than "click out to a separate site" — that's not marketing, that's measured.

Engineering: Next.js + LIFF SDK

Using Next.js as the example. First, register a LIFF app at the LINE Developers Console and get a LIFF ID.

1 · Install the SDK

pnpm add @line/liff

2 · Initialise inside a client component

'use client';
 
import { useEffect, useState } from 'react';
import liff from '@line/liff';
 
type Profile = {
  userId: string;
  displayName: string;
  pictureUrl?: string;
};
 
export function BookingForm() {
  const [profile, setProfile] = useState<Profile | null>(null);
  const [loading, setLoading] = useState(true);
 
  useEffect(() => {
    (async () => {
      try {
        await liff.init({ liffId: process.env.NEXT_PUBLIC_LIFF_ID! });
 
        if (!liff.isLoggedIn()) {
          liff.login(); // auto-redirect to LINE auth, usually invisible
          return;
        }
 
        const userProfile = await liff.getProfile();
        setProfile(userProfile);
      } catch (err) {
        console.error('LIFF init failed:', err);
      } finally {
        setLoading(false);
      }
    })();
  }, []);
 
  if (loading) return <div>Loading…</div>;
  if (!profile) return <div>Please open this page from LINE</div>;
 
  return (
    <form>
      <p>Hi {profile.displayName}!</p>
      {/* ...date / time picker... */}
    </form>
  );
}

3 · Backend API to receive bookings

// app/api/booking/route.ts
import { NextResponse } from 'next/server';
 
export async function POST(req: Request) {
  const { userId, displayName, date, time, service } = await req.json();
 
  const booking = await db.booking.create({
    data: { userId, displayName, date, time, service }
  });
 
  // Push a confirmation message via LINE Messaging API
  await fetch('https://api.line.me/v2/bot/message/push', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${process.env.LINE_CHANNEL_ACCESS_TOKEN}`
    },
    body: JSON.stringify({
      to: userId,
      messages: [{
        type: 'text',
        text: `Booking confirmed ✅\n${date} ${time}\n${service}`
      }]
    })
  });
 
  return NextResponse.json({ ok: true, booking });
}

The MVP is mostly a derivative of these ~50 lines. Less complex than expected.

Real-world traps (ones I've hit)

The parts engineering tutorials skip:

Trap 1 · LIFF URLs behave differently inside vs outside LINE

A LIFF URL (https://liff.line.me/{liffId}) auto-inits when opened inside LINE; opening it directly in Chrome shows a blank page plus an auth bounce — UX is awful.

Fix: detect the user agent on your site. If it's not LINE, route to a normal booking page. LIFF is the "in-LINE enhanced UX," not the only entry point.

const isLineApp = /Line/i.test(navigator.userAgent);
if (!isLineApp) {
  // show standard web booking, or redirect to /booking
}

Trap 2 · liff.login() infinite-loops in some scenarios

The iOS LINE in-app browser has weird cookie behaviour. If init completes but it keeps bouncing back to login, it's usually a SameSite cookie issue — your site needs SameSite=None; Secure.

// Next.js middleware or cookie setup
response.cookies.set('session', token, {
  sameSite: 'none',
  secure: true,
  httpOnly: true,
});

This bug is rarely covered in tutorials, and it kills onboarding for iPhone users who are 50%+ of LINE traffic.

Trap 3 · The LINE in-app browser is a webview, not a real browser

Some CSS / JS APIs are partially supported. Things I've hit:

  • position: sticky fails on some versions
  • File upload doesn't show camera option in Android LINE
  • <input type="date"> renders weirdly in iOS LINE

Fix: any custom interactive component must be tested inside real LINE on real devices (not Chrome DevTools "device emulation"). I push staging URLs into a test LIFF app and open from real phones.

Trap 4 · Customers will "screenshot the success page" as their booking proof

Yes, really. So your confirmation page must clearly display booking number, name, date, and shop info — the screenshot becomes their "ticket." Always also push a LINE message with the same info, double-redundancy.

Trap 5 · "No payment" = customers think bookings aren't real

Pure no-payment booking systems see 30-40% no-show rates. If your service is "time-based and capacity-limited" (haircut: 1 hour, 1 chair), strongly recommend a deposit or full prepayment. LIFF integrates LINE Pay, regional gateways, or Stripe — payment happens inside LINE without leaving.

Which businesses fit LIFF booking?

Not for everyone. My filter:

Good fit

  • Customers primarily contact you via LINE (salons, massage, clinics, cafes, tutoring centres)
  • High booking frequency, slot management matters (5+ bookings per day)
  • Booking → service has a 24-hour gap (advance scheduling needed)

Bad fit

  • Customer base skews older (60+) — they'll likely just call
  • Low booking volume (under 3 per week) — LIFF ROI doesn't justify the build
  • "Booking" = walk-in queue → no system needed

Cheaper alternatives (if LIFF doesn't fit)

If your fit score is low, cheaper paths:

  1. LINE Official Account + rich menu → Google Form / Typeform: clunky but zero engineering. Under $30/month.
  2. SaaS (SimplyBook, Calendly, Cal.com): $30-100/month, templated booking pages, some LINE integration.
  3. Calendly / Cal.com embedded on your site: works for 1-on-1 consultation, not multi-slot service.

LIFF's sweet spot: you already have a LINE Official Account + meaningful booking volume + willingness to invest in custom. There, LIFF clearly outperforms the alternatives in ROI.

Honest build timeline

PhaseScopeTime
1. Register LINE Official + LIFF appSetup, verification1 week
2. Flow + UI designBooking steps, confirm page, reminder logic1-2 weeks
3. Front-end LIFF integrationSDK init, profile, form1-2 weeks
4. Backend + DBBooking schema, conflict checks, persistence1-2 weeks
5. LINE Messaging API notificationsConfirm, reminder, cancel1 week
6. Payment integration (optional)LINE Pay / regional gateway / Stripe2 weeks
7. Real-device testing + webview quirksiOS + Android both1-2 weeks
8. Launch + admin trainingAdmin UI, owner training1 week

MVP: ~6-10 weeks. Full system with payment: 10-14 weeks.

LIFF isn't "build and profit" — it's "build it right, the experience compounds"

The technology isn't that hard, but half-built LIFF is worse than no LIFF. A customer opening a slow, layout-broken, repeatedly-logging-in webview inside LINE — that's worse than just calling you.

If you're considering LINE booking, think through two questions first:

  1. Is your booking volume there yet? Under 3 bookings/day, skip LIFF, use a cheaper path
  2. Can you require payment? Booking without prepayment will kill you on no-shows

If both are yes, LIFF booking will be one of your best engineering investments of 2026-2027. Customer retention costs drop 30-50%, new-customer conversion lifts 2-3× — typically pays back inside a year.

If you're unsure whether your business is the right fit, book 15 minutes. Tell me your current booking flow and I'll tell you straight whether LIFF is the right call — sometimes the answer is "no, just run on Google Form for three months first."

§ MORE · Keep reading
CONTACT · Get in touch

Sound like something worth a chat?
Get in touch.

Book a free call
Reply within 24hQuote and contract includedRemote friendlyEN · 繁中