Naming Conventions
TGraph Backend Generator follows consistent naming patterns across backend and frontend code generation.
Overview
All generation scripts use shared naming utilities to ensure consistency between your Prisma models, API endpoints, and dashboard resources.
Model Naming
Prisma Model
Use PascalCase for model names:
// Good
model CustomFieldType { }
model BlogPost { }
model UserProfile { }
// Avoid
model custom_field_type { }
model blogpost { }
Backend Naming
API Endpoints
REST endpoints use kebab-case-plural:
| Model | Endpoint |
|---|---|
User | /tg-api/users |
BlogPost | /tg-api/blog-posts |
CustomFieldType | /tg-api/custom-field-types |
Example:
@Controller('tg-api/custom-field-types')
export class CustomFieldTypeTgController {}
File Names
TypeScript files use camelCase with .tg. suffix:
| Model | Controller | Service |
|---|---|---|
User | user.tg.controller.ts | user.tg.service.ts |
BlogPost | blogPost.tg.controller.ts | blogPost.tg.service.ts |
CustomFieldType | customFieldType.tg.controller.ts | customFieldType.tg.service.ts |
DTO Files:
| Model | Create DTO | Update DTO |
|---|---|---|
User | create-user.tg.dto.ts | update-user.tg.dto.ts |
BlogPost | create-blog-post.tg.dto.ts | update-blog-post.tg.dto.ts |
Class Names
Classes use PascalCase with suffix:
// Model: User
export class CreateUserTgDto {}
export class UpdateUserTgDto {}
export class UserTgService {}
export class UserTgController {}
// Model: BlogPost
export class CreateBlogPostTgDto {}
export class UpdateBlogPostTgDto {}
export class BlogPostTgService {}
export class BlogPostTgController {}
The suffix (default Tg) is configurable via the suffix option.
Module Folders
Modules use kebab-case:
src/features/
├── user/
├── blog-post/
└── custom-field-type/
Frontend Naming
Resource Names
React Admin resources use kebab-case-plural (matching API endpoints):
<Resource
name="custom-field-types"
list={CustomFieldTypeList}
edit={CustomFieldTypeEdit}
create={CustomFieldTypeCreate}
show={CustomFieldTypeShow}
/>
Resource Folders
Dashboard folders match resource names:
src/dashboard/src/resources/
├── users/
├── blog-posts/
└── custom-field-types/
Component Files
Component files use PascalCase:
| Model | List | Edit | Create | Show |
|---|---|---|---|---|
User | UserList.tsx | UserEdit.tsx | UserCreate.tsx | UserShow.tsx |
BlogPost | BlogPostList.tsx | BlogPostEdit.tsx | BlogPostCreate.tsx | BlogPostShow.tsx |
Component Names
Component names use PascalCase:
// Model: User
export const UserList = () => {};
export const UserEdit = () => {};
// Model: BlogPost
export const BlogPostList = () => {};
export const BlogPostEdit = () => {};
Data Provider Mapping
The data provider maps resources to endpoints:
const endpointMap: Record<string, string> = {
users: 'tg-api/users',
'blog-posts': 'tg-api/blog-posts',
'custom-field-types': 'tg-api/custom-field-types',
// Custom endpoints can still be added manually
'feature-flags': 'admin/feature-flags',
};
Note: Resource names and endpoint paths must match for automatic mapping.
Complete Example
Prisma Model
// @tg_form()
model CustomFieldType {
id String @id @default(uuid())
name String
}
Generated Backend
Files:
src/features/custom-field-type/
├── create-custom-field-type.tg.dto.ts
├── update-custom-field-type.tg.dto.ts
├── custom-field-type.tg.service.ts
└── custom-field-type.tg.controller.ts
Controller:
@Controller('tg-api/custom-field-types')
export class CustomFieldTypeTgController {}
Classes:
export class CreateCustomFieldTypeTgDto {}
export class UpdateCustomFieldTypeTgDto {}
export class CustomFieldTypeTgService {}
export class CustomFieldTypeTgController {}
Generated Frontend
Folder:
src/dashboard/src/resources/custom-field-types/
├── CustomFieldTypeList.tsx
├── CustomFieldTypeEdit.tsx
├── CustomFieldTypeCreate.tsx
├── CustomFieldTypeShow.tsx
├── CustomFieldTypeStudio.tsx
└── index.ts
Resource:
<Resource
name="custom-field-types"
list={CustomFieldTypeList}
edit={CustomFieldTypeEdit}
create={CustomFieldTypeCreate}
show={CustomFieldTypeShow}
/>
Route:
<Route path="custom-field-types/studio" element={<CustomFieldTypeStudio />} />
Data Provider:
endpointMap['custom-field-types'] = 'tg-api/custom-field-types';
Naming Utilities
All naming transformations use these utilities from src/scripts/naming-utils.ts:
getApiEndpoint(modelName)
Returns the API endpoint path:
getApiEndpoint('User'); // 'tg-api/users'
getApiEndpoint('BlogPost'); // 'tg-api/blog-posts'
getApiEndpoint('CustomFieldType'); // 'tg-api/custom-field-types'
getResourceName(modelName)
Returns the frontend resource name:
getResourceName('User'); // 'users'
getResourceName('BlogPost'); // 'blog-posts'
getResourceName('CustomFieldType'); // 'custom-field-types'
toKebabCase(str)
Converts PascalCase to kebab-case:
toKebabCase('User'); // 'user'
toKebabCase('BlogPost'); // 'blog-post'
toKebabCase('CustomFieldType'); // 'custom-field-type'
pluralize(str)
Simple English pluralization:
pluralize('user'); // 'users'
pluralize('post'); // 'posts'
pluralize('category'); // 'categories'
Customization
Custom Suffix
Override the default Tg suffix:
// tgraph.config.ts
export const config: Config = {
// ...
suffix: 'Admin',
};
Generates:
CreateUserAdminDtoUserAdminServiceUserAdminController
Custom Endpoint Prefix
The tg-api prefix is currently hardcoded but can be customized by forking the generator templates.
Migration Guide
If you’re updating from older versions with inconsistent naming:
Step 1: Backup Your Code
git add -A
git commit -m "Backup before naming migration"
Step 2: Regenerate
tgraph api
tgraph dashboard
Step 3: Update Hardcoded References
Search for old endpoint formats and update them:
Old:
fetch('/tg-api/customFieldType');
New:
fetch('/tg-api/custom-field-types');
Step 4: Update Tests
Update any tests that reference the old naming:
// Old
describe('CustomFieldTypeBzController', () => {
it('should be defined', () => {
expect(controller).toBeDefined();
});
});
// New
describe('CustomFieldTypeTgController', () => {
it('should be defined', () => {
expect(controller).toBeDefined();
});
});
Common Patterns
Single Word Models
model User { }
- Endpoint:
/tg-api/users - Resource:
users - Files:
user.tg.controller.ts
Two Word Models
model BlogPost { }
- Endpoint:
/tg-api/blog-posts - Resource:
blog-posts - Files:
blogPost.tg.controller.ts
Three+ Word Models
model CustomFieldType { }
- Endpoint:
/tg-api/custom-field-types - Resource:
custom-field-types - Files:
customFieldType.tg.controller.ts
Irregular Plurals
The pluralizer handles common irregular cases:
model Person { } // /tg-api/people
model Category { } // /tg-api/categories
Best Practices
1. Use PascalCase Models
Always use PascalCase for Prisma models:
// Good
model BlogPost { }
model UserProfile { }
// Avoid
model blog_post { }
model userprofile { }
2. Avoid Abbreviations
// Good
model BlogPost { }
model UserProfile { }
// Avoid
model BP { }
model UsrProf { }
3. Use Singular Model Names
Prisma models should be singular (Prisma convention):
// Good
model User { }
model Post { }
// Avoid
model Users { }
model Posts { }
The generator handles pluralization automatically.
4. Consistent Word Boundaries
// Good - clear boundaries
model BlogPost { }
model UserProfile { }
model CustomFieldType { }
// Avoid - unclear boundaries
model Blogpost { }
model Userprofile { }
Troubleshooting
Endpoint 404 Errors
Problem: API returns 404 for generated endpoints.
Solution: Verify the endpoint in the generated controller matches your request:
// Generated controller
@Controller('tg-api/users') // ✓ Correct
// Your request
fetch('/tg-api/users') // ✓ Matches
Resource Not Found
Problem: React Admin resource not found.
Solution: Ensure resource name matches data provider mapping:
// Resource
<Resource name="blog-posts" ... /> // ✓
// Data Provider
endpointMap['blog-posts'] = 'tg-api/blog-posts'; // ✓ Matches
Import Errors
Problem: Cannot import generated classes.
Solution: Use the exact generated class name:
// Generated class
export class BlogPostTgService {}
// Import
import { BlogPostTgService } from './blogPost.tg.service'; // ✓ Correct
Next Steps
- Prisma Setup – Configure your schema
- Customization – Extend generated code
- API Reference – Understand the generation pipeline