@uidu/skills 0.2.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/README.md +42 -0
- package/package.json +25 -0
- package/skills/uidu/SKILL.md +321 -0
- package/skills/uidu/evals/evals.json +115 -0
- package/skills/uidu/metadata.json +8 -0
- package/skills/uidu-workspace/iteration-1/benchmark.md +43 -0
- package/skills/uidu-workspace/iteration-1/eval-0-event-detail/eval_metadata.json +13 -0
- package/skills/uidu-workspace/iteration-1/eval-0-event-detail/with_skill/grading.json +11 -0
- package/skills/uidu-workspace/iteration-1/eval-0-event-detail/with_skill/outputs/page.tsx +43 -0
- package/skills/uidu-workspace/iteration-1/eval-0-event-detail/without_skill/grading.json +11 -0
- package/skills/uidu-workspace/iteration-1/eval-0-event-detail/without_skill/outputs/page.tsx +46 -0
- package/skills/uidu-workspace/iteration-1/eval-1-stories-listing/eval_metadata.json +12 -0
- package/skills/uidu-workspace/iteration-1/eval-1-stories-listing/with_skill/grading.json +10 -0
- package/skills/uidu-workspace/iteration-1/eval-1-stories-listing/with_skill/outputs/page.tsx +33 -0
- package/skills/uidu-workspace/iteration-1/eval-1-stories-listing/without_skill/grading.json +10 -0
- package/skills/uidu-workspace/iteration-1/eval-1-stories-listing/without_skill/outputs/page.tsx +38 -0
- package/skills/uidu-workspace/iteration-1/eval-2-donations-debug/eval_metadata.json +10 -0
- package/skills/uidu-workspace/iteration-1/eval-2-donations-debug/with_skill/grading.json +8 -0
- package/skills/uidu-workspace/iteration-1/eval-2-donations-debug/with_skill/outputs/answer.md +63 -0
- package/skills/uidu-workspace/iteration-1/eval-2-donations-debug/without_skill/grading.json +9 -0
- package/skills/uidu-workspace/iteration-1/eval-2-donations-debug/without_skill/outputs/answer.md +47 -0
- package/skills/uidu-workspace/iteration-2/benchmark.md +73 -0
- package/skills/uidu-workspace/iteration-2/eval-0-event-detail/with_skill/outputs/page.tsx +37 -0
- package/skills/uidu-workspace/iteration-2/eval-0-event-detail/without_skill/outputs/page.tsx +60 -0
- package/skills/uidu-workspace/iteration-2/eval-1-stories-listing/with_skill/outputs/page.tsx +33 -0
- package/skills/uidu-workspace/iteration-2/eval-1-stories-listing/without_skill/outputs/page.tsx +36 -0
- package/skills/uidu-workspace/iteration-2/eval-2-donations-debug/with_skill/outputs/answer.md +51 -0
- package/skills/uidu-workspace/iteration-2/eval-2-donations-debug/without_skill/outputs/answer.md +77 -0
- package/skills/uidu-workspace/iteration-2/eval-3-client-setup/with_skill/outputs/uidu.ts +13 -0
- package/skills/uidu-workspace/iteration-2/eval-3-client-setup/without_skill/outputs/uidu.ts +47 -0
- package/skills/uidu-workspace/iteration-2/eval-4-cms-pageblocks/with_skill/grading.json +11 -0
- package/skills/uidu-workspace/iteration-2/eval-4-cms-pageblocks/with_skill/outputs/Hero.tsx +17 -0
- package/skills/uidu-workspace/iteration-2/eval-4-cms-pageblocks/with_skill/outputs/page.tsx +21 -0
- package/skills/uidu-workspace/iteration-2/eval-4-cms-pageblocks/without_skill/outputs/Hero.tsx +32 -0
- package/skills/uidu-workspace/iteration-2/eval-4-cms-pageblocks/without_skill/outputs/page.tsx +35 -0
- package/skills/uidu-workspace/iteration-2/eval-5-help-center/with_skill/outputs/page.tsx +54 -0
- package/skills/uidu-workspace/iteration-2/eval-5-help-center/without_skill/outputs/page.tsx +80 -0
- package/skills/uidu-workspace/iteration-2/eval-6-forms-contact/with_skill/grading.json +11 -0
- package/skills/uidu-workspace/iteration-2/eval-6-forms-contact/with_skill/outputs/ContactForm.tsx +277 -0
- package/skills/uidu-workspace/iteration-2/eval-6-forms-contact/with_skill/outputs/page.tsx +48 -0
- package/skills/uidu-workspace/iteration-2/eval-6-forms-contact/without_skill/outputs/ContactForm.tsx +144 -0
- package/skills/uidu-workspace/iteration-2/eval-6-forms-contact/without_skill/outputs/page.tsx +45 -0
- package/skills/uidu-workspace/iteration-2/eval-7-routing-gotcha/with_skill/outputs/answer.md +63 -0
- package/skills/uidu-workspace/iteration-2/eval-7-routing-gotcha/without_skill/outputs/answer.md +131 -0
package/skills/uidu-workspace/iteration-2/eval-7-routing-gotcha/without_skill/outputs/answer.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Diagnostic: `favicon.ico` Hitting Your Story Detail Page
|
|
2
|
+
|
|
3
|
+
## What's Actually Going On
|
|
4
|
+
|
|
5
|
+
Your route `src/app/[id]/page.tsx` is a **catch-all-at-root dynamic segment**. In Next.js App Router, `[id]` at the root of `app/` matches **any single path segment** at the root of your domain — including requests for static assets that the browser auto-requests.
|
|
6
|
+
|
|
7
|
+
When a browser loads your site, it (and crawlers, bots, devtools, link previewers) automatically request:
|
|
8
|
+
|
|
9
|
+
- `/favicon.ico`
|
|
10
|
+
- `/robots.txt`
|
|
11
|
+
- `/sitemap.xml`
|
|
12
|
+
- `/apple-touch-icon.png`
|
|
13
|
+
- `/apple-touch-icon-precomposed.png`
|
|
14
|
+
- `/.well-known/*` (in some cases)
|
|
15
|
+
- Various crawler probes (`/wp-admin`, `/.env`, etc.)
|
|
16
|
+
|
|
17
|
+
If you do not have a physical file at `app/favicon.ico` (or a matching `app/robots.txt`, etc.), **Next.js falls through to the dynamic route** `[id]` and renders `page.tsx` with `params.id = 'favicon.ico'`. Your page then calls something like `getStory({ id: 'favicon.ico' })` against the uidu GraphQL API, which returns a "not found" error — hence the GraphQL errors in your logs.
|
|
18
|
+
|
|
19
|
+
This is **not a uidu SDK bug** — it's a Next.js routing gotcha. Putting a dynamic segment at the root of `app/` is one of the most common footguns in App Router because the root namespace is shared with static asset conventions, metadata files, and crawler probes.
|
|
20
|
+
|
|
21
|
+
### Why It Works for Real IDs
|
|
22
|
+
|
|
23
|
+
For `/abc123`, there's no file at `app/abc123` and `abc123` is a valid story ID in your CMS, so the GraphQL query resolves and the page renders. The route was always firing for *every* root-level path — you just didn't notice for valid IDs because the response was successful.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## How to Fix It
|
|
28
|
+
|
|
29
|
+
The clean fix is to **move the dynamic segment under a static prefix** so the root namespace is reserved for actual root-level concerns (homepage, asset files, metadata routes).
|
|
30
|
+
|
|
31
|
+
### Recommended File-Structure Change
|
|
32
|
+
|
|
33
|
+
**Before (the problem):**
|
|
34
|
+
```
|
|
35
|
+
src/app/
|
|
36
|
+
├── layout.tsx
|
|
37
|
+
├── page.tsx # homepage (if any)
|
|
38
|
+
└── [id]/
|
|
39
|
+
└── page.tsx # matches /favicon.ico, /robots.txt, /anything
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**After (recommended):**
|
|
43
|
+
```
|
|
44
|
+
src/app/
|
|
45
|
+
├── layout.tsx
|
|
46
|
+
├── page.tsx # homepage
|
|
47
|
+
├── favicon.ico # actual favicon file
|
|
48
|
+
├── robots.ts # or robots.txt
|
|
49
|
+
├── sitemap.ts # or sitemap.xml
|
|
50
|
+
└── stories/
|
|
51
|
+
└── [id]/
|
|
52
|
+
└── page.tsx # only matches /stories/:id
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Then update internal links from `/${story.id}` to `/stories/${story.id}` (and add a redirect if you need to preserve old URLs — see below).
|
|
56
|
+
|
|
57
|
+
### If You Must Keep IDs at the Root
|
|
58
|
+
|
|
59
|
+
If the bare-root URL shape (`/abc123`) is a hard product requirement, layer in **defensive guards** instead of moving the route:
|
|
60
|
+
|
|
61
|
+
1. **Add the static files Next.js looks for first.** Place these in `app/` so they short-circuit the dynamic route:
|
|
62
|
+
- `app/favicon.ico` (binary file)
|
|
63
|
+
- `app/robots.ts` or `app/robots.txt`
|
|
64
|
+
- `app/sitemap.ts` or `app/sitemap.xml`
|
|
65
|
+
- `app/apple-icon.png`, `app/icon.png` (see Next.js metadata file conventions)
|
|
66
|
+
|
|
67
|
+
2. **Validate `params.id` in the page** before hitting GraphQL:
|
|
68
|
+
```tsx
|
|
69
|
+
// src/app/[id]/page.tsx
|
|
70
|
+
import { notFound } from 'next/navigation';
|
|
71
|
+
|
|
72
|
+
const VALID_ID = /^[a-z0-9]{6,32}$/i; // adjust to your real ID shape
|
|
73
|
+
|
|
74
|
+
export default async function StoryPage({ params }: { params: Promise<{ id: string }> }) {
|
|
75
|
+
const { id } = await params;
|
|
76
|
+
|
|
77
|
+
// Bail out before the GraphQL call for anything that obviously isn't an ID
|
|
78
|
+
if (id.includes('.') || !VALID_ID.test(id)) {
|
|
79
|
+
notFound();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const story = await getStory({ id });
|
|
83
|
+
if (!story) notFound();
|
|
84
|
+
return <StoryView story={story} />;
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
3. **Use middleware** (`src/middleware.ts`) to reject obvious non-IDs before they reach the route:
|
|
89
|
+
```ts
|
|
90
|
+
import { NextResponse, type NextRequest } from 'next/server';
|
|
91
|
+
|
|
92
|
+
export function middleware(req: NextRequest) {
|
|
93
|
+
const { pathname } = req.nextUrl;
|
|
94
|
+
// anything with a file extension at the root is not a story
|
|
95
|
+
if (/^\/[^/]+\.[a-z0-9]+$/i.test(pathname)) {
|
|
96
|
+
return new NextResponse(null, { status: 404 });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export const config = {
|
|
101
|
+
matcher: '/((?!_next|api).*)',
|
|
102
|
+
};
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Recommended Action
|
|
108
|
+
|
|
109
|
+
**Move the route to `src/app/stories/[id]/page.tsx`.** It's a five-minute change, eliminates the entire class of bug (favicon, robots, sitemap, crawler probes, `.well-known`, link-preview bots), and makes the URL structure self-documenting. Add a redirect in `next.config.ts` if you need to preserve old links:
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
// next.config.ts
|
|
113
|
+
export default {
|
|
114
|
+
async redirects() {
|
|
115
|
+
return [
|
|
116
|
+
// optional: redirect bare IDs to /stories/:id
|
|
117
|
+
// only safe if you have a way to distinguish IDs from other root paths
|
|
118
|
+
];
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Even with the move, **add `app/favicon.ico` and `app/robots.ts`** so the browser's auto-requests resolve cleanly with 200s instead of 404s.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## TL;DR
|
|
128
|
+
|
|
129
|
+
- `app/[id]/page.tsx` at the root catches `/favicon.ico` and every other bare root request that isn't an explicit file or static route.
|
|
130
|
+
- Next.js falls through to your dynamic route, you call `getStory({ id: 'favicon.ico' })`, GraphQL returns an error, your logs fill up.
|
|
131
|
+
- **Fix:** move to `app/stories/[id]/page.tsx` and place the actual `favicon.ico`, `robots.ts`, `sitemap.ts` files in `app/`. If bare-root IDs are required, add metadata files + a regex guard in the page (or middleware).
|