Thank you for your interest in contributing to TribeGuess! This project aims to celebrate and preserve African cultural diversity, and we welcome contributions from everyone.
- Code of Conduct
- How Can I Contribute?
- Data Entry Guidelines
- Translation Guidelines
- Code Contribution Guidelines
- Pull Request Process
- Style Guide
We are committed to making participation in this project a respectful, harassment-free experience for everyone. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
Given the nature of this project, we ask all contributors to:
- β Respect all African cultures and traditions equally
- β Avoid stereotypes that could be offensive or harmful
- β Use verified, factual information from reputable sources
- β Present cultural practices in their proper context
- β Acknowledge the diversity within ethnic groups
- β Never use derogatory language about any ethnic group
- β Avoid generalizations that erase individual experiences
Add or improve tribe, recipe, religion, or language data.
Help translate the UI into African languages.
Fix bugs, add features, or improve performance.
Write blog articles about African cultures.
Contribute properly licensed cultural images.
Verify existing data against authoritative sources.
Report issues you find while using the app.
Tribes are stored in src/data/tribes.json. Each tribe entry should follow this structure:
{
"id": "tribe-name-lowercase",
"name": "Tribe Name",
"alternateNames": ["Alternative Name 1", "Alternative Name 2"],
"countries": ["Country1", "Country2"],
"region": "Specific Region",
"macroRegion": "East Africa | West Africa | Central Africa | Southern Africa | North Africa | Horn of Africa",
"population": "~X million",
"language": "Primary Language",
"languageFamily": "Bantu | Nilotic | Cushitic | Semitic | etc.",
"description": "2-3 sentence overview of the tribe.",
"stereotype": "Common perceptions (presented respectfully)",
"greeting": "Hello in their language",
"greetingPhonetic": "[pho-NE-tic GUIDE]",
"greetingMeaning": "English translation",
"famousPeople": [
{
"name": "Person Name",
"role": "Their role/profession",
"description": "Brief bio"
}
],
"names": [
{
"name": "Example Name",
"meaning": "Name meaning",
"gender": "male | female | unisex"
}
],
"eatingCustoms": {
"mealsPerDay": "Number and pattern",
"mealPattern": "Description of eating habits",
"communalEating": "How meals are shared",
"foodTaboos": ["Taboo 1", "Taboo 2"],
"hospitalityCustoms": "How guests are treated"
},
"tradeRelations": {
"historical": "Pre-colonial trade description",
"modern": "Current economic activities",
"partners": ["Trade partner 1", "Trade partner 2"]
},
"independenceHistory": {
"colonialPower": "Colonial ruler",
"resistance": "How they resisted colonialism",
"independence": "Post-independence status",
"notableEvents": ["Event 1", "Event 2"]
},
"religiousHistory": {
"traditional": "Indigenous beliefs",
"islamIntroduction": "When/how Islam arrived (if applicable)",
"christianityIntroduction": "When/how Christianity arrived (if applicable)",
"currentPractice": "Modern religious landscape"
},
"territoryLat": -1.2345,
"territoryLng": 36.7890,
"territorySpan": 1.5,
"cultureVideoId": "YouTube_Video_ID",
"languageVideoId": "YouTube_Video_ID"
}id,name,countries,region,macroRegion,population,language,languageFamily,description
- Population is from Ethnologue or Joshua Project (within last 5 years)
- Description is factual, not stereotypical
- Name meanings are verified against cultural sources
- YouTube videos are from reputable cultural channels
- Territory coordinates are accurate (verified on map)
Recipes are stored in src/data/recipes.ts. Follow this structure:
{
id: "recipe-slug",
name: "Recipe Name",
localName: "Name in Local Language",
tribe: "Associated Tribe",
tribeSlug: "tribe-slug",
description: "Brief description of the dish",
difficulty: "easy" | "medium" | "hard",
category: "Staple" | "Special" | "Beverage" | "Snack",
prepTime: "15 minutes",
cookTime: "30 minutes",
servings: 4,
ingredients: [
{ item: "Ingredient", amount: "2 cups", notes: "optional notes" }
],
instructions: [
"Step 1 instructions",
"Step 2 instructions"
],
history: "Cultural/historical context of the dish",
videoId: "YouTube_Video_ID",
imageUrl: "/recipes/image.jpg"
}Religions are stored in src/data/traditionalReligions.ts. Include:
- Name and alternate names
- Region/countries where practiced
- Core beliefs and tenets
- Key rituals and ceremonies
- Associated tribes
- Estimated followers
- Historical context
Language families are in src/data/languageFamilies.json. For new phrases:
{
"phrase": "Hello",
"translation": "Local translation",
"pronunciation": "/pho-ne-tic/",
"audioHint": "Notes for TTS engine"
}We're actively seeking translations for:
- π«π· French - Widely spoken in West/Central Africa
- π°πͺ Swahili - East African lingua franca
- πΈπ¦ Arabic - North Africa
- π΅πΉ Portuguese - Lusophone Africa
- πΏπ¦ Zulu/Xhosa - Southern Africa
| File | Content |
|---|---|
src/components/Header.tsx |
Navigation labels |
src/components/Footer.tsx |
Footer links |
src/pages/Index.tsx |
Home page text |
src/components/GuessForm.tsx |
Form labels and placeholders |
Create a new file: src/locales/{language-code}.json
{
"nav.guess": "Guess",
"nav.learn": "Learn",
"nav.blog": "Blog",
"nav.randomTribe": "Random Tribe",
"home.title": "Guess Her Tribe",
"home.subtitle": "Enter a name to discover the tribe...",
"form.name": "Name",
"form.country": "Country",
"form.submit": "Guess the Tribe"
}- β Use natural, colloquial language (not literal translations)
- β Maintain cultural context
- β Test that translated strings fit in the UI
- β Have a native speaker review translations
# Fork and clone the repository
git clone https://github.com/YOUR_USERNAME/tribeguess.git
cd tribeguess
# Install dependencies
npm install
# Start development server
npm run dev
# Run type checking
npm run typecheck
# Build for production
npm run build| Type | Format | Example |
|---|---|---|
| Feature | feature/description |
feature/add-swahili-translation |
| Bug Fix | fix/description |
fix/recipe-link-broken |
| Data | data/description |
data/add-maasai-recipes |
| Docs | docs/description |
docs/update-readme |
Use conventional commits:
feat: add Yoruba language phrases
fix: correct Kikuyu population data
docs: update contributing guidelines
data: add 5 new Nigerian tribes
style: improve mobile navigation
refactor: extract tribe card component
Before submitting:
- Code compiles without errors (
npm run build) - No TypeScript errors (
npm run typecheck) - UI is responsive (test on mobile viewport)
- New features work in both light and dark mode
- Console has no errors or warnings
- Changes are documented in code comments
- Run regression tests (see
src/__tests__/REGRESSION_TESTS.md) - Test key user flows:
- Name search works correctly
- Filters update URL and results
- Links navigate properly
- Audio plays without errors
- Check mobile responsiveness
- β Read the Style Guide
- β Complete the relevant checklist above
- β Test your changes thoroughly
- β Update documentation if needed
When creating a PR, include:
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Data addition/update
- [ ] Translation
- [ ] Documentation
## Checklist
- [ ] Code compiles without errors
- [ ] Changes tested on mobile
- [ ] Data verified against sources
- [ ] No console errors
## Screenshots (if applicable)
Add screenshots of UI changes
## Data Sources (if applicable)
List sources for any new data- Submit PR to
mainbranch - Maintainers review within 48-72 hours
- Address any feedback
- Once approved, PR is merged
// Use functional components with TypeScript
interface TribeCardProps {
tribe: Tribe;
onClick?: () => void;
}
export function TribeCard({ tribe, onClick }: TribeCardProps) {
return (
<div className="card" onClick={onClick}>
{/* Content */}
</div>
);
}- Use semantic color tokens:
bg-primary,text-foreground,border-border - Avoid arbitrary values when possible
- Use responsive prefixes:
sm:,md:,lg: - Group related classes logically
// β
Good
<div className="flex items-center gap-4 p-4 bg-card rounded-lg border">
// β Avoid
<div className="flex items-center gap-[17px] p-[15px] bg-[#fff] rounded-[8px]">- Use sentence case for descriptions
- Population:
~X millionor~X,000 - Dates:
YYYYorXth century - Coordinates: Decimal degrees (4 decimal places)
src/
βββ components/ # Reusable UI components
βββ pages/ # Route-level components
βββ data/ # Static data files
βββ hooks/ # Custom React hooks
βββ lib/ # Utility functions
βββ assets/ # Images, fonts
- π¬ Open a GitHub Discussion
- π File an Issue for bugs
- π§ Contact maintainers
Thank you for helping preserve African cultural heritage! π