1. Before you start
- Tested with: Google Chrome 152 on Linux (Ubuntu), opening
app/index.htmldirectly from disk. Other Chromium-based browsers, Firefox, Safari, Windows and macOS were not tested. - Install: unzip
VolosTally-1.0.1.zipanywhere, for example your Documents folder. There is nothing else to install and no account. - Open: double-click
app/index.html, or drag it into a Chrome window. - What it is not: VolosTally does not schedule lessons, send email, take payments, keep accounts or produce tax invoices. Amounts are calculated lesson charges from your calendar and your rules; a calendar entry does not prove attendance, payment or an amount owed.
2. Your first result in two minutes (fictional sample)

- Click Try the fictional sample. It loads a fictional studio, “Maple Street Piano”, with four students in three families, March 2026, time zone America/New_York, US dollars, and an illustrative set of rules (described in the yellow note).
- In 2 · Students you see each calendar title. Nothing is assigned yet. Click Accept 4 suggestions, then Mark 2 unassigned as not lessons (Dentist and Recital rehearsal).

- Open 4 · Review & export. Expected result: Rivera family $270.00 (Ana 3 × $30; Ben 4 × 45 min at $60/hour), Chen family $140.00 (monthly fee), Okafor family $55.00 (3 lessons from the prepaid package, 1 charged), all families $465.00, and one note: “Tobi Okafor has 0 package lessons left.”
- Tick I have reviewed these calculated statements and click Export month package (.zip).

3. Using your own calendar and roster
Export your calendar
- Google Calendar (web): Settings → Import & export → Export. Google downloads a .zip containing one .ics file per calendar; you can add that .zip directly. To export one calendar, use that calendar's settings → Export calendar. (Google's help article “Export your Google Calendar data”.)
- Apple Calendar or Outlook: export the lesson calendar as an .ics file. These exports were not tested; Outlook files that use Windows time-zone names (for example “Eastern Standard Time”) are listed as “could not be read” in version 1.
In 1 · Calendar, drop the files or click Choose calendar files…. The original files are only read, never changed.

Prepare the roster (CSV)
Click Download roster template in step 2 and fill it in with a spreadsheet, then save as “CSV UTF-8”. One row per student:
| Column | Meaning |
|---|---|
family_id, student_id | Your own short, permanent IDs (letters, digits, _ . -). Keep them the same every month; balances follow these IDs, not names. |
family_name, student_name | Names printed on statements. Students with the same family_id share one statement. |
basis | lesson (rate per lesson), hour (rate per hour, by actual minutes, rounded half-up to the cent per lesson) or flat (monthly fee). |
rate / monthly_fee | Plain numbers such as 30 or 59.99 — no currency symbols, commas or spaces. rate for lesson/hour, monthly_fee for flat only. |
lesson_minutes | Required when credits or a package are on. Entries of a different length are blocked so a 30-minute credit is never spent on a 60-minute lesson. |
makeup_credits, package | yes/no. Only for lesson basis. |
opening_credits, opening_package | Starting balances when you begin without last month's balance file. |
email | Printed on the statement only. |
If any row is invalid, nothing from that file is loaded and the previous roster stays in place:

Assign calendar titles
A title is the calendar event name without its leading type word. Choose a student for each lesson title and Not a lesson — never charge for anything else. Suggestions appear only when a student's full name appears as whole words in the title, and are applied only when you click Accept. Group or shared events must be assigned to one student or marked as not a lesson; version 1 does not split one event between students.
4. Supported files, characters and limits
- iCalendar (.ics, UTF-8) per RFC 5545, or a .zip of .ics files (stored or deflate, no passwords). Up to 50 calendar files and 20 MB of expanded calendar data; up to 5,000 entries in the chosen month; roster up to 200 students.
- Repeat rules:
FREQ=DAILY,WEEKLY,MONTHLYwithINTERVAL,COUNT,UNTIL,BYDAY(numbered like2TUor-1FRfor monthly),BYMONTHDAY,BYMONTH,WKST; skipped dates (EXDATE), added dates (RDATEdate-times) and moved or cancelled single lessons (RECURRENCE-ID). - Times: IANA zone names (such as
America/New_York), UTC times and floating times (read in your studio zone). A lesson that starts in a skipped or repeated clock-change hour is blocked. - Listed as “could not be read” and never charged: yearly or hourly rules,
BYSETPOS,BYWEEKNO,BYYEARDAY,BYHOUR/BYMINUTE/BYSECOND,EXRULE,RANGE=THISANDFUTURE, periodRDATEs, unknown or Windows time-zone names, malformed lines, and a first date that does not match its own repeat rule. All-day, zero-length, negative or sub-minute entries can't be charged. - Identical copies of the same event in two files are counted once and noted; different versions of the same event block until you remove one file.
- Currencies: USD, CAD, AUD, NZD, GBP, EUR, CHF, SEK, NOK, DKK, PLN, ZAR, SGD, HKD, INR (2 decimals), JPY and KRW (whole numbers). One currency per month.
Characters statements can print
Statements include a bundled Noto Sans font to reduce font substitution. Display and PDF export were verified in Chrome 152 on Linux; other browsers, operating systems and physical printing remain untested. It covers Latin letters with accents (including Vietnamese, Polish, Czech, Turkish, Romanian and the Hawaiian ʻokina), Greek, Cyrillic, digits, common punctuation, fractions and currency signs — 1,994 characters in total.
Family names, student names, emails, the studio name, contact lines and the payment note are checked character by character. A character outside that set — for example Chinese, Japanese or Korean characters, Arabic, Hebrew, Devanagari or Thai letters, emoji, or invisible and text-reversing characters copied from other documents — would print as an empty box, so it is listed in red with the field, the roster row and its code (such as U+20000), and export stays disabled. If an agreed supported spelling is appropriate, change the text and load the roster again, or edit the header field in step 3. Otherwise use a different statement workflow; do not silently change a person’s name. The amounts are still calculated so you can keep reviewing.

5. Rules, credits and packages

| Title starts with | Entry type | What happens |
|---|---|---|
| (nothing) | Lesson | Charged; a per-lesson student with a package uses one package lesson first. |
CXL, CANCELLED, CANCELED | Cancelled by student | Your rule: “Not charged”; “Not charged + makeup credit” (credit only for students with makeup credits on); or “Charged as a lesson”. |
NOSHOW, NO-SHOW | No-show | Your rule: charged or not charged. |
TC | Cancelled by teacher | Your rule: “Not charged”, or “Not charged + makeup credit” (credit only for students with makeup credits on). |
MAKEUP, MAKE-UP | Makeup lesson | Uses one credit if available; otherwise you decide per lesson in step 4 (charge it or not). |
| calendar status “cancelled” | Removed in calendar | Listed, never charged, no credit. |
Every rule starts empty. Credits are used in date order; when a credit is earned and used at the same moment, it is earned first. Hourly and monthly-fee students never get credits or packages. A monthly fee is charged only when you choose “Charge the monthly fee” for that student and month — having no lessons never silently charges or exempts anyone. New package lessons are entered as an explicit adjustment in step 3; they are a balance change, not a payment record.
6. Review, export and PDFs
Step 4 lists everything that blocks export (red, with a button to the right step), notes (amber), decisions you still need to make, totals per family, every entry and a live statement preview. Export stays disabled until nothing is blocking and you tick the review box. Any later change — files, roster, rules, month, assignments or decisions — clears that tick.
The exported VolosTally-YYYY-MM.zip contains:
statements-YYYY-MM.html(all families) andfamilies/YYYY-MM Family.html(one per family);ledger-YYYY-MM.csv(every entry with result, amount, credit and package change, calendar title, UID and source file) andsummary-YYYY-MM.csv(one line per family). Values that a spreadsheet could treat as formulas start with an apostrophe;balances-YYYY-MM.jsonfor next month, andreview-YYYY-MM.txt(files, excluded titles, notes and rules).
Every statements file embeds the statement font (about 220 KB), so no separate font file is needed. After copying a statement, check it in Chrome on Linux before sharing it; display in email previews and other applications is unverified. A month package for 30 families is about 7 MB; for the maximum of 200 families it is about 45 MB.
PDF: open a statements file in Chrome and choose Print → Save as PDF. Each family starts on a new page; table headings repeat when a family runs over several pages. The PDF contains the statement font, and names stay searchable and copyable as plain text.


7. Next month: carrying balances forward
- Export your calendar again (it now includes the new month).
- Open your saved project (or load the same roster), replace the calendar file, and set the new month in step 3.
- Click Load last month’s balances… and choose
balances-YYYY-MM.jsonfrom last month's export.
A balance file only opens the month right after it. Loading it for the same month rebuilds that month from its own opening balances (no double deduction). Any other month is blocked; choose Start fresh from the roster instead if you really want a new baseline. With the sample, loading March's balances for April 2026 gives Rivera $225.00, Chen $140.00, Okafor $275.00 (no package lessons left) and $640.00 in total; Ana carries 1 makeup credit into May.

8. Saving and reopening a project
Save project downloads volostally-project-YYYY-MM.json with your calendar files, roster, assignments, rules, decisions and header. Open project… restores it, so you can stop and continue a review later. Statement references (prefix-YYYYMM-family_id) are a convenience; if you re-issue a statement, keep your own record.
9. Troubleshooting
| Message or symptom | What to do |
|---|---|
| “is not valid UTF-8 text” | Export the calendar again; for the roster choose “CSV UTF-8”. |
| “could not be read” in step 1 | Read the reason. If it is a lesson, change it in your calendar app (for example to a weekly rule) and export again; otherwise mark the title as not a lesson. |
| “not a recognised IANA time zone name” | Version 1 needs zone names like America/New_York. Windows names from some Outlook exports are not supported. |
| “does not exist” / “happens twice” (clock change) | Move that lesson out of the skipped or repeated hour in your calendar. |
| “does not match the configured … min” | Fix the event length in the calendar or the student's lesson_minutes. |
| “Statements cannot print U+…” | The named field contains a character the statement font does not have (see Characters statements can print). The item shows where it is, with the character written as its code in square brackets. Change the roster and load it again, or edit the field under Statement header in step 3. |
| Export button disabled | Clear every red item in step 4, then tick the review box. |
| Downloads don't appear | Check Chrome's download bar or allow downloads for local files. |
10. Privacy
VolosTally runs entirely in your browser from local files. It makes no network requests, has no analytics and stores nothing between sessions; closing the tab discards your work unless you saved a project file. Your calendar and roster files are read, never modified. Exports go only where your browser saves downloads.
11. Uninstall
Delete the unzipped VolosTally folder. Optionally delete exported month packages and project files from your downloads folder. Nothing else is installed.
VolosTally 1.0.1 by Perunlight. Statement font: Noto Sans, Copyright 2022 The Noto Project Authors, SIL Open Font License 1.1 (the app package includes the licence as licenses/NotoSans-OFL.txt). The sample studio, families, students and email addresses are fictional.