Example: Tip Calculator
This example walks through building a simple tip calculator app from scratch.
Download the example spreadsheet to follow along or upload directly to NExS.
Live Demo
Try changing the Bill Amount, Tip Percentage, or Number of People to see the calculations update instantly. You can also open the Tip Calculator app in a new window.
What We’re Building
A restaurant tip calculator that:
- Takes a bill amount and tip percentage as inputs
- Calculates the tip and total
- Optionally splits the bill among multiple people
Step 1: Create the Excel Spreadsheet
Open Excel, rename the first worksheet to Calculator, and create this layout:
Calculator
| A | B | |
|---|---|---|
| 1 | Tip Calculator | |
| 2 | ||
| 3 | Bill Amount | $50.00 |
| 4 | Tip Percentage | 18% |
| 5 | Number of People | 1 |
| 6 | ||
| 7 | Tip Amount | =B3*(B4/100) |
| 8 | Total | =B3+B7 |
| 9 | Per Person | =B8/B5 |
The tip percentage in B4 is a whole number (18, not 0.18), so the tip formula divides it by 100. That makes it easy to type, and easy to set from buttons or a custom page.
Formatting
- A1:B1: Merged
- B3, B7, B8, B9: Currency, 2 decimals (
$#,##0.00) - B4: Custom format
0"%", which shows the whole number18as18%in Excel - B5: General
- A1 and the labels in A3:A9: Bold
- Optional: Add borders and background colors
Step 2: Create the NExS.app Worksheet
Create a new worksheet named NExS.app (the name isn’t case-sensitive):
| A | B | C | |
|---|---|---|---|
| 1 | app | Tip Calculator | |
| 2 | view | Calculator!A1:B9 | |
| 3 | editable | Calculator!B3, Calculator!B4, Calculator!B5 |
Step 3: Upload and Test
- Save as
.xlsx - Upload to platform.nexs.com
- Test by changing the bill amount and tip percentage
Step 4: Embed on Your Website
Script Embed (Recommended)
<!-- Replace this UUID with your own app's ID if building from scratch -->
<script class="nexs"
src="https://static.nexs.com/js/nexs_embed.js"
data-nexs-app-url="https://platform.nexs.com/app/59c0b001-81fc-4ac5-85ec-30b21f1626c6">
</script>
Custom UI with Declarative API
Use the same workbook to drive your own interface. Every control is bound with the nexs__input class (see the Declarative API Reference):
- Bill amount: a text input bound to B3. On its own it would show the cell’s raw value (
50), so a shortnexsappupdatedlistener shows the formatted value ($50.00) instead. - Tip percentage: four radio buttons that share cell B4, with values
15,18,20, and25. The selected button’s value is sent to B4, and the matching button is checked when B4 changes. Because B4 holds a whole number, no script is needed. - Split between: a number input bound to B5.
Try It
This custom UI is connected to the Live Demo app at the top of this page, so a change here also shows up in the spreadsheet view above.
Tip Calculator
The Code
<!DOCTYPE html>
<html lang="en">
<head>
<title>Tip Calculator</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
max-width: 400px;
margin: 40px auto;
padding: 20px;
}
h1 {
color: #333;
text-align: center;
}
.card {
background: #f8f9fa;
border-radius: 12px;
padding: 24px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.field {
margin-bottom: 20px;
}
.field-label {
display: block;
font-weight: 600;
margin-bottom: 8px;
color: #555;
}
.field input[type="text"],
.field input[type="number"] {
width: 100%;
padding: 12px;
font-size: 18px;
border: 2px solid #ddd;
border-radius: 8px;
box-sizing: border-box;
}
.field input:focus {
border-color: #4a90d9;
outline: none;
}
.tip-options {
display: flex;
gap: 10px;
}
/* Radio buttons styled as buttons: the input is hidden, the label is the button */
.tip-option {
flex: 1;
position: relative;
padding: 12px;
font-size: 16px;
text-align: center;
border: 2px solid #ddd;
border-radius: 8px;
background: white;
cursor: pointer;
}
.tip-option:hover {
border-color: #4a90d9;
}
.tip-option input {
position: absolute;
opacity: 0;
pointer-events: none;
}
.tip-option:has(input:checked) {
background: #4a90d9;
color: white;
border-color: #4a90d9;
}
.tip-option:has(input:focus-visible) {
outline: 2px solid #333;
outline-offset: 2px;
}
.results {
background: #4a90d9;
color: white;
border-radius: 8px;
padding: 20px;
text-align: center;
}
.results .label {
font-size: 14px;
opacity: 0.9;
}
.results .amount {
font-size: 36px;
font-weight: bold;
margin: 5px 0;
}
.results .detail {
font-size: 14px;
opacity: 0.8;
}
</style>
</head>
<body>
<h1>Tip Calculator</h1>
<div class="card">
<div class="field">
<label class="field-label" for="bill">Bill Amount</label>
<input type="text"
id="bill"
class="nexs__input"
data-nexs-cell-addr="B3"
placeholder="$0.00">
</div>
<!-- Radio buttons: all share cell B4, and the selected value is sent -->
<div class="field">
<span class="field-label">Tip Percentage</span>
<div class="tip-options">
<label class="tip-option">
<input type="radio" name="tip" class="nexs__input"
data-nexs-cell-addr="B4" value="15"> 15%
</label>
<label class="tip-option">
<input type="radio" name="tip" class="nexs__input"
data-nexs-cell-addr="B4" value="18" checked> 18%
</label>
<label class="tip-option">
<input type="radio" name="tip" class="nexs__input"
data-nexs-cell-addr="B4" value="20"> 20%
</label>
<label class="tip-option">
<input type="radio" name="tip" class="nexs__input"
data-nexs-cell-addr="B4" value="25"> 25%
</label>
</div>
</div>
<div class="field">
<label class="field-label" for="people">Split Between</label>
<input type="number"
id="people"
class="nexs__input"
data-nexs-cell-addr="B5"
min="1"
value="1">
</div>
<div class="results">
<div class="label">Each Person Pays</div>
<div class="amount">
<span class="nexs__output_formatted" data-nexs-cell-addr="B9"></span>
</div>
<div class="detail">
Tip: <span class="nexs__output_formatted" data-nexs-cell-addr="B7"></span>
|
Total: <span class="nexs__output_formatted" data-nexs-cell-addr="B8"></span>
</div>
</div>
</div>
<!-- NExS app (handles calculations) -->
<!-- Replace this UUID with your own app's ID if building from scratch -->
<script class="nexs"
src="https://static.nexs.com/js/nexs_embed.js"
data-nexs-app-url="https://platform.nexs.com/app/59c0b001-81fc-4ac5-85ec-30b21f1626c6">
</script>
<script>
// Text inputs receive the cell's raw value (50). After each update,
// show the formatted text instead ($50.00), except while the user is typing.
document.addEventListener('nexsappupdated', () => {
document.querySelectorAll('input[type="text"].nexs__input').forEach(input => {
if (input !== document.activeElement) {
input.value = NEXS.cell(input.dataset.nexsCellAddr).text.trim();
}
});
});
</script>
</body>
</html>
To hide the spreadsheet view and show only your custom controls, wrap the NExS script in <div style="display:none;">. See Hiding the NExS App.
Enhancements
Add Preset Tip Buttons
In Excel, add buttons below the results that set common tip percentages:
| A | B | |
|---|---|---|
| 10 | ||
| 11 | [15%] | [18%] |
| 12 | [20%] | [25%] |
Cell A11 content: 15% {setInputs: ['B4', 15]}
Cell B11 content: 18% {setInputs: ['B4', 18]}
And so on for A12 and B12.
NExS.app update: extend the view to row 12 and add the buttons:
| A | B | C | |
|---|---|---|---|
| 2 | view | Calculator!A1:B12 | |
| 3 | editable | Calculator!B3, Calculator!B4, Calculator!B5 | |
| 4 | buttons | A11:B12 |
Add Rounding Options
Add a checkbox to round the per-person amount up to the nearest dollar:
| A | B | |
|---|---|---|
| 10 | Round up? | 0 |
Formula in B9:
=IF(B10=1, CEILING(B8/B5, 1), B8/B5)
NExS.app:
| A | B | C | D | |
|---|---|---|---|---|
| inputs | B10 | checkbox |
Complete NExS.app
With both enhancements (the Round up? checkbox in row 10 and the buttons in rows 11–12):
| A | B | C | D | |
|---|---|---|---|---|
| 1 | app | Tip Calculator | ||
| 2 | mode | open | ||
| 3 | view | Calculator!A1:B12 | ||
| 4 | name | Calculator | ||
| 5 | backgroundColor | white | ||
| 6 | editable | Calculator!B3, Calculator!B4, Calculator!B5 | ||
| 7 | inputs | B10 | checkbox | |
| 8 | buttons | A11:B12 |
What You Learned
- Creating a basic NExS app from a spreadsheet
- Configuring editable cells
- Using the Declarative API for custom styling, including radio buttons that share one cell
- Adding buttons with
setInputsaction - Using checkbox inputs
Next Steps
- Contact Form Example — Build a form with validation and submission
- Sales Dashboard Example — Create a multi-view dashboard with charts
