- .env.example: полный шаблон, защита секретов - .gitignore: явное исключение .env.* и секретов - layout.tsx: XSS — заменён dangerouslySetInnerHTML на next/script для SW - ESLint: no-console error (allow warn/error), ignore scripts/ - scripts/remove-console-logs.js: очистка console.log без glob - backend/routes/modules: README с планом рефакторинга крупных файлов - SECURITY.md: гид по секретам, XSS, CORS, auth, линту - .husky/pre-commit: запуск npm run lint + прочие правки приложения и бэкенда Co-authored-by: Cursor <cursoragent@cursor.com>
30 lines
855 B
TypeScript
30 lines
855 B
TypeScript
/**
|
||
* App providers — Auth, I18n, dark mode initialization.
|
||
* Разработчик: АО «REFLY»
|
||
*/
|
||
'use client';
|
||
import { ReactNode, useEffect } from 'react';
|
||
import { AuthProvider } from '@/lib/auth-context';
|
||
import { I18nProvider } from '@/hooks/useI18n';
|
||
|
||
function DarkModeInit() {
|
||
useEffect(() => {
|
||
// Apply saved theme on mount
|
||
const saved = typeof localStorage !== 'undefined' ? localStorage.getItem('klg-theme') : null;
|
||
const dark = saved === 'dark' || (!saved && window.matchMedia('(prefers-color-scheme: dark)').matches);
|
||
document.documentElement.classList.toggle('dark', dark);
|
||
}, []);
|
||
return null;
|
||
}
|
||
|
||
export function Providers({ children }: { children: ReactNode }) {
|
||
return (
|
||
<I18nProvider>
|
||
<AuthProvider>
|
||
<DarkModeInit />
|
||
{children}
|
||
</AuthProvider>
|
||
</I18nProvider>
|
||
);
|
||
}
|