Project Structure
Panduan lengkap struktur folder dan file untuk memahami organisasi codebase.
📁 Root Structure
project-root/
├── backend/ # Go services
├── frontend/ # Flutter app
├── docs/ # Documentation (Mintlify)
├── docker-compose.yml # Dev services
├── Taskfile.yml # Task definitions
├── .env.example # Environment template
├── .gitignore
├── README.md
└── observability/ # LGTM configs
🔧 Backend Structure (Go)
backend/
├── cmd/
│ └── api/ # API Gateway
│ └── main.go
│
├── internal/
│ ├── route/ # 7-Domain Route Architecture
│ │ ├── route.go # Main router entry point
│ │ ├── v1/ # API V1 (Backward Compatible)
│ │ │ ├── route_registry.go
│ │ │ ├── core/
│ │ │ │ └── core_route.go
│ │ │ ├── ops/
│ │ │ │ ├── transaction_route.go
│ │ │ │ ├── inventory_route.go
│ │ │ │ └── pos_route.go
│ │ │ ├── support/
│ │ │ │ ├── finance_route.go
│ │ │ │ ├── hr_route.go
│ │ │ │ └── crm_route.go
│ │ │ ├── webhook/
│ │ │ │ └── webhook_route.go
│ │ │ ├── analytics/
│ │ │ ├── holding/
│ │ │ └── global/
│ │ └── v2/ # API V2 (Enhanced)
│ │ ├── route_registry.go
│ │ ├── core/
│ │ ├── ops/
│ │ ├── support/
│ │ ├── governance/
│ │ ├── analytics/
│ │ ├── holding/
│ │ └── global/
│ │
│ ├── domains/ # Business domains (services)
│ │ ├── auth/ # Auth domain
│ │ │ ├── handler/
│ │ │ ├── service/
│ │ │ ├── repository/
│ │ │ ├── model/
│ │ │ └── dto/
│ │ ├── transaction/
│ │ ├── inventory/
│ │ ├── pos/
│ │ ├── webhook/
│ │ └── ...
│ │
│ ├── middleware/ # HTTP middleware
│ │ ├── auth_middleware.go
│ │ ├── rbac_middleware.go
│ │ ├── audit_middleware.go
│ │ └── ...
│ │
│ ├── store/ # Handler registry
│ │ └── handler.go
│ │
│ └── shared/ # Shared packages
│ ├── config/ # Configuration
│ ├── database/ # DB connections
│ ├── logger/ # Logging
│ ├── validator/ # Validation
│ ├── errors/ # Error handling
│ └── utils/ # Utilities
│
├── pkg/ # Public packages
│ ├── common/
│ ├── utils/
│ └── response/
│
├── config/ # Config files
│ ├── api/
│ │ ├── endpoints-registry-v1.yaml
│ │ └── endpoints-registry-v2.yaml
│ ├── rbac/
│ │ ├── policy.csv
│ │ └── sod_rules.yaml
│ └── ...
│
├── migrations/ # Database migrations
│ ├── atlas/
│ │ └── schema/
│ └── ...
│
├── tests/ # Tests
│ ├── integration/
│ ├── e2e/
│ └── fixtures/
│
├── .air.toml # Air config (live reload)
├── go.mod
├── go.sum
├── Dockerfile
└── README.md
Backend File Examples
main.go
handler.go
service.go
repository.go
// cmd/api/main.go
package main
import (
"context"
"log"
"os"
"os/signal"
"syscall"
"github.com/your/project/internal/shared/config"
"github.com/your/project/internal/shared/database"
"github.com/your/project/internal/shared/logger"
)
func main() {
// Load config
cfg, err := config.Load()
if err != nil {
log.Fatal(err)
}
// Setup logger
logger := logger.New(cfg.Log)
// Connect to database
db, err := database.NewMySQL(cfg.Database)
if err != nil {
logger.Fatal("failed to connect database", err)
}
defer db.Close()
// Setup server
server := setupServer(cfg, db, logger)
// Graceful shutdown
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
go func() {
if err := server.Start(); err != nil {
logger.Fatal("server error", err)
}
}()
<-quit
logger.Info("shutting down server...")
if err := server.Shutdown(context.Background()); err != nil {
logger.Fatal("server shutdown error", err)
}
}
🧩 7-Domain Route Architecture
MStore Backend menggunakan 7-Domain Driven Architecture untuk route organization:
Domain Hierarchy
CORE (Foundation)
↓
OPS (Operational)
↓
SUPPORT (Backoffice)
↓
GOVERNANCE (Control)
↓
ANALYTICS (Insight)
↓
HOLDING (Multi-Entity)
↓
GLOBAL (Infrastructure)
V1 Routes (Backward Compatible)
| Domain | Endpoints | Status |
| CORE | 21 | ✅ Auth, User, Merchant, Branches, Roles |
| OPS | 37 | ✅ Stok, Transactions, POS, Inventory |
| SUPPORT | 0 | 📋 Placeholder (Finance, HR, CRM) |
| WEBHOOK | 1 | ✅ Xendit Payments |
V2 Routes (Enhanced)
| Domain | Endpoints | Status |
| CORE | 7 | ✅ Auth, Role, System |
| OPS | 20 | ✅ POS, Sales, Procurement, Inventory |
| SUPPORT | 20 | ✅ Finance, HR, CRM, Marketing, CS |
| GOVERNANCE | 7 | ✅ Audit, Dashboard, Holding, Global |
| ANALYTICS | 6 | ✅ Dashboard, BI, Forecast |
| HOLDING | 10 | ✅ Entity, Consolidation, Intercompany |
| GLOBAL | 12 | ✅ IAM, Security, Data Governance, ESG |
Total: 82 endpoints
Adding New Routes
- Create domain folder:
internal/route/v1/your-domain/
- Create route file:
your_domain_route.go
- Update
route_registry.go with import and call
- Build and test
See: 7-Domain Route Architecture
📱 Frontend Structure (Flutter)
frontend/
├── lib/
│ ├── main.dart
│ │
│ ├── core/ # Core functionality
│ │ ├── config/ # App configuration
│ │ │ ├── env.dart
│ │ │ └── theme.dart
│ │ ├── constants/ # Constants
│ │ │ ├── api_constants.dart
│ │ │ └── app_constants.dart
│ │ ├── di/ # Dependency injection
│ │ │ └── injection.dart
│ │ ├── network/ # Network layer
│ │ │ ├── dio_client.dart
│ │ │ ├── interceptors/
│ │ │ └── api_response.dart
│ │ ├── router/ # Navigation
│ │ │ └── app_router.dart
│ │ └── utils/ # Utilities
│ │ ├── logger.dart
│ │ └── validators.dart
│ │
│ ├── features/ # Feature modules
│ │ ├── auth/
│ │ │ ├── data/
│ │ │ │ ├── models/
│ │ │ │ ├── datasources/
│ │ │ │ └── repositories/
│ │ │ ├── domain/
│ │ │ │ ├── entities/
│ │ │ │ ├── repositories/
│ │ │ │ └── usecases/
│ │ │ └── presentation/
│ │ │ ├── pages/
│ │ │ ├── widgets/
│ │ │ └── providers/
│ │ │
│ │ ├── home/
│ │ │ ├── data/
│ │ │ ├── domain/
│ │ │ └── presentation/
│ │ │
│ │ ├── product/
│ │ │ ├── data/
│ │ │ ├── domain/
│ │ │ └── presentation/
│ │ │
│ │ └── order/
│ │ ├── data/
│ │ ├── domain/
│ │ └── presentation/
│ │
│ └── shared/ # Shared widgets & utils
│ ├── widgets/
│ │ ├── buttons/
│ │ ├── inputs/
│ │ ├── cards/
│ │ └── dialogs/
│ ├── extensions/
│ └── mixins/
│
├── test/ # Tests
│ ├── unit/
│ ├── widget/
│ └── integration/
│
├── assets/ # Assets
│ ├── images/
│ ├── icons/
│ └── fonts/
│
├── pubspec.yaml
├── analysis_options.yaml
└── README.md
Flutter File Examples
main.dart
dio_client.dart
provider.dart
// lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'core/config/theme.dart';
import 'core/di/injection.dart';
import 'core/router/app_router.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Setup dependencies
await setupDependencies();
runApp(
ProviderScope(
child: MyApp(),
),
);
}
class MyApp extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final router = ref.watch(routerProvider);
return MaterialApp.router(
title: 'Windsurf App',
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
routerConfig: router,
);
}
}
🐳 Docker & DevOps
docker-compose.yml # Dev services
Dockerfile # App container
.dockerignore
observability/
├── grafana/
│ ├── dashboards/
│ │ ├── api-performance.json
│ │ └── system-metrics.json
│ └── provisioning/
│ ├── datasources/
│ └── dashboards/
│
├── loki/
│ └── loki-config.yaml
│
├── tempo/
│ └── tempo-config.yaml
│
├── mimir/
│ └── mimir-config.yaml
│
└── promtail/
└── promtail-config.yaml
📚 Documentation
docs/
├── 00-getting-started/
├── 10-architecture/
├── 20-backend-go/
├── 30-frontend-flutter/
├── 40-database/
├── 50-observability-lgtm/
├── 60-devops-go/
├── 70-ci-cd/
├── 80-guides/
├── 90-features/
├── 95-technical-specs/
└── 99-changelog/
mint.json # Mintlify config
🔑 Key Files
Environment Files
.env.example
Taskfile.yml
.air.toml
# Application
APP_ENV=development
APP_NAME=windsurf-app
APP_PORT=8080
# Database
MYSQL_HOST=localhost
MYSQL_PORT=3306
MYSQL_USER=root
MYSQL_PASSWORD=secret
MYSQL_DATABASE=windsurf_db
MONGO_URI=mongodb://localhost:27017
MONGO_DATABASE=windsurf_mongo
# Redis
REDIS_HOST=localhost
REDIS_PORT=6379
# JWT
JWT_SECRET=your-secret-key
JWT_EXPIRY=24h
📊 Naming Conventions
Backend (Go)
- Packages: lowercase, single word (
handler, service, repository)
- Files: snake_case (
user_handler.go, auth_service.go)
- Types: PascalCase (
UserHandler, AuthService)
- Functions: camelCase (exported:
NewUserHandler, private: validateInput)
- Constants: UPPER_SNAKE_CASE atau PascalCase
- Interfaces: PascalCase dengan suffix (e.g.,
UserRepository, AuthService)
Frontend (Flutter)
- Files: snake_case (
login_page.dart, user_model.dart)
- Classes: PascalCase (
LoginPage, UserModel)
- Variables: camelCase (
userName, isLoading)
- Constants: lowerCamelCase atau UPPER_SNAKE_CASE
- Private: prefix underscore (
_privateMethod, _PrivateClass)
🎯 Best Practices
- Gunakan Clean Architecture (handler → service → repository)
- Pisahkan domain logic dari infrastructure
- Setiap service punya folder sendiri di
internal/
- Shared code di
internal/shared/ atau pkg/
- Test files sejajar dengan source files (
*_test.go)
- Gunakan Feature-First structure
- Setiap feature punya layer: data, domain, presentation
- Shared widgets di
shared/widgets/
- State management dengan Riverpod
- Dependency injection di
core/di/
- Naming:
{version}_{description}.{up|down}.sql
- Selalu buat up & down migration
- Test migration sebelum commit
- Jangan edit migration yang sudah di-deploy
- Environment variables untuk secrets
- YAML files untuk app config
- Jangan commit
.env file
- Provide
.env.example sebagai template
📚 Next Steps
Pro Tip: Gunakan VS Code workspace atau GoLand multi-project untuk membuka backend dan frontend secara bersamaan!