From 8a9afa86bc6bf38b0668dd63fd0b1a43d65e2763 Mon Sep 17 00:00:00 2001
From: Thomas Hallock
Date: Tue, 9 Dec 2025 11:25:53 -0600
Subject: [PATCH] fix(practice): disable auto-scroll and add modern PWA meta
tag
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Add scroll: false to all router.push() calls in practice pages
- Add scroll={false} to Link component in not-found page
- Fixes Next.js warning about auto-scroll with fixed position header
- Add mobile-web-app-capable meta tag alongside deprecated apple-mobile-web-app-capable
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude
---
apps/web/src/app/layout.tsx | 5 +++++
apps/web/src/app/practice/PracticeClient.tsx | 2 +-
.../practice/[studentId]/StudentPracticeClient.tsx | 12 ++++++------
.../[studentId]/configure/ConfigureClient.tsx | 6 +++---
apps/web/src/app/practice/[studentId]/not-found.tsx | 1 +
.../placement-test/PlacementTestClient.tsx | 4 ++--
6 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx
index 762ae771..0a0ee240 100644
--- a/apps/web/src/app/layout.tsx
+++ b/apps/web/src/app/layout.tsx
@@ -68,6 +68,11 @@ export const metadata: Metadata = {
title: 'Abaci.One',
},
+ // Modern web app capable meta tag (non-Apple browsers)
+ other: {
+ 'mobile-web-app-capable': 'yes',
+ },
+
// Category
category: 'education',
}
diff --git a/apps/web/src/app/practice/PracticeClient.tsx b/apps/web/src/app/practice/PracticeClient.tsx
index ecd54822..178e066d 100644
--- a/apps/web/src/app/practice/PracticeClient.tsx
+++ b/apps/web/src/app/practice/PracticeClient.tsx
@@ -38,7 +38,7 @@ export function PracticeClient({ initialPlayers }: PracticeClientProps) {
// Handle student selection - navigate to student's practice page
const handleSelectStudent = useCallback(
(student: StudentWithProgress) => {
- router.push(`/practice/${student.id}`)
+ router.push(`/practice/${student.id}`, { scroll: false })
},
[router]
)
diff --git a/apps/web/src/app/practice/[studentId]/StudentPracticeClient.tsx b/apps/web/src/app/practice/[studentId]/StudentPracticeClient.tsx
index b880d2d8..5e5d2c31 100644
--- a/apps/web/src/app/practice/[studentId]/StudentPracticeClient.tsx
+++ b/apps/web/src/app/practice/[studentId]/StudentPracticeClient.tsx
@@ -154,7 +154,7 @@ export function StudentPracticeClient({
// Handle continue practice - navigate to configuration page
const handleContinuePractice = useCallback(() => {
- router.push(`/practice/${studentId}/configure`)
+ router.push(`/practice/${studentId}/configure`, { scroll: false })
}, [studentId, router])
// Handle resuming an existing session
@@ -187,7 +187,7 @@ export function StudentPracticeClient({
{
onSuccess: () => {
// Navigate to configure page for a fresh start
- router.push(`/practice/${studentId}/configure`)
+ router.push(`/practice/${studentId}/configure`, { scroll: false })
},
}
)
@@ -220,12 +220,12 @@ export function StudentPracticeClient({
{ playerId: studentId, planId: currentPlan.id },
{
onSuccess: () => {
- router.push(`/practice/${studentId}/configure`)
+ router.push(`/practice/${studentId}/configure`, { scroll: false })
},
}
)
} else {
- router.push(`/practice/${studentId}/configure`)
+ router.push(`/practice/${studentId}/configure`, { scroll: false })
}
}, [studentId, currentPlan, abandonSession, router])
@@ -275,7 +275,7 @@ export function StudentPracticeClient({
endEarly.reset()
abandonSession.reset()
// Navigate to configure page for new session
- router.push(`/practice/${studentId}/configure`)
+ router.push(`/practice/${studentId}/configure`, { scroll: false })
}, [
generatePlan,
approvePlan,
@@ -314,7 +314,7 @@ export function StudentPracticeClient({
// Handle opening placement test - navigate to placement test route
const handleRunPlacementTest = useCallback(() => {
- router.push(`/practice/${studentId}/placement-test`)
+ router.push(`/practice/${studentId}/placement-test`, { scroll: false })
}, [studentId, router])
// Handle opening manual skill selector
diff --git a/apps/web/src/app/practice/[studentId]/configure/ConfigureClient.tsx b/apps/web/src/app/practice/[studentId]/configure/ConfigureClient.tsx
index aa585b90..ee10ced5 100644
--- a/apps/web/src/app/practice/[studentId]/configure/ConfigureClient.tsx
+++ b/apps/web/src/app/practice/[studentId]/configure/ConfigureClient.tsx
@@ -59,7 +59,7 @@ export function ConfigureClient({ studentId, playerName }: ConfigureClientProps)
{
onSuccess: () => {
// Redirect to main practice page - view will derive from session data
- router.push(`/practice/${studentId}`)
+ router.push(`/practice/${studentId}`, { scroll: false })
},
onError: (err) => {
// If an active session already exists, use it and redirect
@@ -67,7 +67,7 @@ export function ConfigureClient({ studentId, playerName }: ConfigureClientProps)
// Update the cache with the existing plan so the practice page has it
queryClient.setQueryData(sessionPlanKeys.active(studentId), err.existingPlan)
// Redirect to practice page
- router.push(`/practice/${studentId}`)
+ router.push(`/practice/${studentId}`, { scroll: false })
}
},
}
@@ -76,7 +76,7 @@ export function ConfigureClient({ studentId, playerName }: ConfigureClientProps)
const handleCancel = useCallback(() => {
generatePlan.reset()
- router.push(`/practice/${studentId}`)
+ router.push(`/practice/${studentId}`, { scroll: false })
}, [studentId, generatePlan, router])
return (
diff --git a/apps/web/src/app/practice/[studentId]/not-found.tsx b/apps/web/src/app/practice/[studentId]/not-found.tsx
index cd9fe4bb..33da6206 100644
--- a/apps/web/src/app/practice/[studentId]/not-found.tsx
+++ b/apps/web/src/app/practice/[studentId]/not-found.tsx
@@ -53,6 +53,7 @@ export default function StudentNotFound() {
{
- router.push(`/practice/${studentId}`)
+ router.push(`/practice/${studentId}`, { scroll: false })
}, [studentId, router])
return (