Skip to content

DomoAppStudio

DomoAppStudio

DomoAppStudio package.

AppStudioDefinition dataclass

AppStudioDefinition(
    data_app_id: int,
    title: str,
    enabled: bool = True,
    locked: bool = False,
    description: str | None = None,
    landing_view_id: int | None = None,
    nav_orientation: str = "TOP",
    show_domo_navigation: bool = True,
    show_logo: bool = False,
    show_navigation: bool = True,
    show_title: bool = True,
    app_type: str = "app",
    theme: dict | None = None,
    navigations: list[AppStudioNavigation] = list(),
    views: list[AppStudioViewRef] = list(),
    persist_settings: (
        AppStudioPersistSettings | None
    ) = None,
    owners: list[dict] = list(),
    icon_data_file_id: int = 0,
    nav_icon_data_file_id: int | None = None,
)

Typed representation of the v1/dataapps API response.

Contains app-level metadata: title, theme, navigation, views, etc. Use via DomoAppStudio.Definition.get() / .update().

AppStudioNavigation dataclass

AppStudioNavigation(
    data_app_id: int,
    entity: str,
    entity_id: str,
    title: str,
    nav_order: int,
    visible: bool,
    description: str | None = None,
    interaction: dict | None = None,
    icon: dict | None = None,
    icon_position: str | None = None,
    style: dict | None = None,
)

Navigation item in an AppStudio app.

AppStudioPersistSettings dataclass

AppStudioPersistSettings(
    data_app_id: int,
    persist_filters_enabled: bool = False,
    persist_interactions_enabled: bool = False,
    persist_date_enabled: bool = False,
    persist_variables_enabled: bool = False,
    persisted_columns: list = list(),
)

Persist settings for an AppStudio app.

AppStudioStylePreset dataclass

AppStudioStylePreset(
    name: str,
    nav_orientation: str = "TOP",
    show_domo_navigation: bool = False,
    show_logo: bool = True,
    show_title: bool = True,
    background_color: str = "#FFFFFF",
    text_color: str = "#333333",
    dark_mode: bool = False,
    hide_borders: bool = True,
    hide_margins: bool = True,
    hide_footers: bool = True,
    fit_to_frame: bool = True,
    card_spacing: int = 4,
)

Pre-built styling configuration for AppStudio apps.

Captures the most common styling knobs in a single object so they can be applied consistently to both the app definition and every view layout.

Attributes:

Name Type Description
name str

Human-readable preset name.

nav_orientation str

Navigation bar position — TOP, LEFT, RIGHT, BOTTOM.

show_domo_navigation bool

Whether to show the Domo chrome navigation bar.

show_logo bool

Whether to show the instance logo.

show_title bool

Whether to show the app title.

background_color str

Hex color for the page background.

text_color str

Hex color for text on the background.

dark_mode bool

Whether the background is dark (affects Domo rendering).

hide_borders bool

Whether to hide card borders.

hide_margins bool

Whether to hide card margins.

hide_footers bool

Whether to hide card footers.

fit_to_frame bool

Whether cards should fit to their frame.

card_spacing int

Page density / card spacing in pixels.

AppStudioViewRef dataclass

AppStudioViewRef(
    view_id: int,
    title: str,
    parent_view_id: int = 0,
    view_order: int = 1,
    visible: bool = True,
    children: list = list(),
)

Reference to a view (page) within an AppStudio app.

This is a lightweight reference — the actual DomoPage is fetched separately via the Views manager.

DomoAppStudio dataclass

DomoAppStudio(
    auth: DomoAuth,
    id: int,
    raw: dict,
    title: str = None,
    is_locked: bool = None,
    owners: list = list(),
    custom_attributes: dict = dict(),
    Lineage: DomoLineage = None,
    Definition: (
        DomoAppStudio_DefinitionManager | None
    ) = None,
    Views: DomoAppStudio_ViewsManager | None = None,
)

Bases: DomoEntity_w_Lineage

from_dict classmethod

from_dict(auth: DomoAuth, obj: dict[str, Any])

Create a DomoAppStudio instance from a dictionary representation.

Source code in src/crew_dcs/classes/DomoAppStudio/core.py
165
166
167
168
@classmethod
def from_dict(cls, auth: DomoAuth, obj: dict[str, Any]):
    """Create a DomoAppStudio instance from a dictionary representation."""
    return cls._from_content_stacks_v3(page_obj=obj, auth=auth)

optimize_style async

optimize_style(
    preset_name: str = "minimal_light",
    save: bool = True,
    *,
    context: RouteContext | None = None,
    **context_kwargs
)

Apply a style preset to the entire app (definition + all views).

Convenience method that delegates to the styling optimizer module.

Parameters:

Name Type Description Default
preset_name str

Name of the preset to apply (case-insensitive). Available presets: MINIMAL_LIGHT, MINIMAL_DARK, EXECUTIVE, DENSE.

'minimal_light'
save bool

If True, saves all changes to the API.

True
context RouteContext | None

Optional RouteContext for request configuration.

None
**context_kwargs

Additional context parameters.

{}

Returns:

Type Description

The updated AppStudioDefinition.

Source code in src/crew_dcs/classes/DomoAppStudio/core.py
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
async def optimize_style(
    self,
    preset_name: str = "minimal_light",
    save: bool = True,
    *,
    context: RouteContext | None = None,
    **context_kwargs,
):
    """Apply a style preset to the entire app (definition + all views).

    Convenience method that delegates to the styling optimizer module.

    Args:
        preset_name: Name of the preset to apply (case-insensitive).
            Available presets: MINIMAL_LIGHT, MINIMAL_DARK, EXECUTIVE, DENSE.
        save: If True, saves all changes to the API.
        context: Optional RouteContext for request configuration.
        **context_kwargs: Additional context parameters.

    Returns:
        The updated AppStudioDefinition.
    """
    from .styling_optimizer import get_preset_by_name, optimize_app

    context = RouteContext.build_context(context=context, **context_kwargs)
    preset = get_preset_by_name(preset_name)

    return await optimize_app(
        app=self,
        preset=preset,
        save=save,
        context=context,
    )

DomoAppStudio_DefinitionManager dataclass

DomoAppStudio_DefinitionManager(
    parent: DomoEntity,
    definition: AppStudioDefinition | None = None,
)

Bases: DomoSubEntity

Manager for app-level metadata (title, theme, navigation, views).

Usage

app = await DomoAppStudio.get_by_id(auth=auth, appstudio_id='667742883') await app.Definition.get() app.Definition.title # "Dynamic card rendering" app.Definition.update() # push current state

apply_style async

apply_style(
    preset=None,
    *,
    context: RouteContext | None = None,
    **context_kwargs
) -> AppStudioDefinition

Apply a style preset to the app definition and save.

Fetches the definition if not already loaded, applies the preset, and saves the updated definition to the API.

Parameters:

Name Type Description Default
preset

An AppStudioStylePreset instance. Defaults to MINIMAL_LIGHT.

None
context RouteContext | None

Optional RouteContext for request configuration

None
**context_kwargs

Additional context parameters

{}

Returns:

Type Description
AppStudioDefinition

The updated AppStudioDefinition.

Source code in src/crew_dcs/classes/DomoAppStudio/definition.py
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
async def apply_style(
    self,
    preset=None,
    *,
    context: RouteContext | None = None,
    **context_kwargs,
) -> AppStudioDefinition:
    """Apply a style preset to the app definition and save.

    Fetches the definition if not already loaded, applies the preset,
    and saves the updated definition to the API.

    Args:
        preset: An AppStudioStylePreset instance. Defaults to MINIMAL_LIGHT.
        context: Optional RouteContext for request configuration
        **context_kwargs: Additional context parameters

    Returns:
        The updated AppStudioDefinition.
    """
    from .styling_optimizer import (
        MINIMAL_LIGHT,
        apply_preset_to_definition,
    )

    context = RouteContext.build_context(context=context, **context_kwargs)

    preset = preset or MINIMAL_LIGHT

    if not self.definition:
        await self.get(context=context)

    apply_preset_to_definition(self.definition, preset)
    await self.update(context=context)

    return self.definition

get async

get(
    *, context: RouteContext | None = None, **context_kwargs
) -> AppStudioDefinition

Fetch the app definition from the v1/dataapps API.

Parameters:

Name Type Description Default
context RouteContext | None

Optional RouteContext for request configuration

None
**context_kwargs

Additional context parameters

{}

Returns:

Type Description
AppStudioDefinition

AppStudioDefinition with typed access to all app metadata

Source code in src/crew_dcs/classes/DomoAppStudio/definition.py
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
async def get(
    self,
    *,
    context: RouteContext | None = None,
    **context_kwargs,
) -> AppStudioDefinition:
    """Fetch the app definition from the v1/dataapps API.

    Args:
        context: Optional RouteContext for request configuration
        **context_kwargs: Additional context parameters

    Returns:
        AppStudioDefinition with typed access to all app metadata
    """
    context = RouteContext.build_context(context=context, **context_kwargs)

    res = await appstudio_routes.get_appstudio_by_id(
        auth=self.parent.auth,
        appstudio_id=str(self.parent.id),
        context=context,
    )

    self.definition = AppStudioDefinition.from_dict(res.response)
    return self.definition

update async

update(
    *, context: RouteContext | None = None, **context_kwargs
) -> bool

Push the current definition state to the v1/dataapps API.

Parameters:

Name Type Description Default
context RouteContext | None

Optional RouteContext for request configuration

None
**context_kwargs

Additional context parameters

{}

Returns:

Type Description
bool

True if successful, raises AppStudio_CRUD_Error otherwise

Source code in src/crew_dcs/classes/DomoAppStudio/definition.py
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
async def update(
    self,
    *,
    context: RouteContext | None = None,
    **context_kwargs,
) -> bool:
    """Push the current definition state to the v1/dataapps API.

    Args:
        context: Optional RouteContext for request configuration
        **context_kwargs: Additional context parameters

    Returns:
        True if successful, raises AppStudio_CRUD_Error otherwise
    """
    context = RouteContext.build_context(context=context, **context_kwargs)

    if not self.definition:
        raise ValueError("Definition not loaded. Call get() first.")

    res = await appstudio_routes.update_appstudio(
        auth=self.parent.auth,
        appstudio_id=str(self.parent.id),
        body=self.definition.get_body(),
        context=context,
    )

    return res.is_success

DomoAppStudio_ViewsManager dataclass

DomoAppStudio_ViewsManager(
    parent: DomoEntity, views: list[Any] = list()
)

Bases: DomoSubEntity

Manager for AppStudio views as DomoPage instances.

Each view in an AppStudio app IS a page — this manager fetches view IDs from the app definition and hydrates them as DomoPage objects, giving you full access to Layout.get(), Layout.swap_cards(), etc.

Usage

app = await DomoAppStudio.get_by_id(auth=auth, appstudio_id='667742883') await app.Views.get() for view in app.Views.views: print(f'View: {view.title} (page_id={view.id})') await view.Layout.get() await view.Layout.swap_cards({0: 123456})

get async

get(
    *, context: RouteContext | None = None, **context_kwargs
) -> list[Any]

Fetch all views as DomoPage instances.

Requires that the app definition has been loaded (via Definition.get() or get_by_id). Hydrates each view_id into a full DomoPage.

Parameters:

Name Type Description Default
context RouteContext | None

Optional RouteContext for request configuration

None
**context_kwargs

Additional context parameters

{}

Returns:

Type Description
list[Any]

List of DomoPage instances, one per view

Source code in src/crew_dcs/classes/DomoAppStudio/definition.py
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
async def get(
    self,
    *,
    context: RouteContext | None = None,
    **context_kwargs,
) -> list[Any]:
    """Fetch all views as DomoPage instances.

    Requires that the app definition has been loaded (via Definition.get()
    or get_by_id). Hydrates each view_id into a full DomoPage.

    Args:
        context: Optional RouteContext for request configuration
        **context_kwargs: Additional context parameters

    Returns:
        List of DomoPage instances, one per view
    """
    from .. import DomoPage as dp

    context = RouteContext.build_context(context=context, **context_kwargs)

    # Get view IDs from the definition
    if not self.parent.Definition or not self.parent.Definition.definition:
        await self.parent.Definition.get(context=context)

    view_refs = self.parent.Definition.definition.views
    if not view_refs:
        self.views = []
        return self.views

    # Hydrate each view as a DomoPage
    self.views = []
    for view_ref in view_refs:
        page = await dp.DomoPage.get_by_id(
            auth=self.parent.auth,
            page_id=str(view_ref.view_id),
            include_layout=True,
            context=context,
        )
        self.views.append(page)

    return self.views

DomoAppStudios dataclass

DomoAppStudios()

get_appstudios async classmethod

get_appstudios(
    auth=DomoAuth,
    return_raw: bool = False,
    debug_api: bool = False,
    debug_loop: bool = False,
    session: AsyncClient = None,
    *,
    context: RouteContext | None = None,
    **context_kwargs
)

use admin_summary to retrieve all appstudios in an instance -- regardless of user access NOTE: some appstudios APIs will not return results if appstudio access isn't explicitly shared

Source code in src/crew_dcs/classes/DomoAppStudio/core.py
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
@classmethod
async def get_appstudios(
    cls,
    auth=DomoAuth,
    return_raw: bool = False,
    debug_api: bool = False,
    debug_loop: bool = False,
    session: httpx.AsyncClient = None,
    *,
    context: RouteContext | None = None,
    **context_kwargs,
):
    """use admin_summary to retrieve all appstudios in an instance -- regardless of user access
    NOTE: some appstudios APIs will not return results if appstudio access isn't explicitly shared
    """
    is_close_session = not session

    session = session or httpx.AsyncClient()

    context = RouteContext.build_context(
        session=session,
        debug_api=debug_api,
        parent_class=cls.__name__,
        **context_kwargs,
    )

    try:
        res = await appstudio_routes.get_appstudios_adminsummary(
            auth=auth, debug_loop=debug_loop, context=context
        )

        if return_raw:
            return res

        if not res.is_success:
            raise Exception("unable to retrieve appstudios")

        return await dmce.gather_with_concurrency(
            n=60,
            *[  # noqa: B026
                DomoAppStudio._from_adminsummary(
                    page_obj, auth=auth, context=context
                )
                for page_obj in res.response
            ],
        )

    finally:
        if is_close_session:
            await session.aclose()

apply_preset_to_definition

apply_preset_to_definition(
    definition: AppStudioDefinition,
    preset: AppStudioStylePreset,
) -> AppStudioDefinition

Apply a style preset to an AppStudioDefinition.

Mutates the definition in-place and returns it for chaining.

Sets
  • nav_orientation
  • show_domo_navigation
  • show_logo
  • show_title
  • theme (updated with background_color and text_color if present)

Parameters:

Name Type Description Default
definition AppStudioDefinition

The AppStudioDefinition to modify.

required
preset AppStudioStylePreset

The style preset to apply.

required

Returns:

Type Description
AppStudioDefinition

The same definition object, mutated in-place.

Source code in src/crew_dcs/classes/DomoAppStudio/styling_optimizer.py
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
def apply_preset_to_definition(
    definition: AppStudioDefinition,
    preset: AppStudioStylePreset,
) -> AppStudioDefinition:
    """Apply a style preset to an AppStudioDefinition.

    Mutates the definition in-place and returns it for chaining.

    Sets:
        - nav_orientation
        - show_domo_navigation
        - show_logo
        - show_title
        - theme (updated with background_color and text_color if present)

    Args:
        definition: The AppStudioDefinition to modify.
        preset: The style preset to apply.

    Returns:
        The same definition object, mutated in-place.
    """
    definition.nav_orientation = preset.nav_orientation
    definition.show_domo_navigation = preset.show_domo_navigation
    definition.show_logo = preset.show_logo
    definition.show_title = preset.show_title

    # Update theme dict with preset colors
    if definition.theme is None:
        definition.theme = {}

    definition.theme["backgroundColor"] = preset.background_color
    definition.theme["textColor"] = preset.text_color
    definition.theme["darkMode"] = preset.dark_mode

    return definition

apply_preset_to_layout

apply_preset_to_layout(
    layout, preset: AppStudioStylePreset
)

Apply a style preset to a PageLayout.

Mutates the layout in-place and returns it for chaining.

Sets
  • background.selected_color, text_color, is_darkMode
  • For each CARD content: hide_border, hide_margins, hide_footer, fit_to_frame

Parameters:

Name Type Description Default
layout

The PageLayout to modify.

required
preset AppStudioStylePreset

The style preset to apply.

required

Returns:

Type Description

The same layout object, mutated in-place.

Source code in src/crew_dcs/classes/DomoAppStudio/styling_optimizer.py
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
def apply_preset_to_layout(layout, preset: AppStudioStylePreset):
    """Apply a style preset to a PageLayout.

    Mutates the layout in-place and returns it for chaining.

    Sets:
        - background.selected_color, text_color, is_darkMode
        - For each CARD content: hide_border, hide_margins, hide_footer, fit_to_frame

    Args:
        layout: The PageLayout to modify.
        preset: The style preset to apply.

    Returns:
        The same layout object, mutated in-place.
    """
    # Update page-level background
    if layout.background is not None:
        layout.background.selected_color = preset.background_color
        layout.background.text_color = preset.text_color
        layout.background.is_darkMode = preset.dark_mode

    # Update each CARD content slot
    for content in layout.content:
        if content.type == "CARD":
            content.hide_border = preset.hide_borders
            content.hide_margins = preset.hide_margins
            content.hide_footer = preset.hide_footers
            content.fit_to_frame = preset.fit_to_frame

    return layout

get_preset_by_name

get_preset_by_name(name: str) -> AppStudioStylePreset

Look up a preset by name (case-insensitive).

Parameters:

Name Type Description Default
name str

Preset name, e.g. "minimal_light" or "MINIMAL_LIGHT".

required

Returns:

Type Description
AppStudioStylePreset

The matching AppStudioStylePreset.

Raises:

Type Description
ValueError

If no preset matches the given name.

Source code in src/crew_dcs/classes/DomoAppStudio/styling_optimizer.py
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
def get_preset_by_name(name: str) -> AppStudioStylePreset:
    """Look up a preset by name (case-insensitive).

    Args:
        name: Preset name, e.g. "minimal_light" or "MINIMAL_LIGHT".

    Returns:
        The matching AppStudioStylePreset.

    Raises:
        ValueError: If no preset matches the given name.
    """
    key = name.upper()
    if key not in PRESETS:
        available = ", ".join(sorted(PRESETS.keys()))
        raise ValueError(f"Unknown preset '{name}'. Available presets: {available}")
    return PRESETS[key]

optimize_app async

optimize_app(
    app,
    preset: AppStudioStylePreset | None = None,
    save: bool = True,
    *,
    context: RouteContext | None = None,
    **context_kwargs
) -> AppStudioDefinition

Apply a style preset to an entire AppStudio app.

Fetches the definition (if not already loaded), applies the preset to the definition, fetches all views, applies the preset to each view's layout, and optionally saves all changes.

Parameters:

Name Type Description Default
app

A DomoAppStudio instance.

required
preset AppStudioStylePreset | None

The style preset to apply. Defaults to MINIMAL_LIGHT.

None
save bool

If True, saves definition and layout changes to the API.

True
context RouteContext | None

Optional RouteContext for request configuration.

None
**context_kwargs

Additional context parameters.

{}

Returns:

Type Description
AppStudioDefinition

The AppStudioDefinition after applying the preset.

Source code in src/crew_dcs/classes/DomoAppStudio/styling_optimizer.py
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
async def optimize_app(
    app,
    preset: AppStudioStylePreset | None = None,
    save: bool = True,
    *,
    context: RouteContext | None = None,
    **context_kwargs,
) -> AppStudioDefinition:
    """Apply a style preset to an entire AppStudio app.

    Fetches the definition (if not already loaded), applies the preset
    to the definition, fetches all views, applies the preset to each
    view's layout, and optionally saves all changes.

    Args:
        app: A DomoAppStudio instance.
        preset: The style preset to apply. Defaults to MINIMAL_LIGHT.
        save: If True, saves definition and layout changes to the API.
        context: Optional RouteContext for request configuration.
        **context_kwargs: Additional context parameters.

    Returns:
        The AppStudioDefinition after applying the preset.
    """
    from ...utils import chunk_execution as dmce

    context = RouteContext.build_context(context=context, **context_kwargs)
    preset = preset or MINIMAL_LIGHT

    # 1. Fetch definition if not loaded
    if not app.Definition.definition:
        await app.Definition.get(context=context)

    # 2. Apply preset to definition
    apply_preset_to_definition(app.Definition.definition, preset)

    # 3. Save definition if requested
    if save:
        await app.Definition.update(context=context)

    # 4. Fetch all views
    if not app.Views.views:
        await app.Views.get(context=context)

    # 5. Apply preset to each view's layout and save
    async def _apply_and_save_layout(view):
        if not view.Layout.layout:
            await view.Layout.get(context=context)

        apply_preset_to_layout(view.Layout.layout, preset)

        if save:
            await view.Layout.update(context=context)

    if app.Views.views:
        await dmce.gather_with_concurrency(
            n=10,
            *[_apply_and_save_layout(view) for view in app.Views.views],  # noqa: B026
        )

    return app.Definition.definition

Modules