Quick Start
Build a complete blog system with users and posts in under 5 minutes.
Step 1: Set Up Your Prisma Schema
Add these models to prisma/schema.prisma:
// @tg_form()
// @tg_label(name)
model User {
id String @id @default(uuid())
name String
email String @unique
/// @tg_format(url)
avatar String?
role Role @default(USER)
posts Post[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// @tg_form()
// @tg_label(title)
model Post {
id String @id @default(uuid())
title String
content String
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId String
/// @tg_upload(image)
coverImage String?
publishedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([authorId])
}
enum Role {
USER
AUTHOR
ADMIN
}
Key features:
// @tg_form()– Marks models for generation// @tg_label(name)– Sets the display field for relations/// @tg_format(url)– Validates URL fields/// @tg_upload(image)– Enables image upload
Step 2: Initialize Configuration
First, create your configuration file with the interactive wizard:
tgraph init
The wizard will ask about:
- Prisma schema path
- API configuration (suffix, prefix, authentication)
- Output directories for generated files
Or use defaults:
tgraph init --yes
Step 3: Generate Everything
Run the generator:
tgraph all
When prompted, confirm generation of static files (guards, interceptors, DTOs).
This creates:
- 4 controllers (User, Post with full CRUD)
- 4 services with Prisma integration and unique field getters
- 8 DTOs (Create + Update for each model)
- 8 React Admin pages (List, Edit, Create, Show for each)
- 2 Studio pages for bulk editing
- Static infrastructure files (guards, decorators, interceptors)
Step 4: Review Generated API
The generator created two complete REST APIs with enhanced features:
User API (/tg-api/users)
// src/features/user/user.tg.controller.ts
@Controller('tg-api/users')
@UseGuards(JwtAuthGuard, AdminGuard)
export class UserTgController {
@Get()
async findAll(@Query() query: PaginationSearchDto) {
// Paginated list with search
}
@Get(':id')
async findOne(@Param('id') id: string) {
// Get by ID
}
@Post()
async create(@Body() dto: CreateUserTgDto) {
// Create user
}
@Put(':id')
async update(@Param('id') id: string, @Body() dto: UpdateUserTgDto) {
// Update user
}
@Delete(':id')
async remove(@Param('id') id: string) {
// Delete user
}
}
// Generated service includes unique field getters
// src/features/user/user.tg.service.ts
export class UserTgService {
// ... standard CRUD methods ...
// Auto-generated from @unique email field
async getOneByEmail(email: string) {
const item = await this.prisma.user.findUnique({
where: { email },
select: this.getSelectFields(),
});
if (!item) {
throw new NotFoundException('User not found');
}
return item;
}
}
Post API (/tg-api/posts)
Same structure with relation support – filtering by authorId and optional relation includes.
Step 5: Review Generated DTOs
DTOs include validation from your schema:
// src/features/user/create-user.tg.dto.ts
export class CreateUserTgDto {
@IsString()
@IsNotEmpty()
name: string;
@IsEmail()
@IsNotEmpty()
email: string;
@IsUrl()
@IsOptional()
avatar?: string;
@IsEnum(Role)
@IsOptional()
role?: Role;
}
Notice:
@IsEmail()from@uniqueconstraint@IsUrl()from@tg_format(url)directive@IsEnum()for enum fields@IsOptional()for nullable fields
Step 6: Generate Dashboard Types
Generate TypeScript types for your dashboard API client:
# Generate swagger.json and types/api.ts
tgraph types
This creates type-safe API clients for your React Admin dashboard:
// src/dashboard/src/types/api.ts (generated)
import { Api } from '../types/api';
const api = new Api({ baseUrl: 'http://localhost:3000' });
// Fully typed API calls
const users = await api.users.usersControllerFindAll();
const user = await api.users.usersControllerFindOne('123');
Step 7: Review Dashboard Pages
Check the generated React Admin resources:
// src/dashboard/src/resources/users/UserList.tsx
export const UserList = () => (
<List>
<Datagrid rowClick="edit">
<TextField source="name" />
<EmailField source="email" />
<UrlField source="avatar" />
<SelectField source="role" choices={roleChoices} />
<DateField source="createdAt" />
<EditButton />
</Datagrid>
</List>
);
// src/dashboard/src/resources/posts/PostEdit.tsx
export const PostEdit = () => (
<Edit>
<SimpleForm>
<TextInput source="title" required />
<TextInput source="content" multiline required />
<BooleanInput source="published" />
<ReferenceInput source="authorId" reference="users">
<AutocompleteInput optionText="name" />
</ReferenceInput>
<FileInput source="coverImage" accept="image/*">
<ImageField source="src" title="title" />
</FileInput>
<DateTimeInput source="publishedAt" />
</SimpleForm>
</Edit>
);
Notice:
- Automatic relation handling with
ReferenceInput - File upload for
coverImage(from@tg_upload(image)) - Type-appropriate inputs (Boolean, DateTime, etc.)
Step 8: Test the API
Start your server:
npm run start:dev
Create a user:
curl -X POST http://localhost:3000/tg-api/users \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{
"name": "John Doe",
"email": "john@example.com",
"role": "AUTHOR"
}'
List users:
curl http://localhost:3000/tg-api/users?page=1&limit=10 \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Step 9: Test the Dashboard
Start the dashboard:
cd src/dashboard
npm run dev
Open http://localhost:5173 and:
- Navigate to
/users– See the user list - Click “Create” – Add a new user with the form
- Navigate to
/posts– Create a post - Upload a cover image – The file will be uploaded automatically
- Select an author from the dropdown – Search-enabled autocomplete
- Navigate to
/users/studio– Bulk edit users in spreadsheet mode
Step 10: Customize
Extend the generated code with your custom logic:
// src/features/post/post.service.ts
import { PostTgService } from './post.tg.service';
@Injectable()
export class PostService extends PostTgService {
async publish(id: string): Promise<Post> {
return this.prisma.post.update({
where: { id },
data: {
published: true,
publishedAt: new Date(),
},
});
}
async getPublishedPosts(): Promise<Post[]> {
return this.prisma.post.findMany({
where: { published: true },
include: { author: true },
orderBy: { publishedAt: 'desc' },
});
}
}
The generated .tg. files remain unchanged and can be regenerated safely.
Step 11: Add Custom Endpoint
Create a custom controller alongside the generated one:
// src/features/post/post.controller.ts
import { PostService } from './post.service';
@Controller('posts')
@UseGuards(JwtAuthGuard)
export class PostController {
constructor(private readonly postService: PostService) {}
@Get('published')
async getPublished() {
return this.postService.getPublishedPosts();
}
@Put(':id/publish')
@UseGuards(AdminGuard)
async publish(@Param('id') id: string) {
return this.postService.publish(id);
}
}
What You’ve Built
In 5 minutes, you created:
- 2 complete REST APIs with pagination, search, and filtering
- Unique field getters for direct lookups by email or other unique fields
- 8 validated DTOs with email, URL, and enum validation
- 8 admin pages with relation support and file uploads
- 2 studio pages for bulk editing
- Type-safe API client generated from Swagger
- Static infrastructure (guards, interceptors, decorators)
- Complete type safety from database to frontend
Next Steps
- CLI Reference – Complete command documentation
- Static Files Guide – Understand infrastructure generation
- Dashboard Types Guide – Type-safe API client setup
- Field Directives – Learn all available directives
- Authentication Guards – Configure authentication
- Custom Validation – Add complex validation rules
- Extending Generated Code – Advanced patterns
- File Uploads – Configure upload handling
Regenerating After Changes
When you modify your schema:
# Regenerate everything
tgraph all
# Or selectively
tgraph api # Backend only
tgraph dashboard # Frontend only
# Regenerate static files
tgraph static --include admin.guard,pagination.interceptor
# Update dashboard types
tgraph types
Generated files (.tg.*) are overwritten, but your custom code remains untouched.
Additional Commands
# Check system health
tgraph doctor
# Preview changes without writing files
tgraph preflight
# List available static modules
tgraph static --list
# Generate specific static modules
tgraph static --include admin.guard,is-admin.decorator
# Regenerate swagger.json only
tgraph swagger