Project Structure

This guide explains the directory structure and file organization of Azu projects created with the CLI. Understanding this structure will help you navigate and develop your applications more effectively.

Overview

Azu follows a convention-over-configuration approach with a well-defined directory structure that promotes maintainability, testability, and scalability.

Complete Project Structure

When you create a new Azu project with azu new my_app, you get this structure:

my_app/
├── 📁 src/                           # Application source code
│   ├── 📄 my_app.cr                  # Main application module
│   ├── 📄 server.cr                  # HTTP server configuration
│   ├── 📁 endpoints/                 # HTTP endpoints (controllers)
│   │   └── 📁 welcome/
│   │       └── 📄 index_endpoint.cr
│   ├── 📁 models/                    # Database models (CQL/Jennifer)
│   │   └── 📄 your_models_goes_here.txt
│   ├── 📁 contracts/                 # Request/response contracts
│   │   └── 📁 welcome/
│   │       └── 📄 index_contract.cr
│   ├── 📁 pages/                     # Page components (views)
│   │   └── 📁 welcome/
│   │       └── 📄 index_page.cr
│   ├── 📁 services/                  # Business logic services
│   ├── 📁 middleware/                # HTTP middleware components
│   ├── 📁 components/                # Reusable live components
│   ├── 📁 validators/                # Custom validation logic
│   ├── 📁 initializers/              # Application startup configuration
│   │   ├── 📄 database.cr
│   │   └── 📄 logger.cr
│   └── 📁 db/                        # Database-related files
│       ├── 📄 schema.cr              # Database schema definition
│       ├── 📄 seed.cr                # Sample data seeding
│       ├── 📁 migrations/            # Database migrations
│       └── 📄 README.md
├── 📁 spec/                          # Test files
│   ├── 📄 my_app_spec.cr             # Main application tests
│   ├── 📄 spec_helper.cr             # Test configuration
│   ├── 📁 endpoints/                 # Endpoint tests
│   ├── 📁 models/                    # Model tests
│   ├── 📁 services/                  # Service tests
│   └── 📁 support/                   # Test support files
├── 📁 public/                        # Static assets
│   ├── 📁 assets/                    # CSS, JS, images
│   │   ├── 📁 css/
│   │   │   ├── 📄 bootstrap.min.css
│   │   │   └── 📄 cover.css
│   │   └── 📁 js/
│   │       └── 📄 bootstrap.min.js
│   └── 📁 templates/                 # Jinja2 templates
│       ├── 📄 layout.jinja           # Base layout template
│       ├── 📁 helpers/               # Partial templates
│       │   └── 📄 _nav.jinja
│       └── 📁 welcome/
│           └── 📄 index_page.jinja
├── 📁 tasks/                         # Custom task definitions
│   └── 📄 taskfile.cr
├── 📁 config/                        # Configuration files
├── 📄 shard.yml                      # Crystal dependencies
├── 📄 README.md                      # Project documentation
└── 📄 LICENSE                        # License file

Directory Details

/src - Application Source Code

The heart of your application where all Crystal source code lives.

Main Files

  • my_app.cr: Main application module that defines routes, middleware, and configuration

  • server.cr: HTTP server startup and configuration

/src/endpoints - HTTP Endpoints (Controllers)

Contains the HTTP request handlers, similar to controllers in other frameworks.

Structure:

Example Endpoint:

/src/models - Database Models

Contains your data models using CQL ORM or Jennifer ORM.

Example Model:

/src/contracts - Request/Response Contracts

Type-safe request validation and response formatting.

Example Contract:

/src/pages - Page Components (Views)

Render HTML responses using templates.

Example Page:

/src/services - Business Logic Services

Encapsulate complex business logic following Domain-Driven Design principles.

Example Service:

/src/middleware - HTTP Middleware

Custom middleware for request/response processing.

Example Middleware:

/src/components - Live Components

Real-time interactive components for dynamic user interfaces.

Example Component:

/src/validators - Custom Validators

Reusable validation logic for models and contracts.

Example Validator:

/src/initializers - Application Initializers

Configure various aspects of your application during startup.

Database Initializer (database.cr):

/src/db - Database Files

  • schema.cr: Database schema definition

  • seed.cr: Sample data for development

  • migrations/: Database migration files

/spec - Test Files

Mirror the structure of /src for organized testing.

Example Test:

/public - Static Assets

  • /assets: CSS, JavaScript, images, fonts

  • /templates: Jinja2 templates for HTML rendering

Template Structure:

/tasks - Custom Tasks

Define custom command-line tasks for your application.

Example Task:

File Naming Conventions

General Rules

  • Files: snake_case.cr

  • Classes: PascalCase

  • Methods/Variables: snake_case

  • Constants: SCREAMING_SNAKE_CASE

Specific Conventions

Endpoints

  • File: src/endpoints/users/index_endpoint.cr

  • Class: Users::IndexEndpoint

Models

  • File: src/models/user.cr

  • Class: User

Services

  • File: src/services/user_registration_service.cr

  • Class: UserRegistrationService

Contracts

  • File: src/contracts/users/create_contract.cr

  • Struct: Users::CreateContract

Pages

  • File: src/pages/users/index_page.cr

  • Class: Users::IndexPage

Components

  • File: src/components/counter_component.cr

  • Class: CounterComponent

Middleware

  • File: src/middleware/authentication_middleware.cr

  • Class: AuthenticationMiddleware

Tests

  • File: spec/models/user_spec.cr

  • Describes: User

Configuration Files

shard.yml - Dependencies

Environment Configuration

Create environment-specific configuration:

Best Practices

Organization

  1. Group related files in subdirectories

  2. Mirror test structure in /spec

  3. Use descriptive names for files and classes

  4. Keep files focused on single responsibilities

Dependencies

  1. Explicit imports in each file

  2. Group imports by source (stdlib, shards, local)

  3. Avoid circular dependencies

Example Import Organization:

Testing

  1. Test files mirror source structure

  2. Use descriptive test names

  3. Group related tests in nested describe blocks

  4. Test both success and failure scenarios

Working with the Structure

Adding New Features

  1. Generate scaffolding: azu generate scaffold Feature name:string

  2. Implement business logic in services

  3. Add validations in models and contracts

  4. Create custom middleware for cross-cutting concerns

  5. Write comprehensive tests

Refactoring

  1. Extract shared logic into services

  2. Create reusable components for common UI patterns

  3. Use modules for shared behavior

  4. Keep controllers thin by moving logic to services


This structure provides a solid foundation for building maintainable, testable, and scalable Azu applications. The conventions help maintain consistency across projects and make it easier for team members to navigate the codebase.

Next Steps:

Last updated