* feat: upgrade to svelte 5 & tailwind v4 + add navigation menu to ui package * feat: website navigation with nav menu from shadcn * chore: refactor navigation menu storybook * fix: responsiveness bug * chore: remove tailwind config file * chore: - remove carbon icons from repo - add Geist font family * refactor website --------- Co-authored-by: Rotimi Best <[email protected]>
12 KiB
Folder Structure Documentation
This document describes the folder structure for the apps/website project, specifically focusing on the src/lib directory organization.
Overview
The codebase follows a clear separation of concerns with three main categories:
- Components: Presentational UI components (dummy components)
- Features: Business logic and functional components
- Utils: Utility functions, constants, and shared types
Directory Structure
src/lib/
├── components/ # UI Components (Presentational)
│ ├── index.ts # Centralized exports - use this for imports
│ ├── blog-list-item.svelte
│ ├── core-feature-section.svelte
│ ├── core-features.svelte
│ ├── custom-img.svelte
│ ├── faq.svelte
│ ├── footer.svelte
│ ├── hero.svelte
│ ├── modal.svelte
│ ├── more-features.svelte
│ ├── navigation.svelte
│ ├── not-found.svelte
│ ├── page-header.svelte
│ ├── page-signup-cta.svelte
│ ├── senja-embed.svelte
│ ├── student-dashboard.svelte
│ ├── success.svelte
│ ├── testimonial.svelte
│ ├── timeline.svelte
│ ├── tools-header.svelte
│ └── upload-widget.svelte
│
├── features/ # Features (Business Logic)
│ ├── contact/
│ │ ├── feedback-form.svelte
│ │ └── help-form.svelte
│ └── tools/
│ ├── progress/
│ │ ├── avatar.svelte
│ │ ├── background.svelte
│ │ ├── download-button.svelte
│ │ ├── full-view.svelte
│ │ ├── mood.svelte
│ │ ├── report.svelte
│ │ └── store.ts
│ ├── stopwatch/
│ │ └── timer.svelte
│ └── tic-tac-toe/
│ ├── board.svelte
│ ├── board.ts
│ ├── store.ts
│ └── winning-line.svelte
│
├── utils/ # Utilities
│ ├── constants/
│ │ └── tools.ts
│ ├── posthog/
│ │ └── index.ts
│ ├── faqs.ts
│ ├── format-date.ts
│ ├── is-form-valid.ts
│ ├── submit-form.ts
│ └── types.ts
│
└── index.ts # Root index - re-exports from components
│
└── emojis/ # Assets (Static files)
├── crossed-fingers.svg
├── folder.svg
├── globe.svg
├── index.js
├── left-fist.svg
├── printer.svg
├── right-fist.svg
├── robot-arm.svg
├── team.svg
├── thumbs-up.svg
└── ...
Naming Conventions
Files and Folders
- Kebab-case: All file and folder names use kebab-case (e.g.,
blog-list-item.svelte,feedback-form.svelte) - Single-file folders: If a folder contains only one file, it should be flattened to a single file (e.g.,
Footer/Footer.svelte→components/footer.svelte)
Components
- Component files use
.svelteextension - Component names match their file names in kebab-case
- Example:
blog-list-item.svelteexports a component that can be imported asBlogListItem
Directory Purposes
/components - UI Components
Purpose: Presentational components with minimal or no business logic. These are "dummy" components that receive props and render UI.
Characteristics:
- No API calls or complex state management
- Primarily focused on rendering and styling
- May have simple local state for UI interactions (e.g., open/close modals)
- Reusable across different pages/features
Examples:
footer.svelte- Site footer componentnavigation.svelte- Site navigation barhero.svelte- Hero section componentmodal.svelte- Generic modal wrapper
Import Pattern:
// ✅ CORRECT - Use named imports from the index
import { Footer, Navigation, Hero } from '$lib/components';
// ❌ INCORRECT - Direct file imports are not allowed
// import Footer from '$lib/components/footer.svelte';
Note: All components must be imported using named imports from $lib/components. Direct file imports are not allowed.
/features - Features
Purpose: Components and modules that contain business logic, API calls, form handling, state management, or domain-specific functionality.
Characteristics:
- Contains business logic and data handling
- May include API calls, form submissions, or data transformations
- Often includes stores, utilities, or helper functions specific to the feature
- Organized by feature domain (e.g.,
contact/,tools/)
Examples:
features/contact/feedback-form.svelte- Form with submission logicfeatures/tools/progress/store.ts- State management for progress toolfeatures/tools/tic-tac-toe/board.ts- Game logic
Import Pattern:
import FeedbackForm from '$lib/features/contact/feedback-form.svelte';
import { htmlBody, openModal } from '$lib/features/tools/progress/store';
/utils - Utilities
Purpose: Shared utility functions, constants, types, and helper modules used across the application.
Characteristics:
- Pure functions or utility modules
- No component-specific logic
- Reusable across different features/components
- May include TypeScript types and interfaces
Examples:
utils/format-date.ts- Date formatting utilityutils/is-form-valid.ts- Form validation helperutils/submit-form.ts- Generic form submission utilityutils/types.ts- Shared TypeScript typesutils/constants/tools.ts- Application constants
Import Pattern:
import { formatDate } from '$lib/utils/format-date';
import { isFormValid } from '$lib/utils/is-form-valid';
import type { BlogPost } from '$lib/utils/types';
Migration from Old Structure
Old Structure (Before Refactoring)
src/lib/
├── Blog/BlogListItem.svelte
├── Contact/FeedbackForm.svelte, HelpForm.svelte, Sucess.svelte
├── Footer/Footer.svelte
├── Home/*.svelte, faqs.ts
├── Navigation/Navigation.svelte
├── Modal/Modal.svelte
├── PageHeader/PageHeader.svelte
├── PageSignupCTA/index.svelte
├── Senja/Embed.svelte
├── Timeline/Timeline.svelte
├── ToolsHeader/ToolsHeader.svelte
├── UploadWidget/UploadWidget.svelte
├── NotFound/NotFound.svelte
├── custom/img.svelte, index.ts
├── utils/*.ts
└── types.ts
Key Changes
-
Flattened single-file folders: Folders with only one file were flattened (e.g.,
Footer/Footer.svelte→components/footer.svelte) -
Kebab-case conversion: All PascalCase file names converted to kebab-case (e.g.,
BlogListItem.svelte→blog-list-item.svelte) -
Separation of concerns: Components split into
components/(UI) andfeatures/(logic) -
Routes components moved: Capitalized
components/folders fromroutes/tools/*/moved tofeatures/tools/*/ -
Types moved:
types.tsmoved toutils/types.ts -
Fixed typos:
Sucess.svelte→success.svelte -
Centralized component exports: Created
components/index.tsto export all components with PascalCase names -
Standardized imports: All component imports now use named imports from
$lib/componentsinstead of direct file imports
Import Examples
Components
<script>
// ✅ CORRECT - Named imports from centralized index
import { Footer, Navigation, Hero, Testimonial } from '$lib/components';
// ❌ INCORRECT - Direct file imports are not allowed
// import Footer from '$lib/components/footer.svelte';
</script>
Important: All components are exported from components/index.ts with PascalCase names. Always use named imports from $lib/components.
Features
<script>
import FeedbackForm from '$lib/features/contact/feedback-form.svelte';
import { htmlBody, openModal } from '$lib/features/tools/progress/store';
import Board from '$lib/features/tools/tic-tac-toe/board.svelte';
</script>
Utils
<script>
import { formatDate } from '$lib/utils/format-date';
import { isFormValid } from '$lib/utils/is-form-valid';
import { submitForm } from '$lib/utils/submit-form';
import type { BlogPost } from '$lib/utils/types';
import { tools } from '$lib/utils/constants/tools';
</script>
Best Practices
-
When to create a component vs feature:
- Component: If it's purely presentational and reusable
- Feature: If it contains business logic, API calls, or domain-specific functionality
-
File naming:
- Always use kebab-case for file and folder names
- Match component file names with their import names (converted to PascalCase in imports)
-
Component imports:
- Always import components using named imports from
$lib/components - Never import directly from component files (e.g.,
$lib/components/footer.svelte) - All components are exported from
components/index.tswith PascalCase names - Example:
import { Footer, Navigation } from '$lib/components'
- Always import components using named imports from
-
Folder organization:
- Group related features in subfolders (e.g.,
features/contact/,features/tools/progress/) - Keep utility functions organized by purpose in
utils/
- Group related features in subfolders (e.g.,
-
Avoid single-file folders:
- If a folder contains only one file, flatten it to a single file
- Example:
Footer/Footer.svelte→components/footer.svelte
-
Type definitions:
- Shared types go in
utils/types.ts - Feature-specific types can be co-located with the feature
- Shared types go in
-
Adding new components:
- Add the component file in kebab-case (e.g.,
new-component.svelte) - Export it from
components/index.tswith PascalCase name (e.g.,NewComponent) - Import using:
import { NewComponent } from '$lib/components'
- Add the component file in kebab-case (e.g.,
Routes Structure
Routes that previously had capitalized components/ folders have been refactored:
Before:
routes/tools/progress/components/Avatar.svelte
routes/tools/stopwatch/components/Timer.svelte
routes/tools/tic-tac-toe/components/Board.svelte
After:
lib/features/tools/progress/avatar.svelte
lib/features/tools/stopwatch/timer.svelte
lib/features/tools/tic-tac-toe/board.svelte
Routes now import from $lib/features/tools/*/ instead of ./components/.
Assets
Static assets like images, SVGs, and other media files remain in their respective locations:
emojis/- Emoji SVG filespublic/- Public static assets (images, fonts, etc.)
Component Index File
All components are exported from components/index.ts with PascalCase names:
// components/index.ts
export { default as BlogListItem } from './blog-list-item.svelte';
export { default as Footer } from './footer.svelte';
export { default as Navigation } from './navigation.svelte';
// ... etc
This allows for clean, consistent imports:
import { Footer, Navigation, Hero } from '$lib/components';
Rule: Direct file imports (e.g., import Footer from '$lib/components/footer.svelte') are not allowed. Always use named imports from $lib/components.
Summary
This structure provides:
- ✅ Clear separation between UI and business logic
- ✅ Consistent naming conventions (kebab-case)
- ✅ Flattened structure (no unnecessary single-file folders)
- ✅ Centralized component exports via
index.ts - ✅ Standardized import pattern (named imports from
$lib/components) - ✅ Easy to navigate and maintain
- ✅ Scalable for future growth
For questions or suggestions about this structure, please refer to the project maintainers.