Why naming conventions matter
A project with inconsistent names becomes chaos as it scales. In a 5-dev React team, if one uses button.jsx, another Button.js, and another ButtonComponent.tsx, wasting time searching for files becomes a daily ritual.
Conventions solve this at the root. React expects PascalCase because each component is technically a class or constructor function. Vue allows both styles but the community prefers PascalCase for SFCs since Vue 3. Angular enforces kebab-case with mandatory suffixes (.component.ts) because the CLI has generated it this way since 2016.
Common mistakes: mixing camelCase with kebab-case in the same project, forgetting suffixes in Angular, using .js when the project is pure TypeScript, or naming everything index.tsx (impossible to debug stack traces). Golden rule: a human should be able to guess the framework just by looking at the filename.
File structure by framework
React doesn't dictate structure, but the winning practice is /components/Button/Button.tsx + Button.module.css + Button.test.tsx in the same folder. Flat alternative: /components/Button.tsx for small projects.
Angular follows feature/button/button.component.ts + .html + .css + .spec.ts separated. Never mix logic from different features in the same folder. Vue 3 prefers /components/TheButton.vue (single SFC) with the 'The' prefix for singleton components like TheHeader.
Next.js complicates things: /pages uses automatic kebab-case (about-us.tsx → /about-us), but /components can be PascalCase. Svelte recommends PascalCase though the compiler accepts anything. Web Components require kebab-case with hyphen (custom-button.js) by HTML specification.
Suffixes and prefixes that communicate function
Suffixes clarify responsibilities without opening the file. .container.tsx indicates logic + state, .view.tsx only presentation. .controller.ts in Stimulus must end with 'Controller' mandatory. .page.tsx in Next.js 13+ goes in /app with Server Components by default.
Prefixes work too: BaseButton.vue for design system base components, AppHeader.tsx for app-specific components (not reusable), TheSidebar.vue for guaranteed singletons. Stripe uses StripeButton in their SDK to avoid name collisions.
In mobile, Flutter requires _widget.dart with underscore for privates, React Native uses .native.tsx vs .web.tsx for platform-specific code, SwiftUI adopts View as mandatory suffix (ButtonView.swift). Don't invent conventions: follow the ecosystem's or your team will hate code review.
Automation and linters
ESLint with eslint-plugin-filename-rules enforces conventions: rejects commits if ButtonComponent.tsx doesn't match /^[A-Z][a-zA-Z]+\.tsx$/. Angular CLI generates everything correctly from the start with ng generate component. Vue CLI does the same with vue create component.
Prettier doesn't touch filenames, you need a pre-commit hook. Husky + lint-staged can run a custom script that validates against your convention. Example: if your repo is pure React, any .jsx should be .tsx or CI explodes.
Tools like plop.js generate components from templates: run plop component Button and it creates Button/index.ts + Button.tsx + Button.test.tsx with correct imports. Nx workspace in monorepos enforces structure with predefined generators. Result: zero inconsistencies, junior onboarding in 1 day instead of 2 weeks.