Naming Conventions
Grit enforces consistent naming conventions across the entire stack. When you generate a resource, the CLI automatically converts your resource name into the correct case for each context -- PascalCase for Go structs, snake_case for database columns, kebab-case for TypeScript files, and more.
Complete Naming Table
This table shows the naming convention used for every context in a Grit project. The code generator handles all conversions automatically.
| Context | Convention | Example |
|---|---|---|
| Go file name | snake_case.go | blog_post.go |
| Go struct | PascalCase | BlogPost |
| Go struct fields | PascalCase | PublishDate |
| Go handler struct | PascalCaseHandler | BlogPostHandler |
| Go handler variable | camelCaseHandler | blogPostHandler |
| Go service struct | PascalCaseService | BlogPostService |
| JSON field | snake_case | publish_date |
| Database table | plural_snake_case | blog_posts |
| Database column | snake_case | publish_date |
| API route | /api/plural_snake | /api/blog_posts |
| TypeScript file | kebab-case.ts | blog-post.ts |
| TypeScript interface | PascalCase | BlogPost |
| React Query hook file | use-plural-kebab.ts | use-blog-posts.ts |
| React Query hook name | usePluralPascal | useBlogPosts |
| Zod schema | CreatePascalSchema | CreateBlogPostSchema |
| Resource slug | plural-kebab-case | blog-posts |
| Resource variable | camelCaseResource | blogPostResource |
| Admin page route | /resources/plural-kebab | /resources/blog-posts |
| API route constant | PLURAL_UPPER | BLOG_POSTS |
How the Generator Handles Names
The generator builds a Names struct with all naming variants from your resource name. You can provide the name in PascalCase, snake_case, or kebab-case -- the generator normalizes it to PascalCase first, then derives all other forms.
type Names struct {
Pascal string // BlogPost
Camel string // blogPost
Snake string // blog_post
Kebab string // blog-post
Lower string // blogpost
Plural string // blog_posts
PluralPascal string // BlogPosts
PluralSnake string // blog_posts
PluralKebab string // blog-posts
}Conversion Flow
Input normalization
The raw input is converted to PascalCase. Input "blog_post", "blog-post", or "BlogPost" all become "BlogPost".
Snake case derivation
PascalCase is split at uppercase boundaries. "BlogPost" becomes "blog_post". This is used for file names, JSON fields, and DB columns.
Kebab case derivation
Snake case with underscores replaced by hyphens. "blog_post" becomes "blog-post". Used for TypeScript files and resource slugs.
Camel case derivation
PascalCase with the first letter lowered. "BlogPost" becomes "blogPost". Used for handler variables and resource definitions.
Pluralization
The snake_case form is pluralized using English rules. "blog_post" becomes "blog_posts". This is used for API routes, table names, and hook names.
Full Name Derivation Examples
Here are complete examples showing how a resource name maps to every file and identifier in the project:
Example: "Post"
| Usage | Value |
|---|---|
| Go model file | models/post.go |
| Go struct | type Post struct |
| Go handler | PostHandler / postHandler |
| DB table | posts |
| API routes | /api/posts, /api/posts/:id |
| TS type file | types/post.ts |
| Zod schema file | schemas/post.ts |
| React hooks | use-posts.ts / usePosts() |
| Admin page | /resources/posts/page.tsx |
| Resource definition | resources/posts.ts / postResource |
Example: "BlogPost"
| Usage | Value |
|---|---|
| Go model file | models/blog_post.go |
| Go struct | type BlogPost struct |
| Go handler | BlogPostHandler / blogPostHandler |
| DB table | blog_posts |
| API routes | /api/blog_posts, /api/blog_posts/:id |
| TS type file | types/blog-post.ts |
| Zod schema file | schemas/blog-post.ts |
| React hooks | use-blog-posts.ts / useBlogPosts() |
| Admin page | /resources/blog-posts/page.tsx |
| Resource definition | resources/blog-posts.ts / blogPostResource |
Example: "Category"
| Usage | Value |
|---|---|
| Go model file | models/category.go |
| Go struct | type Category struct |
| DB table | categories |
| API routes | /api/categories, /api/categories/:id |
| React hooks | use-categories.ts / useCategories() |
| Admin page | /resources/categories/page.tsx |
Notice how "Category" correctly pluralizes to "categories" (y preceded by a consonant becomes -ies).
Pluralization Rules
The Grit CLI includes a built-in English pluralization engine that handles regular and irregular forms. Pluralization is applied to the snake_case form of the resource name.
Regular Rules
| Rule | Singular | Plural |
|---|---|---|
| Default: add -s | post | posts |
| Ends in -y (consonant before): -ies | category | categories |
| Ends in -y (vowel before): -ys | key | keys |
| Ends in -s, -ss, -sh, -ch, -x, -z: -es | address | addresses |
| Ends in -f or -fe: -ves | leaf | leaves |
Irregular Plurals
The generator handles these irregular English plurals:
| Singular | Plural |
|---|---|
| person | people |
| child | children |
| mouse | mice |
| goose | geese |
| man | men |
| woman | women |
| tooth | teeth |
| foot | feet |
| ox | oxen |
| datum | data |
| medium | media |
| index | indices |
| matrix | matrices |
| vertex | vertices |
| crisis | crises |
| axis | axes |
| analysis | analyses |
Automatic Icon Selection
When generating an admin resource definition, the CLI automatically picks a Lucide icon based on the resource name. It matches the lowercase resource name against a dictionary of common domain terms. If no match is found, it defaults to the Database icon.
| Resource Name Contains | Lucide Icon |
|---|---|
| post, page, document | FileText |
| article, blog | Newspaper |
| comment | MessageSquare |
| category | FolderTree |
| tag | Tag |
| product | Package |
| order | ShoppingCart |
| invoice | Receipt |
| payment, subscription | CreditCard |
| customer | UserCircle |
| user | Users |
| project | Briefcase |
| task | CheckSquare |
| event | Calendar |
| file | File |
| image, media | Image |
| message, email | |
| notification | Bell |
| setting | Settings |
| role | Shield |
| permission | Lock |
| team | UsersRound |
| company, organization | Building2 |
| report | BarChart3 |
| analytic | TrendingUp |
| log | ScrollText |
| review | Star |
| plan | Gem |
| coupon | Ticket |
| discount | Percent |
| shipping | Truck |
| address, location | MapPin |
| contact | Contact |
| lead | Target |
| deal | Handshake |
| pipeline | GitBranch |
| workflow | Workflow |
| template | LayoutTemplate |
| campaign | Megaphone |
| survey | ClipboardList |
| form | FormInput |
| question | HelpCircle |
| answer | MessageCircle |
| ticket, issue | Ticket / AlertCircle |
| bug | Bug |
| feature | Sparkles |
| release | Rocket |
| version | GitCommit |
| deploy | CloudUpload |
The matching is substring-based. A resource named "ProductCategory" would match "product" first and get the Package icon. You can always change the icon in the generated resource definition file.
File Naming Summary
Different ecosystems use different naming conventions for files. Grit follows the idiomatic convention for each language:
Go files: snake_case
All Go source files use snake_case. This is the idiomatic Go convention. Examples: user_handler.go,blog_post.go,auth.go
TypeScript utility files: kebab-case
Non-component TypeScript files use kebab-case. This matches Next.js and modern TypeScript conventions. Examples: api-client.ts,use-posts.ts,blog-post.ts
React components: PascalCase
React component files use PascalCase to match the component name inside. Examples: DataTable.tsx,StatsCard.tsx,AdminLayout.tsx
Next.js pages: lowercase
Next.js App Router requires directory names to be lowercase (since they map to URL paths). Examples: app/resources/posts/page.tsx,app/(auth)/login/page.tsx
Column Label Generation
When the generator creates admin DataTable columns and form fields, it converts field names to human-readable labels by splitting PascalCase into separate words.
| Field Name | PascalCase | Generated Label |
|---|---|---|
| title | Title | Title |
| due_date | DueDate | Due Date |
| is_published | IsPublished | Is Published |
| author_id | AuthorId | Author Id |
| total_amount | TotalAmount | Total Amount |
The label splitting algorithm finds uppercase letter boundaries in PascalCase and inserts spaces. You can always customize labels in the generated resource definition file after generation.