ANAR Web Framework - Complete Documentation
Introduction
ANAR is a powerful Go web framework built on top of GORM and Gin that provides rapid application development through code generation and scaffolding. It follows the convention-over-configuration principle and offers a comprehensive CLI tool for managing your web application lifecycle.
Key Features
- Rapid Development: Generate models, handlers, and migrations with simple commands
- GORM Integration: Full ORM support with automatic model parsing
- Gin Framework: High-performance HTTP web framework
- Live Reload: Built-in air integration for development
- Relationship Management: Support for all GORM relationship types
- Pagination & Search: Built-in pagination and search functionality
- RESTful APIs: Automatic CRUD operation generation
- Migration System: Database schema management
- Modular Architecture: Clean separation of concerns
- JWT-based authentication support
- Redis integration
- SMTP email support
- S3-compatible storage support
- Built-in scheduler for background jobs and tasks
- OAuth login via Facebook, Google, Apple, and GitHub
- Modular, extensible, and configurable architecture
Architecture
ANAR follows a modular architecture with the following components:
- CLI Handler: Command processing and routing
- Generators: Code generation for models, handlers, and migrations
- Model Parser: Automatic model detection and parsing
- Project Management: Build and run utilities
- Configuration: Centralized configuration management
Installation and Setup
Prerequisites
- Go 1.19 or higher
- Git
- Database (PostgreSQL, MySQL, SQLite, etc.)
Installation
- Clone or install ANAR:
go install codeberg.org/anarproject/anar@latest - Initialize a new project:
anar init github.com/yourusername/yourproject - Navigate to your project directory:
cd yourproject
Project Settings in ANAR
Every project generated with ANAR comes with a centralized configuration system located in the config/ package. This ensures that all environment variables and project-wide settings are managed in one place. This section explains in detail every available setting, its purpose, defaults, and how to customize it.
Server Settings
The server settings control how your application is served.
SERVER_PORT: The port where the HTTP server will run.- Default:
8000 - Example:
SERVER_PORT=8002
- Default:
When the application runs, it will start listening on http://localhost:8002.
JWT (Authentication)
ANAR provides JWT-based authentication by default.
JWT_SECRET: The secret key used to sign JWT tokens.- Must be a long, random string for security.
- Example:
JWT_SECRET=supersecretkey123
JWT_EXPIRATION: The lifetime of issued tokens.- Format: a duration string (e.g.,
24h,72h). - Example:
JWT_EXPIRATION=72h
- Format: a duration string (e.g.,
TOKEN_ISSUER: Identifies the token issuer (used in token validation).- Example:
TOKEN_ISSUER=anar-api
- Example:
Database Settings
ANAR integrates with GORM, supporting PostgreSQL, MySQL, SQLite, and SQL Server.
DB_DRIVER: Selects the database driver. Options:postgres,mysql,sqlite,sqlserver.DB_HOST: Database host (not needed for SQLite).DB_PORT: Port number (default varies by database).DB_USER: Username.DB_PASSWORD: Password.DB_NAME: Database name.DB_SSLMODE: SSL mode (PostgreSQL only). Common values:disable,require.
Example for PostgreSQL:
DB_DRIVER=postgres
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=password
DB_NAME=anar_db
DB_SSLMODE=disable
For SQLite (no host/port needed):
DB_DRIVER=sqlite
DB_NAME=database.db
CORS (Cross-Origin Resource Sharing)
CORS allows you to define which domains can access your API.
CORS_ALLOWED_ORIGINS: A comma-separated list of allowed origins.- Example:
CORS_ALLOWED_ORIGINS=http://localhost:3000,http://example.com
- Example:
If not set, ANAR defaults to allowing requests from * (all origins), which is fine for development but not recommended for production.
Redis Settings
Redis can be used for caching, sessions, and other high-performance storage needs.
REDIS_ENABLED: Enables Redis integration (trueorfalse).REDIS_HOST: Hostname of the Redis server.REDIS_PORT: Port of the Redis server.REDIS_TTL: Default time-to-live for cached items, in seconds.
Example:
REDIS_ENABLED=true
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_TTL=60
SMTP (Email)
ANAR supports sending emails via SMTP (e.g., Gmail, Postfix, SendGrid).
SMTP_HOST: SMTP server host.SMTP_PORT: SMTP port (587 for TLS, 465 for SSL).SMTP_USER: SMTP username (usually your email).SMTP_PASSWORD: Password or app-specific password.SMTP_FROM: The email address used as the sender.
Example (Gmail):
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your_email@gmail.com
SMTP_PASSWORD=your_password
SMTP_FROM=your_email@gmail.com
Application Settings
APP_URL: Base URL of your application. Used in places where absolute URLs are needed (such as OAuth callbacks, password reset links, etc.).
Example:
APP_URL=http://localhost:8002
S3 Storage (File Uploads)
ANAR supports object storage services like AWS S3 and MinIO for file uploads.
S3_ENABLED: Enables or disables S3 integration.S3_ENDPOINT: Endpoint of the storage server (e.g., MinIOhttp://localhost:9000).S3_REGION: Storage region (e.g.,us-east-1).S3_ACCESS_KEY: Access key.S3_SECRET_KEY: Secret key.S3_BUCKET: Default bucket name.S3_USE_SSL: Whether to use SSL (trueorfalse).
Example (MinIO):
S3_ENABLED=true
S3_ENDPOINT=http://localhost:9000
S3_REGION=us-east-1
S3_ACCESS_KEY=minioadmin
S3_SECRET_KEY=minioadmin
S3_BUCKET=anar
S3_USE_SSL=false
If you don’t want to use S3, ANAR falls back to local uploads automatically - no extra setup is needed.
OAuth Providers
ANAR comes with built-in support for third-party login via Google, Facebook, Apple, and GitHub.
Each provider requires:
- Client ID
- Client Secret
- Redirect URL (must match the callback URL configured in your provider dashboard)
Example for Google:
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_REDIRECT_URL=http://localhost:8002/api/auth/google/callback
Similarly, you can configure:
FACEBOOK_CLIENT_ID,FACEBOOK_CLIENT_SECRET,FACEBOOK_REDIRECT_URLGITHUB_CLIENT_ID,GITHUB_CLIENT_SECRET,GITHUB_REDIRECT_URLAPPLE_CLIENT_ID,APPLE_CLIENT_SECRET,APPLE_REDIRECT_URL
Default Uploads
File uploads work out-of-the-box in ANAR without requiring configuration. If S3 is not enabled, files will be stored locally in the project. Developers can immediately start uploading files using the provided APIs.
Command Line Interface (CLI)
ANAR provides a comprehensive CLI for managing your application. All commands follow the pattern:
anar <command> [arguments]
Available Commands
Project Management
# Initialize a new project
anar init <module_name>
# Build the project
anar build
# Run with live reload (using air)
anar run
Code Generation
# Generate complete project scaffold
anar scaffold
# Generate only handlers
anar handlers
# Generate only migrations
anar migrations
Model Management
# Create a new model
anar model <ModelName> [field:type ...]
# Add fields to existing model
anar add-field-to-model <ModelName> field:type [field:type ...]
# Remove field from existing model
anar remove-field-from-model <ModelName> <FieldName>
Command Examples
# Initialize project
anar init github.com/mycompany/blogapi
# Create models
anar model User name:string email:string age:int
anar model Post title:string content:text user:belongsTo
anar model Category name:string posts:hasMany
# Generate all handlers and migrations
anar scaffold
# Add new field to existing model
anar add-field-to-model User phone:string
# Remove field from model
anar remove-field-from-model User age
# Run the application
anar run
Model Generation and Management
Creating Models
ANAR supports comprehensive model generation with various field types and relationships.
Basic Model Creation
anar model User name:string email:string age:int active:bool
This generates:
type User struct {
gorm.Model
Name string `json:"name"`
Email string `json:"email"`
Age int `json:"age"`
Active bool `json:"active"`
}
Supported Field Types
| Type | Go Type | Description | Example |
|---|---|---|---|
string | string | Basic string field | name:string |
text | string | Large text field | content:text |
int / integer | int | Integer field | age:int |
uint | uint | Unsigned integer | score:uint |
float / decimal | float64 | Float field | price:float |
bool / boolean | bool | Boolean field | active:bool |
time / datetime | time.Time | Time field | published_at:time |
json / jsonb | string | JSON field | metadata:json |
uuid | string | UUID field with auto-generation | external_id:uuid |
file | types.FileField | File upload field | avatar:file |
Special Field Types
- text: Creates a text field in the database
- json: Creates a JSON field with appropriate GORM tags
- uuid: Includes UUID generation functionality
- file: Specialized field type for file uploads
Model Field Management
Adding Fields to Existing Models
# Add single field
anar add-field-to-model User phone:string
# Add multiple fields
anar add-field-to-model User phone:string verified:bool last_login:time
Removing Fields from Models
anar remove-field-from-model User age
Note: When removing relationship fields, both the foreign key and the relationship struct will be removed automatically.
Model Structure
All generated models include:
- gorm.Model: Embedded struct providing
ID,CreatedAt,UpdatedAt,DeletedAt - Custom Fields: Your specified fields with appropriate types and tags
- JSON Tags: Automatic JSON serialization tags
- GORM Tags: Database-specific tags and constraints
Example generated model:
type User struct {
gorm.Model
Name string `json:"name"`
Email string `json:"email"`
Age int `json:"age"`
Active bool `json:"active"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Database Relationships
ANAR supports all GORM relationship types with automatic foreign key and join table management.
Relationship Types
1. BelongsTo Relationship
Creates a foreign key reference to another model.
anar model Post title:string content:text user:belongsTo
Generates:
type Post struct {
gorm.Model
Title string `json:"title"`
Content string `json:"content" gorm:"type:text"`
UserID uint `json:"user_id"`
User User `json:"user" gorm:"foreignKey:UserID"`
}
2. HasOne Relationship
Creates a one-to-one relationship.
anar model Profile bio:text avatar:string user:hasOne
Generates:
type Profile struct {
gorm.Model
Bio string `json:"bio" gorm:"type:text"`
Avatar string `json:"avatar"`
User User `json:"user" gorm:"foreignKey:UserID"`
}
3. HasMany Relationship
Creates a one-to-many relationship.
anar model User name:string email:string posts:hasMany
Generates:
type User struct {
gorm.Model
Name string `json:"name"`
Email string `json:"email"`
Posts []Post `json:"posts" gorm:"foreignKey:UserID"`
}
4. ManyToMany Relationship
Creates a many-to-many relationship with automatic join table.
anar model User name:string email:string categories:manyToMany
Generates:
type User struct {
gorm.Model
Name string `json:"name"`
Email string `json:"email"`
Categories []Category `json:"categories" gorm:"many2many:user_categories;"`
}
Handler Generation
ANAR automatically generates RESTful API handlers for all your models with full CRUD functionality.
Generated Handler Methods
For each model, ANAR generates the following handlers:
1. GetAll (with Pagination)
- Endpoint:
GET /models - Features: Pagination, search, filtering
- Parameters:
page,limit,search,sort
2. GetAllSimple (Legacy)
- Endpoint:
GET /models/simple - Features: Basic listing without pagination
3. GetByID
- Endpoint:
GET /models/:id - Features: Single record retrieval
4. Create
- Endpoint:
POST /models - Features: JSON body validation and creation
5. Update
- Endpoint:
PUT /models/:id - Features: Partial or full record updates
6. Delete
- Endpoint:
DELETE /models/:id - Features: Soft delete support
Handler Generation
# Generate handlers for all models
anar handlers
# Or generate complete scaffold (includes handlers)
anar scaffold
Generated Handler Example
For a User model, ANAR generates user_handler.go:
package handlers
import (
"github.com/gin-gonic/gin"
"yourproject/models"
)
// User Handlers
// GetAllUsers handles fetching all users with pagination, search, and filtering
func (h Handler) GetAllUsers(c *gin.Context) {
// Define which fields can be searched
searchFields := []string{"name", "email"}
// Use the new paginated method
h.getAllWithPagination(models.User{}, searchFields, c)
}
// GetAllUsersSimple handles fetching all users without pagination (legacy)
func (h Handler) GetAllUsersSimple(c *gin.Context) {
h.getAll(models.User{}, c)
}
// GetUserByID handles fetching a single user by ID
func (h Handler) GetUserByID(c *gin.Context) {
h.getByID(models.User{}, c, "User not found")
}
// AddUser handles creating a new user
func (h Handler) AddUser(c *gin.Context) {
h.add(models.User{}, c)
}
// UpdateUser handles updating an existing user
func (h Handler) UpdateUser(c *gin.Context) {
h.update(models.User{}, c, "User not found")
}
// DeleteUser handles deleting a user by ID
func (h Handler) DeleteUser(c *gin.Context) {
h.delete(models.User{}, c, "User not found")
}
Search and Pagination Features
Pagination Parameters
page: Page number (default: 1)limit: Items per page (default: 10)
Search Parameters
search: Search term to look for in searchable fieldssort: Sort field and direction (e.g.,name,-created_at)
Usage Examples
# Get first page with 20 items
GET /users?page=1&limit=20
# Search for users
GET /users?search=john
# Sort by name ascending
GET /users?sort=name
# Sort by creation date descending
GET /users?sort=-created_at
# Combine parameters
GET /users?page=2&limit=15&search=admin&sort=name
Custom Search Fields
ANAR automatically determines searchable fields for each model, but you can customize them by modifying the generated handler:
// Customize searchable fields
searchFields := []string{"name", "email", "phone"}
Migration System
ANAR provides automatic database migration generation based on your models.
Migration Generation
# Generate migrations for all models
anar migrations
# Or generate complete scaffold (includes migrations)
anar scaffold
Generated Migration File
ANAR creates a single auto_migrations.go file containing all model migrations:
package migrations
import (
"fmt"
"gorm.io/gorm"
"yourproject/models"
)
// AutoMigrate runs all model migrations
func AutoMigrate(db *gorm.DB) error {
fmt.Println("Running auto migrations...")
if err := db.AutoMigrate(&models.User{}); err != nil {
return fmt.Errorf("failed to migrate User: %w", err)
}
if err := db.AutoMigrate(&models.Post{}); err != nil {
return fmt.Errorf("failed to migrate Post: %w", err)
}
fmt.Println("All migrations completed successfully!")
return nil
}
// DropAllTables drops all model tables (use with caution)
func DropAllTables(db *gorm.DB) error {
fmt.Println("Dropping all tables...")
// Drop tables in reverse order to handle dependencies
if err := db.Migrator().DropTable(&models.Post{}); err != nil {
return fmt.Errorf("failed to drop Post table: %w", err)
}
if err := db.Migrator().DropTable(&models.User{}); err != nil {
return fmt.Errorf("failed to drop User table: %w", err)
}
fmt.Println("All tables dropped successfully!")
return nil
}
// GetModelList returns list of all models being migrated
func GetModelList() []string {
return []string{"User", "Post"}
}
Migration Features
- Auto Migration: Uses GORM’s AutoMigrate for schema synchronization
- Dependency Handling: Manages table creation order for relationships
- Drop Tables: Provides safe table dropping in reverse order
- Model Tracking: Maintains list of all migrated models
Scaffolding System
The scaffolding system generates complete CRUD functionality for your entire application.
Scaffold Generation
anar scaffold
This command:
- Parses all models in the
models/directory - Generates handlers for each model
- Creates database migrations
- Sets up the complete API structure
Custom Scaffold Generators
ANAR supports custom scaffold generators. If you have a custom generator at ./cmd/gen/gen, it will be used instead of the built-in generator.
What Gets Generated
When you run anar scaffold, the following files are created:
- Handler Files:
handlers/model_handler.gofor each model - Migration File:
migrations/auto_migrations.go
Example Scaffold Output
Generated 3 handler files in handlers/ directory:
- user_handler.go
- post_handler.go
- category_handler.go
Generated single migration file: migrations/auto_migrations.go
Models included: User, Post, Category
Routes
Every project generated with ANAR comes with a pre-configured routing system located in the file:
routes/routes.go
This file is the central place where all API endpoints (routes) are registered and connected to their corresponding handlers. ANAR uses the Gin framework for routing, so the syntax is both simple and powerful.
Route Structure
Routes in ANAR are organized into three main categories:
- Public Routes
- Accessible without authentication.
- Typically used for registration, login, or fetching general data.
- OAuth Routes
- Handle login via third-party providers like Google, GitHub, Facebook, or Apple.
- Protected Routes
- Require authentication using the built-in JWT middleware.
- These routes are ideal for sensitive operations such as adding, updating, or deleting records.
Example of routes/routes.go
package routes
import (
"github.com/gin-gonic/gin"
"codeberg.org/anarproject/anar/handlers"
"codeberg.org/anarproject/anar/middleware/jwt"
"codeberg.org/anarproject/anar/config"
"codeberg.org/anarproject/anar/db"
)
func SetupRoutes(r *gin.Engine, database db.Database, config *config.Config) {
handler := handlers.Init(database, config)
jwtMiddleware := jwt.NewJWTMiddleware(config)
api := r.Group("/api")
// Public routes
api.POST("/register", handler.Register)
api.GET("/confirm/:token", handler.ConfirmEmail)
api.POST("/login", handler.Login)
api.GET("/users", handler.GetAllUsers)
api.GET("/users/:id", handler.GetUserByID)
// OAuth routes
auth := api.Group("/auth")
{
auth.GET("/:provider", handler.OAuthLogin)
auth.GET("/:provider/callback", handler.OAuthCallback)
}
// Protected routes
protected := api.Group("/")
protected.Use(jwtMiddleware.AuthRequired())
{
protected.POST("/users", handler.AddUser)
protected.PUT("/users/:id", handler.UpdateUser)
protected.DELETE("/users/:id", handler.DeleteUser)
}
}
Adding New Routes
When you create a new model and its handler, you need to manually register routes for it in routes/routes.go.
For example, after generating a Product model and handler:
anar model Product name:string price:float
anar scaffold
You can add routes like this:
api.GET("/products", handler.GetAllProducts)
api.GET("/products/:id", handler.GetProductByID)
protected.POST("/products", handler.AddProduct)
protected.PUT("/products/:id", handler.UpdateProduct)
protected.DELETE("/products/:id", handler.DeleteProduct)
Workflow with Routes
- Generate models and handlers using the CLI.
- Open
routes/routes.goand register the new handler methods. - Run the project to make the new endpoints available:
anar run
Key Notes
- All public routes can be accessed without authentication.
- Protected routes are guarded by JWT middleware, requiring a valid token.
- OAuth routes are automatically supported; you only need to configure providers in your project settings.
Advanced Features
File Upload Support
ANAR includes support for file upload fields using the file type:
anar model User name:string avatar:file
This generates:
type User struct {
gorm.Model
Name string `json:"name"`
Avatar types.FileField `json:"avatar"`
}
JSON Field Support
For storing JSON data:
anar model Settings config:json metadata:jsonb
Generates:
type Settings struct {
gorm.Model
Config string `json:"config" gorm:"type:json"`
Metadata string `json:"metadata" gorm:"type:json"`
}
UUID Field Support
For UUID fields with automatic generation:
anar model User name:string external_id:uuid
Generates:
type User struct {
gorm.Model
Name string `json:"name"`
ExternalID string `json:"external_id" gorm:"type:uuid;default:uuid_generate_v4()"`
}
Live Reload Development
ANAR includes integration with Air for live reload during development:
anar run
This:
- Automatically installs Air if not present
- Starts the application with live reload
- Watches for file changes and rebuilds automatically
Best Practices
Model Design
- Use descriptive names: Choose clear, meaningful model names
- Plan relationships: Design your data model before generating
- Consider search fields: Think about which fields users will search
- Use appropriate types: Choose the right field types for your data
Development Workflow
- Start with models: Design and create your models first
- Generate scaffold: Use
anar scaffoldto generate all code - Customize as needed: Modify generated code to fit your requirements
- Use live reload: Develop with
anar runfor faster iteration
Code Organization
- Keep models simple: Focus on data structure in models
- Business logic in services: Create service layers for complex logic
- Customize handlers: Modify generated handlers for specific needs
- Version control: Commit generated code to track changes
Database Management
- Use migrations: Always use the migration system
- Plan relationships: Design foreign keys and constraints properly
- Index important fields: Add database indexes for performance
- Backup before changes: Always backup before major migrations
Troubleshooting
Common Issues
1. Model Not Found Errors
Problem: “no models found in models/ directory”
Solutions:
- Ensure models exist in the
models/directory - Check that models follow proper Go struct syntax
- Verify the
models.gofile exists and is properly formatted
2. Import Path Issues
Problem: Import path errors in generated files
Solutions:
- Run
anar initwith the correct module name - Ensure
go.modhas the right module path - Check that package names match directory structure
3. Generation Failures
Problem: Code generation fails with permission errors
Solutions:
- Check directory permissions
- Ensure you’re in the project root directory
- Verify Go workspace is properly configured
4. Relationship Errors
Problem: Foreign key or relationship errors
Solutions:
- Ensure related models exist before creating relationships
- Check that foreign key names follow conventions
- Verify relationship types are correct
Debugging Tips
- Verbose Output: Check console output for detailed error messages
- File Permissions: Ensure proper read/write permissions
- Go Module: Verify
go.modis properly configured - Directory Structure: Follow the standard project layout
Getting Help
- Check Documentation: Review this documentation thoroughly
- Examine Generated Code: Look at generated files for patterns
- Issue Reporting: Report bugs with detailed reproduction steps
Examples and Use Cases
Example 1: Blog API
Complete blog API with authentication:
# Initialize project
anar init github.com/mycompany/blog-api
# Create models
anar model Category name:string description:text
anar model Post title:string content:text published:bool user:belongsTo
anar model Comment content:text user:belongsTo post:belongsTo
# Create many-to-many relationship
anar add-field-to-model Post categories:manyToMany
# Generate all handlers and migrations
anar scaffold
# Run the application
anar run
Example 2: E-commerce API
Product catalog with inventory management:
# Initialize
anar init github.com/store/ecommerce-api
# Create core models
anar model Category name:string description:text
anar model Product name:string description:text price:float stock:int category:belongsTo
anar model Customer name:string email:string phone:string
anar model Order total:float status:string customer:belongsTo
anar model OrderItem quantity:int price:float order:belongsTo product:belongsTo
# Generate scaffold
anar scaffold
Example 3: Social Media API
User profiles and content sharing:
# Initialize
anar init github.com/social/api
# Create user and profile models
anar model Profile bio:text avatar:file location:string user:belongsTo
# Create content models
anar model Post content:text image:file likes:int user:belongsTo
anar model Comment content:text user:belongsTo post:belongsTo
# Create social features
anar model Follow follower:belongsTo following:belongsTo
anar model Like user:belongsTo post:belongsTo
# Generate complete API
anar scaffold
Conclusion
ANAR provides a comprehensive solution for rapid Go web application development. By leveraging code generation, intelligent scaffolding, and convention-over-configuration principles, developers can focus on business logic rather than boilerplate code.
The framework’s strength lies in its simplicity and power - with just a few commands, you can generate a complete RESTful API with CRUD operations, database migrations, and relationship management.
Whether you’re building a simple blog API or a complex enterprise application, ANAR’s flexible architecture and comprehensive feature set provide the foundation for scalable, maintainable web applications.
For continued learning and development with ANAR:
- Practice with Examples: Work through the provided examples
- Customize Generated Code: Adapt the generated code to your specific needs
- Explore Advanced Features: Experiment with relationships and special field types
- Build Real Applications: Apply ANAR to actual projects
- Contribute Back: Share improvements and extensions with the community
Happy coding with ANAR!