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.
- package/.hch/issues.json +156 -0
- package/.hch/issues.md +2 -0
- package/README.md +67 -0
- package/app/api/jsonl/route.ts +71 -0
- package/app/globals.css +125 -0
- package/app/layout.tsx +48 -0
- package/app/page.tsx +284 -0
- package/cli.ts +170 -0
- package/components/chart-detail.tsx +213 -0
- package/components/chart-list.tsx +184 -0
- package/components/data-stats.tsx +49 -0
- package/components/file-upload.tsx +73 -0
- package/components/narrative-beats.tsx +108 -0
- package/components/relation-graph.tsx +81 -0
- package/components/theme-provider.tsx +11 -0
- package/components/ui/badge.tsx +46 -0
- package/components/ui/button.tsx +60 -0
- package/components/ui/card.tsx +92 -0
- package/components/ui/scroll-area.tsx +58 -0
- package/components/ui/separator.tsx +28 -0
- package/components/ui/tabs.tsx +66 -0
- package/components.json +21 -0
- package/dist/cli.js +144 -0
- package/feat-2-webui-local-editing/IMPLEMENTATION.md +245 -0
- package/feat-2-webui-local-editing/INTEGRATION.md +302 -0
- package/feat-2-webui-local-editing/QUICKSTART.md +129 -0
- package/feat-2-webui-local-editing/README.md +254 -0
- package/feat-2-webui-local-editing/api-route-jsonl.ts +71 -0
- package/feat-2-webui-local-editing/cli.ts +170 -0
- package/feat-2-webui-local-editing/demo.sh +98 -0
- package/feat-2-webui-local-editing/package.json +82 -0
- package/feat-2-webui-local-editing/test-integration.sh +93 -0
- package/feat-2-webui-local-editing/updated-page.tsx +284 -0
- package/hooks/use-toast.ts +17 -0
- package/lib/jsonl-parser.ts +153 -0
- package/lib/types.ts +39 -0
- package/lib/utils.ts +6 -0
- package/next.config.mjs +12 -0
- package/package.json +82 -0
- package/postcss.config.mjs +8 -0
- package/public/apple-icon.png +0 -0
- package/public/icon-dark-32x32.png +0 -0
- package/public/icon-light-32x32.png +0 -0
- package/public/icon.svg +26 -0
- package/public/placeholder-logo.png +0 -0
- package/public/placeholder-logo.svg +1 -0
- package/public/placeholder-user.jpg +0 -0
- package/public/placeholder.jpg +0 -0
- package/public/placeholder.svg +1 -0
- package/styles/globals.css +125 -0
- package/tsconfig.json +41 -0
package/.hch/issues.json
ADDED
|
@@ -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
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
|
+
}
|
package/app/globals.css
ADDED
|
@@ -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
|
+
}
|