Quick Start

This guide will walk you through creating your first Azu application in just a few minutes. By the end of this tutorial, you'll have a running web application with a database, complete with CRUD operations.

Prerequisites

  • Database server running (PostgreSQL, MySQL, or SQLite)

  • Basic familiarity with Crystal syntax

Step 1: Create a New Project

Let's create a blog application:

azu new my_blog --database postgres

This command will:

  • Create a new directory called my_blog

  • Generate the complete project structure

  • Configure PostgreSQL as the database

  • Set up all necessary dependencies

  • Initialize a Git repository

Output:

πŸš€ Creating new Azu project: my_blog
πŸ“¦ Using database: postgres
πŸ“ Generating project structure...
   create  my_blog/
   create  my_blog/src/
   create  my_blog/src/my_blog.cr
   create  my_blog/src/server.cr
   create  my_blog/shard.yml
   create  my_blog/README.md
   ... (more files)
βœ… Project created successfully!

πŸ“‹ Next Steps:
  cd my_blog
  azu db create
  azu serve

Step 2: Navigate to Your Project

cd my_blog

Let's examine the generated project structure:

my_blog/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ my_blog.cr              # Main application file
β”‚   β”œβ”€β”€ server.cr               # HTTP server configuration
β”‚   β”œβ”€β”€ endpoints/              # API endpoints (controllers)
β”‚   β”œβ”€β”€ models/                 # Database models
β”‚   β”œβ”€β”€ contracts/              # Request/response contracts
β”‚   β”œβ”€β”€ pages/                  # Page components (views)
β”‚   β”œβ”€β”€ services/               # Business logic services
β”‚   β”œβ”€β”€ middleware/             # HTTP middleware
β”‚   └── initializers/           # Application initializers
β”œβ”€β”€ spec/                       # Test files
β”œβ”€β”€ public/                     # Static assets
β”œβ”€β”€ db/                         # Database files
β”‚   β”œβ”€β”€ migrations/             # Database migrations
β”‚   └── seed.cr                 # Database seeds
β”œβ”€β”€ shard.yml                   # Dependencies
└── README.md                   # Project documentation

Step 3: Set Up the Database

Create your database:

azu db create

Output:

πŸ—„οΈ  Creating database: my_blog_development
βœ… Database created successfully!

Run initial migrations:

azu db migrate

Output:

πŸ”„ Running migrations...
βœ… All migrations completed successfully!

Step 4: Start the Development Server

Launch the development server with hot reloading:

azu serve

Output:

πŸš€ Starting Azu development server...
πŸ“¦ Compiling application...
βœ… Compilation successful!
🌐 Server running at: http://localhost:3000
πŸ”₯ Hot reloading enabled
πŸ‘€ Watching for file changes...

Press Ctrl+C to stop the server

Open your browser and navigate to http://localhost:3000. You should see the Azu welcome page!

Step 5: Generate Your First Resource

Let's create a complete blog post resource with CRUD operations:

azu generate scaffold Post title:string content:text published:boolean

Output:

πŸ› οΈ  Generating scaffold: Post
   create  src/models/post.cr
   create  src/endpoints/posts/index_endpoint.cr
   create  src/endpoints/posts/show_endpoint.cr
   create  src/endpoints/posts/new_endpoint.cr
   create  src/endpoints/posts/create_endpoint.cr
   create  src/endpoints/posts/edit_endpoint.cr
   create  src/endpoints/posts/update_endpoint.cr
   create  src/endpoints/posts/destroy_endpoint.cr
   create  src/contracts/posts/index_contract.cr
   create  src/contracts/posts/show_contract.cr
   create  src/contracts/posts/create_contract.cr
   create  src/contracts/posts/update_contract.cr
   create  src/pages/posts/index_page.cr
   create  src/pages/posts/show_page.cr
   create  src/pages/posts/new_page.cr
   create  src/pages/posts/edit_page.cr
   create  public/templates/posts/index_page.jinja
   create  public/templates/posts/show_page.jinja
   create  public/templates/posts/new_page.jinja
   create  public/templates/posts/edit_page.jinja
   create  spec/models/post_spec.cr
   create  spec/endpoints/posts_spec.cr
βœ… Scaffold Post generated successfully!

Step 6: Create the Database Migration

Generate a migration for the posts table:

azu generate migration create_posts_table title:string content:text published:boolean

Output:

πŸ› οΈ  Generating migration: create_posts_table
   create  db/migrations/20231214_120000_create_posts_table.cr
βœ… Migration create_posts_table generated successfully!

Run the migration:

azu db migrate

Output:

πŸ”„ Running migrations...
   migrate  20231214_120000_create_posts_table.cr
βœ… All migrations completed successfully!

Step 7: Explore Your Application

The development server should automatically reload your application. Visit these URLs:

  • Homepage: http://localhost:3000

  • Posts Index: http://localhost:3000/posts

  • New Post: http://localhost:3000/posts/new

Generated Files Explained

1. Model (src/models/post.cr)

require "cql"

class Post < CQL::Model
  db_table "posts"

  field title : String
  field content : String
  field published : Boolean = false

  validate :title, presence: true, length: {min: 1, max: 255}
  validate :content, presence: true
end

2. Endpoint (src/endpoints/posts/index_endpoint.cr)

class Posts::IndexEndpoint
  include Azu::Endpoint

  def call(request)
    posts = Post.all
    index_page = Posts::IndexPage.new(posts: posts)
    index_page.render
  end
end

3. Contract (src/contracts/posts/create_contract.cr)

struct Posts::CreateContract
  include Azu::Request

  validate title, presence: true, length: {min: 1, max: 255}
  validate content, presence: true
  validate published, inclusion: [true, false]
end

4. Page (src/pages/posts/index_page.cr)

class Posts::IndexPage
  include Azu::Page

  def initialize(@posts : Array(Post))
  end

  def render
    template("posts/index_page.jinja", {
      "posts" => @posts.map(&.to_h)
    })
  end
end

Step 8: Test Your Application

Run the test suite:

crystal spec

Output:

πŸ§ͺ Running tests...

Post
  βœ“ should be valid with valid attributes
  βœ“ should validate presence of title
  βœ“ should validate presence of content

Posts::IndexEndpoint
  βœ“ should return all posts
  βœ“ should render index page

Finished in 0.045 seconds
5 examples, 0 failures

Step 9: Add Sample Data

Seed your database with sample data:

# Edit db/seed.cr
cat > db/seed.cr << 'EOF'
require "../src/models/**"

# Create sample posts
Post.create!(
  title: "Welcome to My Blog",
  content: "This is my first blog post using Azu!",
  published: true
)

Post.create!(
  title: "Getting Started with Crystal",
  content: "Crystal is an amazing language for web development...",
  published: true
)

Post.create!(
  title: "Draft Post",
  content: "This is a draft post that's not published yet.",
  published: false
)

puts "βœ… Sample data created successfully!"
EOF

# Run the seed
azu db:seed

Output:

🌱 Seeding database...
βœ… Sample data created successfully!

Step 10: Customize Your Application

Add Custom Styling

Edit public/assets/css/cover.css to customize your application's appearance:

/* Add custom styles */
.blog-header {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  padding: 2rem 0;
}

.post-card {
  border: 1px solid #e9ecef;
  border-radius: 0.5rem;
  padding: 1.5rem;
  margin-bottom: 1rem;
  transition: transform 0.2s;
}

.post-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

Add a Custom Endpoint

Generate a custom endpoint for published posts only:

azu generate endpoint published_posts

Edit the generated endpoint:

# src/endpoints/published_posts/index_endpoint.cr
class PublishedPosts::IndexEndpoint
  include Azu::Endpoint

  def call(request)
    published_posts = Post.where(published: true)
    index_page = PublishedPosts::IndexPage.new(posts: published_posts)
    index_page.render
  end
end

Next Steps

Congratulations! You've successfully created your first Azu application. Here's what you can explore next:

🎯 Immediate Next Steps

  1. Add Authentication - Secure your blog

  2. Add Real-time Features - Live comments or reactions

  3. Create an API - Build a REST API for your blog

  4. Add Testing - Write comprehensive tests

πŸ“š Learn More

πŸ› οΈ Advanced Features

🌟 Community Examples

Troubleshooting

Server Won't Start

# Check for compilation errors
crystal build src/main.cr

# Check database connection
azu db:create

Port Already in Use

# Use a different port
azu serve --port 4000

Database Connection Error

# Verify database is running
sudo systemctl status postgresql  # Linux
brew services list | grep postgres  # macOS

# Check database configuration
cat src/initializers/database.cr

Hot Reloading Not Working

# Restart the server
# Make sure you're editing files in the src/ directory

Congratulations! πŸŽ‰ You've built your first Azu application. The development server will automatically reload when you make changes, so start experimenting and building something amazing!

Need Help? Check out the troubleshooting guide or create an issue on GitHub.

Last updated