Project templates

Rather than building everything from scratch, you can start from a Garvan project skeleton. The recommended layout matches what the bundled kalpasan CLI and garvan-migrate tools expect to find.

Directory layout

my-app/
├── app/
│   ├── controllers/        # request handlers, one class per resource
│   ├── models/             # database models extending OModel
│   └── services/           # business logic between controllers and models
├── db/
│   ├── migrations/         # SQL files run by garvan-migrate
│   └── seeders/            # initial data
├── public/                 # mustache templates (HTML)
├── static/                 # served at /static/* (css, js, images)
├── routes/
│   ├── ApiRoutes.cpp       # JSON / REST endpoints
│   └── WebRoutes.cpp       # HTML pages
├── vendors/Garvan/         # bundled libgarvan.a + headers
├── .env                    # environment configuration
├── CMakeLists.txt
└── main.cpp                # entry point: wires the routes

CMake template

A minimal CMakeLists.txt that follows the layout above:

cmake_minimum_required(VERSION 3.20)
project(MyApp CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)

file(GLOB_RECURSE SOURCES
    "main.cpp"
    "routes/*.cpp"
    "app/controllers/*.cpp"
    "app/models/*.cpp"
    "app/services/*.cpp"
)

add_executable(app_bin ${SOURCES})

target_include_directories(app_bin PRIVATE
    .
    vendors/Garvan
    vendors/Garvan/include
)

target_link_libraries(app_bin PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/vendors/Garvan/libgarvan.a
    pthread
)

set_target_properties(app_bin PROPERTIES OUTPUT_NAME app.bin)

From there, your main.cpp only needs to wire the routes together:

#include "vendors/Garvan/crow.h"
#include "routes/ApiRoutes.h"
#include "routes/WebRoutes.h"

using namespace Routes;

int main()
{
    crow::SimpleApp app;
    crow::mustache::set_global_base("public/");

    WebRoutes  webRoutes(app);
    ApiRoutes  apiRoutes(app);

    app.port(9090).multithreaded().run();
}