Your First App: a WhatsApp Button
In this tutorial you build a complete storefront app: a floating WhatsApp button that appears on every page of the merchant's site. It is a slimmed-down version of the WhatsApp app in the SitePack Marketplace.
The app needs no server, no database and no OAuth. SitePack renders the settings page for the merchant, stores the answers and renders your template on the storefront with those answers filled in.
Before you start
- A free partner account and organisation. See The Partner Portal, Step by Step.
- The SitePack CLI, signed in.
Step 1: Create the app
sitepack app:init
Give the directory a name (whatsapp-button) and the app a name (WhatsApp Button). The CLI registers the app in your organisation and creates the starter files:
whatsapp-button/
├── app.json
├── templates/
├── assets/
└── translations/
These four are the only things sitepack app:publish uploads. Everything else in the folder stays on your machine.
Step 2: Describe the settings
The merchant needs to fill in a phone number, and may pick a corner and a colour. Describe those fields in app.json under admin.settings_schema. SitePack turns them into a settings form in the merchant's admin; you write no HTML for it.
{
"uuid": "(filled in by the CLI, do not change)",
"name": "WhatsApp Button",
"version": 1,
"description": "Adds a floating WhatsApp button to every page, so visitors can start a chat in one tap.",
"author": "Your company",
"admin": {
"settings_type": "abstract",
"settings_schema": {
"type": "object",
"properties": {
"phone_number": {
"type": "string",
"title": "admin.settings.phone_number.title",
"description": "admin.settings.phone_number.description",
"placeholder": "+44 7700 900123"
},
"position": {
"type": "string",
"title": "admin.settings.position.title",
"enum": ["bottom_right", "bottom_left"],
"enum_titles": [
"admin.settings.position.options.bottom_right",
"admin.settings.position.options.bottom_left"
],
"default": "bottom_right"
},
"button_color": {
"type": "string",
"title": "admin.settings.button_color.title",
"format": "color",
"default": "#25D366"
}
},
"required": ["phone_number"]
}
},
"blocks": {
"body_end": "whatsapp_widget.twig"
},
"scripts": [],
"webhooks": []
}
What you get for free:
enumwithenum_titlesbecomes a dropdown,"format": "color"a colour picker.requiredstops the merchant from saving without a number.- Every
titleis a translation key, so the form shows up in the merchant's own language (Step 4). - The saved values are typed and checked against your schema; keys outside it are dropped.
There is no auth section. The app does not call the API, so it asks for no scopes and needs no OAuth. See App Settings for every field type.
Step 3: Render the button
blocks maps a spot in the page to a Twig template. body_end renders right before </body> on every page, in every theme. Create the template:
{# wa.me wants digits only, so strip the + and spaces the merchant may have typed. #}
{% set number = settings.phone_number|default('')|replace({' ': '', '+': '', '-': ''}) %}
{% set color = settings.button_color|default('#25D366') %}
{% set color = color matches '/^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i' ? color : '#25D366' %}
{% set side = settings.position == 'bottom_left' ? 'left' : 'right' %}
{% if number matches '/^[0-9]{6,20}$/' %}
<style>
#my-whatsapp {
position: fixed;
bottom: 20px;
{{ side }}: 20px;
z-index: 2147483000;
width: 60px;
height: 60px;
border-radius: 50%;
background: {{ color }};
display: flex;
align-items: center;
justify-content: center;
color: #fff;
}
</style>
<a id="my-whatsapp" href="https://wa.me/{{ number }}" target="_blank" rel="noopener noreferrer"
aria-label="{{ 'widget.aria_label'|trans }}">
{{ sitepack_icon('whatsapp') }}
</a>
{% endif %}
settings holds what the merchant saved, with your defaults filled in. The template renders nothing until a valid number is set, so a fresh install never shows a broken button.
The merchant types these values. Check a colour before you put it in CSS and a number before you put it in a URL, as above. Twig escapes output for you; never use raw. See The sandbox.
Need JavaScript, for example to show a greeting bubble after a few seconds? Put the file in assets/js/ and list it under "scripts". See Storefront Blocks & Events.
Step 4: Translate the labels
Add one JSON file per language in translations/. English is the fallback for anything a language leaves out.
{
"widget": {
"aria_label": "Chat with us on WhatsApp"
},
"admin": {
"settings": {
"phone_number": {
"title": "WhatsApp number",
"description": "Your WhatsApp (Business) number in international format."
},
"position": {
"title": "Button position",
"options": { "bottom_right": "Bottom right", "bottom_left": "Bottom left" }
},
"button_color": { "title": "Button colour" }
}
}
}
{
"widget": {
"aria_label": "Chat met ons via WhatsApp"
},
"admin": {
"settings": {
"phone_number": {
"title": "WhatsApp-nummer",
"description": "Je WhatsApp (Business) nummer in internationaal formaat."
},
"position": {
"title": "Plek van de knop",
"options": { "bottom_right": "Rechtsonder", "bottom_left": "Linksonder" }
},
"button_color": { "title": "Kleur van de knop" }
}
}
}
The merchant sees the settings form in their admin language; the visitor sees the button label in the language of the page. See Translations.
Step 5: Publish
sitepack app:publish
The CLI checks your JSON, uploads the files and creates a new version. Open your app in the Partner Portal: the App Overview shows the new version and the description from your app.json.
Step 6: Try it on your own site
Open your app in the Partner Portal and copy the Install link from the Distribution card. Open it while you are signed in to a site you manage, and approve the consent screen. SitePack installs the app and takes you to its settings page: fill in the number and save. Reload the storefront: the button is there.
Change something, run sitepack app:publish again and reload. The new version is live on every site that has the app installed.
Step 7: Go live
Upload an icon, write the Marketplace listing, set the app to Public and submit it for review. The Partner Portal guide walks you through it.
Once approved, merchants find your app in the Marketplace and install it with one click. Because it is free and asks for no data access, there is no consent screen in between: the settings page opens straight away.
Where to go next
- App Settings: every field type, image pickers and translatable text.
- Storefront Blocks & Events: all block spots, scripts, and the events you can react to.
- API Integrations: when your app needs the merchant's orders, products or customers.