{
  "name": "Mat",
  "slug": "mat",
  "blocks": ["Pages", "Lists", "Sign-in: users", "Actions: pay, scan"],
  "persona": "teachers",
  "keywords": [
    "yoga",
    "yoga classes",
    "class pass",
    "class packs",
    "class booking",
    "waitlist",
    "yoga teacher",
    "pilates",
    "check-in",
    "member app",
    "monthly pass",
    "yoga studio",
    "drop-in classes",
    "members area"
  ],
  "description": "An app template for a yoga studio: students book a mat in class from their phone (the teacher confirms, or puts them on the waitlist when the room is full), show a code at the door to check in, and see how many classes their pass has left this month. Drop-in, Four a month or Unlimited. A public page with the week's classes and passes, six member screens under /app and a privacy notice with blanks.",
  "audience": [
    "yoga teachers and studios",
    "pilates and dance teachers who sell class packs",
    "small studios with a weekly timetable"
  ],
  "category": "Membership & classes",
  "job": "member-app",
  "categoryId": "membership",
  "alsoFits": [
    "yoga studio app",
    "class pack and drop-in",
    "studio class check-in",
    "pilates class pass",
    "dance class booking",
    "weekly class attendance"
  ],
  "direction": "Sand-to-lilac wash with arched windows that fill with dawn or evening light, in olive and clay",
  "mood": [
    "light",
    "calm",
    "modern"
  ],
  "fonts": ["Gilda Display", "Manrope"],
  "memberApp": {
    "path": "/app",
    "setup": {
      "signup": "open",
      "profile_fields": [
        {
          "name": "name",
          "type": "text",
          "label": "Your name",
          "required": true
        }
      ],
      "display_field": "name"
    },
    "lists": [
      {
        "list": "bookings",
        "label": "Class bookings",
        "by": "member",
        "status_options": [
          "Requested",
          "Waitlist",
          "Booked",
          "Attended",
          "Cancelled"
        ],
        "reply": true,
        "fields": [
          {
            "name": "class",
            "type": "choice",
            "label": "Class",
            "required": true,
            "options": [
              "Lunchtime Flow",
              "Vinyasa",
              "Morning Slow Flow",
              "Yin & Breath",
              "Saturday Flow"
            ]
          },
          {
            "name": "date",
            "type": "date",
            "label": "Date",
            "required": true
          },
          {
            "name": "time",
            "type": "choice",
            "label": "Time",
            "required": true,
            "options": [
              "07:00",
              "09:30",
              "12:30",
              "19:00",
              "19:30"
            ]
          },
          {
            "name": "mat",
            "type": "choice",
            "label": "Mat",
            "required": true,
            "options": [
              "I'll bring my own",
              "Borrow a studio mat"
            ]
          },
          {
            "name": "spot",
            "type": "choice",
            "label": "Where in the room",
            "options": [
              "Anywhere",
              "By the windows",
              "Near the front",
              "At the back"
            ]
          },
          {
            "name": "message",
            "type": "text",
            "label": "Note for Saffi"
          }
        ]
      },
      {
        "list": "cancellations",
        "label": "Cancellations",
        "by": "member",
        "status_options": [
          "Sent",
          "Done",
          "Counted as a class"
        ],
        "reply": true,
        "fields": [
          {
            "name": "class",
            "type": "choice",
            "label": "Class",
            "required": true,
            "options": [
              "Lunchtime Flow",
              "Vinyasa",
              "Morning Slow Flow",
              "Yin & Breath",
              "Saturday Flow"
            ]
          },
          {
            "name": "date",
            "type": "date",
            "label": "Date",
            "required": true
          },
          {
            "name": "time",
            "type": "choice",
            "label": "Time",
            "required": true,
            "options": [
              "07:00",
              "09:30",
              "12:30",
              "19:00",
              "19:30"
            ]
          },
          {
            "name": "message",
            "type": "text",
            "label": "A note for Saffi"
          }
        ]
      },
      {
        "list": "attendance",
        "label": "Classes attended",
        "by": "owner",
        "fields": [
          {
            "name": "class_name",
            "type": "text",
            "label": "Class",
            "required": true
          }
        ]
      }
    ],
    "scan": [
      {
        "list": "attendance",
        "actions": [
          {
            "label": "Vinyasa check-in",
            "values": {
              "class_name": "Vinyasa"
            },
            "daily_limit": 1
          },
          {
            "label": "Lunchtime Flow check-in",
            "values": {
              "class_name": "Lunchtime Flow"
            },
            "daily_limit": 1
          },
          {
            "label": "Morning Slow Flow check-in",
            "values": {
              "class_name": "Morning Slow Flow"
            },
            "daily_limit": 1
          },
          {
            "label": "Yin & Breath check-in",
            "values": {
              "class_name": "Yin & Breath"
            },
            "daily_limit": 1
          },
          {
            "label": "Saturday Flow check-in",
            "values": {
              "class_name": "Saturday Flow"
            },
            "daily_limit": 1
          }
        ]
      }
    ],
    "plans": [
      {
        "plan": "dropin",
        "name": "Drop-in",
        "free": true
      },
      {
        "plan": "fourclass",
        "name": "Four a month",
        "paid": true,
        "price": {
          "amount": 4200,
          "currency": "gbp",
          "interval": "month"
        }
      },
      {
        "plan": "monthly",
        "name": "Unlimited",
        "paid": true,
        "price": {
          "amount": 5800,
          "currency": "gbp",
          "interval": "month"
        }
      }
    ],
    "demo": {
      "member": {
        "name": "Maya Ellis",
        "email": "maya.ellis@example.com",
        "profile": {
          "name": "Maya Ellis"
        }
      },
      "plans": [
        "fourclass"
      ],
      "rows": {
        "bookings": [
          {
            "class": "Saturday Flow",
            "date": "+1w:sat",
            "time": "09:30",
            "mat": "I'll bring my own",
            "spot": "By the windows",
            "_added": "today",
            "_status": "Waitlist",
            "_reply": "Saturday is full for now. You're first on the waitlist, and I'll move you in if a mat frees up.",
            "message": "Coming straight from work, may be two minutes late"
          },
          {
            "class": "Vinyasa",
            "date": "+1w:tue",
            "time": "19:00",
            "mat": "Borrow a studio mat",
            "spot": "By the windows",
            "_added": "-1d",
            "_status": "Booked",
            "_reply": "Booked. Your mat will be out by the windows.",
            "message": "First vinyasa in a while, may take it easy"
          },
          {
            "class": "Saturday Flow",
            "date": "-1w:sat",
            "time": "09:30",
            "mat": "I'll bring my own",
            "spot": "By the windows",
            "_added": "-2w:sun",
            "_status": "Attended"
          },
          {
            "class": "Yin & Breath",
            "date": "-1w:thu",
            "time": "19:30",
            "mat": "Borrow a studio mat",
            "spot": "At the back",
            "_added": "-2w:sat",
            "_status": "Attended"
          },
          {
            "class": "Morning Slow Flow",
            "date": "-2w:wed",
            "time": "07:00",
            "mat": "I'll bring my own",
            "spot": "Anywhere",
            "_added": "-3w:sun",
            "_status": "Cancelled",
            "_reply": "No problem, I've given your mat to the waitlist."
          },
          {
            "class": "Vinyasa",
            "date": "-3w:tue",
            "time": "19:00",
            "mat": "Borrow a studio mat",
            "spot": "Near the front",
            "_added": "-4w:sat",
            "_status": "Attended"
          },
          {
            "class": "Saturday Flow",
            "date": "-4w:sat",
            "time": "09:30",
            "mat": "I'll bring my own",
            "spot": "By the windows",
            "_added": "-5w:mon",
            "_status": "Attended"
          }
        ],
        "attendance": [
          {
            "class_name": "Saturday Flow",
            "_added": "-1w:sat"
          },
          {
            "class_name": "Yin & Breath",
            "_added": "-1w:thu"
          },
          {
            "class_name": "Vinyasa",
            "_added": "-3w:tue"
          },
          {
            "class_name": "Saturday Flow",
            "_added": "-4w:sat"
          }
        ],
        "cancellations": [
          {
            "class": "Morning Slow Flow",
            "date": "-2w:wed",
            "time": "07:00",
            "message": "Early meeting, sorry",
            "_added": "-3w:sun",
            "_status": "Done",
            "_reply": "No problem, I've given your mat to the waitlist."
          }
        ]
      },
      "staff": {
        "members": [
          {
            "name": "Maya Ellis",
            "plan": "fourclass",
            "since": "2026-05-09",
            "counts": {
              "Saturday Flow check-in": 2,
              "Yin & Breath check-in": 1,
              "Vinyasa check-in": 1
            }
          },
          {
            "name": "Joanna Pryce",
            "plan": "monthly",
            "since": "2025-01-14",
            "counts": {
              "Vinyasa check-in": 14,
              "Saturday Flow check-in": 15,
              "Yin & Breath check-in": 12,
              "Morning Slow Flow check-in": 3
            }
          },
          {
            "name": "Dev Mistry",
            "plan": "monthly",
            "since": "2026-02-03",
            "counts": {
              "Morning Slow Flow check-in": 11,
              "Lunchtime Flow check-in": 12,
              "Vinyasa check-in": 3
            }
          },
          {
            "name": "Ruth Okonjo",
            "plan": "fourclass",
            "since": "2026-08-30",
            "counts": {
              "Vinyasa check-in": 5,
              "Yin & Breath check-in": 4,
              "Morning Slow Flow check-in": 3
            }
          },
          {
            "name": "Ellie Tran",
            "since": "2026-10-01",
            "counts": {
              "Vinyasa check-in": 1
            }
          },
          {
            "name": "Hamish Byrne",
            "plan": "fourclass",
            "since": "2026-03-22",
            "counts": {
              "Saturday Flow check-in": 9,
              "Morning Slow Flow check-in": 6
            }
          }
        ],
        "log": [
          {
            "name": "Hamish Byrne",
            "action": "Morning Slow Flow check-in",
            "at": "06:51",
            "by": "Saffi"
          },
          {
            "name": "Dev Mistry",
            "action": "Morning Slow Flow check-in",
            "at": "06:54",
            "by": "Saffi"
          },
          {
            "name": "Joanna Pryce",
            "action": "Morning Slow Flow check-in",
            "at": "06:56",
            "by": "Saffi"
          },
          {
            "name": "Ruth Okonjo",
            "action": "Morning Slow Flow check-in",
            "at": "06:58",
            "by": "Saffi"
          }
        ],
        "logDay": "0w:wed"
      }
    }
  },
  "files": [
    "index.html",
    "privacy.html",
    "app/index.html",
    "app/classes.html",
    "app/bookings.html",
    "app/cancel.html",
    "app/pass.html",
    "app/plans.html",
    "app/account.html",
    "styles.css",
    "site.js",
    "kit.css",
    "kit.js",
    "kit-icons.svg",
    "site.webmanifest",
    "favicon.svg",
    "og.png",
    "apple-touch-icon.png",
    "icon-192.png",
    "icon-512.png",
    "icon-512-maskable.png",
    "art/chapel-room.svg",
    "art/class-lunch.svg",
    "art/class-vinyasa.svg",
    "art/class-slow-flow.svg",
    "art/class-yin.svg",
    "art/class-saturday.svg"
  ],
  "pages": [
    {
      "path": "index.html",
      "label": "Home",
      "purpose": "The public page: Saffi Lund Yoga in the Old Chapel Rooms, what the app does (book a mat, check in at the door, see your pass), the week's five classes, the three passes with prices, the teacher and how to find the studio"
    },
    {
      "path": "app/index.html",
      "label": "Home",
      "purpose": "Signed out: the welcome screen with the passes and sign-in. Signed in: a greeting, the pass card with classes used this month and Show my code, the next class with its status, quick actions and the week's classes"
    },
    {
      "path": "app/classes.html",
      "label": "Classes",
      "purpose": "The week's classes starting today; tapping one fills the booking form (class, date, time, own or studio mat, where in the room) and Book my mat saves it; the waitlist and late-cancel rules sit next to the button"
    },
    {
      "path": "app/bookings.html",
      "label": "Bookings",
      "purpose": "Upcoming classes with the teacher's status (Requested, Booked, Waitlist) and reply, and past classes newest first with Book again"
    },
    {
      "path": "app/cancel.html",
      "label": "Cancel",
      "purpose": "Can't make it: cancel a booked class (filled from the booking) so the mat goes to the waitlist; your cancellations with Saffi's answer (Sent, Done)"
    },
    {
      "path": "app/pass.html",
      "label": "Pass",
      "purpose": "The check-in code to show at the door, classes used this month against the pass, and every class attended newest first"
    },
    {
      "path": "app/plans.html",
      "label": "Passes",
      "purpose": "The member's pass, what it covers and its price, the other passes to join or switch to, and the rules for pausing and cancelling"
    },
    {
      "path": "app/account.html",
      "label": "Account",
      "purpose": "The member's name, email, devices, billing, renewal date and leaving (Page Lemon's account block)"
    },
    {
      "path": "privacy.html",
      "label": "Privacy",
      "purpose": "The privacy notice, with blanks the Site Owner fills in"
    }
  ],
  "facts": [
    "studio name",
    "address",
    "phone",
    "contact email",
    "teacher name and training",
    "class timetable and places per class",
    "pass names and prices",
    "privacy contact and address"
  ],
  "interview": [
    "What is your studio called, and where is it?",
    "Which classes do you teach each week, and at what times?",
    "Which passes do you sell, and what does each cost a month or a class?",
    "How many mats does each class have, and what happens when a class is full?",
    "Who scans students in at the mat? Each needs a Page Lemon sign-in: invite them as collaborators with only Scan users ticked.",
    "Which email address and phone number should students use?",
    "What address and privacy contact should the privacy notice show?"
  ],
  "customise": {
    "strings": [
      "Saffi Lund Yoga, its address, phone, email and teacher in the header, footer, titles and copy: replace every data-pl-fill fact with the owner's own. Replace the name in site.webmanifest too.",
      "Fill in every highlighted blank on privacy.html before students join (not legal advice: https://pagelemon.com/agents/member-app-legal).",
      "Make the bookings and cancellations lists (with status_options and reply) and the attendance list with its scan actions (one check-in per class, so the pass shows which class) exactly as memberApp.lists and memberApp.scan say. Keep the class names and times on app/classes.html, app/cancel.html, index.html, the lists' options and the scan labels the same.",
      "Set the passes with save_plan: dropin (free; students pay at the door), fourclass and monthly at the owner's prices, and change the prices on index.html, app/index.html and app/plans.html together. Call setup_app with signup \"open\" and the name profile field, so the teacher sees the student's name when they scan.",
      "The teacher answers bookings in the Dashboard (Apps, Entries): Booked, Waitlist, Attended or Cancelled, with a short reply the student reads on app/bookings.html; a cancellation request is answered by setting the booking to Cancelled and the request to Done. Page Lemon does not count mats or enforce the Four a month allowance: app/classes.html shows classes left this month, and the teacher decides.",
      "Whoever scans at the door needs Scan users: invite them with add_people and that permission only.",
      "A yoga studio app only: never add health, injury, body measurement, payment card, bank or ID fields, and never collect anything about under-18s."
    ],
    "colours": "Edit the --k-brand, --k-hero and --k-gold tokens at the top of styles.css; light and dark follow the device.",
    "fonts": "Gilda Display and Manrope, loaded from Google Fonts on every page; your AI can self-host them on request.",
    "sections": "Public: index.html. Member pages under /app use the shared app kit (kit.css, kit.js, kit-icons.svg: never edit them) and site.js (class dates, class pictures, the booking summary). On app/classes.html each class is one link with data-day, data-class and data-time.",
    "images": "art/chapel-room.svg is the app welcome picture (1200×1260), not the public hero, which is drawn as a chapel window;the five art/class-*.svg are the class pictures (600×600). Replace them with the studio's own photos at the same sizes (WebP under 300 KB), never a stranger's face."
  },
  "updated": "2026-10-22",
  "schemaVersion": 2
}
