How to Use — Recommended LookML Project Structure ================================================== Droughty generates your base LookML layer automatically, but it generates into a larger project that you own and extend. This guide describes the folder structure used by production Looker projects built on top of droughty, explains what belongs where, and shows how the generated files slot in. .. note:: This is the structure used on multi-schema dbt + BigQuery or Snowflake projects. The folder names are conventions, not requirements — Looker only cares about ``include:`` paths. But consistent naming makes projects far easier to navigate. ---- Full folder structure --------------------- .. code-block:: text lookml/ ├── models/ │ └── my_project.model.lkml # Model file — declares explores and global includes │ ├── base/ # ← droughty writes here — DO NOT edit these files │ ├── _base.layer.lkml # Base views generated from warehouse schema │ ├── _aggregate.layer.lkml # Base views for aggregate tables │ └── _base_parameters.layer.lkml # PoP parameters layer (if lookml_pop is configured) │ ├── staging/ # Refinements of base views — light customisations │ ├── stg_commerce.layer.lkml │ ├── stg_finance.layer.lkml │ ├── stg_core.layer.lkml │ └── stg_marketing.layer.lkml │ ├── int/ # Integration layer — explores, joins, business logic │ ├── int_explore_commerce.explore.lkml │ ├── int_explore_finance.explore.lkml │ ├── int_explore_core.explore.lkml │ └── int_explore_marketing.explore.lkml │ ├── aggregate/ # Aggregate-awareness layers │ ├── agg_commerce.layer.lkml │ ├── agg_finance.layer.lkml │ ├── agg_core.layer.lkml │ └── agg_marketing.layer.lkml │ ├── derived/ # Derived tables (PDTs) │ ├── utils/ # Shared utility dimensions and measures │ └── utils_period_boundaries.layer.lkml │ └── dashboards/ # LookML dashboard definitions ├── commerce__orders_overview.dashboard.lookml ├── commerce__customers_retention.dashboard.lookml └── ... ---- What goes in each folder ------------------------- base/ ~~~~~ **Auto-generated by droughty. Never edit these files.** This folder is the contract between your warehouse schema and Looker. Every table in your analytics schema gets a view here, and every column gets a dimension. When the schema changes, you run ``droughty lookml`` and these files are overwritten. Files droughty writes here: .. list-table:: :header-rows: 1 :widths: 45 55 * - File - Source * - ``_base.layer.lkml`` - ``droughty lookml`` — views from your analytics schema * - ``_aggregate.layer.lkml`` - ``droughty lookml`` — views from aggregate tables (if configured) * - ``_base_parameters.layer.lkml`` - ``droughty lookml`` — PoP refinements (if ``lookml_pop`` is configured) Because these are ``.layer.lkml`` files (using Looker `refinements `_), they extend the base view definitions rather than replacing them. staging/ ~~~~~~~~ **You own these files.** Refinements of the base views — the right place for: - Hiding or relabelling dimensions that don't belong in Looker - Overriding ``sql:`` for computed fields - Adding ``drill_fields`` sets - Setting field-level access filters - Adding ``tags`` for content organisation File naming convention: ``stg_{domain}.layer.lkml`` — one file per domain or functional area. Each file uses ``view: +table_name { }`` blocks (refinements) so its changes stack on top of the base layer without touching it. **Example** (``stg_commerce.layer.lkml``): .. code-block:: text view: +fct_orders { dimension: order_pk { hidden: yes # already hidden by droughty but confirmed explicitly here } dimension: order_status { label: "Status" tags: ["commerce", "orders"] } measure: total_revenue { type: sum sql: ${order_value} ;; value_format_name: gbp } } int/ ~~~~ **You own these files.** The integration (explore) layer — where you define explores and their joins. This is what Looker users actually see when they open an explore. Use ``.explore.lkml`` for files that contain ``explore:`` blocks, and ``.layer.lkml`` for files that only add refinements to explores. File naming convention: ``int_explore_{domain}.explore.lkml`` **Example** (``int_explore_commerce.explore.lkml``): .. code-block:: text explore: fct_orders { label: "Orders" join: dim_customers { type: left_outer sql_on: ${fct_orders.customer_fk} = ${dim_customers.customer_pk} ;; relationship: many_to_one } join: dim_products { type: left_outer sql_on: ${fct_orders.product_fk} = ${dim_products.product_pk} ;; relationship: many_to_one } } aggregate/ ~~~~~~~~~~ **You own these files.** `Aggregate awareness `_ layers — Looker-level rollup tables that let it query pre-aggregated data instead of scanning the full fact table when possible. Only needed if you have aggregate tables in your warehouse (e.g. daily/monthly rollup tables built in dbt). The file points Looker at the aggregate view and maps its fields to those in the fact explore. utils/ ~~~~~~ **You own these files.** Shared utility dimensions and measures that are reused across multiple views or explores. Common examples: - Period boundary dimensions (``utils_period_boundaries.layer.lkml``) - Shared fiscal calendar logic - Currency conversion dimensions dashboards/ ~~~~~~~~~~~ **You own these files.** `LookML dashboards `_ — version-controlled dashboard definitions. These allow dashboards to be deployed with the LookML project rather than created ad-hoc in the Looker UI. derived/ ~~~~~~~~ **You own these files.** `Persistent Derived Tables (PDTs) `_ — SQL or LookML-defined derived tables that Looker materialises in the warehouse. models/ ~~~~~~~ **You own this file.** The model file ties the project together. It declares which explores are available in the project and which files to include: **Example** (``my_project.model.lkml``): .. code-block:: text connection: "my_bigquery_connection" # Base layer (generated by droughty) include: "/lookml/base/_base.layer.lkml" include: "/lookml/base/_aggregate.layer.lkml" include: "/lookml/base/_base_parameters.layer.lkml" # Staging refinements include: "/lookml/staging/*.layer.lkml" # Utility layers include: "/lookml/utils/*.layer.lkml" # Aggregate awareness include: "/lookml/aggregate/*.layer.lkml" # Explores include: "/lookml/int/*.lkml" # Dashboards include: "/lookml/dashboards/*.dashboard.lookml" The order of includes matters: base must be included before staging, and staging before int, so each layer can reference the one below it. ---- The layering principle ----------------------- The structure follows a strict bottom-up dependency order. Each layer only references layers below it: .. code-block:: text ┌──────────────────────────────────┐ │ dashboards/ │ What users see ├──────────────────────────────────┤ │ int/ (explores) │ Joins and business logic ├──────────────────────────────────┤ │ aggregate/ utils/ │ Performance + shared logic ├──────────────────────────────────┤ │ staging/ │ Your refinements ├──────────────────────────────────┤ │ base/ ← droughty generates │ Auto-synced from warehouse └──────────────────────────────────┘ The key constraint: **never put anything in** ``base/`` **that you'd have to maintain manually**. Everything you'd normally put in a base view — labels, tags, custom measures, access filters — belongs in ``staging/`` instead. That way ``droughty lookml`` can safely overwrite ``base/`` at any time. ---- droughty_project.yaml for this structure ------------------------------------------ To match the folder layout above, set these paths in your ``droughty_project.yaml``: .. code-block:: yaml profile: my_profile lookml_path: lookml/base lookml_base_filename: _base.layer lookml_explore_filename: _explores lookml_measures_filename: _measures With ``lookml_pop`` configured, the PoP file lands in the same ``lookml/base/`` folder: .. code-block:: yaml lookml_pop: views: fct_orders: - order_date This generates ``lookml/base/_base_parameters.layer.lkml`` — the PoP filename is fixed and is not affected by ``lookml_base_filename``. See :doc:`howto_lookml_pop` for full PoP setup details. ---- File naming conventions ------------------------ .. list-table:: :header-rows: 1 :widths: 30 35 35 * - Pattern - Extension - Contains * - ``_base`` - ``.layer.lkml`` - Base views (droughty-generated) * - ``stg_{domain}`` - ``.layer.lkml`` - Staging refinements * - ``int_explore_{domain}`` - ``.explore.lkml`` or ``.layer.lkml`` - Explore definitions * - ``agg_{domain}`` - ``.layer.lkml`` - Aggregate awareness * - ``utils_{name}`` - ``.layer.lkml`` - Utility dimensions * - ``{area}__{name}`` - ``.dashboard.lookml`` - LookML dashboards The double-underscore in dashboard filenames (``commerce__retail_cockpit``) is a convention for grouping dashboards by area in the Looker UI — Looker displays the first segment as a folder label.