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 atdata.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 configurationmodel.rs: Database models matching theclipsandapi_keystablesquery.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 variantsclip/field/: Newtype wrappers for type safety (ClipId, Content, Expires, Hits, Password, Posted, Shortcode, Title)maintenance.rs: Background tasks for expired clip cleanuptime.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 authenticationhttp.rs: Web UI routes (/,/clip/<shortcode>,/clip/raw/<shortcode>)hitcounter.rs: Asynchronous hit counting with batching via crossbeam channelsform.rs: Form handling and validation for web UIrenderer.rs: Handlebars template renderingctx.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 thetests/ directory:
Test Coverage
Install tarpaulin for test coverage:Templates and Static Assets
Templates
Zingat uses Handlebars templates located in thetemplates/ directory:
base.hbs: Base template layout with common HTML structurehome.hbs: Home page with clip creation formclip.hbs: Clip display page showing content and metadataclip_need_password.hbs: Password prompt for protected clipserror_box.hbs: Error display componentheader.hbs: Page header componentfooter.hbs: Page footer component
renderer.rs module which provides template context and error handling.
Static Assets
Static files are served from thestatic/ directory:
zingat.css: Custom CSS styling for the web interfacetiny-date-picker.min.js: JavaScript library for date picker functionalitylogo.svg: Zingat logo (available in light and dark variants)
Dependencies Overview
Key dependencies used in Zingat: Core:serde,serde_json: Serializationthiserror: Error handlingchrono: Date/time handlinguuid: UUID generation
rocket: Web framework (0.5.0-rc.1)handlebars: Template engine (4.x)tokio: Async runtime (1.8.0)
sqlx: Database toolkit (0.8.2)
structopt: Command-line argument parsingdotenv: Environment variable loading
derive_more: Additional derive macrosrand: Random number generationbase64: Base64 encoding/decodingreqwest: HTTP client for CLIstrum: String enum conversions
crossbeam-channel: Multi-producer, multi-consumer channels for hit counter batchingparking_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
rustfmtfor consistent formatting - Apply Clippy recommendations
- Document public APIs with
///comments
Error Handling
Zingat uses comprehensive error types with thethiserror crate:
ClipError Variants (defined in src/lib/domain/clip/mod.rs):
NotFound: Clip doesn’t existAlreadyExists: Shortcode collisionExpired: Clip has passed expiration dateInvalidPassword: Wrong password providedInvalidTitle: Title validation failedEmptyContent: Content cannot be emptyInvalidDate: Date parsing error
NotFound: Resource not found (404)Server: Internal server error (500)User: Client error (401)KeyError: API key issues (400)
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:Debugging Tools
- println! debugging: Simple output debugging
- dbg! macro: Quick value inspection
- Rust debugger: Use GDB or LLDB
- Tracing: Structured logging