ugly-app 0.1.146 → 0.1.147

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.
@@ -1,2 +1,2 @@
1
- export declare const CLI_VERSION = "0.1.146";
1
+ export declare const CLI_VERSION = "0.1.147";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1,3 +1,3 @@
1
1
  // Auto-generated by prebuild — do not edit manually
2
- export const CLI_VERSION = "0.1.146";
2
+ export const CLI_VERSION = "0.1.147";
3
3
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ugly-app",
3
- "version": "0.1.146",
3
+ "version": "0.1.147",
4
4
  "type": "module",
5
5
  "main": "./dist/server/index.js",
6
6
  "exports": {
@@ -1,2 +1,2 @@
1
1
  // Auto-generated by prebuild — do not edit manually
2
- export const CLI_VERSION = "0.1.146";
2
+ export const CLI_VERSION = "0.1.147";
@@ -10,12 +10,40 @@ Run one full autonomous cycle. No human input. No clarifying questions. Make the
10
10
 
11
11
  **CORE PRINCIPLE: Be maximally ambitious. Every bot in this swarm — feedback bots, maintain bot, manager — should push for big changes, not incremental tweaks. Feedback bots should request new features, major redesigns, and bold improvements — not just "move this button 2px." The maintain bot must implement everything requested, no matter how large. "Too complex" is never a valid reason to skip work. The only limit is violating Critical Rules in CLAUDE.md.**
12
12
 
13
+ ## About the Website
14
+
15
+ This website can do **anything**. It is a full-stack app with AI capabilities, real-time data, and a complete UI component library. The current sample pages demonstrate a subset of what's possible:
16
+
17
+ - **AI Test** (`/ai-test`) — text generation (textGen) and image generation (imageGen)
18
+ - **Audio Test** (`/audio-test`) — text-to-speech (TTS) and speech-to-text (STT)
19
+ - **Kagi Test** (`/kagi-test`) — Kagi search API integration
20
+ - **UI Components** (`/ui-components`) — suite of common UI controls (buttons, cards, inputs, selects, modals, etc.)
21
+ - **Todo Demo** (`/todo-demo`) — real-time CRUD with live sync
22
+ - **Auth Demo** (`/auth-demo`) — OAuth login/logout
23
+ - **Path Params** (`/user/:userId`) and **Query Params** (`/search`) — routing demos
24
+
25
+ These are just samples. The bot swarm should treat the site as a blank canvas — feedback bots can request entirely new pages, features, layouts, data models, or integrations. There are no limits on what can be built.
26
+
13
27
  ## Prerequisites
14
28
 
15
- - `npm run dev` must be running (Docker, server, Vite)
29
+ - The dev server must be running with HMR and watchers disabled (see below)
16
30
  - `.env` must have `UGLY_BOT_TOKEN` (from `npx ugly-app login`)
17
31
  - Playwright must be installed (`npx playwright install chromium`)
18
32
 
33
+ ### Starting the dev server (no HMR, no watch)
34
+
35
+ The bot swarm modifies source files while the server runs. To avoid HMR reloads and watcher interference mid-cycle, start the server without watchers:
36
+
37
+ ```bash
38
+ # 1. Start Docker (MongoDB + Redis)
39
+ docker compose up -d
40
+
41
+ # 2. Run the server directly (no tsx watch, no tsc --watch, no eslint --watch)
42
+ npx tsx --env-file=.env server/index.ts &
43
+ ```
44
+
45
+ Do **not** use `npm run dev` — it enables tsx watch, tsc watch, and eslint watch which conflict with bot file edits. After the maintain bot finishes and commits, the restart step (Step 5) will kill and restart the server to pick up changes.
46
+
19
47
  ## First Run Bootstrap
20
48
 
21
49
  If `bots/` directory does not exist:
@@ -257,7 +285,7 @@ Run sequentially in one session. No questions. Make autonomous decisions.
257
285
 
258
286
  ## Step 5 — Restart Loop
259
287
 
260
- 1. Stop the dev server (find and kill the `npm run dev` process group)
288
+ 1. Stop the server (find and kill the `npx tsx` server process)
261
289
  2. Run `npm install` (maintain bot may have added packages in Step 3)
262
290
  3. Run `npm run build`
263
291
  4. **If build fails:**
@@ -267,13 +295,13 @@ Run sequentially in one session. No questions. Make autonomous decisions.
267
295
  - Commit: `[bot] fix: build errors`
268
296
  - Run `npm run build` again
269
297
  - **Repeat until build succeeds. Do not stop. Do not ask for help.**
270
- 5. Start `npm run dev` in the background
298
+ 5. Start the server without watchers: `npx tsx --env-file=.env server/index.ts &`
271
299
  6. Wait for the server to be ready — poll `http://localhost:3000` with up to 60 retries (1s apart)
272
300
  7. **If server fails to start or crashes:**
273
301
  - Read the error output and/or `npm run error`
274
302
  - Fix the code
275
303
  - Commit: `[bot] fix: startup errors`
276
- - Kill and restart `npm run dev`
304
+ - Kill and restart `npx tsx --env-file=.env server/index.ts &`
277
305
  - **Repeat until server is healthy. Do not stop. Do not ask for help.**
278
306
  8. Once healthy: update the journal cycle file's Restart outcome to `success` or note any fixes made
279
307
  9. Commit any remaining changes: `[bot] fix: restart issues`
@@ -48,6 +48,14 @@ if (!token) {
48
48
  );
49
49
  })
50
50
  .catch(() => {
51
- window.location.reload();
51
+ root.render(
52
+ <RouterProvider
53
+ fallback={<div>404 — Page not found</div>}
54
+ loginFallback={loginPopup}
55
+ isAuthenticated={() => false}
56
+ >
57
+ <App socket={null} />
58
+ </RouterProvider>,
59
+ );
52
60
  });
53
61
  }
@@ -142,39 +142,6 @@ function HomePageBody({
142
142
 
143
143
  const ctaLabel = getCtaLabel(branches);
144
144
 
145
- const navItems = [
146
- {
147
- href: '/auth-demo',
148
- label: 'Auth Demo',
149
- desc: 'Login, logout, and user info',
150
- },
151
- {
152
- href: '/user/example-user-id',
153
- label: 'Path Params Demo',
154
- desc: 'URL: /user/:userId',
155
- },
156
- {
157
- href: '/search?q=hello',
158
- label: 'Query Params Demo',
159
- desc: 'URL: /search?q=...',
160
- },
161
- {
162
- href: '/ai-test',
163
- label: 'AI Test',
164
- desc: 'Text & image generation models',
165
- },
166
- {
167
- href: '/ui-components',
168
- label: 'UI Components',
169
- desc: 'Live demos of all built-in components',
170
- },
171
- {
172
- href: '/todo-demo',
173
- label: 'Todo Demo',
174
- desc: 'Real-time CRUD with trackDocs & trackKeys',
175
- },
176
- ];
177
-
178
145
  return (
179
146
  <div style={{ maxWidth: 640, margin: '0 auto', padding: 24, display: 'flex', flexDirection: 'column', gap: 16 }}>
180
147
  <Card>
@@ -195,29 +162,24 @@ function HomePageBody({
195
162
  </div>
196
163
  )}
197
164
  </Card>
198
-
199
- <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
200
- {navItems.map(({ href, label, desc }) => (
201
- <a key={href} href={href} style={{ textDecoration: 'none', color: 'inherit' }}>
202
- <Card>
203
- <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
204
- <div>
205
- <Text weight="medium">{label}</Text>
206
- <Text size="sm" style={{ opacity: 0.6, marginTop: 2 }}>{desc}</Text>
207
- </div>
208
- <span style={{ fontSize: 20, opacity: 0.3 }}>&rarr;</span>
209
- </div>
210
- </Card>
211
- </a>
212
- ))}
213
- </div>
214
165
  </div>
215
166
  );
216
167
  }
217
168
 
218
169
  export default function HomePage(): React.ReactElement {
219
- const isLoggedIn = !!(window as unknown as { __AUTH_TOKEN__?: string })
220
- .__AUTH_TOKEN__;
170
+ // Check both that a token exists AND that AppProvider is available.
171
+ // When the token is present but invalid (e.g. expired), the socket
172
+ // connection fails and we render without AppProvider — so we must
173
+ // fall back to the unauthenticated view to avoid a useApp() crash
174
+ // that causes an infinite reload loop.
175
+ let isLoggedIn = false;
176
+ try {
177
+ // useApp throws if there is no AppProvider ancestor
178
+ useApp();
179
+ isLoggedIn = true;
180
+ } catch {
181
+ isLoggedIn = false;
182
+ }
221
183
  if (isLoggedIn) return <HomePageAuthenticated />;
222
184
  return <HomePageUnauthenticated />;
223
185
  }