This guide outlines the code style and standards expected for all GitFolio contributions.
General Principles
All code contributions should follow these core principles:
Consistency - Follow existing patterns in the codebase
Readability - Write code that’s easy to understand
Maintainability - Keep code modular and well-organized
Quality - Test thoroughly and handle edge cases
Accessibility - Ensure templates are usable by everyone
TypeScript Standards
All template files must be written in TypeScript. JavaScript is not accepted for new contributions.
Type Safety
Always use proper TypeScript types:
import { DATA } from "@workspace/types" ;
import { FC } from "react" ;
interface TemplateProps {
data : DATA ;
}
const Template : FC < TemplateProps > = ({ data }) => {
return < div > { data . name } </ div > ;
};
// Avoid using 'any'
const Template = ({ data } : any ) => {
return < div > { data . name } </ div > ;
};
Type Imports
Use the shared types package for data structures:
import { DATA } from "@workspace/types" ;
import { useTheme } from "next-themes" ;
Interface vs Type
Use interface for component props and object shapes
Use type for unions, intersections, and utility types
// Component props - use interface
interface HeaderProps {
title : string ;
subtitle ?: string ;
}
// Union types - use type
type Theme = "light" | "dark" | "system" ;
React Component Patterns
Functional Components
Always use functional components with hooks:
import React , { FC } from "react" ;
import { DATA } from "@workspace/types" ;
import { useTheme } from "next-themes" ;
interface TemplateProps {
data ?: DATA ;
}
const Template : FC < TemplateProps > = ({ data = DummyData }) => {
const { setTheme } = useTheme ();
React . useEffect (() => {
setTheme ( "dark" );
}, []);
return (
< div className = "container" >
{ /* Template content */ }
</ div >
);
};
export default Template ;
Component Organization
Structure components logically:
Imports - External dependencies first, then internal
Type definitions - Interfaces and types
Component definition - Main component logic
Exports - Default and named exports
// 1. Imports
import React , { FC , useState } from "react" ;
import { DATA } from "@workspace/types" ;
import { Header } from "./components/Header" ;
// 2. Type definitions
interface TemplateProps {
data : DATA ;
}
// 3. Component
const Template : FC < TemplateProps > = ({ data }) => {
const [ isOpen , setIsOpen ] = useState ( false );
return < div > ... </ div > ;
};
// 4. Exports
export default Template ;
Component Composition
Keep components small and focused:
// Small, focused components
const Header : FC < HeaderProps > = ({ title }) => (
< header > { title } </ header >
);
const Footer : FC < FooterProps > = ({ links }) => (
< footer > { links . map ( link => ... ) } </ footer >
);
const Template : FC < TemplateProps > = ({ data }) => (
< div >
< Header title = { data . name } />
< main > { /* content */ } </ main >
< Footer links = { data . links } />
</ div >
);
// Monolithic component with everything
const Template = ({ data }) => (
< div >
< header >
{ /* 100 lines of header code */ }
</ header >
< main >
{ /* 200 lines of main content */ }
</ main >
< footer >
{ /* 100 lines of footer code */ }
</ footer >
</ div >
);
Styling with Tailwind CSS
All styling must use Tailwind CSS for consistency across templates.
Tailwind Best Practices
// Use Tailwind utility classes
< div className = "container mx-auto px-4 py-8" >
< h1 className = "text-4xl font-bold text-gray-900 dark:text-white" >
{ title }
</ h1 >
</ div >
// Avoid inline styles
< div style = { { margin: '0 auto' , padding: '2rem' } } >
< h1 style = { { fontSize: '2.25rem' , fontWeight: 'bold' } } >
{ title }
</ h1 >
</ div >
Responsive Design
Always implement responsive designs:
< div className = "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4" >
{ projects . map ( project => (
< ProjectCard key = { project . id } { ... project } />
)) }
</ div >
Use Tailwind breakpoints:
sm: - 640px and up
md: - 768px and up
lg: - 1024px and up
xl: - 1280px and up
2xl: - 1536px and up
Dark Mode Support
Implement dark mode using next-themes:
import { useTheme } from "next-themes" ;
const Template : FC < TemplateProps > = ({ data }) => {
const { setTheme } = useTheme ();
React . useEffect (() => {
setTheme ( "dark" ); // Set default theme
}, []);
return (
< div className = "bg-white dark:bg-gray-900 text-gray-900 dark:text-white" >
{ /* Content */ }
</ div >
);
};
Accessibility Standards
All templates must follow accessibility best practices:
Semantic HTML
< header >
< nav aria-label = "Main navigation" >
< ul >
< li >< a href = "#about" > About </ a ></ li >
< li >< a href = "#projects" > Projects </ a ></ li >
</ ul >
</ nav >
</ header >
< main >
< section aria-labelledby = "about-heading" >
< h2 id = "about-heading" > About Me </ h2 >
</ section >
</ main >
< div >
< div >
< div onClick = { () => navigate ( '/about' ) } > About </ div >
< div onClick = { () => navigate ( '/projects' ) } > Projects </ div >
</ div >
</ div >
Keyboard Navigation
Ensure all interactive elements are keyboard accessible:
// Buttons should be actual button elements
< button
onClick = { handleClick }
aria-label = "Close menu"
className = "focus:outline-none focus:ring-2 focus:ring-blue-500"
>
Close
</ button >
// Links should be actual anchor elements
< a
href = { project . url }
target = "_blank"
rel = "noopener noreferrer"
className = "focus:outline-none focus:ring-2 focus:ring-blue-500"
>
View Project
</ a >
ARIA Labels
Use ARIA attributes when needed:
< button
aria-label = "Toggle dark mode"
aria-pressed = { isDark }
onClick = { toggleTheme }
>
< Icon name = { isDark ? "sun" : "moon" } aria-hidden = "true" />
</ button >
Alt Text for Images
< img
src = { data . avatar }
alt = { ` ${ data . name } 's profile picture` }
className = "rounded-full"
/>
File Organization
Template Structure
Templates/
└── YourTemplate/
├── components/
│ ├── Header.tsx
│ ├── About.tsx
│ ├── Projects.tsx
│ └── Footer.tsx
└── template.tsx
Component Files
Each component should:
Have a single responsibility
Be in its own file
Export as a named or default export
Include proper TypeScript types
GitFolio uses Prettier for automatic code formatting. Run pnpm run format before committing.
Prettier Configuration
The project uses standard Prettier settings. Code is automatically formatted on commit.
# Format all files
pnpm run format
# Check formatting
pnpm run lint
Testing Requirements
Before submitting your contribution:
Visual Testing
Test your template on multiple screen sizes:
Mobile (375px, 414px)
Tablet (768px, 1024px)
Desktop (1280px, 1920px)
Browser Testing
Test in modern browsers:
Chrome/Edge
Firefox
Safari
Dark Mode Testing
Verify your template works in both light and dark modes.
Accessibility Testing
Navigate using only keyboard
Test with screen reader
Check color contrast ratios
Build Testing
Ensure your template builds without errors: pnpm run build --filter=renderer
Use conventional commit format:
feat: add new portfolio template
fix: resolve responsive layout issue
docs: update contribution guidelines
style: format code with prettier
refactor: simplify component structure
test : add unit tests for components
Commit message structure:
Type : feat, fix, docs, style, refactor, test, chore
Scope (optional): Area of change
Description : Clear, concise description
Common Mistakes to Avoid
Avoid using any type. Use proper TypeScript types or unknown if type is truly dynamic. // Bad
const handleData = ( data : any ) => { ... }
// Good
const handleData = ( data : DATA ) => { ... }
Use data from props instead of hardcoded values. // Bad
< h1 > John Doe </ h1 >
// Good
< h1 > { data . name } </ h1 >
Missing Responsive Design
Always implement responsive breakpoints. // Bad
< div className = "w-1/3" >
// Good
< div className = "w-full md:w-1/2 lg:w-1/3" >
Use semantic HTML and proper ARIA attributes. // Bad
< div onClick = { handleClick } > Click me </ div >
// Good
< button onClick = { handleClick } aria-label = "Submit form" > Click me </ button >
Resources
Questions?
If you have questions about code standards, check our FAQ or reach out for support .