Project Structure
Khadem projects follow a clean, organized structure inspired by Laravel. When you create a new project using the Khadem CLI, it generates a complete folder structure designed for scalability, maintainability, and modern development practices.
Well-Organized Structure
Every file and folder has a specific purpose, making your codebase easy to navigate and maintain.
Complete Project Structure
Here's the complete folder structure generated by khadem new
:
my_api/
├── lib/
│ ├── main.dart # Application entry point
│ ├── app/
│ │ ├── http/
│ │ │ ├── controllers/
│ │ │ │ └── home_controller.dart
│ │ │ └── middleware/
│ │ │ └── cors_middleware.dart
│ │ ├── jobs/
│ │ │ └── send_user_notification_job.dart
│ │ ├── listeners/
│ │ │ └── user_events_handler.dart
│ │ ├── models/
│ │ │ └── user.dart
│ │ └── providers/
│ │ ├── app_service_provider.dart
│ │ ├── event_service_provider.dart
│ │ └── scheduler_service_provider.dart
│ ├── bin/ # CLI commands and utilities
│ ├── config/
│ │ └── app.dart # Application configuration
│ ├── core/
│ │ └── kernel.dart # Application kernel
│ ├── database/
│ │ ├── migrations/
│ │ │ ├── 0_create_users_table.dart
│ │ │ ├── 0_create_personal_access_token_table.dart
│ │ │ └── migrations.dart
│ │ └── seeders/
│ │ ├── seeders.dart
│ │ └── user_seeder.dart
│ └── routes/
│ ├── socket.dart
│ └── web.dart
├── config/
│ ├── development/
│ │ └── logging.json
│ └── production/
│ └── logging.json
├── lang/
│ ├── ar/
│ │ ├── ar.json
│ │ ├── fields.json
│ │ └── validation.json
│ └── en/
│ ├── en.json
│ ├── fields.json
│ └── validation.json
├── public/
│ └── assets/
│ └── logo.png
├── resources/
│ └── views/
│ └── welcome.khdm.html
├── storage/
│ └── logs/
│ └── app.log
├── tests/ # Test files
├── .env # Environment variables
├── .gitignore # Git ignore rules
├── pubspec.yaml # Package configuration
└── pubspec.lock # Package lock file
📂 Application Layer
- lib/app/ - Business logic and domain code
- lib/core/ - Application kernel and bootstrap
- routes/ - HTTP and WebSocket route definitions
- config/ - Environment-specific configurations
🗄️ Data & Storage
- lib/database/ - Migrations and database seeders
- storage/ - File storage and cache directories
- lang/ - Localization files
- resources/ - Views and assets
lib/ Directory
The core of your Dart application, following modern Dart package conventions. All application code lives within the lib/
directory.
lib/app/ Directory
The heart of your application. Contains all business logic, domain models, and application services.
HTTP Layer
Handles web requests, responses, and HTTP-specific logic:
- controllers/ - Route handlers that process requests and return responses
- middleware/ - Request/response filters (auth, CORS, logging, etc.)
Domain Layer
Core business logic and data models:
- models/ - Database entity representations with relationships
- providers/ - Service providers for dependency injection
- jobs/ - Background job classes for queue processing
- listeners/ - Event listeners for async processing
lib/app/
├── http/
│ ├── controllers/
│ │ ├── home_controller.dart
│ │ ├── user_controller.dart
│ │ └── api/
│ │ └── v1/
│ │ └── auth_controller.dart
│ └── middleware/
│ ├── auth_middleware.dart
│ ├── cors_middleware.dart
│ └── logging_middleware.dart
├── models/
│ ├── user.dart
│ └── post.dart
├── providers/
│ ├── app_service_provider.dart
│ ├── event_service_provider.dart
│ └── scheduler_service_provider.dart
├── jobs/
│ ├── send_welcome_email_job.dart
│ ├── process_image_job.dart
│ └── email/
│ └── send_notification_job.dart
├── listeners/
│ └── user_registered_listener.dart
routes/ Directory
Define all your application routes here. Routes are organized by protocol and purpose:
- web.dart - HTTP routes for web endpoints
- socket.dart - WebSocket routes for real-time communication
// lib/routes/web.dart
import 'package:khadem/khadem_dart.dart';
import '../app/http/controllers/home_controller.dart';
import '../core/kernel.dart';
void registerRoutes(Server server) {
// Register global middlewares
server.useMiddlewares(Kernel.middlewares);
// API Routes
server.group(
prefix: '/api',
middleware: [],
routes: (router) async {
router.get('/hello', HomeController.index);
router.get('/welcome', HomeController.welcome);
router.get('/stream', HomeController.stream);
},
);
// Serve static files
server.serveStatic();
}
// routes/socket.dart
import 'package:khadem/khadem_dart.dart';
void registerSocketRoutes(SocketServer socketServer) {
socketServer.on('chat:message', (socket, data) {
// Handle chat messages
socketServer.broadcast('chat:message', data);
});
socketServer.on('user:join', (socket, data) {
// Handle user joining
socket.broadcast('user:joined', data);
});
}
config/ Directory
Environment-specific configuration files. Each file exports configuration maps that are merged with environment variables:
Configuration Structure
- app.dart - Main application configuration
- development/ - Development-specific settings
- production/ - Production-specific settings
// config/app.dart
import 'package:khadem/khadem_dart.dart';
class AppConfig {
static final env = Khadem.env;
static Map<String, Map<String, dynamic>> get configs => {
'database': {
'driver': env.getOrDefault('DB_CONNECTION', 'mysql'),
'host': env.getOrDefault('DB_HOST', 'localhost'),
'port': env.getInt('DB_PORT'),
'database': env.get('DB_DATABASE'),
'username': env.get('DB_USERNAME'),
'password': env.get('DB_PASSWORD'),
'run_migrations': true,
'run_seeders': false,
},
'cache': {
'default': 'hybrid',
'drivers': {
'file': {'driver': 'file', 'path': 'storage/cache'},
'memory': {'driver': 'memory'},
'hybrid': {'driver': 'hybrid', 'path': 'storage/cache'},
},
},
'queue': {
'driver': 'file',
'run_in_background': true,
'auto_start': true,
},
'auth': {
'default': 'users',
'guards': {
'users': {'driver': 'token', 'provider': 'users'},
},
'providers': {
'users': {
'table': 'users',
'primary_key': 'id',
'fields': ['email'],
},
},
},
};
}
lib/core/ Directory
Contains the application kernel that handles bootstrapping, service registration, and core framework setup:
// lib/core/kernel.dart
import 'package:khadem/khadem_dart.dart';
import '../app/providers/app_service_provider.dart';
import '../app/providers/event_service_provider.dart';
import '../app/providers/scheduler_service_provider.dart';
import '../../config/app.dart';
import '../database/migrations/migrations.dart';
class Kernel {
Kernel._();
static List<ServiceProvider> get coreProviders => [
QueueServiceProvider(),
AuthServiceProvider(),
DatabaseServiceProvider(),
];
static List<ServiceProvider> get applicationProviders => [
AppServiceProvider(),
EventServiceProvider(),
SchedulerServiceProvider(),
];
static List<ServiceProvider> get allProviders => [
...coreProviders,
...applicationProviders,
];
static List<Middleware> get middlewares => [
CorsMiddleware(),
LoggingMiddleware(),
SetLocaleMiddleware(),
];
static final Map<String, Map<String, dynamic>> configs = AppConfig.configs;
static List<MigrationFile> get migrations => migrationsFiles;
static Future<void> bootstrap() async {
await Khadem.registerCoreServices();
Khadem.register(allProviders);
Khadem.loadConfigs(configs);
await Khadem.boot();
if (configs['database']?['run_migrations'] == true) {
await Khadem.migrator.upAll(migrations);
}
}
}
lib/database/ Directory
Database-related files including migrations and seeders:
- migrations/ - Database schema changes and migrations.dart registry
- seeders/ - Database seeding scripts
lib/database/
├── migrations/
│ ├── 001_create_users_table.dart
│ ├── 002_create_posts_table.dart
│ ├── 003_add_user_id_to_posts.dart
│ └── migrations.dart
└── seeders/
├── database_seeder.dart
├── user_seeder.dart
└── post_seeder.dart
storage/ Directory
File storage system with organized subdirectories:
- app/ - Application-specific files
- framework/ - Framework cache, sessions, and views
- logs/ - Application log files
storage/
├── app/
│ ├── public/
│ └── private/
├── framework/
│ ├── cache/
│ │ ├── data/
│ │ └── views/
│ ├── sessions/
│ └── views/
└── logs/
├── khadem.log
└── error.log
lang/ Directory
Localization files for multi-language support:
- ar/ - Arabic language files
- en/ - English language files
public/ Directory
Publicly accessible files served directly by the web server:
- index.html - Default HTML page
- assets/ - Static assets (CSS, JS, images)
resources/ Directory
Application resources like views and templates:
- views/ - Template files for rendering
lib/main.dart
The main application entry point following Dart package conventions:
- lib/main.dart - Application bootstrap and server startup
// lib/main.dart
import 'dart:async';
import 'dart:io';
import 'package:khadem/khadem_dart.dart';
import 'lib/core/kernel.dart';
import '../routes/socket.dart';
import '../routes/web.dart';
Future<void> main(List<String> args) async {
if (_isSnapshotBuild()) return;
final container = Khadem.container;
await Kernel.bootstrap();
final port = _extractPort(args) ?? Khadem.env.getInt("APP_PORT", defaultValue: 8080);
await Future.wait([
_startHttpServer(port, container),
_startSocketServer(container, Khadem.socket),
]);
}
bool _isSnapshotBuild() => Platform.environment.containsKey('KHADIM_JIT_TRAINING');
Future _startHttpServer(int port, ContainerInterface container) async {
final server = Server();
registerRoutes(server);
server.setInitializer(() async {
registerRoutes(server);
await server.start(port: port);
});
await server.reload();
}
Future<void> _startSocketServer(container, manager) async {
final socketPort = Khadem.env.getInt("SOCKET_PORT", defaultValue: 8080);
final socketServer = SocketServer(socketPort, manager: manager);
registerSocketRoutes(socketServer);
await socketServer.start();
}
int? _extractPort(List<String> args) {
final portIndex = args.indexOf('--port');
if (portIndex != -1 && args.length > portIndex + 1) {
return int.tryParse(args[portIndex + 1]);
}
return null;
}
bin/ Directory
CLI entry points and command-line scripts:
- server.dart - CLI wrapper for the main application
// lib/main.dart
import '../lib/main.dart' as app;
Future<void> main(List<String> args) async {
await app.main(args);
}
tests/ Directory
Unit and integration tests for your application:
- Unit tests for individual components
- Integration tests for full workflows
- Test utilities and mocks
Configuration Files
pubspec.yaml
Dart project configuration and dependencies:
name: my_api
description: A new Khadem Dart project.
version: 1.0.0
environment:
sdk: '>=3.0.0 <4.0.0'
dependencies:
khadem:
path: ../khadem
dev_dependencies:
lints: ^6.0.0
build_runner: ^2.4.6
.env
Environment variables for configuration:
# Application Configuration
APP_NAME=MyFirstAPI
APP_ENV=development
APP_PORT=8080
APP_LOCALE=en
# Database Configuration (MySQL)
DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=my_first_api_db
DB_USERNAME=root
DB_PASSWORD=
# JWT Authentication
JWT_SECRET="your-super-secret-jwt-key-here"
JWT_ACCESS_EXPIRY_MINUTES=60
JWT_REFRESH_EXPIRY_DAYS=30
.gitignore
Git ignore patterns for Dart/Khadem projects:
# Dart
.dart_tool/
.packages
pubspec.lock
# Environment variables
.env
.env.local
.env.*.local
# Build outputs
build/
.dart_tool/
# IDEs
.vscode/
.idea/
*.swp
*.swo
# OS
.DS_Store
Thumbs.db
# Logs
*.log
logs/
# Temporary files
tmp/
temp/
# Test coverage
coverage/
# Khadem specific
storage/framework/cache/*
storage/framework/sessions/*
storage/framework/views/*
storage/logs/*
Best Practices
✅ Do's
- • Keep controllers thin and delegate to services
- • Use meaningful names for files and directories
- • Group related functionality together
- • Follow the single responsibility principle
❌ Don'ts
- • Don't put business logic in controllers
- • Don't create deep directory nesting
- • Don't mix different concerns in one file
- • Don't hardcode configuration values
Customizing the Structure
While Khadem provides a solid foundation, you can customize the structure to fit your needs:
⚠️ Important
When customizing the structure, ensure you update the corresponding imports and service registrations in lib/core/kernel.dart
.
Adding New Directories
You can add custom directories for specific functionality:
my_api/
├── lib/
│ ├── app/
│ │ ├── http/
│ │ ├── services/
│ │ │ ├── payment/
│ │ │ │ ├── stripe_service.dart
│ │ │ │ └── paypal_service.dart
│ │ │ └── notification/
│ │ │ ├── email_service.dart
│ │ │ └── sms_service.dart
│ │ └── repositories/
│ │ ├── user_repository.dart
│ │ └── post_repository.dart
│ ├── core/
│ └── database/
├── config/
│ ├── payment.dart
│ └── notification.dart
└── tests/
├── unit/
│ ├── services/
│ └── repositories/
└── feature/
├── payment/
└── notification/
Next Steps
Now that you understand the project structure: