Skip to content

Fix/monorepo dependency consolidation#312

Open
TS-mfon wants to merge 4 commits intorinafcode:mainfrom
TS-mfon:fix/monorepo-dependency-consolidation
Open

Fix/monorepo dependency consolidation#312
TS-mfon wants to merge 4 commits intorinafcode:mainfrom
TS-mfon:fix/monorepo-dependency-consolidation

Conversation

@TS-mfon
Copy link
Copy Markdown
Contributor

@TS-mfon TS-mfon commented Apr 28, 2026

Closes #240

Description

Brief description of changes

Related Issue

Closes #

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

Checklist

  • Code follows project style guidelines
  • Self-review completed
  • No console errors
  • Uses Lucide icons consistently
  • Responsive design implemented
  • Starknet best practices followed

TS-mfon and others added 4 commits April 28, 2026 01:06
Stabilize date rendering across server/client, avoid navigator access during SSR initialization, add error boundary for pages router, and add SSR-focused tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep SSR hydration-safe rendering while retaining EmptyState/BellOff UI from main.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adopt pnpm workspaces as the monorepo dependency source of truth, add shared tooling configs, and update CI/scripts to run consistently across workspace packages.

Made-with: Cursor
Resolve duplicate imports and conflicting type declarations, fix error boundary fallback rendering, and remove duplicated Starknet env helpers to keep validation behavior consistent.

Made-with: Cursor
Copilot AI review requested due to automatic review settings April 28, 2026 10:11
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR migrates the repo toward pnpm workspaces with centralized tooling config, while also addressing some SSR/hydration stability concerns and wiring global error handling.

Changes:

  • Introduce pnpm workspaces + shared tooling package (@teachlink/tooling) and update root TypeScript/ESLint configs to consume it.
  • Update CI and docs to use pnpm; add workspace-wide lint/test/typecheck scripts.
  • Improve SSR determinism (search date formatting + SSR test) and add global error boundary; adjust client components for hydration/Next.js compatibility.

Reviewed changes

Copilot reviewed 17 out of 20 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
tsconfig.json Switch root TS config to extend shared base config from @teachlink/tooling.
src/utils/web3/envValidation.ts Reorder imports and remove duplicated exported helpers; keeps Web3 env validation logic.
src/pages/_app.tsx Wrap app with ErrorBoundary.
src/components/search/tests/SearchResultsVisualizer.ssr.test.tsx Add SSR-focused test for deterministic date formatting.
src/components/search/SearchResultsVisualizer.tsx Introduce formatSearchResultDate() and use it in render for UTC-stable dates.
src/components/notificationcenter.tsx Mark as client component; swap empty state UI; add hydration-safe timestamp rendering; switch avatar rendering to next/image.
src/components/errors/ErrorBoundarySystem.tsx Adjust UserFriendlyErrorDisplay import style and update fallback rendering.
src/app/store/messagingStore.ts Fix socket.io-client import to use named io.
src/app/mobile/components/OfflineContentManager.tsx Avoid navigator.onLine in initial state (SSR-safe); set online state in effect.
src/app/mobile/components/MobileProgressTracker.tsx Avoid navigator.onLine in initial state (SSR-safe); set online state in effect.
pnpm-workspace.yaml Define workspace package globs for pnpm.
packages/tooling/tsconfig/base.json Add shared base tsconfig used by root.
packages/tooling/package.json Define internal tooling workspace package exports (ESLint + tsconfig).
packages/tooling/eslint/base.js Add shared flat ESLint config factory.
package.json Pin pnpm via packageManager, add workspace scripts, add overrides, and depend on @teachlink/tooling.
eslint.config.js Replace inline config with @teachlink/tooling factory.
README.md Update setup instructions to pnpm and document monorepo tooling decision.
.github/workflows/ci.yml Switch CI install/cache/run steps from npm to pnpm.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/ci.yml
Comment on lines +21 to +24
- name: Set up pnpm
uses: pnpm/action-setup@v4
with:
version: 10
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

CI installs pnpm with version: 10, but the repo pins packageManager to pnpm@10.33.2 in package.json. To avoid lockfile/behavior mismatches between local and CI, pin the action to the same exact version (or use corepack to activate the version from packageManager).

Copilot uses AI. Check for mistakes.
Comment on lines 3 to 11
@@ -7,7 +9,7 @@ export function validateStarknetEnv(): { valid: boolean; missing: string[] } {
export function getStarknetNetwork(): string {
return process.env.NEXT_PUBLIC_STARKNET_NETWORK ?? 'testnet';
}
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

validateStarknetEnv()/getStarknetNetwork() are now out of sync with the Zod schema in this same file: the default network is 'testnet', but envSchema only allows mainnet-alpha | goerli-alpha | sepolia-alpha. With EnvGuard calling validateAppEnv(), following the default/README value will trip validation and block the app. Align the default + allowed values (either add a 'testnet' alias to the schema/NETWORKS mapping, or switch defaults/docs back to goerli-alpha/sepolia-alpha).

Copilot uses AI. Check for mistakes.
Comment thread README.md
Create a `.env.local` with:

```ini
NEXT_PUBLIC_STARKNET_NETWORK=testnet
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

The README now instructs NEXT_PUBLIC_STARKNET_NETWORK=testnet, but validateAppEnv() only accepts mainnet-alpha, goerli-alpha, or sepolia-alpha (and defaults to goerli-alpha). As written, users following these steps will hit a configuration error. Update the example value to one of the accepted networks or update the validation to accept testnet as an alias.

Suggested change
NEXT_PUBLIC_STARKNET_NETWORK=testnet
NEXT_PUBLIC_STARKNET_NETWORK=goerli-alpha

Copilot uses AI. Check for mistakes.
Comment on lines +91 to +105
<>
<div style={{ padding: '20px' }}>
<h2>Something went wrong.</h2>
<p>{this.state.error?.message}</p>

<button onClick={this.resetError}>Try Again</button>
</div>
<UserFriendlyErrorDisplay
error={this.state.error}
title="Application Error"
onRetry={this.resetError}
showDetails={true}
severity="error"
/>
</>
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

The error fallback currently renders both the inline "Something went wrong" block and UserFriendlyErrorDisplay, which will show two error UIs at once. Pick one presentation (preferably the shared UserFriendlyErrorDisplay) or wrap the legacy block behind a condition so only a single fallback is rendered.

Suggested change
<>
<div style={{ padding: '20px' }}>
<h2>Something went wrong.</h2>
<p>{this.state.error?.message}</p>
<button onClick={this.resetError}>Try Again</button>
</div>
<UserFriendlyErrorDisplay
error={this.state.error}
title="Application Error"
onRetry={this.resetError}
showDetails={true}
severity="error"
/>
</>
<UserFriendlyErrorDisplay
error={this.state.error}
title="Application Error"
onRetry={this.resetError}
showDetails={true}
severity="error"
/>

Copilot uses AI. Check for mistakes.
Comment on lines +54 to +58
const [isHydrated, setIsHydrated] = useState(false);

useEffect(() => {
setIsHydrated(true);
}, []);
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

NotificationItem sets its own isHydrated state via useEffect, which causes an extra render per notification and duplicates hydration logic across list items. Consider lifting a single isHydrated flag to NotificationCenter (or a small hook used once) and passing it down, so opening the panel only triggers one hydration state change regardless of list size.

Copilot uses AI. Check for mistakes.
Comment on lines 76 to +83
{avatarUrl ? (
<img src={avatarUrl} alt="" className="notification-item__avatar" />
<Image
src={avatarUrl}
alt=""
width={24}
height={24}
className="notification-item__avatar"
/>
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

Switching from <img> to next/image for avatarUrl can break rendering when the notification payload contains an image host that isn't allowed in next.config.ts (images.remotePatterns is currently limited to a few domains). Since avatarUrl comes from WebSocket payloads and isn't constrained, either keep a plain <img> for this case, or ensure the expected avatar domains are added to remotePatterns / use a safe proxy/loader.

Copilot uses AI. Check for mistakes.
Comment on lines +27 to +37
export function formatSearchResultDate(value: string | Date): string {
const date = new Date(value);
if (Number.isNaN(date.getTime())) {
return '';
}
return new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
timeZone: 'UTC',
}).format(date);
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

formatSearchResultDate creates a new Intl.DateTimeFormat instance on every call. Since this runs per-result render, consider hoisting a single formatter (module-level constant) and reusing it to reduce allocations during large result renders.

Suggested change
export function formatSearchResultDate(value: string | Date): string {
const date = new Date(value);
if (Number.isNaN(date.getTime())) {
return '';
}
return new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
timeZone: 'UTC',
}).format(date);
const SEARCH_RESULT_DATE_FORMATTER = new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
timeZone: 'UTC',
});
export function formatSearchResultDate(value: string | Date): string {
const date = new Date(value);
if (Number.isNaN(date.getTime())) {
return '';
}
return SEARCH_RESULT_DATE_FORMATTER.format(date);

Copilot uses AI. Check for mistakes.
@RUKAYAT-CODER
Copy link
Copy Markdown
Contributor

Kindly resolve conflict

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.

Monorepo Dependency Management

3 participants