Add type-safe navigation helpers and public pages

- Create gotoLogin() helper for login redirects with search params
- Add /terms and /privacy public routes with Tailwind typography
- Update auth-guard to allow unauthenticated access to public pages
- Fix resolve() usage across navigation components using as const pattern
- Fix eslint-disable-next-line placement for svelte/no-navigation-without-resolve
- Document SvelteKit resolve() patterns in CLAUDE.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
igm
2026-01-11 14:19:33 +08:00
parent 76a5e40900
commit 628b01f4d8
33 changed files with 281 additions and 96 deletions

View File

@@ -14,3 +14,50 @@ macOS uses BSD sed which differs from GNU sed:
- GNU sed (Linux): `sed -i 's/old/new/g' file`
- Use `|` as delimiter when patterns contain `/`: `sed -i '' 's|old/path|new/path|g' file`
- For multiple files: `for f in *.txt; do sed -i '' 's/old/new/g' "$f"; done`
## SvelteKit resolve() Usage
Use `resolve()` from `$app/paths` for type-safe navigation. The patterns are:
### Static routes - use resolve() directly
```svelte
href={resolve("/auth/login")}
href={resolve("/dashboard")}
```
### Dynamic routes - use two-argument form
```svelte
href={resolve("/dashboard/[slug]", { slug: orgSlug })}
href={resolve("/account/org-invites/[inviteId]", { inviteId: String(invite.id) })}
```
### Login redirects - use gotoLogin helper
For redirecting to login with a return URL, use the helper from `$lib/utils/navigation`:
```typescript
import { gotoLogin } from "$lib/utils/navigation";
gotoLogin(page.url.pathname);
```
This helper uses resolve() internally and handles the query string correctly.
### Navigation arrays - use `as const` with route patterns
For type-safe navigation arrays, define routes as literal strings with `as const`:
```typescript
const navItems = [
{ route: "/dashboard/[slug]/settings", icon: Settings, label: "General" },
{ route: "/dashboard/[slug]/settings/members", icon: Users, label: "Members" },
] as const;
```
Then use resolve with params:
```svelte
{#each navItems as item (item.route)}
<a href={resolve(item.route, { slug })}>
{/each}
```
### Runtime strings - skip resolve, use eslint-disable
When paths are fully dynamic (e.g., server-provided redirects), skip resolve:
```typescript
// eslint-disable-next-line svelte/no-navigation-without-resolve
goto(redirectUrl);
```