Website
The business's public website, with every word and picture editable by the owner in each language.
Website is the business's public site at / and /<lang>. Its pages are built in code from a kit
of ready-made pieces: a hero, feature cards, a gallery, testimonials, questions and answers, contact
buttons, Locations and opening hours. Every word, picture, link, switch and date the owner may
change is a field the code declares, and the owner edits it on the admin Website page, one tab
per language, live as it saves. Around each page sit the site's navbar and footer, a promo bar, a
welcome popup and a consent bar. The navbar holds the logo, the main menu (Shop, Book and the
owner's own links), the language switch, and the shop's Account and Cart; on a phone the menu opens
in a sheet. Website also has a blog and, with
Booking on, a page for each bookable service or tour. Opening
hours and addresses come from Branches. Products, bookings and
prices stay with their own Modules: Website shows them but doesn't store them.
What it handles
- Writing one language first. When the owner writes the headline in Thai only, English visitors see the Thai until an English version is written, not the code's English default. Resetting a field brings back the defaults in every language. Tested: "Website: content"
- Edits that would break the page. A field the code doesn't declare, a value of the wrong shape,
a
javascript:link or a link that leaves the site through//is refused, and nothing is stored. Staff without the website permission, or tied to one Location, can't change the site. Every edit and reset goes to the audit log with the value before and after. Tested: "Website: content" - Uploads that aren't what they claim. The file's stored type and size decide, not what the browser said, so a disguised SVG or an oversized file is refused, as is an upload that never arrived. An image field refuses a PDF, while a file field takes it. A picture still on the site can't be deleted. Tested: "Website: attachments"
- A promo or popup on a schedule. A promo bar and a popup show only inside their dates and only while the owner has them switched on. The end date is exclusive, and outside the window they never reach the browser. Tested: "Website: site chrome"
- Opening hours in each Location's own time. A Bangkok restaurant on a UTC business shows closed between lunch and dinner and open at dinner, a bar stays open past midnight into Sunday, and a retired Location is left out. Tested: "Website: opening hours and locations"
- A blog that publishes on time. A post dated in the future stays off the blog and the sitemap until its day. Two posts can't share an address: a chosen one is refused and a derived one gets a number added. A picture a post uses can't be deleted from the library until the post lets it go. Tested: "Website: blog"
- Pages for tours and services. Each bookable resource gets at most one page, even when it's created twice at once. Visitors see live fares and seats, and Book now opens with that tour chosen. A draft, an unpublished page, or a deactivated or removed tour is off the site and the sitemap, and reactivating the tour brings its page back as the owner left it. With Booking off, these pages answer not found and the blog is untouched. Tested: "Website + booking: offerings" Tested: "Website + booking: offering visibility" Tested: "Website: offerings"
- Renames that would lose an owner's words. A stored value lives under its field's key, so renaming a field would drop what the owner wrote. A test fails until the record of keys is updated on purpose. Content groups an app declares are edited the same way, and keys it doesn't declare are refused. Tested: "Website: content keys" Tested: "Website: content an app registers"
What you build on top
- Switch it on. Website ships switched off. Turn it on in the app's Modules tab (see
two switches). Until then,
/shows the developer launcher. - Your own pages. Start from the default homepage, which is built only from kit pieces, and copy
it for new pages. Declare each page's editable words and pictures so they appear on the Website
page. The steps are in your app's
AGENTS.md § "Website (the public site)", andnpm run lintrefuses copy or a picture written straight into a website page. See Build on a Module. - Other Modules on the site. Booking, Storefront and Membership each add a homepage button
through the
website.home-actionslot. Storefront and Booking add Shop and Book to the menu throughwebsite.nav(Shop opens the collections), Storefront adds featured products to the homepage throughwebsite.home-section, puts the shop's Account and Cart in the header throughwebsite.header-action, and adds the shop page's fields throughwebsite.content. Each appears only while both Modules are on and in use: a business that switches the shop off in Features in use loses its menu entry and homepage section too. The owner can hide or rename each menu entry, add up to eight links of their own, and turn on a homepage banner for a sale. See Extend a Module. - Pictures and files. Uploads need the optional
mediafile storage connected to the app. Without it, text still edits and the Website page says uploads are unavailable. - The look. The kit uses the app's theme colours, so restyling the theme restyles the site. To rearrange the header, footer and other chrome, use Customize screens.
- In code. Your coding agent imports Website only through its public API:
index.tsandserver/index.tsinapps/web/src/modules/website/. See Build on a Module.
Limits
- Owners change only what the code declares. There's no drag-and-drop page builder: a new page or layout is a code change.
- The site is business-wide. There's one site for every Location, and staff tied to one Location can read it but not change it.
- Tour and service pages exist only with Booking on.
Facts
- Kind: feature Module, can be switched on and off
- Needs: Audit log, Branches, Formatting, i18n, Identity, Infra, Standard UI
- Needed by: Nothing
- Adds to these when they're on: Booking
- Added to by: Booking, Discounts, Membership, Storefront
- Off by default for these business types: none
Pages
| Where | Path |
|---|---|
| Admin | /admin/website |
| Public website | /blog |
| Public website | /offerings |
Permissions
Admin holds every key. The other roles listed hold it when the app first gets the Module; after that, roles are yours to change under Settings → Roles & Permissions.
| Permission | What it allows | Organization roles that start with it |
|---|---|---|
website:write | Edit the public website's text, images, links and switches. | Admin |
Data
- Tables:
site_content,site_attachment,site_post,site_offering - File storage
media: optional, shared across the organization
Slots
Places other Modules and your app code can add to. See Extend a Module.
website.contentwebsite.home-actionwebsite.header-actionwebsite.navwebsite.home-section
Tested workflows
- Website: content
- Website: attachments
- Website: content keys
- Website: content an app registers
- Website: site chrome
- Website: kit catalog
- Website: opening hours and locations
- Website: blog
- Website: offerings
- Website + booking: offerings (with Booking on)
- Website + booking: offering visibility (with Booking on)