react-core
Skill0 starsChanged 4 months agoMITView on GitHub
How to implement the src/core folder — app-level infrastructure shared by every feature. Covers folder structure, Axios config with auth interceptors, QueryClient, router config, i18n setup, theme, AuthContext, SnackbarContext, ThemeContext, type-safe storage utility, Zustand layout store, and main.tsx provider composition. Use whenever setting up a new project, adding a new core concern, or modifying any of these foundational files.
- Reads credentials
In this repository12 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- feature-architectureSkill
- frontend-auditSkill
- frontend-i18nSkill
- mui-themeSkill
- react-standardSkill
- table-mrtSkill
- tanstack-formSkill
- tanstack-querySkill
- tanstack-routerSkill
- flutter-clean-arch-getxSkill
- flutter-flavorsSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 1 is distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 16
Read the relevant file when you need it:
- Very specific: line 83
All feature services: import axiosInstance from '@/core/api/axios.config'
- Very specific: line 137
Import as a side-effect in main.tsx — never import the default export unless you need the i18n instance.
- Very specific: line 161
Add languages by adding keys under resources and JSON files under src/locales/.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Core Folder
src/core/ contains app-level infrastructure that every feature depends on but no single feature owns. Nothing in core/ should import from features/.
Core Invariants (always enforced — never violate)
- Nothing in
core/may import fromfeatures/.
References
Read the relevant file when you need it:
references/contexts.md— full implementation ofThemeContext,AuthContext,SnackbarContextreferences/storage-store.md—storageutility,STORAGE_KEYS,useLayoutStore(Zustand)
Folder Structure
src/core/
├── api/
│ └── axios.config.ts # Axios instance — auth header + 401 handling
├── config/
│ ├── i18n.config.ts # i18next init — import side-effect in main.tsx
│ ├── query-client.config.ts # QueryClient singleton with default options
│ └── theme.config.ts # createAppTheme(mode) factory
├── router/
│ ├── index.tsx # createRouter + Register declaration
│ └── routeTree.gen.ts # auto-generated — never edit manually
├── context/
│ ├── AuthContext.tsx # user state, login(), logout()
│ ├── SnackbarContext.tsx # showSuccess/Error/Warning/Info
│ └── ThemeContext.tsx # ThemeProvider + MUI + dayjs
├── store/
│ └── layout.store.ts # Zustand — sidebar open/close (persisted)
└── utils/
└── storage.ts # Type-safe localStorage + STORAGE_KEYScore/api/axios.config.ts
Single Axios instance. Attaches the Bearer token on every request; handles global 401 by clearing the token and redirecting to /login.
import axios from 'axios'
import { storage, STORAGE_KEYS } from '@/core/utils/storage'
const axiosInstance = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
timeout: 30000,
headers: { 'Content-Type': 'application/json' },
})
axiosInstance.interceptors.request.use((config) => {
const token = storage.get<string>(STORAGE_KEYS.ACCESS_TOKEN)
if (token) config.headers.Authorization = `Bearer ${token}`
return config
})
axiosInstance.interceptors.response.use(
(response) => response,
(error) => {
const isLoginRequest = error.config?.url?.includes('/auth/login')
const isOnLoginPage = window.location.pathname.includes('/login')
if (error.response?.status === 401 && !isLoginRequest && !isOnLoginPage) {
storage.remove(STORAGE_KEYS.ACCESS_TOKEN)
window.location.href = '/login'
}
return Promise.reject(error)
}
)
export default axiosInstanceAll feature services: import axiosInstance from '@/core/api/axios.config'
core/config/query-client.config.ts
import { QueryClient } from '@tanstack/react-query'
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000 * 60 * 5, // 5 min
gcTime: 1000 * 60 * 10, // 10 min
retry: 1,
refetchOnWindowFocus: false,
},
},
})core/router/index.tsx
Route tree generation config → see tanstack-router skill.
import { createRouter as createTanStackRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'
import { queryClient } from '@/core/config/query-client.config'
import type { RouterContext } from '@/routes/__root'
export function createRouter() {
return createTanStackRouter({
routeTree,
defaultPreload: 'intent',
scrollRestoration: true,
context: {
queryClient,
user: undefined,
} as RouterContext,
})
}
declare module '@tanstack/react-router' {
interface Register { router: ReturnType<typeof createRouter> }
}core/config/i18n.config.ts
Import as a side-effect in main.tsx — never import the default export unless you need the i18n instance.
import i18n from 'i18next'
import { initReactI18next } from 'react-i18next'
import LanguageDetector from 'i18next-browser-languagedetector'
import enTranslation from '@/locales/en.json'
i18n
.use(LanguageDetector)
.use(initReactI18next)
.init({
resources: { en: { translation: enTranslation } },
lng: 'en',
fallbackLng: 'en',
defaultNS: 'translation',
interpolation: { escapeValue: false },
detection: { order: ['localStorage', 'navigator'], caches: ['localStorage'] },
debug: import.meta.env.DEV,
})
export default i18nAdd languages by adding keys under resources and JSON files under src/locales/.
main.tsx — Provider Composition
Order matters — outer providers must not depend on inner ones.
import { StrictMode, Suspense } from 'react'
import { createRoot } from 'react-dom/client'
import { QueryClientProvider } from '@tanstack/react-query'
import { RouterProvider } from '@tanstack/react-router'
import { ThemeProvider } from '@/core/context/ThemeContext'
import { AuthProvider } from '@/core/context/AuthContext'
import { SnackbarProvider } from '@/core/context/SnackbarContext'
import { queryClient } from '@/core/config/query-client.config'
import { createRouter } from '@/core/router'
import '@/core/config/i18n.config' // side-effect — init i18next before first render
import './index.css'
const router = createRouter()
createRoot(document.getElementById('root')!).render(
<StrictMode>
<QueryClientProvider client={queryClient}> {/* outermost — loaders + AuthProvider need it */}
<ThemeProvider> {/* MUI theme always available */}
<AuthProvider> {/* inside Theme, outside Snackbar */}
<SnackbarProvider> {/* route components can call useSnackbar() */}
<Suspense fallback={null}>
<RouterProvider router={router} />
</Suspense>
</SnackbarProvider>
</AuthProvider>
</ThemeProvider>
</QueryClientProvider>
</StrictMode>,
)Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

