coaia-visualizer 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/.hch/issues.json +156 -0
  2. package/.hch/issues.md +2 -0
  3. package/README.md +67 -0
  4. package/app/api/jsonl/route.ts +71 -0
  5. package/app/globals.css +125 -0
  6. package/app/layout.tsx +48 -0
  7. package/app/page.tsx +284 -0
  8. package/cli.ts +170 -0
  9. package/components/chart-detail.tsx +213 -0
  10. package/components/chart-list.tsx +184 -0
  11. package/components/data-stats.tsx +49 -0
  12. package/components/file-upload.tsx +73 -0
  13. package/components/narrative-beats.tsx +108 -0
  14. package/components/relation-graph.tsx +81 -0
  15. package/components/theme-provider.tsx +11 -0
  16. package/components/ui/badge.tsx +46 -0
  17. package/components/ui/button.tsx +60 -0
  18. package/components/ui/card.tsx +92 -0
  19. package/components/ui/scroll-area.tsx +58 -0
  20. package/components/ui/separator.tsx +28 -0
  21. package/components/ui/tabs.tsx +66 -0
  22. package/components.json +21 -0
  23. package/dist/cli.js +144 -0
  24. package/feat-2-webui-local-editing/IMPLEMENTATION.md +245 -0
  25. package/feat-2-webui-local-editing/INTEGRATION.md +302 -0
  26. package/feat-2-webui-local-editing/QUICKSTART.md +129 -0
  27. package/feat-2-webui-local-editing/README.md +254 -0
  28. package/feat-2-webui-local-editing/api-route-jsonl.ts +71 -0
  29. package/feat-2-webui-local-editing/cli.ts +170 -0
  30. package/feat-2-webui-local-editing/demo.sh +98 -0
  31. package/feat-2-webui-local-editing/package.json +82 -0
  32. package/feat-2-webui-local-editing/test-integration.sh +93 -0
  33. package/feat-2-webui-local-editing/updated-page.tsx +284 -0
  34. package/hooks/use-toast.ts +17 -0
  35. package/lib/jsonl-parser.ts +153 -0
  36. package/lib/types.ts +39 -0
  37. package/lib/utils.ts +6 -0
  38. package/next.config.mjs +12 -0
  39. package/package.json +82 -0
  40. package/postcss.config.mjs +8 -0
  41. package/public/apple-icon.png +0 -0
  42. package/public/icon-dark-32x32.png +0 -0
  43. package/public/icon-light-32x32.png +0 -0
  44. package/public/icon.svg +26 -0
  45. package/public/placeholder-logo.png +0 -0
  46. package/public/placeholder-logo.svg +1 -0
  47. package/public/placeholder-user.jpg +0 -0
  48. package/public/placeholder.jpg +0 -0
  49. package/public/placeholder.svg +1 -0
  50. package/styles/globals.css +125 -0
  51. package/tsconfig.json +41 -0
@@ -0,0 +1,156 @@
1
+ [
2
+ {
3
+ "url": "https://api.github.com/repos/jgwill/coaia-visualizer/issues/2",
4
+ "repository_url": "https://api.github.com/repos/jgwill/coaia-visualizer",
5
+ "labels_url": "https://api.github.com/repos/jgwill/coaia-visualizer/issues/2/labels{/name}",
6
+ "comments_url": "https://api.github.com/repos/jgwill/coaia-visualizer/issues/2/comments",
7
+ "events_url": "https://api.github.com/repos/jgwill/coaia-visualizer/issues/2/events",
8
+ "html_url": "https://github.com/jgwill/coaia-visualizer/issues/2",
9
+ "id": 3801143336,
10
+ "node_id": "I_kwDOQzbrH87ikNgo",
11
+ "number": 2,
12
+ "title": "CLI Web UI Launcher",
13
+ "user": {
14
+ "login": "jgwill",
15
+ "id": 23141173,
16
+ "node_id": "MDQ6VXNlcjIzMTQxMTcz",
17
+ "avatar_url": "https://avatars.githubusercontent.com/u/23141173?v=4",
18
+ "gravatar_id": "",
19
+ "url": "https://api.github.com/users/jgwill",
20
+ "html_url": "https://github.com/jgwill",
21
+ "followers_url": "https://api.github.com/users/jgwill/followers",
22
+ "following_url": "https://api.github.com/users/jgwill/following{/other_user}",
23
+ "gists_url": "https://api.github.com/users/jgwill/gists{/gist_id}",
24
+ "starred_url": "https://api.github.com/users/jgwill/starred{/owner}{/repo}",
25
+ "subscriptions_url": "https://api.github.com/users/jgwill/subscriptions",
26
+ "organizations_url": "https://api.github.com/users/jgwill/orgs",
27
+ "repos_url": "https://api.github.com/users/jgwill/repos",
28
+ "events_url": "https://api.github.com/users/jgwill/events{/privacy}",
29
+ "received_events_url": "https://api.github.com/users/jgwill/received_events",
30
+ "type": "User",
31
+ "user_view_type": "public",
32
+ "site_admin": false
33
+ },
34
+ "labels": [
35
+
36
+ ],
37
+ "state": "open",
38
+ "locked": false,
39
+ "assignee": null,
40
+ "assignees": [
41
+
42
+ ],
43
+ "milestone": null,
44
+ "comments": 0,
45
+ "created_at": "2026-01-11T11:38:37Z",
46
+ "updated_at": "2026-01-11T11:38:37Z",
47
+ "closed_at": null,
48
+ "author_association": "OWNER",
49
+ "active_lock_reason": null,
50
+ "sub_issues_summary": {
51
+ "total": 0,
52
+ "completed": 0,
53
+ "percent_completed": 0
54
+ },
55
+ "issue_dependencies_summary": {
56
+ "blocked_by": 0,
57
+ "total_blocked_by": 0,
58
+ "blocking": 0,
59
+ "total_blocking": 0
60
+ },
61
+ "body": "....",
62
+ "closed_by": null,
63
+ "reactions": {
64
+ "url": "https://api.github.com/repos/jgwill/coaia-visualizer/issues/2/reactions",
65
+ "total_count": 0,
66
+ "+1": 0,
67
+ "-1": 0,
68
+ "laugh": 0,
69
+ "hooray": 0,
70
+ "confused": 0,
71
+ "heart": 0,
72
+ "rocket": 0,
73
+ "eyes": 0
74
+ },
75
+ "timeline_url": "https://api.github.com/repos/jgwill/coaia-visualizer/issues/2/timeline",
76
+ "performed_via_github_app": null,
77
+ "state_reason": null
78
+ },
79
+ {
80
+ "url": "https://api.github.com/repos/jgwill/coaia-visualizer/issues/1",
81
+ "repository_url": "https://api.github.com/repos/jgwill/coaia-visualizer",
82
+ "labels_url": "https://api.github.com/repos/jgwill/coaia-visualizer/issues/1/labels{/name}",
83
+ "comments_url": "https://api.github.com/repos/jgwill/coaia-visualizer/issues/1/comments",
84
+ "events_url": "https://api.github.com/repos/jgwill/coaia-visualizer/issues/1/events",
85
+ "html_url": "https://github.com/jgwill/coaia-visualizer/issues/1",
86
+ "id": 3801141885,
87
+ "node_id": "I_kwDOQzbrH87ikNJ9",
88
+ "number": 1,
89
+ "title": "Init",
90
+ "user": {
91
+ "login": "jgwill",
92
+ "id": 23141173,
93
+ "node_id": "MDQ6VXNlcjIzMTQxMTcz",
94
+ "avatar_url": "https://avatars.githubusercontent.com/u/23141173?v=4",
95
+ "gravatar_id": "",
96
+ "url": "https://api.github.com/users/jgwill",
97
+ "html_url": "https://github.com/jgwill",
98
+ "followers_url": "https://api.github.com/users/jgwill/followers",
99
+ "following_url": "https://api.github.com/users/jgwill/following{/other_user}",
100
+ "gists_url": "https://api.github.com/users/jgwill/gists{/gist_id}",
101
+ "starred_url": "https://api.github.com/users/jgwill/starred{/owner}{/repo}",
102
+ "subscriptions_url": "https://api.github.com/users/jgwill/subscriptions",
103
+ "organizations_url": "https://api.github.com/users/jgwill/orgs",
104
+ "repos_url": "https://api.github.com/users/jgwill/repos",
105
+ "events_url": "https://api.github.com/users/jgwill/events{/privacy}",
106
+ "received_events_url": "https://api.github.com/users/jgwill/received_events",
107
+ "type": "User",
108
+ "user_view_type": "public",
109
+ "site_admin": false
110
+ },
111
+ "labels": [
112
+
113
+ ],
114
+ "state": "open",
115
+ "locked": false,
116
+ "assignee": null,
117
+ "assignees": [
118
+
119
+ ],
120
+ "milestone": null,
121
+ "comments": 0,
122
+ "created_at": "2026-01-11T11:37:31Z",
123
+ "updated_at": "2026-01-11T11:37:31Z",
124
+ "closed_at": null,
125
+ "author_association": "OWNER",
126
+ "active_lock_reason": null,
127
+ "sub_issues_summary": {
128
+ "total": 0,
129
+ "completed": 0,
130
+ "percent_completed": 0
131
+ },
132
+ "issue_dependencies_summary": {
133
+ "blocked_by": 0,
134
+ "total_blocked_by": 0,
135
+ "blocking": 0,
136
+ "total_blocking": 0
137
+ },
138
+ "body": "...",
139
+ "closed_by": null,
140
+ "reactions": {
141
+ "url": "https://api.github.com/repos/jgwill/coaia-visualizer/issues/1/reactions",
142
+ "total_count": 0,
143
+ "+1": 0,
144
+ "-1": 0,
145
+ "laugh": 0,
146
+ "hooray": 0,
147
+ "confused": 0,
148
+ "heart": 0,
149
+ "rocket": 0,
150
+ "eyes": 0
151
+ },
152
+ "timeline_url": "https://api.github.com/repos/jgwill/coaia-visualizer/issues/1/timeline",
153
+ "performed_via_github_app": null,
154
+ "state_reason": null
155
+ }
156
+ ]
package/.hch/issues.md ADDED
@@ -0,0 +1,2 @@
1
+ [2::CLI Web UI Launcher](https://github.com/jgwill/coaia-visualizer/issues/2)
2
+ [1::Init](https://github.com/jgwill/coaia-visualizer/issues/1)
package/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # `coaia-visualizer`
2
+
3
+ ## Overview
4
+
5
+ `coaia-visualizer` is the dedicated client-side application for visualizing and interacting with data generated by the `coaia-narrative` system. It transforms raw JSONL (JSON Lines) data, representing Structural Tension Charts and Multi-Universe Narrative Beats, into an intuitive and interactive user interface.
6
+
7
+ This tool allows users to upload their `coaia-narrative` memory files and gain clear insights into their creative projects, understanding the dynamic interplay of their Desired Outcomes, Current Realities, and Action Steps, alongside the rich context of Narrative Beats.
8
+
9
+ This project's development and deployment are automatically synchronized with `v0.app`, ensuring continuous access to the latest visual interpretations of your creative journey.
10
+
11
+ ## Key Features
12
+
13
+ * **Local JSONL File Upload & Export:** Securely upload `coaia-narrative` JSONL files from your local system for visualization and export the processed data back.
14
+ * **Hierarchical Chart Visualization:** Explore your Structural Tension Charts in both a comprehensive list view and an expandable, nested hierarchy, revealing master charts and their telescoped sub-charts.
15
+ * **Detailed Chart Inspector:** Select any chart to access a detailed view, showcasing its Desired Outcome, Current Reality, metadata (creation/due dates, level), and associated components.
16
+ * **Dynamic Structural Tension Display:** Clearly distinguishes and presents the core Desired Outcome and Current Reality observations, making the generative force of structural tension visible.
17
+ * **Action Step Tracking:** View all Action Steps for a selected chart, complete with their descriptions, completion status, and due dates, facilitating a clear understanding of strategic advancement.
18
+ * **Narrative Beat Integration:** Displays associated Narrative Beats, offering multi-universe perspectives (Engineer-World, Ceremony-World, Story-Engine-World) to enrich the context of your creative efforts.
19
+ * **Inter-Chart Relation Graph:** Visualizes the relationships between charts and entities, illustrating how different creative projects and their components are interconnected.
20
+ * **Data Statistics Overview:** Provides summary statistics of the loaded data, including total charts, entities, and relations, for quick comprehension of your creative landscape.
21
+
22
+ ## Technologies Used
23
+
24
+ * **Framework:** Next.js
25
+ * **Language:** TypeScript
26
+ * **UI Library:** React
27
+ * **Styling:** Tailwind CSS with Radix UI components (for accessible and customizable UI)
28
+ * **Charting:** `recharts` (for potential future data visualizations)
29
+ * **Form Management:** `react-hook-form`
30
+ * **Schema Validation:** `zod`
31
+
32
+ ## Getting Started
33
+
34
+ 1. **Clone the repository:**
35
+ ```bash
36
+ git clone <repository-url>
37
+ cd coaia-visualizer
38
+ ```
39
+ 2. **Install dependencies:**
40
+ ```bash
41
+ pnpm install
42
+ ```
43
+ 3. **Run the development server:**
44
+ ```bash
45
+ pnpm run dev
46
+ ```
47
+ 4. Open your browser to `http://localhost:3000` (or the port indicated by `pnpm run dev`).
48
+ 5. Upload a `coaia-narrative` generated JSONL file to begin visualizing your creative projects.
49
+
50
+ ## Deployment
51
+
52
+ Your project is live at:
53
+
54
+ **[https://vercel.com/jgwills-projects/v0-jsonl-visualizer](https://vercel.com/jgwills-projects/v0-jsonl-visualizer)**
55
+
56
+ ## Build your app
57
+
58
+ Continue building your app on:
59
+
60
+ **[https://v0.app/chat/drYe7XUyCIv](https://v0.app/chat/drYe7XUyCIv)**
61
+
62
+ ## How It Works (v0.app Integration)
63
+
64
+ 1. Create and modify your project using [v0.app](https://v0.app).
65
+ 2. Deploy your chats from the v0 interface.
66
+ 3. Changes are automatically pushed to this repository.
67
+ 4. Vercel deploys the latest version from this repository.
@@ -0,0 +1,71 @@
1
+ // app/api/jsonl/route.ts
2
+ import { NextRequest, NextResponse } from 'next/server';
3
+ import { promises as fs } from 'fs';
4
+ import path from 'path';
5
+
6
+ export async function GET(request: NextRequest) {
7
+ const memoryPath = process.env.COAIAV_MEMORY_PATH;
8
+
9
+ if (!memoryPath) {
10
+ return NextResponse.json(
11
+ { error: 'No memory file configured. Launch with --memory-path flag.' },
12
+ { status: 400 }
13
+ );
14
+ }
15
+
16
+ try {
17
+ const content = await fs.readFile(memoryPath, 'utf-8');
18
+ const filename = path.basename(memoryPath);
19
+
20
+ return NextResponse.json({
21
+ content,
22
+ filename,
23
+ path: memoryPath
24
+ });
25
+ } catch (error: any) {
26
+ return NextResponse.json(
27
+ { error: `Failed to read memory file: ${error.message}` },
28
+ { status: 500 }
29
+ );
30
+ }
31
+ }
32
+
33
+ export async function POST(request: NextRequest) {
34
+ const memoryPath = process.env.COAIAV_MEMORY_PATH;
35
+
36
+ if (!memoryPath) {
37
+ return NextResponse.json(
38
+ { error: 'No memory file configured' },
39
+ { status: 400 }
40
+ );
41
+ }
42
+
43
+ try {
44
+ const { content } = await request.json();
45
+
46
+ if (!content) {
47
+ return NextResponse.json(
48
+ { error: 'No content provided' },
49
+ { status: 400 }
50
+ );
51
+ }
52
+
53
+ // Backup original file
54
+ const backupPath = `${memoryPath}.backup-${Date.now()}`;
55
+ await fs.copyFile(memoryPath, backupPath);
56
+
57
+ // Write new content
58
+ await fs.writeFile(memoryPath, content, 'utf-8');
59
+
60
+ return NextResponse.json({
61
+ success: true,
62
+ backup: backupPath,
63
+ message: 'Memory file updated successfully'
64
+ });
65
+ } catch (error: any) {
66
+ return NextResponse.json(
67
+ { error: `Failed to write memory file: ${error.message}` },
68
+ { status: 500 }
69
+ );
70
+ }
71
+ }
@@ -0,0 +1,125 @@
1
+ @import 'tailwindcss';
2
+ @import 'tw-animate-css';
3
+
4
+ @custom-variant dark (&:is(.dark *));
5
+
6
+ :root {
7
+ --background: oklch(1 0 0);
8
+ --foreground: oklch(0.145 0 0);
9
+ --card: oklch(1 0 0);
10
+ --card-foreground: oklch(0.145 0 0);
11
+ --popover: oklch(1 0 0);
12
+ --popover-foreground: oklch(0.145 0 0);
13
+ --primary: oklch(0.205 0 0);
14
+ --primary-foreground: oklch(0.985 0 0);
15
+ --secondary: oklch(0.97 0 0);
16
+ --secondary-foreground: oklch(0.205 0 0);
17
+ --muted: oklch(0.97 0 0);
18
+ --muted-foreground: oklch(0.556 0 0);
19
+ --accent: oklch(0.97 0 0);
20
+ --accent-foreground: oklch(0.205 0 0);
21
+ --destructive: oklch(0.577 0.245 27.325);
22
+ --destructive-foreground: oklch(0.577 0.245 27.325);
23
+ --border: oklch(0.922 0 0);
24
+ --input: oklch(0.922 0 0);
25
+ --ring: oklch(0.708 0 0);
26
+ --chart-1: oklch(0.646 0.222 41.116);
27
+ --chart-2: oklch(0.6 0.118 184.704);
28
+ --chart-3: oklch(0.398 0.07 227.392);
29
+ --chart-4: oklch(0.828 0.189 84.429);
30
+ --chart-5: oklch(0.769 0.188 70.08);
31
+ --radius: 0.625rem;
32
+ --sidebar: oklch(0.985 0 0);
33
+ --sidebar-foreground: oklch(0.145 0 0);
34
+ --sidebar-primary: oklch(0.205 0 0);
35
+ --sidebar-primary-foreground: oklch(0.985 0 0);
36
+ --sidebar-accent: oklch(0.97 0 0);
37
+ --sidebar-accent-foreground: oklch(0.205 0 0);
38
+ --sidebar-border: oklch(0.922 0 0);
39
+ --sidebar-ring: oklch(0.708 0 0);
40
+ }
41
+
42
+ .dark {
43
+ --background: oklch(0.145 0 0);
44
+ --foreground: oklch(0.985 0 0);
45
+ --card: oklch(0.145 0 0);
46
+ --card-foreground: oklch(0.985 0 0);
47
+ --popover: oklch(0.145 0 0);
48
+ --popover-foreground: oklch(0.985 0 0);
49
+ --primary: oklch(0.985 0 0);
50
+ --primary-foreground: oklch(0.205 0 0);
51
+ --secondary: oklch(0.269 0 0);
52
+ --secondary-foreground: oklch(0.985 0 0);
53
+ --muted: oklch(0.269 0 0);
54
+ --muted-foreground: oklch(0.708 0 0);
55
+ --accent: oklch(0.269 0 0);
56
+ --accent-foreground: oklch(0.985 0 0);
57
+ --destructive: oklch(0.396 0.141 25.723);
58
+ --destructive-foreground: oklch(0.637 0.237 25.331);
59
+ --border: oklch(0.269 0 0);
60
+ --input: oklch(0.269 0 0);
61
+ --ring: oklch(0.439 0 0);
62
+ --chart-1: oklch(0.488 0.243 264.376);
63
+ --chart-2: oklch(0.696 0.17 162.48);
64
+ --chart-3: oklch(0.769 0.188 70.08);
65
+ --chart-4: oklch(0.627 0.265 303.9);
66
+ --chart-5: oklch(0.645 0.246 16.439);
67
+ --sidebar: oklch(0.205 0 0);
68
+ --sidebar-foreground: oklch(0.985 0 0);
69
+ --sidebar-primary: oklch(0.488 0.243 264.376);
70
+ --sidebar-primary-foreground: oklch(0.985 0 0);
71
+ --sidebar-accent: oklch(0.269 0 0);
72
+ --sidebar-accent-foreground: oklch(0.985 0 0);
73
+ --sidebar-border: oklch(0.269 0 0);
74
+ --sidebar-ring: oklch(0.439 0 0);
75
+ }
76
+
77
+ @theme inline {
78
+ --font-sans: 'Geist', 'Geist Fallback';
79
+ --font-mono: 'Geist Mono', 'Geist Mono Fallback';
80
+ --color-background: var(--background);
81
+ --color-foreground: var(--foreground);
82
+ --color-card: var(--card);
83
+ --color-card-foreground: var(--card-foreground);
84
+ --color-popover: var(--popover);
85
+ --color-popover-foreground: var(--popover-foreground);
86
+ --color-primary: var(--primary);
87
+ --color-primary-foreground: var(--primary-foreground);
88
+ --color-secondary: var(--secondary);
89
+ --color-secondary-foreground: var(--secondary-foreground);
90
+ --color-muted: var(--muted);
91
+ --color-muted-foreground: var(--muted-foreground);
92
+ --color-accent: var(--accent);
93
+ --color-accent-foreground: var(--accent-foreground);
94
+ --color-destructive: var(--destructive);
95
+ --color-destructive-foreground: var(--destructive-foreground);
96
+ --color-border: var(--border);
97
+ --color-input: var(--input);
98
+ --color-ring: var(--ring);
99
+ --color-chart-1: var(--chart-1);
100
+ --color-chart-2: var(--chart-2);
101
+ --color-chart-3: var(--chart-3);
102
+ --color-chart-4: var(--chart-4);
103
+ --color-chart-5: var(--chart-5);
104
+ --radius-sm: calc(var(--radius) - 4px);
105
+ --radius-md: calc(var(--radius) - 2px);
106
+ --radius-lg: var(--radius);
107
+ --radius-xl: calc(var(--radius) + 4px);
108
+ --color-sidebar: var(--sidebar);
109
+ --color-sidebar-foreground: var(--sidebar-foreground);
110
+ --color-sidebar-primary: var(--sidebar-primary);
111
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
112
+ --color-sidebar-accent: var(--sidebar-accent);
113
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
114
+ --color-sidebar-border: var(--sidebar-border);
115
+ --color-sidebar-ring: var(--sidebar-ring);
116
+ }
117
+
118
+ @layer base {
119
+ * {
120
+ @apply border-border outline-ring/50;
121
+ }
122
+ body {
123
+ @apply bg-background text-foreground;
124
+ }
125
+ }
package/app/layout.tsx ADDED
@@ -0,0 +1,48 @@
1
+ import type React from "react"
2
+ import type { Metadata } from "next"
3
+ import { Geist, Geist_Mono } from "next/font/google"
4
+ import { Analytics } from "@vercel/analytics/next"
5
+ import { Toaster } from "sonner"
6
+ import "./globals.css"
7
+
8
+ const _geist = Geist({ subsets: ["latin"] })
9
+ const _geistMono = Geist_Mono({ subsets: ["latin"] })
10
+
11
+ export const metadata: Metadata = {
12
+ title: "COAIA Narrative Visualizer",
13
+ description: "Visualize and explore structural tension charts from coaia-narrative JSONL files",
14
+ generator: "v0.app",
15
+ icons: {
16
+ icon: [
17
+ {
18
+ url: "/icon-light-32x32.png",
19
+ media: "(prefers-color-scheme: light)",
20
+ },
21
+ {
22
+ url: "/icon-dark-32x32.png",
23
+ media: "(prefers-color-scheme: dark)",
24
+ },
25
+ {
26
+ url: "/icon.svg",
27
+ type: "image/svg+xml",
28
+ },
29
+ ],
30
+ apple: "/apple-icon.png",
31
+ },
32
+ }
33
+
34
+ export default function RootLayout({
35
+ children,
36
+ }: Readonly<{
37
+ children: React.ReactNode
38
+ }>) {
39
+ return (
40
+ <html lang="en">
41
+ <body className={`font-sans antialiased`}>
42
+ {children}
43
+ <Toaster />
44
+ <Analytics />
45
+ </body>
46
+ </html>
47
+ )
48
+ }