This guide will teach you how to create a custom setup page for any quest and generate the JSON configuration that QuestPhone uses.
You can see a working example here.
A Quest Setup Page is a webpage where users can:
- Give your quest a name
- Pick active days
- Set a time range (start and end hour)
- Configure custom settings for your quest
- Generate a JSON that QuestPhone uses to run the quest
Think of it as a form that builds the “instruction sheet” for your quest.
Your page should have these sections:
-
Header
- Title of the quest
- Short description
-
Step Inputs
- Quest Title (
string) - Active Days (
array of strings) - Time Range (
array of two numbers) - Optional Settings (
all strings)
- Quest Title (
-
Generate Button
- Builds the JSON configuration from all input values
-
JSON Output
- Displays the JSON so the user can copy it
- Input field for quest name
- Data type:
string
<input type="text" id="inputQuestTitle" placeholder="Enter quest name">Example value: "Pomodoro Quest"
- Buttons for each day: Mon, Tue, Wed…
- Users can select one or more days
- Data type:
array of strings
const selectedDays = new Set();
document.querySelectorAll('.day-button').forEach(btn => {
btn.addEventListener('click', () => {
const day = btn.dataset.day;
if (selectedDays.has(day)) selectedDays.delete(day);
else selectedDays.add(day);
});
});Example value: ["MON","TUE","WED"]
- Start and end hours (24-hour format, minutes ignored)
- Data type:
array of two integers
const startTime = parseInt(document.getElementById('startTime').value.split(':')[0]);
const endTime = parseInt(document.getElementById('endTime').value.split(':')[0]);Example value: [8,22] → quest active from 8 AM to 10 PM
- Any configuration your quest webpage needs can go here
- All values must be strings, even checkboxes or numbers
Examples:
<label>Focus Duration: <input type="text" id="focusDuration" value="25"></label>
<label>Auto-start Focus Sessions: <input type="text" id="autoStart" value="true"></label>Notes:
- All keys inside
quest_jsonwill be injected into your webpage atwebviewUrl. - You can use them to configure timers, display messages, or any interactive feature.
- Because values are strings, your webpage can parse numbers or booleans as needed:
const focusMinutes = parseInt(quest_json.focusDuration); // Convert string to number
const autoStart = quest_json.autoStart === "true"; // Convert string to boolean- Purpose: The link to the webpage that opens when the user starts your quest.
- This page receives
quest_jsondirectly, so all dynamic string values are immediately available.
Example:
quest_json: {
webviewUrl: "https://yourusername.github.io/my-quest-page/"
}IMPORTANT: Make sure to convert quest_json variable here into a string!!! Notes for beginners:
- Replace the URL with your own hosted webpage.
- When the quest starts, QuestPhone injects
quest_jsoninto your page, so you can use the values immediately. - Start with our example: setup.html. Later you can build your own page with interactive elements.
- Collect all input data and combine into this structure:
{
"title": "Pomodoro Quest",
"selected_days": ["MON","TUE","WED"],
"time_range": [8,22],
"unique_id": "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx",
"quest_json": {
"webviewUrl": "https://yourusername.github.io/my-quest-page/",
"focusDuration": "25",
"autoStart": "true"
}
}IMPORTANT: Make sure to convert quest_json variable here into a string!!!
Key points:
unique_idis a new ID for every quest (usegenerateUUID()).- All values inside
quest_jsonmust be strings webviewUrlis where your webpage loads and receives the config.
UUID example function:
function generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
const r = Math.random() * 16 | 0;
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
}- Show JSON on the page
- Let users copy it to paste into QuestPhone
document.getElementById('copyBtn').addEventListener('click', () => {
navigator.clipboard.writeText(generatedJSON)
.then(() => alert('Copied!'))
.catch(err => alert('Failed to copy: ' + err));
});Header → Quest Title → Active Days → Time Range → Custom Settings → Generate JSON → Copy JSON
- Header: Quest name & subtitle
- Quest Title: string
- Active Days: array of strings
- Time Range: array of numbers
- Settings & webviewUrl: object with all dynamic strings (directly injected into webpage)
- JSON Output: display + copy
-
Keep it simple at first: title, days, time
-
Validate inputs:
- At least one day must be selected
- Start time < End time
-
Place all quest-specific configurations inside
quest_json -
Remember: all values in
quest_jsonmust be strings -
Test the generated JSON in QuestPhone
-
Later, make your page interactive, colorful, and fun
Working example page: setup.html