Skip to content

Commit be11189

Browse files
snapsynapseclaude
andcommitted
Differentiate soft and hard returns; add tabbed usage section
Import now treats a blank line as a hard return (new chapter / Camera Hub scroll-save point) and a single newline as a soft return kept as an embedded line break inside the chapter, matching how Camera Hub stores text. Export and edit use the same convention so scripts round-trip. Adds group_into_chapters and chapters_to_text as the shared source of truth. Site: Instructions, CLI commands, and Troubleshooting are now one tabbed Usage section styled like Quick setup; canonical date bumped. Docs: README script-format, ARCHITECTURE data model, and llms.txt updated; CHANGELOG 0.6.0. Co-Authored-By: Claude Opus 4.8 <[email protected]>
1 parent 6e048ef commit be11189

9 files changed

Lines changed: 282 additions & 47 deletions

File tree

ARCHITECTURE.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@ Two kinds of file matter:
3737

3838
- `AppSettings.json` — the registry. Each script has a GUID, an index that
3939
sets library order, and a friendly name.
40-
- `Texts/<GUID>.json` — per-script content. Each chapter is one entry; on
41-
import, each non-empty input line becomes one chapter.
40+
- `Texts/<GUID>.json` — per-script content. Each chapter is one entry and one
41+
Camera Hub scroll/save point. On import, a blank line (hard return) starts a
42+
new chapter and a single newline (soft return) is kept as a line break inside
43+
the chapter, matching how Camera Hub itself stores embedded newlines.
4244

4345
A script exists only when both its registry entry and its `Texts/` file are
4446
present and their GUIDs agree. Most write operations touch both files, which
@@ -57,7 +59,10 @@ Grouped by responsibility:
5759
`update_appsettings`.
5860
- Verification: `verify_script_registered`, `verify_script_absent`. Called
5961
after writes to confirm the expected change is visible on disk.
60-
- Conversion: `strip_markdown`, `convert_text_file`, `generate_json_data`.
62+
- Conversion: `strip_markdown`, `group_into_chapters`, `chapters_to_text`,
63+
`convert_text_file`, `generate_json_data`. `group_into_chapters` and
64+
`chapters_to_text` are inverses over the blank-line chapter convention, so
65+
import, export, and `edit` all round-trip through one definition.
6166
- Core operations: `import_script`, `list_scripts`, `export_script`,
6267
`export_all`, `delete_script`, `rename_script`, `reindex_scripts`,
6368
`edit_script`, `backup`, `restore`.

CHANGELOG.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.6.0] - 2026-05-28
11+
12+
### Changed
13+
- Import now distinguishes soft returns from hard returns. A blank line is a
14+
hard return that starts a new chapter (a new Camera Hub scroll/save point); a
15+
single newline is a soft return kept as a line break inside the chapter. This
16+
matches how Camera Hub itself stores embedded newlines. Previously every line
17+
became its own chapter and blank lines were discarded.
18+
- Export and `edit` use the same convention: chapters are separated by a blank
19+
line and soft breaks are preserved, so a script round-trips through export
20+
and re-import without losing structure.
21+
22+
### Added
23+
- `group_into_chapters` and `chapters_to_text` helpers in `prompter_kit.py`,
24+
the single source of truth for the chapter/return convention shared by
25+
import, export, and `edit`.
26+
27+
### Note
28+
- A chapter that itself contains a blank line (only possible from manual Camera
29+
Hub authoring) will split into two chapters if exported to text and
30+
re-imported, since flat text uses the blank line as the chapter boundary.
31+
32+
## [0.5.2] - 2026-05-28
33+
34+
### Added
35+
- Site landing page now has an Instructions section above the optional CLI
36+
commands, walking through how to start and use PrompterKit after install,
37+
with a matching nav link.
38+
- Site landing page now has a Troubleshooting section covering common launch
39+
failures (wrong directory, missing Flask, Python version, port in use, and
40+
Camera Hub not reflecting changes), with a matching nav link.
41+
1042
### Fixed
1143
- Replace-mode `restore` now stages replacement files before touching the live
1244
library and rolls back the prior `Texts/` directory and `AppSettings.json` if

README.md

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ Prefer the terminal? After setting up the virtual environment (see Terminal
8888
Install above), every action is also a one-liner:
8989

9090
```
91-
# Import a .txt or .md file (one line per chapter)
91+
# Import a .txt or .md file (blank line = new chapter, single newline = soft break)
9292
python3 prompter_kit.py import script.md --name "My Script"
9393
9494
# Import and auto-restart Camera Hub around the write
@@ -160,17 +160,26 @@ a copied Camera Hub directory before touching the live device data.
160160

161161
## Script format
162162

163-
Plain `.txt` or `.md`. Each non-empty line becomes one chapter.
163+
Plain `.txt` or `.md`. A chapter is one Camera Hub scroll/save point. Returns
164+
map to chapters the way you would expect from a teleprompter:
165+
166+
- A blank line is a hard return: it ends the current chapter and starts a new
167+
one (a new scroll/save point).
168+
- A single newline is a soft return: it stays inside the chapter as a line
169+
break, with no new scroll point.
164170

165171
```markdown
166-
# Act One
172+
Welcome to the show.
173+
Tonight we cover three topics.
167174

168-
- Welcome to the show.
169-
- **Tonight** we cover three topics.
175+
Topic one is the easy one.
170176
```
171177

172-
imports as three plain chapters. Markdown headings, bold, italic, links,
178+
imports as two chapters. The first keeps both lines together as soft breaks;
179+
the blank line starts the second. Markdown headings, bold, italic, links,
173180
images, inline code, blockquotes, list bullets, and strikethrough are stripped.
181+
Export and `edit` use the same convention, so a script round-trips: a blank
182+
line between chapters, soft breaks preserved within each.
174183

175184
## Safety
176185

docs/index.html

Lines changed: 134 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,32 @@
305305
}
306306
.cmd-list .desc { color: var(--text-muted); }
307307

308+
/* Troubleshooting */
309+
.trouble {
310+
list-style: none;
311+
display: flex;
312+
flex-direction: column;
313+
gap: 1rem;
314+
margin: 1.5rem 0 0;
315+
}
316+
.trouble li {
317+
padding: 1rem 1.25rem;
318+
background: var(--bg-alt);
319+
border: 1px solid var(--border);
320+
border-radius: 8px;
321+
font-size: 0.9rem;
322+
color: var(--text-muted);
323+
}
324+
.trouble strong { color: var(--text); display: block; margin-bottom: 0.35rem; }
325+
.trouble code {
326+
font-family: var(--mono);
327+
font-size: 0.82rem;
328+
color: var(--accent);
329+
background: var(--code-bg);
330+
padding: 0.1rem 0.4rem;
331+
border-radius: 4px;
332+
}
333+
308334
/* Buttons */
309335
.cta-row { display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; }
310336
.btn {
@@ -425,6 +451,21 @@
425451
outline: 3px solid var(--accent);
426452
outline-offset: 2px;
427453
}
454+
#tab-instructions:checked ~ .tab-labels label[for="tab-instructions"],
455+
#tab-cli:checked ~ .tab-labels label[for="tab-cli"],
456+
#tab-trouble:checked ~ .tab-labels label[for="tab-trouble"] {
457+
color: var(--accent);
458+
border-bottom-color: var(--accent);
459+
}
460+
#tab-instructions:checked ~ .tab-panels #panel-instructions,
461+
#tab-cli:checked ~ .tab-panels #panel-cli,
462+
#tab-trouble:checked ~ .tab-panels #panel-trouble { display: block; }
463+
#tab-instructions:focus-visible ~ .tab-labels label[for="tab-instructions"],
464+
#tab-cli:focus-visible ~ .tab-labels label[for="tab-cli"],
465+
#tab-trouble:focus-visible ~ .tab-labels label[for="tab-trouble"] {
466+
outline: 3px solid var(--accent);
467+
outline-offset: 2px;
468+
}
428469

429470
/* Feature table */
430471
table { width: 100%; border-collapse: collapse; margin-bottom: 1.5rem; }
@@ -493,6 +534,7 @@
493534
<div class="links mobile-compact">
494535
<a href="#features">Features</a>
495536
<a href="#install">Install</a>
537+
<a href="#usage">Usage</a>
496538
<a href="https://github.com/snapsynapse/prompter-kit" class="gh-star" target="_blank" rel="noopener" aria-label="Star snapsynapse/prompter-kit on GitHub">
497539
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true">
498540
<path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.75.75 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z"/>
@@ -535,7 +577,7 @@ <h2>Everything Camera Hub is missing</h2>
535577
<div class="pillar">
536578
<span class="icon" aria-hidden="true">📄</span>
537579
<h3>Import any text file</h3>
538-
<p>Drop a .txt or Markdown file onto the page. PrompterKit converts each line into a chapter and registers it with Camera Hub instantly &mdash; no copy-paste required.</p>
580+
<p>Drop a .txt or Markdown file onto the page. PrompterKit groups it into chapters (a blank line starts a new scroll point, a single line break stays inside one) and registers it with Camera Hub instantly. No copy-paste required.</p>
539581
</div>
540582
<div class="pillar">
541583
<span class="icon" aria-hidden="true">🗄️</span>
@@ -625,23 +667,100 @@ <h2>Quick setup</h2>
625667
</div>
626668
</section>
627669

628-
<section id="cli">
670+
<section class="alt" id="usage">
629671
<div class="container">
630-
<h2>CLI commands (optional)</h2>
631-
<p>Prefer the terminal? Every action is also a one-liner.</p>
632-
<ul class="cmd-list">
633-
<li><code>import script.txt --name "Episode 42"</code><span class="desc">Import a text file as a new script</span></li>
634-
<li><code>export --list</code><span class="desc">See all registered scripts</span></li>
635-
<li><code>backup</code><span class="desc">Archive your whole library to a zip</span></li>
636-
<li><code>restore backup.zip</code><span class="desc">Restore from a backup archive</span></li>
637-
<li><code>delete "Old Draft"</code><span class="desc">Remove a script by name</span></li>
638-
<li><code>rename "Draft" "Episode 42 Final"</code><span class="desc">Rename a script</span></li>
639-
<li><code>import --restart script.txt --name "Live"</code><span class="desc">Auto-stop Camera Hub, import, restart after success or failure</span></li>
640-
</ul>
672+
<h2>Using PrompterKit</h2>
673+
<div class="tabs">
674+
<input type="radio" name="usage-tab" id="tab-instructions" class="tab-input" checked aria-label="Instructions">
675+
<input type="radio" name="usage-tab" id="tab-cli" class="tab-input" aria-label="CLI commands">
676+
<input type="radio" name="usage-tab" id="tab-trouble" class="tab-input" aria-label="Troubleshooting">
677+
<div class="tab-labels">
678+
<label for="tab-instructions" class="tab-label">Instructions</label>
679+
<label for="tab-cli" class="tab-label">CLI commands</label>
680+
<label for="tab-trouble" class="tab-label">Troubleshooting</label>
681+
</div>
682+
<div class="tab-panels">
683+
<div class="tab-panel" id="panel-instructions">
684+
<p>Once PrompterKit is installed, here is how to start it and manage your library day to day.</p>
685+
<ol class="steps">
686+
<li>
687+
<div>
688+
<strong>Quit Camera Hub first</strong>
689+
PrompterKit and Camera Hub share the same local script files. Close Camera Hub before launching so the two never write at the same time.
690+
</div>
691+
</li>
692+
<li>
693+
<div>
694+
<strong>Start the app</strong>
695+
Activate your environment, then run the GUI. Your browser opens automatically at <code>http://127.0.0.1:5000</code>.
696+
<pre>source .venv/bin/activate
697+
python3 prompter_kit_gui.py</pre>
698+
<p style="margin-top:0.5rem">On Windows, activate with <code>.venv\Scripts\activate</code></p>
699+
</div>
700+
</li>
701+
<li>
702+
<div>
703+
<strong>Import and organize your scripts</strong>
704+
Drop in any <code>.txt</code> or Markdown file to add a script, then rename, reorder, or delete entries from the library list. The index stays normalized so Camera Hub reads the library cleanly.
705+
</div>
706+
</li>
707+
<li>
708+
<div>
709+
<strong>Back up your library</strong>
710+
Run a backup to archive every script to a zip. Keep it somewhere safe so a Camera Hub reinstall or a new computer never costs you your scripts.
711+
</div>
712+
</li>
713+
<li>
714+
<div>
715+
<strong>Stop the server and reopen Camera Hub</strong>
716+
When you are done, press <code>Ctrl+C</code> in the terminal to stop PrompterKit, then reopen Camera Hub to record with your updated library.
717+
</div>
718+
</li>
719+
</ol>
720+
</div>
721+
<div class="tab-panel" id="panel-cli">
722+
<p>Prefer the terminal? Every action is also a one-liner. The CLI is optional; the GUI covers daily use.</p>
723+
<ul class="cmd-list">
724+
<li><code>import script.txt --name "Episode 42"</code><span class="desc">Import a text file as a new script</span></li>
725+
<li><code>export --list</code><span class="desc">See all registered scripts</span></li>
726+
<li><code>backup</code><span class="desc">Archive your whole library to a zip</span></li>
727+
<li><code>restore backup.zip</code><span class="desc">Restore from a backup archive</span></li>
728+
<li><code>delete "Old Draft"</code><span class="desc">Remove a script by name</span></li>
729+
<li><code>rename "Draft" "Episode 42 Final"</code><span class="desc">Rename a script</span></li>
730+
<li><code>import --restart script.txt --name "Live"</code><span class="desc">Auto-stop Camera Hub, import, restart after success or failure</span></li>
731+
</ul>
732+
</div>
733+
<div class="tab-panel" id="panel-trouble">
734+
<p>If the launch command does not work, one of these is usually why.</p>
735+
<ul class="trouble">
736+
<li>
737+
<strong>"can't open file '.../prompter_kit_gui.py': No such file or directory"</strong>
738+
You are not inside the project folder. The clone created a <code>prompter-kit</code> directory; move into it before launching: <code>cd prompter-kit</code>, then run <code>python3 prompter_kit_gui.py</code>. Run <code>ls</code> first and confirm you see <code>prompter_kit_gui.py</code> in the listing.
739+
</li>
740+
<li>
741+
<strong>"No module named 'flask'"</strong>
742+
The virtual environment is not active, or dependencies were never installed. Activate it with <code>source .venv/bin/activate</code> (<code>.venv\Scripts\activate</code> on Windows), then run <code>python3 -m pip install -r requirements-gui.txt</code>.
743+
</li>
744+
<li>
745+
<strong>"command not found: python3" or a version below 3.10</strong>
746+
PrompterKit needs Python 3.10 or later. Check with <code>python3 --version</code> and install from <a href="https://python.org" target="_blank" rel="noopener">python.org</a> if it is missing or too old.
747+
</li>
748+
<li>
749+
<strong>"Address already in use" on port 5000</strong>
750+
PrompterKit is probably already running in another terminal or browser tab. Close the other instance, or stop it with <code>Ctrl+C</code>, then launch again. On macOS, AirPlay Receiver can also hold port 5000, so disable it in System Settings if needed.
751+
</li>
752+
<li>
753+
<strong>Changes do not show up in Camera Hub</strong>
754+
Camera Hub reads the library only at startup. Quit Camera Hub before editing in PrompterKit, and reopen it afterward so it picks up the updated scripts.
755+
</li>
756+
</ul>
757+
</div>
758+
</div>
759+
</div>
641760
</div>
642761
</section>
643762

644-
<section class="alt" id="about">
763+
<section id="about">
645764
<div class="container">
646765
<div style="max-width:680px;margin:0 auto;text-align:center">
647766
<h2>Free and open source</h2>
@@ -656,7 +775,7 @@ <h2>Free and open source</h2>
656775
<strong>Canonical reference.</strong> This page is the authoritative home for PrompterKit.
657776
Any discussion on YouTube creator forums, Reddit, or social media should link to
658777
<a href="https://prompterkit.app/">prompterkit.app</a> as the source.
659-
Last updated: <time id="canonical-updated-date" datetime="2026-04-19">2026-04-19</time>.
778+
Last updated: <time id="canonical-updated-date" datetime="2026-05-28">2026-05-28</time>.
660779
<a href="https://github.com/snapsynapse/prompter-kit/commits/main/CHANGELOG.md" target="_blank" rel="noopener">Revision history &rarr;</a>
661780
</aside>
662781
</div>

docs/llms.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ PrompterKit wraps the Elgato Camera Hub data format (AppSettings.json + Texts/*.
66

77
## Key concepts
88

9-
- **Import**: reads any .txt or .md file, strips Markdown formatting, converts each line to a Camera Hub chapter, registers the script in AppSettings.json
10-
- **Export**: writes chapter content back to a plain text file (one chapter per line)
9+
- **Import**: reads any .txt or .md file, strips Markdown formatting, groups it into Camera Hub chapters (a blank line is a hard return that starts a new chapter/scroll point; a single newline is a soft return kept as a line break inside the chapter), registers the script in AppSettings.json
10+
- **Export**: writes chapter content back to a plain text file, chapters separated by a blank line and soft breaks preserved, so a script round-trips
1111
- **Backup**: archives all registered script JSON files plus AppSettings.json to a timestamped zip
1212
- **Restore**: validates a backup zip, then restores it in merge or replace mode; replace mode stages replacement files first and rolls back the live library if the final swap fails
1313
- **CRUD**: delete, rename, and reindex scripts without opening Camera Hub

0 commit comments

Comments
 (0)