How Code Is Organized into Modules and Packages in macro-inc/macro: A Complete Workspace Guide

The macro-inc/macro repository structures its Rust code as a Cargo workspace divided into three functional tiers: reusable core libraries in crates/, independent microservices in services/, and user-facing applications plus build tooling in apps/ and tooling/, all centrally declared in the workspace root Cargo.toml.

Understanding how code is organized into modules and packages in macro-inc/macro reveals a domain-driven architecture optimized for cloud-native deployment. The project uses a single Cargo workspace to share dependency resolution across dozens of internal packages while enforcing strict boundaries between infrastructure libraries, business-logic services, and UI layers. This layout allows developers to iterate on shared utilities in crates/ without triggering rebuilds of unrelated microservices in services/.

Workspace Root and Member Declaration

At the top level, the repository is governed by a root Cargo.toml that defines the workspace boundaries. According to the macro-inc/macro source code, the workspace members are declared using glob patterns that encompass the three primary directories:

[workspace]
members = [
    "crates/*",
    "services/*",
    "apps/web/tauri",
    "tooling/xtask/*",
]

This configuration instructs Cargo to treat every subdirectory under crates/ and services/ as an independent package, while also including the Tauri desktop application and the automation scripts in tooling/xtask/. The root manifest ensures that all crates share a single Cargo.lock file and compatible dependency versions, even though each maintains its own Cargo.toml with specific feature flags and binary targets.

Core Library Crates

The crates/ directory houses the foundational libraries that implement cross-cutting concerns such as configuration, persistence, and cloud integrations. These packages are compiled as library crates (lib targets) and expose public APIs consumed by services and applications.

Key crates identified in the source include:

  • macro_env_var – Provides safe wrappers for environment variable access
  • macro_aws_config – Encapsulates AWS SDK initialization and S3 client management
  • macro_db_client – Supplies database connection pools and query builders
  • macro_event_broker – Handles asynchronous event publishing between services
  • macro_middleware – Shared Axum middleware for authentication and logging
  • macro_axum_utils – Common HTTP utilities and request handlers

Each crate follows the standard Rust layout with src/lib.rs as the entry point. For example, crates/macro_env_var/src/lib.rs exposes a structure that centralizes environment access:

pub struct EnvVar;

impl EnvVar {
    /// Reads an environment variable using the macro‑provided helper.
    pub fn get(key: &str) -> Result<String, std::env::VarError> {
        macro_env::var(key)  // delegates to internal macro_env implementation
    }
}

Microservices Layer

The services/ directory contains standalone binary crates (bin targets) that compile into deployable units—either long-running servers or AWS Lambda handlers. Each service owns its own Cargo.toml that references core crates via path dependencies like path = "../../crates/macro_env_var".

Notable services in the workspace include:

  • document_storage_service – Handles file uploads and archival
  • search_processing_service – Indexes documents for全文検索
  • email_service – Manages transactional email delivery
  • static_file_service – Serves cached assets via CDN
  • sync-service – Orchestrates real-time data synchronization
  • upload_extractor_lambda_handler – AWS Lambda for processing uploads
  • docx_unzip_handler – Lambda for DOCX content extraction

A service entry point typically wires together multiple core crates. In services/document_storage_service/src/main.rs, the initialization code demonstrates how these modules interact:

use macro_env_var::EnvVar;               // Load env vars safely
use macro_aws_config::S3Client;          // AWS S3 client wrapper
use macro_db_client::DbPool;             // Database connection pool
use macro_event_broker::EventBroker;     // Publish domain events

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let db_pool = DbPool::connect(EnvVar::get("DATABASE_URL")?)?;
    let s3_client = S3Client::from_env();
    let event_broker = EventBroker::new();
    // ... service logic
    Ok(())
}

Applications and Build Tooling

Beyond libraries and services, the workspace integrates end-user software and automation utilities.

apps/web/tauri/ contains the desktop UI built with the Tauri framework. The Rust backend code lives at apps/web/tauri/src-tauri/src/main.rs and imports shared utilities just like any other crate:

fn main() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![macro_axum_utils::handle_request])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

tooling/xtask/ houses custom automation crates such as xtask_graphql_soup_schema and xtask_kafka_topics. These are development tools executed via cargo xtask commands to generate code, manage Kafka topics, or perform schema migrations without bloating the production service binaries.

Cross-Package Dependency Patterns

The dependency graph follows a strict acyclic direction: services depend on crates, crates depend on other crates, and apps depend on crates. The root Cargo.toml workspace membership allows Cargo to resolve these path-based links efficiently.

When a service needs a core library, it declares the dependency with a relative path:

[dependencies]
macro_env_var = { path = "../../crates/macro_env_var" }
macro_db_client = { path = "../../crates/macro_db_client" }

This organization ensures that changes to macro_env_var propagate automatically to all dependent services during the next build, while keeping service-specific concerns isolated in their respective src/main.rs files.

Summary

  • Workspace Structure: A single Cargo workspace unifies all code under crates/, services/, and apps/, defined in the root Cargo.toml.
  • Library Tier: The crates/ directory contains reusable infrastructure libraries like macro_env_var and macro_db_client that hide implementation details behind clean public APIs.
  • Service Tier: The services/ directory houses deployable binaries that compose core crates into business-logic endpoints and Lambda handlers.
  • Application Tier: The apps/web/tauri crate delivers the desktop UI, while tooling/xtask provides build automation.
  • Dependency Flow: Path-based dependencies enforce a unidirectional flow from core crates outward to services and applications, preventing circular references.

Frequently Asked Questions

What is the difference between the crates/ and services/ directories?

The crates/ directory contains library crates designed for reuse across the codebase, such as macro_aws_config or macro_event_broker, each exposing a lib.rs for other packages to import. The services/ directory contains binary crates with main.rs entry points that compile into standalone executables or Lambda deployment packages, such as document_storage_service or docx_unzip_handler. Services consume crates, but crates never depend on services.

How do microservices depend on core libraries without publishing to crates.io?

Services reference core libraries using path dependencies in their individual Cargo.toml files, such as macro_env_var = { path = "../../crates/macro_env_var" }. Because all packages belong to the same workspace, Cargo resolves these paths locally during compilation, eliminating the need to publish internal libraries to an external registry.

What code resides in the tooling/xtask directory?

The tooling/xtask/ directory contains automation scripts and build utilities that support the development workflow. Crates here, such as xtask_graphql_soup_schema and xtask_kafka_topics, are executed via the cargo xtask command pattern to perform tasks like generating GraphQL schemas or provisioning Kafka topics without including that logic in production service binaries.

Where is the desktop application entry point located?

The desktop application built with Tauri resides in apps/web/tauri/. The Rust backend entry point is located at apps/web/tauri/src-tauri/src/main.rs, which initializes the Tauri runtime and wires in shared utilities like macro_axum_utils to handle frontend-invoked commands.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →