Skip to content

UI example app: Pico CSS#27

Merged
kattsushi merged 3 commits into
masterfrom
feat/router-fm-pico-ui
Feb 7, 2026
Merged

UI example app: Pico CSS#27
kattsushi merged 3 commits into
masterfrom
feat/router-fm-pico-ui

Conversation

@kattsushi

@kattsushi kattsushi commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • Style

    • Added Pico CSS stylesheet and light/dark color-scheme support
    • Simplified login and signup UIs with cleaner semantic HTML
  • New Features

    • Added a Todo App route with full create/read/update/delete UI
    • Updated site navigation with a sticky header, new links and improved sign-out flow
  • Refactor

    • Reorganized main layout and header for clearer page structure and navigation
    • Removed the previous About page

@coderabbitai

coderabbitai Bot commented Feb 7, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Added Pico CSS to root; simplified login/signup UIs; enhanced nav with sign-out navigation; switched auth database wiring to use a Postgres Pool; removed About route/file and added a new auth-guarded Todo app route with loader, action, and Prisma-backed CRUD UI; added a DATABASE_URL guard.

Changes

Cohort / File(s) Summary
Root / Global Layout
apps/react-app-router-fm/app/root.tsx
Added Pico CSS stylesheet entry (integrity + crossOrigin) into links array; ordering placed before Google Fonts.
Authentication UI
apps/react-app-router-fm/app/routes/login.tsx, apps/react-app-router-fm/app/routes/signup.tsx
Replaced Tailwind-heavy layouts with simplified semantic structure (main/article/form); preserved submit handlers and navigation; simplified error rendering and replaced console logging in signup error path.
Navigation
apps/react-app-router-fm/app/app-nav.tsx
Expanded nav to a sticky header with brand and route links; added useNavigate, async sign-out that navigates to /login on completion/failure.
Auth / DB wiring
apps/react-app-router-fm/app/lib/better-auth-options.server.ts
Switched authOptions.database from a commented better-sqlite3 instantiation to using an existing pool (removed commented import/lines).
Routing: removed About, added Todo
apps/react-app-router-fm/app/routes.tsx, apps/react-app-router-fm/app/routes/about.tsx (deleted), apps/react-app-router-fm/app/routes/todo-app.tsx
Removed about route/file; added todo-app route and new todo-app.tsx implementing auth-guarded loader and action (Prisma-backed CRUD) plus default component rendering create/edit/delete/toggle UI and forms.
Prisma / Env guard
apps/react-app-router-fm/app/lib/prisma.ts
Added explicit guard that throws if process.env.DATABASE_URL is missing/empty and switched from interpolated string to direct env access before creating Pool and PrismaPg adapter.

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant Route as "Route (loader/action)"
  participant Guard as "Auth Guard"
  participant Server as "Effect / Route Handler"
  participant DB as "Prisma → Postgres Pool"

  Browser->>Route: GET /todo-app
  Route->>Guard: invoke loader with session
  Guard->>Server: allow (or reject)
  Server->>DB: fetch todos
  DB-->>Server: todos
  Server-->>Route: httpSuccess({todos})
  Route-->>Browser: render with loaderData

  Browser->>Route: POST /todo-app (form)
  Route->>Guard: invoke action with session
  Guard->>Server: allow (or reject)
  Server->>DB: create/update/delete/toggle
  DB-->>Server: result
  Server-->>Route: httpRedirect or httpFailure
  Route-->>Browser: navigation or validation response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I swapped a sheet for Pico, light and spry,
Tidied forms and let the old styles fly,
I nudged the DB toward a Postgres pool,
Brought todos, guards, and routes to play it cool,
A tiny hop — the app feels bright and spry.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'UI ejemplo: Pico CSS en router-fm' directly reflects the main change: adding Pico CSS to the router-fm app and simplifying UI components.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/router-fm-pico-ui

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud

nx-cloud Bot commented Feb 7, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 6f2ba95

Command Status Duration Result
nx affected --target=test --base=87c40a1ce45893... ✅ Succeeded 11s View ↗
nx affected --target=build --base=87c40a1ce4589... ✅ Succeeded 10s View ↗
nx affected --target=lint --base=origin/master ... ✅ Succeeded <1s View ↗
nx affected --target=typecheck --base=origin/ma... ✅ Succeeded 1s View ↗

☁️ Nx Cloud last updated this comment at 2026-02-07 05:23:45 UTC

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Fix all issues with AI agents
In `@apps/react-app-router-fm/app/root.tsx`:
- Around line 23-26: The external Pico CSS link object (the object with rel:
"stylesheet" and href:
"https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.classless.min.css")
should either be pinned with SRI or replaced by a local asset: add an integrity
property with the correct SHA384 (or SHA512) hash and set crossorigin:
"anonymous" on that link object, or download the pico.classless.min.css into
your static assets and update the href to the local path (removing the external
crossorigin/integrity if self-hosted) so supply‑chain integrity is preserved.

In `@apps/react-app-router-fm/app/routes/login.tsx`:
- Line 60: The small error message rendering in the login route currently lacks
ARIA attributes so screen readers won't announce it; update the JSX that renders
{error} (the small element in app/routes/login.tsx) to include role="alert" or
aria-live="polite" (and keep the existing error styling) so dynamic errors are
announced to assistive technology when they appear.
- Around line 64-66: Replace the anchor element in the login route JSX with
React Router's Link to enable client-side navigation: change <a href="/signup">
to <Link to="/signup"> in the routes/login.tsx component and add Link to the
existing import from "react-router" (or "react-router-dom" if used in the
project) so the component uses the Link symbol for internal navigation.

In `@apps/react-app-router-fm/app/routes/signup.tsx`:
- Line 73: The error message rendering line in the Signup component currently
uses {error && <small ...>{error}</small>}; update that small element to include
accessibility attributes so screen readers announce dynamic errors (e.g., add
role="alert" and/or aria-live="polite" to the <small> rendering the error).
Locate the JSX where the "error" variable is rendered in the signup.tsx route
and add those attributes to the small element (or use an equivalent aria-live
container) so the error is announced when it appears.
- Around line 76-79: Replace the plain anchor in the signup route footer with
React Router's Link to enable client-side navigation: in
apps/react-app-router-fm/app/routes/signup.tsx locate the footer/small block
containing <a href="/login">Sign in</a>, import Link (e.g. import { Link } from
"react-router-dom") at the top of the module, and change the anchor to use <Link
to="/login">Sign in</Link> so routing uses the Link component instead of a full
page reload.

Comment thread apps/react-app-router-fm/app/root.tsx
Comment thread apps/react-app-router-fm/app/routes/login.tsx Outdated
Comment thread apps/react-app-router-fm/app/routes/login.tsx Outdated
Comment thread apps/react-app-router-fm/app/routes/signup.tsx Outdated
Comment thread apps/react-app-router-fm/app/routes/signup.tsx Outdated
…t todo route with auth guard; better-auth pg pool for migrate CLI

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@apps/react-app-router-fm/app/lib/better-auth-options.server.ts`:
- Around line 7-10: The file creates a new pg Pool instance (symbol "pool" via
new Pool(...)) which duplicates connection pools; instead import and reuse the
shared Pool exported from prisma.ts (the shared Pool export) instead of
constructing a new Pool. Replace the new Pool(...) usage in
better-auth-options.server.ts with an import of the shared Pool export from
prisma.ts and update references to use that imported pool instance so only one
pg Pool is created and connection management is centralized.
- Around line 7-10: This file creates a new pg Pool with an unvalidated
connection string which duplicates the shared pool in prisma.ts and can produce
"undefined"; instead import and reuse the exported pool from prisma.ts (remove
the local new Pool and any reference to Pool/pool here) and update prisma.ts to
validate process.env.DATABASE_URL at startup (throw or process.exit with a clear
error if missing) so the shared export always has a real connection string;
reference the exported pool symbol from prisma.ts when replacing the local Pool
usage.

In `@apps/react-app-router-fm/app/routes/todo-app.tsx`:
- Around line 118-120: The inline error message for actionData (the small
element that renders when actionData.ok === false and actionData.errors?.length)
needs ARIA so screen readers announce it; update the small element rendered by
the Todo route component to include role="alert" and/or aria-live="assertive"
(and keep the same error text content) so assistive tech is notified when the
error appears.
- Around line 14-24: The loader and todo actions (e.g., the loader generator
using PrismaRepository.make(TodoModel) and repo.findMany, plus
create/update/delete/toggle handlers) currently expose and mutate all todos and
hardcode authorId; scope access to the authenticated user by pulling the current
user id from AuthService.AuthContext provided by the guards, then filter queries
(e.g., replace findMany({}) with findMany({ where: { authorId: currentUserId }
})) and add authorId: currentUserId to create, and include authorId in
update/delete/toggle conditions (e.g., update/delete where { id, authorId:
currentUserId }) so users can only read/modify their own todos; ensure
httpSuccess still returns the filtered todos.

Comment thread apps/react-app-router-fm/app/lib/better-auth-options.server.ts Outdated
Comment thread apps/react-app-router-fm/app/routes/todo-app.tsx
Comment thread apps/react-app-router-fm/app/routes/todo-app.tsx
- Replace Pico CSS with classless version and add integrity/crossorigin for security
- Centralize database pool usage and add validation for DATABASE_URL
- Use React Router Link for internal navigation instead of anchor tags
- Add ARIA attributes to error messages for accessibility
- Remove console.error in signup to avoid exposing error details
- Implement user-specific todo operations by filtering by authorId
- Use updateMany/deleteMany with user ID constraints to prevent unauthorized access
@kattsushi kattsushi changed the title UI ejemplo: Pico CSS en router-fm UI example app: Pico CSS en router-fm Feb 7, 2026
@kattsushi kattsushi changed the title UI example app: Pico CSS en router-fm UI example app: Pico CSS Feb 7, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@apps/react-app-router-fm/app/lib/prisma.ts`:
- Around line 6-9: The code reads process.env.DATABASE_URL into connectionString
but only trims for the check — change it to use a trimmed value everywhere:
compute a trimmed variable (e.g., const connectionString =
process.env.DATABASE_URL?.trim();), validate that trimmed value and throw the
same error if empty, and then pass that trimmed connectionString downstream
wherever the current untrimmed value was used so no leading/trailing whitespace
can break connections.

In `@apps/react-app-router-fm/app/routes/todo-app.tsx`:
- Around line 174-177: The update form's title input (the <input> element with
name="title" and defaultValue={todo.title}) lacks client-side validation,
causing UX inconsistency with the server which rejects blank titles; add the
required attribute to that input so the browser enforces non-empty titles on
update to mirror server validation.
- Around line 21-24: The loader/mutation is incorrectly coercing
AuthService.AuthContext.user.id to Number (currentUserId) but better-auth
provides a string ID while Todo.authorId is an Int; stop numeric coercion and
treat the auth id as a string or make the schema numeric consistently. Fix by
replacing Number(user.id)/Number.isInteger checks with using the raw user.id
string (e.g., currentUserIdStr = user.id) and update any comparisons/inserts
that reference Todo.authorId to use a string authorId (or alternatively change
the Todo.authorId schema/type to String), and apply the same change where
similar coercion occurs in the mutations (the code around lines 47-50) so all DB
writes/reads use the consistent ID type.

Comment on lines +6 to +9
const connectionString = process.env.DATABASE_URL
if (!connectionString || connectionString.trim().length === 0) {
throw new Error("Missing DATABASE_URL environment variable")
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Trim DATABASE_URL before using it.

You validate .trim() but still pass the untrimmed value downstream. That can fail if the env var contains whitespace.

Proposed fix
-const connectionString = process.env.DATABASE_URL
-if (!connectionString || connectionString.trim().length === 0) {
+const connectionString = process.env.DATABASE_URL?.trim()
+if (!connectionString) {
   throw new Error("Missing DATABASE_URL environment variable")
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const connectionString = process.env.DATABASE_URL
if (!connectionString || connectionString.trim().length === 0) {
throw new Error("Missing DATABASE_URL environment variable")
}
const connectionString = process.env.DATABASE_URL?.trim()
if (!connectionString) {
throw new Error("Missing DATABASE_URL environment variable")
}
🤖 Prompt for AI Agents
In `@apps/react-app-router-fm/app/lib/prisma.ts` around lines 6 - 9, The code
reads process.env.DATABASE_URL into connectionString but only trims for the
check — change it to use a trimmed value everywhere: compute a trimmed variable
(e.g., const connectionString = process.env.DATABASE_URL?.trim();), validate
that trimmed value and throw the same error if empty, and then pass that trimmed
connectionString downstream wherever the current untrimmed value was used so no
leading/trailing whitespace can break connections.

Comment on lines +21 to +24
const { user } = yield* AuthService.AuthContext
const currentUserId = Number(user.id)
if (!Number.isInteger(currentUserId)) {
return yield* httpSuccess({ todos: [] })

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Locate Prisma schema(s) and inspect User/Todo models + authorId types
echo "=== Looking for Prisma schema files ==="
fd -a "schema.prisma" 2>/dev/null || echo "No schema.prisma found"

echo -e "\n=== Looking for schema files with alternative names ==="
find . -name "*schema*.prisma" -o -name "*.prisma" 2>/dev/null | head -20

echo -e "\n=== Checking common locations ==="
if [ -f "prisma/schema.prisma" ]; then
  echo "Found at prisma/schema.prisma"
  cat -n prisma/schema.prisma
fi

Repository: devx-op/effectify

Length of output: 400


🏁 Script executed:

#!/bin/bash
# Inspect the todo-app.tsx file to see lines 21-24 and 47-50
echo "=== Inspecting todo-app.tsx around lines 21-24 ==="
if [ -f "apps/react-app-router-fm/app/routes/todo-app.tsx" ]; then
  sed -n '15,30p' apps/react-app-router-fm/app/routes/todo-app.tsx
fi

echo -e "\n=== Inspecting todo-app.tsx around lines 47-50 ==="
if [ -f "apps/react-app-router-fm/app/routes/todo-app.tsx" ]; then
  sed -n '40,55p' apps/react-app-router-fm/app/routes/todo-app.tsx
fi

Repository: devx-op/effectify

Length of output: 1082


🏁 Script executed:

#!/bin/bash
# Check AuthService and user ID typing
echo "=== Looking for AuthService ==="
find . -name "*AuthService*" -type f 2>/dev/null | head -20

echo -e "\n=== Searching for AuthContext and user.id typing ==="
rg -n "AuthContext|interface.*User|type.*User" -g "*.{ts,tsx}" --max-count 20 2>/dev/null || echo "No matches found"

Repository: devx-op/effectify

Length of output: 4725


🏁 Script executed:

#!/bin/bash
echo "=== Inspecting apps/react-app-router-fm/prisma/schema.prisma ==="
cat apps/react-app-router-fm/prisma/schema.prisma

echo -e "\n=== Inspecting packages/prisma/prisma/schema.prisma (first 100 lines) ==="
head -100 packages/prisma/prisma/schema.prisma

Repository: devx-op/effectify

Length of output: 1942


🏁 Script executed:

#!/bin/bash
echo "=== Inspecting auth-service.ts for User type ==="
head -80 packages/node/better-auth/src/lib/auth-service.ts

echo -e "\n=== Checking better-auth version and User type import ==="
rg -n "User|user\.id" packages/node/better-auth/src/lib/auth-service.ts -A 3

Repository: devx-op/effectify

Length of output: 2474


🏁 Script executed:

#!/bin/bash
echo "=== Looking for User model in apps/react-app-router-fm schema ==="
rg -n "model User" apps/react-app-router-fm/prisma/schema.prisma -A 10

echo -e "\n=== Complete schema file to see if User model exists ==="
wc -l apps/react-app-router-fm/prisma/schema.prisma
cat -n apps/react-app-router-fm/prisma/schema.prisma

Repository: devx-op/effectify

Length of output: 1528


🏁 Script executed:

#!/bin/bash
echo "=== Check better-auth configuration/setup in the app ==="
find apps/react-app-router-fm -name "*.ts" -o -name "*.tsx" | xargs grep -l "betterAuth\|AuthService" | head -5

echo -e "\n=== Check how better-auth is instantiated/configured ==="
fd -t f "auth" apps/react-app-router-fm -x grep -l "betterAuth" {} \;

echo -e "\n=== Look for auth middleware setup ==="
cat -n apps/react-app-router-fm/app/lib/http/auth-middleware.server.ts 2>/dev/null || echo "File not found"

Repository: devx-op/effectify

Length of output: 2740


🏁 Script executed:

#!/bin/bash
echo "=== Check better-auth package.json to understand user.id type ==="
find . -path "*/better-auth/package.json" -o -path "*/node_modules/better-auth/package.json" 2>/dev/null | head -3

echo -e "\n=== Search for better-auth user ID pattern in codebase ==="
rg "user\\.id|User\\.id" --type ts --type tsx -B 2 -A 2 apps/react-app-router-fm/ | head -30

Repository: devx-op/effectify

Length of output: 272


🏁 Script executed:

#!/bin/bash
echo "=== Check better-auth-options.server.ts ==="
cat -n apps/react-app-router-fm/app/lib/better-auth-options.server.ts

echo -e "\n=== Check api.auth.ts route setup ==="
cat -n apps/react-app-router-fm/app/routes/api.auth.ts

Repository: devx-op/effectify

Length of output: 1653


🏁 Script executed:

#!/bin/bash
echo "=== Search for user.id patterns in tsx/ts files ==="
rg "user\.id" apps/react-app-router-fm -A 2 -B 2 --type-add 'ts:*.{ts,tsx}'

echo -e "\n=== Search for authorId usage ==="
rg "authorId" apps/react-app-router-fm -A 2 -B 2 --type-add 'ts:*.{ts,tsx}'

Repository: devx-op/effectify

Length of output: 4647


🏁 Script executed:

#!/bin/bash
echo "=== Check if better-auth User type is string or number ==="
rg -n "type User" packages/node/better-auth/src -A 5 2>/dev/null || echo "Type definition not in better-auth src"

echo -e "\n=== Check better-auth package exports ==="
head -50 packages/node/better-auth/package.json | grep -E "name|version|main"

echo -e "\n=== Check if there's a database schema for better-auth ==="
fd -a "schema" packages/node/better-auth -x cat {} \; 2>/dev/null | head -50

Repository: devx-op/effectify

Length of output: 881


🏁 Script executed:

#!/bin/bash
echo "=== Check if there's any User/Auth table creation or migration for better-auth ==="
find apps/react-app-router-fm -name "*.sql" -o -name "migration*" | xargs grep -l "user\|auth" 2>/dev/null | head -5

echo -e "\n=== Check prisma migrations for any user-related tables ==="
ls -la apps/react-app-router-fm/prisma/migrations/

echo -e "\n=== Display migration SQL content ==="
cat apps/react-app-router-fm/prisma/migrations/20251126024643_init/migration.sql

Repository: devx-op/effectify

Length of output: 960


🏁 Script executed:

#!/bin/bash
echo "=== Verify better-auth default behavior - check if any custom id config ==="
rg -i "id.*config\|customid\|numericid" packages/node/better-auth/src -A 3 2>/dev/null || echo "No custom ID config found"

echo -e "\n=== Check better-auth npm package documentation reference ==="
grep -i "better-auth" apps/react-app-router-fm/package.json packages/node/better-auth/package.json 2>/dev/null | head -20

Repository: devx-op/effectify

Length of output: 953


🏁 Script executed:

#!/bin/bash
echo "=== Check better-auth migration files ==="
ls -la apps/react-app-router-fm/better-auth_migrations/

echo -e "\n=== Display better-auth migration 1 ==="
cat apps/react-app-router-fm/better-auth_migrations/2025-11-22T04-27-51.619Z.sql

echo -e "\n=== Display better-auth migration 2 ==="
cat apps/react-app-router-fm/better-auth_migrations/2025-11-23T05-47-31.745Z.sql

Repository: devx-op/effectify

Length of output: 2958


Incompatible user ID type: string vs integer authorId.

better-auth provides user.id as TEXT (string), but the schema defines Todo.authorId as Int. Coercing to Number(user.id) yields NaN, failing the Number.isInteger() check at line 23. This causes silent failures: the loader returns empty todos, and mutations fail.

Align the ID types: either change Todo.authorId to String, or store numeric user IDs from better-auth. Do not use numeric coercion unless the auth service guarantees numeric IDs.

Also applies to: 47-50

🤖 Prompt for AI Agents
In `@apps/react-app-router-fm/app/routes/todo-app.tsx` around lines 21 - 24, The
loader/mutation is incorrectly coercing AuthService.AuthContext.user.id to
Number (currentUserId) but better-auth provides a string ID while Todo.authorId
is an Int; stop numeric coercion and treat the auth id as a string or make the
schema numeric consistently. Fix by replacing Number(user.id)/Number.isInteger
checks with using the raw user.id string (e.g., currentUserIdStr = user.id) and
update any comparisons/inserts that reference Todo.authorId to use a string
authorId (or alternatively change the Todo.authorId schema/type to String), and
apply the same change where similar coercion occurs in the mutations (the code
around lines 47-50) so all DB writes/reads use the consistent ID type.

Comment on lines +174 to +177
<input type="hidden" name="intent" value="update" />
<input type="hidden" name="id" value={String(todo.id)} />
<input name="title" type="text" defaultValue={todo.title} placeholder="Title" />
<input name="content" type="text" defaultValue={todo.content ?? ""} placeholder="Content" />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Mirror server validation on update titles.

Update rejects blank titles server-side; add required to the update title input for consistent UX.

Proposed fix
-  <input name="title" type="text" defaultValue={todo.title} placeholder="Title" />
+  <input name="title" type="text" defaultValue={todo.title} placeholder="Title" required />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<input type="hidden" name="intent" value="update" />
<input type="hidden" name="id" value={String(todo.id)} />
<input name="title" type="text" defaultValue={todo.title} placeholder="Title" />
<input name="content" type="text" defaultValue={todo.content ?? ""} placeholder="Content" />
<input type="hidden" name="intent" value="update" />
<input type="hidden" name="id" value={String(todo.id)} />
<input name="title" type="text" defaultValue={todo.title} placeholder="Title" required />
<input name="content" type="text" defaultValue={todo.content ?? ""} placeholder="Content" />
🤖 Prompt for AI Agents
In `@apps/react-app-router-fm/app/routes/todo-app.tsx` around lines 174 - 177, The
update form's title input (the <input> element with name="title" and
defaultValue={todo.title}) lacks client-side validation, causing UX
inconsistency with the server which rejects blank titles; add the required
attribute to that input so the browser enforces non-empty titles on update to
mirror server validation.

@kattsushi kattsushi merged commit 66ae7b3 into master Feb 7, 2026
7 checks passed
kattsushi added a commit that referenced this pull request Mar 15, 2026
* ui(router-fm): integrar Pico CSS por CDN; simplificar login/signup con formularios semánticos

* feat(router-fm): responsive nav UX, responsive todo container, protect todo route with auth guard; better-auth pg pool for migrate CLI

* refactor(auth): improve security and user data isolation

- Replace Pico CSS with classless version and add integrity/crossorigin for security
- Centralize database pool usage and add validation for DATABASE_URL
- Use React Router Link for internal navigation instead of anchor tags
- Add ARIA attributes to error messages for accessibility
- Remove console.error in signup to avoid exposing error details
- Implement user-specific todo operations by filtering by authorId
- Use updateMany/deleteMany with user ID constraints to prevent unauthorized access
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant