# Custom code

Where you can add your own Liquid, HTML, CSS and JavaScript to Techno without editing theme files, and how to do it safely.

Techno has three places for custom code that survive theme updates, because the code is stored as a setting rather than in a theme file. Use them before reaching for **Edit code**.

> **Warning:** Before you add custom code or edit theme files, duplicate your theme in **Online Store › Themes › ⋯ › Duplicate** and make changes on the copy. Custom code isn't covered by Techno support. If you need help writing it, consider hiring a [Shopify Partner](https://www.shopify.com/partners/directory).

## Where custom code can go

| Place | Available in | Use it for |
| --- | --- | --- |
| Custom Liquid section | Any template, and the Footer group. Not the Header. | Embeds, app snippets, a one-off block of HTML |
| Custom Liquid block | Product, Featured product, Article, Rich text and Footer sections, and the section Shopify creates for a generated block | Code placed among other blocks, including code that needs the product or article, such as a size chart link or a metafield readout |
| App blocks | Product and Featured product sections, and the section Shopify creates for a generated block | Reviews, size guides, wishlists and other app features |

App embeds, such as chat widgets and analytics, are turned on in **Theme settings › App embeds**, not in a section.

## Custom Liquid block

The block renders in the position you place it: in the product or article column, among a Rich text section's blocks, or in the footer's row of columns. When its Liquid outputs nothing, shoppers see nothing and the theme editor shows a "Not shown to shoppers" note in its place. Liquid in a Custom Liquid setting can use global objects and the objects of the template it's on, such as `product` on a product template and `article` and `blog` on an article template. It can't use `section`, `block` or theme `settings`.

For a label and a value from a product metafield, such as "Battery life: 40 h", you don't need code: add a Spec row to the Spec table. See [Product page › Rows from metafields](../features/product-page.md#rows-from-metafields).

Example: a line on the product page that shows a product metafield when it has a value.

```liquid
{%- if product.metafields.custom.warranty != blank -%}
  <p class="tc-meta">Warranty: {{ product.metafields.custom.warranty }}</p>
{%- endif -%}
```

> **Note:** In a Featured product section on another template, such as the home page, `product` isn't available, so a Custom Liquid block there can't read the section's chosen product. Reference the product by handle instead, for example `all_products['your-handle']`.

## Matching the theme's look

Use the theme's classes and CSS variables so your code follows the active color palette. See [Design tokens](design-tokens.md) for the full list.

| Class | Renders |
| --- | --- |
| `tc-panel` | A bordered panel with the panel background |
| `tc-panel__head` | A panel's header strip. Put a label `<span>` inside, and optionally a second `<span class="tc-panel__status">` for a status in the accent color. |
| `tc-panel__body` | Padded panel content |
| `tc-btn` | An outlined button. Add `tc-btn--primary` for the filled style or `tc-btn--sm` for a small one. |
| `tc-meta` | Small, wide-spaced metadata text in the "Secondary text" color |
| `tc-rte` | Rich text formatting for paragraphs, lists and links |
| `tc-badge` | A small label. Add `tc-badge--accent` or `tc-badge--danger` for color. |
| `tc-visually-hidden` | Hidden on screen, still read by screen readers |

Example: a panel that matches the spec table.

```liquid
<div class="tc-panel">
  <div class="tc-panel__head">
    <span>Compatibility</span>
    <span class="tc-panel__status">Verified</span>
  </div>
  <div class="tc-panel__body tc-rte">
    <p>Works with USB-C and Thunderbolt 4 hosts.</p>
  </div>
</div>
```

For CSS, add a `<style>` tag in the same Custom Liquid setting and use the theme's variables:

```liquid
<style>
  .my-callout {
    border: 1px solid var(--tc-border-control);
    background: var(--tc-panel);
    color: var(--tc-ink-strong);
  }
</style>
```

## Opening the cart drawer from your code

Any element with `data-drawer-open="CartDrawer"` opens the cart drawer when clicked. Use a link to `/cart` so it still works without JavaScript:

```liquid
<a href="{{ routes.cart_url }}" data-drawer-open="CartDrawer">View cart</a>
```

To add a product with the theme's cart drawer behavior, wrap a standard product form in `<tc-product-form>`. See [JavaScript components](javascript.md#using-tc-product-form-in-custom-code).

From a script, use Shopify's storefront actions, which Techno configures: `Shopify.actions.openCart()` opens the drawer, and `Shopify.actions.updateCart({ lines: [{ merchandiseId: 'gid://shopify/ProductVariant/123', quantity: 1 }] })` changes the cart and updates the drawer, the cart page and the header count without a reload. Call them after `DOMContentLoaded`. See [JavaScript components › Standard events and actions](javascript.md#standard-events-and-actions).

## Editing theme files

If you edit theme files in **Edit code**:

* Your changes won't carry over when you update Techno. Keep a list of every file and change.
* Run `shopify theme check` on your copy to catch Liquid errors.
* Read [Theme architecture](architecture.md) first, especially how CSS and notes are organized.

## Support policy for custom code

Techno support covers the theme as released. We can't write, debug or maintain custom code, including code in Custom Liquid settings and edits made in **Edit code**. If an issue only happens with custom code in place, we'll ask you to reproduce it on an unmodified copy of Techno. See [Support](../help/support.md).

## See also

* [Design tokens](design-tokens.md): CSS variables for every color and size setting
* [JavaScript components](javascript.md): the theme's custom elements and data attributes
* [Theme architecture](architecture.md): where things live
