Skip to main content

Development Environment Setup

Prerequisites

  • Rust 1.56+: Latest stable Rust version
  • Cargo: Rust package manager
  • SQLx CLI: For database migrations
  • Git: Version control

Clone Repository

Install Dependencies

Confirm tools with cargo --version, sqlx --version, and cargo audit --version.

Database Setup

Development Database

Zingat uses SQLite for development by default. The database file is created at data.db in the project root (default connection string: sqlite:data.db).

Codebase Structure

Key Modules

Data Layer (src/lib/data/)

  • mod.rs: Database connection pooling and configuration
  • model.rs: Database models matching the clips and api_keys tables
  • query.rs: SQL queries using SQLx with prepared statements

Domain Layer (src/lib/domain/)

  • clip/mod.rs: Core Clip struct and ClipError enum with all error variants
  • clip/field/: Newtype wrappers for type safety (ClipId, Content, Expires, Hits, Password, Posted, Shortcode, Title)
  • maintenance.rs: Background tasks for expired clip cleanup
  • time.rs: Time utilities for date parsing and expiration checks

Service Layer (src/lib/service/)

  • action.rs: Business logic for clip operations (create, read, update)
  • ask.rs: Request/response DTOs for API operations

Web Layer (src/lib/web/)

  • api.rs: REST API endpoints (/api/clip/*) with API key authentication
  • http.rs: Web UI routes (/, /clip/<shortcode>, /clip/raw/<shortcode>)
  • hitcounter.rs: Asynchronous hit counting with batching via crossbeam channels
  • form.rs: Form handling and validation for web UI
  • renderer.rs: Handlebars template rendering
  • ctx.rs: Template context structures

Development Workflow

Running Development Server

Running CLI Client

Code Formatting

Linting

Testing

Unit Tests

Run unit tests:

Integration Tests

Integration tests are in the tests/ directory:

Test Coverage

Install tarpaulin for test coverage:

Templates and Static Assets

Templates

Zingat uses Handlebars templates located in the templates/ directory:
  • base.hbs: Base template layout with common HTML structure
  • home.hbs: Home page with clip creation form
  • clip.hbs: Clip display page showing content and metadata
  • clip_need_password.hbs: Password prompt for protected clips
  • error_box.hbs: Error display component
  • header.hbs: Page header component
  • footer.hbs: Page footer component
Templates are rendered via the renderer.rs module which provides template context and error handling.

Static Assets

Static files are served from the static/ directory:
  • zingat.css: Custom CSS styling for the web interface
  • tiny-date-picker.min.js: JavaScript library for date picker functionality
  • logo.svg: Zingat logo (available in light and dark variants)
Static assets are served directly by Rocket and don’t require template rendering.

Dependencies Overview

Key dependencies used in Zingat: Core:
  • serde, serde_json: Serialization
  • thiserror: Error handling
  • chrono: Date/time handling
  • uuid: UUID generation
Web:
  • rocket: Web framework (0.5.0-rc.1)
  • handlebars: Template engine (4.x)
  • tokio: Async runtime (1.8.0)
Database:
  • sqlx: Database toolkit (0.8.2)
CLI:
  • structopt: Command-line argument parsing
  • dotenv: Environment variable loading
Utilities:
  • derive_more: Additional derive macros
  • rand: Random number generation
  • base64: Base64 encoding/decoding
  • reqwest: HTTP client for CLI
  • strum: String enum conversions
Concurrency:
  • crossbeam-channel: Multi-producer, multi-consumer channels for hit counter batching
  • parking_lot: Faster mutex implementation

Code Quality

Security Audits

Documentation

Generate documentation:

Benchmarking

Create benchmarks for performance-critical code:

Code Standards

Rust Conventions

  • Follow Rust naming conventions
  • Use rustfmt for consistent formatting
  • Apply Clippy recommendations
  • Document public APIs with /// comments

Error Handling

Zingat uses comprehensive error types with the thiserror crate: ClipError Variants (defined in src/lib/domain/clip/mod.rs):
  • NotFound: Clip doesn’t exist
  • AlreadyExists: Shortcode collision
  • Expired: Clip has passed expiration date
  • InvalidPassword: Wrong password provided
  • InvalidTitle: Title validation failed
  • EmptyContent: Content cannot be empty
  • InvalidDate: Date parsing error
API Errors:
  • NotFound: Resource not found (404)
  • Server: Internal server error (500)
  • User: Client error (401)
  • KeyError: API key issues (400)
All errors implement std::error::Error and can be converted to appropriate HTTP responses.

Database Operations

  • Use prepared statements with SQLx
  • Handle database errors appropriately
  • Implement proper connection pooling

Security

  • Hash passwords with Argon2
  • Validate all user input
  • Implement rate limiting
  • Use HTTPS in production

Performance Considerations

Database Optimization

  • Use batch operations for view tracking
  • Implement proper indexing
  • Monitor query performance

Memory Management

  • Use Rust’s ownership system effectively
  • Avoid unnecessary allocations
  • Implement proper caching

Async Programming

  • Use Tokio for async operations
  • Avoid blocking calls in async context
  • Implement proper error handling in async code

Debugging

Logging

Enable different log levels:
1

Start the API server

Run cargo run --bin httpd and ensure the server listens on the expected port.
2

Smoke test the API

3

Run CLI client

Debugging Tools

  • println! debugging: Simple output debugging
  • dbg! macro: Quick value inspection
  • Rust debugger: Use GDB or LLDB
  • Tracing: Structured logging

Database Inspection