Skip to content

Commit 49fce0d

Browse files
committed
Refactor application structure and simplify implementation
1 parent 5a3d82c commit 49fce0d

16 files changed

Lines changed: 461 additions & 795 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,4 @@ next-env.d.ts
4141
/.cache/
4242
/outputs/
4343
/work/
44+
/public/diff-data.json

PRODUCT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Use the name “Diff Presenter” for now. Describe it as an open-source develop
4343

4444
- `README.md` documents the current product, supported review targets, commands, and data flow.
4545
- `app/page.tsx` contains the working review interface and its loading, empty, search, navigation, and long-diff states.
46-
- `public/diff-data.json` contains a ten-file todo-list demo with change and file notes.
46+
- `public/demo-diff-data.json` contains a ten-file todo-list demo with change and file notes.
4747
- `data/todo-demo-summaries.json` contains the agent notes used by the demo.
4848
- Tests cover rendering, remote targets, summary paths, agent notes, and snapshot generation.
4949
- No confirmed testimonials, customer claims, pricing, or benchmark data exists in this repo; future work must not invent them.

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,12 @@ npx diff-presenter \
128128
--summaries /path/to/summaries.json
129129
```
130130

131-
The watcher updates `public/diff-data.json` when Git state or the summary file
132-
changes. It checks remote PRs and branches every 30 seconds. The open page checks
133-
the data file every 1.5 seconds and keeps the current file selected when a new
134-
snapshot arrives.
131+
The watcher updates the ignored `.cache/diff-data.json` when Git state or the
132+
summary file changes. The local server exposes it at `/diff-data.json`. It
133+
checks remote PRs and branches every 30 seconds. The open page checks the data
134+
every 1.5 seconds and keeps the current file selected when a new snapshot
135+
arrives. Without a live snapshot, the page shows the checked-in
136+
`public/demo-diff-data.json`.
135137

136138
## Generate or revise the agent notes
137139

app/globals.css

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,63 @@ kbd {
816816
max-width: 40em;
817817
}
818818

819+
.note-skeleton {
820+
margin-top: 25px;
821+
max-width: 40em;
822+
}
823+
824+
.note-skeleton-group {
825+
display: grid;
826+
gap: 10px;
827+
}
828+
829+
.note-skeleton-group + .note-skeleton-group {
830+
border-top: 1px solid var(--line);
831+
margin-top: 30px;
832+
padding-top: 20px;
833+
}
834+
835+
.note-skeleton-line {
836+
animation: note-skeleton-shimmer 1.6s ease-in-out infinite;
837+
background: linear-gradient(
838+
100deg,
839+
#ddd6ca 20%,
840+
#ebe5da 42%,
841+
#ddd6ca 64%
842+
);
843+
background-size: 300% 100%;
844+
border-radius: 2px;
845+
display: block;
846+
height: 11px;
847+
}
848+
849+
.note-skeleton-line--label {
850+
height: 8px;
851+
margin-bottom: 3px;
852+
width: 23%;
853+
}
854+
855+
.note-skeleton-line--long {
856+
width: 94%;
857+
}
858+
859+
.note-skeleton-line--medium {
860+
width: 72%;
861+
}
862+
863+
.note-skeleton-line--short {
864+
width: 48%;
865+
}
866+
867+
@keyframes note-skeleton-shimmer {
868+
from {
869+
background-position: 100% 0;
870+
}
871+
to {
872+
background-position: -100% 0;
873+
}
874+
}
875+
819876
.note-section {
820877
border-top: 1px solid var(--line);
821878
margin-top: 30px;

app/page.tsx

Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,13 @@ export default function Home() {
279279

280280
const refresh = useCallback(async () => {
281281
try {
282-
const response = await fetch(`/diff-data.json?t=${Date.now()}`, {
282+
const liveResponse = await fetch(`/diff-data.json?t=${Date.now()}`, {
283283
cache: "no-store",
284284
});
285+
const response =
286+
liveResponse.status === 404
287+
? await fetch("/demo-diff-data.json")
288+
: liveResponse;
285289
if (!response.ok) throw new Error(`Snapshot returned ${response.status}`);
286290
const next = (await response.json()) as DiffSnapshot;
287291
if (!Array.isArray(next.files)) throw new Error("Snapshot has no files");
@@ -639,26 +643,42 @@ export default function Home() {
639643
</span>
640644
</div>
641645

642-
{notesInProgress || noteUnavailable ? (
646+
{notesInProgress ? (
647+
<div
648+
className="summary-loading"
649+
role="status"
650+
aria-live="polite"
651+
>
652+
<h2 id="summary-heading">Writing summary of diff...</h2>
653+
<div className="note-skeleton" aria-hidden="true">
654+
<div className="note-skeleton-group">
655+
<span className="note-skeleton-line note-skeleton-line--long" />
656+
<span className="note-skeleton-line note-skeleton-line--medium" />
657+
</div>
658+
<div className="note-skeleton-group">
659+
<span className="note-skeleton-line note-skeleton-line--label" />
660+
<span className="note-skeleton-line note-skeleton-line--long" />
661+
<span className="note-skeleton-line note-skeleton-line--short" />
662+
</div>
663+
<div className="note-skeleton-group">
664+
<span className="note-skeleton-line note-skeleton-line--label" />
665+
<span className="note-skeleton-line note-skeleton-line--medium" />
666+
<span className="note-skeleton-line note-skeleton-line--long" />
667+
<span className="note-skeleton-line note-skeleton-line--short" />
668+
</div>
669+
</div>
670+
</div>
671+
) : noteUnavailable ? (
643672
<>
644-
<h2 id="summary-heading">
645-
{notesInProgress
646-
? "Writing this note."
647-
: "This note is not ready."}
648-
</h2>
673+
<h2 id="summary-heading">This note is not ready.</h2>
649674
<p className="summary-lead">
650-
{notesInProgress
651-
? "The diff is ready to review. This file’s note will appear when its batch finishes."
652-
: "The agent stopped before it reached this file. The diff is still ready to review."}
675+
The agent stopped before it reached this file. The diff is
676+
still ready to review.
653677
</p>
654678
<section className="note-section note-section--pending">
655-
<p className="eyebrow">
656-
{notesInProgress ? "NOTE PROGRESS" : "WHAT TO DO"}
657-
</p>
679+
<p className="eyebrow">WHAT TO DO</p>
658680
<p>
659-
{notesInProgress
660-
? `${noteProgress}. You can review any finished file now.`
661-
: "Check the terminal error, then start Diff Presenter again."}
681+
Check the terminal error, then start Diff Presenter again.
662682
</p>
663683
</section>
664684
</>
@@ -699,28 +719,27 @@ export default function Home() {
699719
</ul>
700720
</section>
701721
) : null}
702-
703722
</div>
704723

705-
<footer className="agent-signoff">
706-
<span className="agent-glyph" aria-hidden="true">
707-
708-
</span>
709-
<span>
710-
{notesInProgress
711-
? "The coding agent is writing notes"
712-
: noteUnavailable
724+
{!notesInProgress ? (
725+
<footer className="agent-signoff">
726+
<span className="agent-glyph" aria-hidden="true">
727+
728+
</span>
729+
<span>
730+
{noteUnavailable
713731
? "The coding agent stopped"
714732
: "Written by the coding agent"}
715-
<small>
716-
{notesInProgress || noteUnavailable
717-
? noteProgress
718-
: `Snapshot ${snapshot.version.slice(0, 10)} · ${new Date(
719-
snapshot.generatedAt,
720-
).toLocaleString()}`}
721-
</small>
722-
</span>
723-
</footer>
733+
<small>
734+
{noteUnavailable
735+
? noteProgress
736+
: `Snapshot ${snapshot.version.slice(0, 10)} · ${new Date(
737+
snapshot.generatedAt,
738+
).toLocaleString()}`}
739+
</small>
740+
</span>
741+
</footer>
742+
) : null}
724743
</aside>
725744
</div>
726745
</section>

data/README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# Diff data
22

3-
`scripts/build-diff-data.mjs` writes `public/diff-data.json` for the review
4-
page. Diff Presenter is an open-source developer tool meant to run on pull
5-
requests, so a GitHub PR is its main input:
3+
`scripts/build-diff-data.mjs` writes the ignored `.cache/diff-data.json` live
4+
snapshot for the review page. The local server exposes it at
5+
`/diff-data.json`. Diff Presenter is an open-source developer tool meant to run
6+
on pull requests, so a GitHub PR is its main input:
67

78
```sh
89
node scripts/build-diff-data.mjs --repo /path/to/repo --pr 42
@@ -20,7 +21,8 @@ new file only when the data changed.
2021
## Refresh the bundled todo demo
2122

2223
`docs/todo-demo.js` holds the ten illustrative files used by both the landing
23-
page and the bundled app data. Rebuild the JSON files after changing it:
24+
page and the checked-in `public/demo-diff-data.json`. Rebuild the demo files
25+
after changing it:
2426

2527
```sh
2628
node scripts/write-todo-demo.mjs
@@ -34,7 +36,7 @@ Example:
3436

3537
```sh
3638
node scripts/build-diff-data.mjs --repo /path/to/repo --base BASE --head HEAD \
37-
--summaries data/todo-demo-summaries.json --output public/diff-data.json
39+
--summaries data/todo-demo-summaries.json --output .cache/diff-data.json
3840
```
3941

4042
Add `--watch` to check Git state and the note file every two seconds. The

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"summarize": "node scripts/generate-summaries.mjs",
1919
"snapshot": "node scripts/build-diff-data.mjs",
2020
"watch:diff": "node scripts/build-diff-data.mjs --watch",
21-
"build": "WRANGLER_LOG_PATH=.wrangler/wrangler.log vinext build",
21+
"build": "WRANGLER_LOG_PATH=.wrangler/wrangler.log vinext build && node scripts/clean-built-live-data.mjs",
2222
"start": "WRANGLER_LOG_PATH=.wrangler/wrangler.log vinext start",
2323
"prepack": "npm run build",
2424
"test": "npm run build && node --test tests/*.test.mjs",

0 commit comments

Comments
 (0)