> For the complete documentation index, see [llms.txt](https://guides.paynow.gg/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://guides.paynow.gg/your-webstore/editing-template-files.md).

# Editing Template Files

Hosted webstore templates use [**Twig**](https://twig.symfony.com/). Each customer-facing route renders a specific template file, and each file receives a set of variables.

*Dashboard → Appearance → Webstore → Templates → (a template) → files.*

The developer docs at [docs.paynow.gg/hosted-webstores](https://docs.paynow.gg/hosted-webstores/routes) are the canonical reference, and are updated first.

{% hint style="danger" %}
**Duplicate before you edit.** There is no version history and no rollback. Your only backup is **Export Template**. Edit a duplicate, preview it, then set it active. See [Templates](/your-webstore/templates.md).
{% endhint %}

## Routes and their template files

| Route                      | Method | Template file        | Renders                                     |
| -------------------------- | ------ | -------------------- | ------------------------------------------- |
| `/`                        | GET    | `index.html`         | The storefront homepage                     |
| `/products`                | GET    | `category.html`      | Product listing, optionally filtered by tag |
| `/products/{product.slug}` | GET    | `product.html`       | A single product's detail page              |
| `/cart`                    | GET    | `cart.html`          | The shopping cart                           |
| `/subscriptions`           | GET    | `subscriptions.html` | The customer's subscriptions                |
| `/complete`                | GET    | `complete.html`      | Confirmation after a successful transaction |
| `/legal/terms-of-service`  | GET    | None                 | Terms of Service                            |
| `/legal/user-agreement`    | GET    | None                 | User Agreement                              |
| `/legal/privacy`           | GET    | None                 | Privacy Policy                              |

### Action endpoints

These accept POSTs and do not render a template. Point forms and buttons at them.

| Endpoint                                  | Method | Does                                          |
| ----------------------------------------- | ------ | --------------------------------------------- |
| `/products/{product.slug}/checkout`       | POST   | Starts checkout for one product               |
| `/cart/add/{product.slug}`                | POST   | Adds to cart                                  |
| `/cart/set/{product.slug}`                | POST   | Modifies or removes a cart line item          |
| `/cart/empty`                             | POST   | Clears the cart                               |
| `/cart/checkout`                          | POST   | Checks out the cart                           |
| `/auth/sign-in`                           | POST   | Signs the customer in, with optional redirect |
| `/auth/sign-out`                          | POST   | Signs the customer out                        |
| `/subscriptions/{subscription.id}/cancel` | POST   | Cancels a subscription                        |

Wire the cancel endpoint into your subscriptions page, or link customers to [checkout.paynow.gg/subscriptions](https://checkout.paynow.gg/subscriptions), rather than building your own cancellation flow. A customer who cannot find how to cancel disputes the charge instead. See [Subscriptions](/orders-and-subscriptions/subscriptions.md).

## Variables

### Global, available in every template

| Variable               | What it holds                                                      |
| ---------------------- | ------------------------------------------------------------------ |
| `store`                | Your store's details                                               |
| `webstore`             | Webstore configuration                                             |
| `cart`                 | The current customer's cart                                        |
| `navlinks`             | Your configured [navlinks](/your-webstore/navlinks.md)             |
| `tags`                 | Your [tags](/your-webstore/tags.md)                                |
| `customer`             | The signed-in customer, if any                                     |
| `request`              | The current request                                                |
| `notification`         | Any notification to surface to the customer                        |
| `currency`             | The active display currency                                        |
| `available_currencies` | Currencies the customer can switch to                              |
| `modules`              | Configured [modules](/your-webstore/webstore.md#modules), rendered |
| `favicon`              | The store favicon                                                  |

Always check `customer` before using it. It is empty for signed-out visitors, and a template that assumes a signed-in customer breaks the storefront for everyone browsing anonymously, which is most of your traffic.

### Page-specific

| Template             | Variable                | What it holds                                |
| -------------------- | ----------------------- | -------------------------------------------- |
| `index.html`         | `products`              | All available products                       |
| `category.html`      | `products`              | Products matching the active tag             |
|                      | `activeTag`             | The tag currently filtering                  |
|                      | `activeTags`            | All active filtering tags                    |
|                      | `activeNavlink`         | The active navigation link object            |
| `product.html`       | `product`               | The selected product                         |
|                      | `available_gameservers` | Optional gameserver choices for the customer |
| `complete.html`      | `complete`              | Information about the completed order        |
| `subscriptions.html` | `subscriptions`         | The customer's subscriptions                 |

`available_gameservers` is how a customer chooses which server their purchase applies to. Leave it out of `product.html` in a multi-server store and purchases land on the wrong server, which generates refund requests. See [Game Servers](/integrations-and-commands/game-servers.md).

## Modules

Modules are rendered wherever you output the `modules` variable:

This auto-populates every module you have configured. The `raw` filter is required; without it the HTML is escaped and customers see markup instead of content.

Each module type has its own file, so you can override the markup individually:

| Module            | File                           |
| ----------------- | ------------------------------ |
| Featured Product  | `module.featured_product.html` |
| Payment Goal      | `module.payment_goal.html`     |
| Recent Payments   | `module.recent_payments.html`  |
| Top Customer      | `module.top_customers.html`    |
| Gift Card Balance | `module.giftcard_balance.html` |
| Text Box          | `module.text_box.html`         |

The Top Customer file is plural while the module name is singular. That's not a typo here.

Configuration lives in the dashboard, not the template: Payment Goal's **Goal Target** and **Period**, Top Customer's **Field** and limit. See [Webstore → Modules](/your-webstore/webstore.md#modules).

## Before activating any template change

Click through all of these in **Live Template Preview**:

* Homepage
* A category page, with a tag filter applied
* A product page, signed **out**
* A product page, signed **in**
* Cart, with and without items
* The subscriptions page
* The completion page

Signed-out states are the ones that break, because they are the ones you never look at while developing.
