DEV Community

Prateek Kr
Prateek Kr

Posted on

Understanding app.config.ts in Angular 19 Standalone Applications — A Complete Guide

In this article, we’ll deep-dive into every line of a real-world app.config.ts file that integrates:

  • Angular Standalone APIs
  • PrimeNG theming (Lara theme)
  • NgRx Store + Effects + DevTools
  • HTTP Client with Fetch
  • Markdown rendering (ngx-markdown + PrismJS highlighting)
  • Zone optimization for better performance

By the end, you’ll understand how to structure, configure, and optimize your Angular 19 standalone app configuration file like a pro.

The Complete app.config.ts Code
Here’s the full configuration we’ll be dissecting:

import { ApplicationConfig, provideZoneChangeDetection, SecurityContext, isDevMode } from '@angular/core';
import { provideRouter } from '@angular/router';

import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { providePrimeNG } from 'primeng/config';
import Lara from '@primeng/themes/lara';

import { routes } from './app.routes';
import { provideHttpClient, withFetch } from '@angular/common/http';
import { CLIPBOARD_OPTIONS, ClipboardButtonComponent, MARKED_OPTIONS, MERMAID_OPTIONS, provideMarkdown } from 'ngx-markdown';
import 'prismjs';
import 'prismjs/components/prism-typescript.min.js';
import 'prismjs/plugins/line-numbers/prism-line-numbers.js';
import 'prismjs/plugins/line-highlight/prism-line-highlight.js';
import { provideStore } from '@ngrx/store';
import { provideStoreDevtools } from '@ngrx/store-devtools';
import { provideEffects } from '@ngrx/effects';
import { getModalsReducer } from './store/reducers';
import { Effects } from './store/effects';

export const appConfig: ApplicationConfig = {
  providers: [
    provideZoneChangeDetection({ eventCoalescing: true }),
    provideRouter(routes),
    provideAnimationsAsync(),
    providePrimeNG({
        theme: {
            preset: Lara,
            options: {
                // prefix: 'p',
                darkModeSelector: 'false',
                // colorScheme:  'light',
                cssLayer: false
            }
        }
    }),
    provideHttpClient(withFetch()),
    provideMarkdown({
        mermaidOptions: {
            provide: MERMAID_OPTIONS,
            useValue: {
                darkMode: true,
                look: 'handDrawn',
            },
        },
        clipboardOptions: {
            provide: CLIPBOARD_OPTIONS,
            useValue: {
                buttonComponent: ClipboardButtonComponent,
            },
        },
        sanitize: SecurityContext.NONE,
        markedOptions: {
            provide: MARKED_OPTIONS,
            useValue: {
                gfm: true,
                breaks: false,
                pedantic: false,
            }
        },
    }),
    provideStore({ modals: getModalsReducer }),
    provideStoreDevtools({ maxAge: 25, logOnly: !isDevMode() }),
    provideEffects([Effects])
  ]
};

Enter fullscreen mode Exit fullscreen mode

What is app.config.ts in Angular 19?

In Angular 19 standalone apps, you don’t use AppModule anymore. Instead, you configure all global providers in one place — app.config.ts.

This configuration object (ApplicationConfig) is passed to your app’s entry point:

bootstrapApplication(AppComponent, appConfig);

Enter fullscreen mode Exit fullscreen mode

It defines everything your app needs globally: routing, HTTP, theming, markdown, animations, NgRx, and more.

Line-by-Line Explanation
Let’s break it down step by step:

Core Angular Imports

import { ApplicationConfig, provideZoneChangeDetection, SecurityContext, isDevMode } from '@angular/core';

Enter fullscreen mode Exit fullscreen mode
  • ApplicationConfig — Type that defines app-wide providers for standalone apps.
  • provideZoneChangeDetection — Configures Angular’s zone-based change detection.
  • SecurityContext — Controls how Angular sanitizes content (used in Markdown rendering).
  • isDevMode() — Detects if the app is running in development mode — handy for enabling debug tools conditionally.

Angular Router

import { provideRouter } from '@angular/router';
import { routes } from './app.routes';

Enter fullscreen mode Exit fullscreen mode
  • provideRouter(routes) installs Angular Router without needing RouterModule.forRoot().
  • Your route definitions live in app.routes.ts, typically as a Routes array.

Animations Setup

import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
Enter fullscreen mode Exit fullscreen mode
  • Enables Angular’s animation engine asynchronously.
  • The async variant helps tree-shake animation code and reduce bundle size when animations aren’t immediately needed.

PrimeNG Theme Configuration

import { providePrimeNG } from 'primeng/config';
import Lara from '@primeng/themes/lara';
Enter fullscreen mode Exit fullscreen mode

Then configured like this:

providePrimeNG({
  theme: {
    preset: Lara,
    options: {
      darkModeSelector: 'false',
      cssLayer: false
    }
  }
})

Enter fullscreen mode Exit fullscreen mode
  • providePrimeNG() globally sets up PrimeNG.
  • preset: Lara applies the beautiful Lara theme.
  • darkModeSelector — defines a CSS selector for dark mode (here it’s disabled).
  • cssLayer — controls CSS layering behavior. Setting it false prevents layering issues if you manage your own global styles.

You can customize prefix, color scheme, or even dynamically switch themes later.

HTTP Client with Fetch API

import { provideHttpClient, withFetch } from '@angular/common/http';
Enter fullscreen mode Exit fullscreen mode
  • provideHttpClient() — Bootstraps the modern Angular HTTP Client for standalone apps.
  • withFetch() — Uses the native Fetch API under the hood (instead of XMLHttpRequest).

Benefits:

  • Smaller bundle size
  • Modern streaming support
  • Better Service Worker integration

If your app relies on progress events, verify behavior as Fetch doesn’t provide them the same way as XHR.

Markdown Rendering with ngx-markdown

import { CLIPBOARD_OPTIONS, ClipboardButtonComponent, MARKED_OPTIONS, MERMAID_OPTIONS, provideMarkdown } from 'ngx-markdown';

Enter fullscreen mode Exit fullscreen mode

Then configured as:

provideMarkdown({
  mermaidOptions: {
    provide: MERMAID_OPTIONS,
    useValue: {
      darkMode: true,
      look: 'handDrawn',
    },
  },
  clipboardOptions: {
    provide: CLIPBOARD_OPTIONS,
    useValue: {
      buttonComponent: ClipboardButtonComponent,
    },
  },
  sanitize: SecurityContext.NONE,
  markedOptions: {
    provide: MARKED_OPTIONS,
    useValue: {
      gfm: true,
      breaks: false,
      pedantic: false,
    }
  },
})
Enter fullscreen mode Exit fullscreen mode

This setup enables:

  • Markdown rendering via the marked library.
  • Mermaid diagrams (MERMAID_OPTIONS) with dark mode and hand-drawn style.
  • Clipboard copy button (ClipboardButtonComponent) for code snippets.
  • sanitize: SecurityContext.NONE — disables sanitization, allowing raw HTML in Markdown.

Security Tip:
Only set SecurityContext.NONE if the Markdown content is 100% trusted. Otherwise, use SecurityContext.HTML to avoid XSS risks.

Syntax Highlighting with PrismJS

import 'prismjs';
import 'prismjs/components/prism-typescript.min.js';
import 'prismjs/plugins/line-numbers/prism-line-numbers.js';
import 'prismjs/plugins/line-highlight/prism-line-highlight.js';
Enter fullscreen mode Exit fullscreen mode
  • These are side-effect imports.
  • They load PrismJS with TypeScript syntax highlighting and plugins for line numbers and line highlighting.
  • Perfect for rendering code blocks in documentation or Markdown.

You can add more languages by importing other Prism components.

State Management with NgRx

import { provideStore } from '@ngrx/store';
import { provideStoreDevtools } from '@ngrx/store-devtools';
import { provideEffects } from '@ngrx/effects';
import { getModalsReducer } from './store/reducers';
import { Effects } from './store/effects';
Enter fullscreen mode Exit fullscreen mode

Configured as:

provideStore({ modals: getModalsReducer }),
provideStoreDevtools({ maxAge: 25, logOnly: !isDevMode() }),
provideEffects([Effects])
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • provideStore() — Registers your global store with a reducer map.
  • modals: getModalsReducer — Example slice managing modal dialogs.
  • provideStoreDevtools() — Enables Redux DevTools integration (logs up to 25 states).
  • logOnly: !isDevMode() — Prevents dispatching actions from DevTools in production.
  • provideEffects() — Registers side effects for async logic (API calls, etc.).

Bonus: Zone Optimization

provideZoneChangeDetection({ eventCoalescing: true })
Enter fullscreen mode Exit fullscreen mode
  • eventCoalescing: true batches multiple synchronous DOM events to reduce unnecessary change detection cycles.
  • Results in better performance for interactive UIs (forms, scroll events, etc.).

Putting It All Together

This single file replaces what used to be spread across multiple NgModules, AppModules, and providers.

Here’s how it connects to your main.ts:

import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { appConfig } from './app.config';

bootstrapApplication(AppComponent, appConfig)
  .catch(err => console.error(err));
Enter fullscreen mode Exit fullscreen mode

And just like that — your Angular 19 standalone app is ready with routing, theming, Markdown rendering, Prism highlighting, and NgRx state management — all bootstrapped from a single file.

Best Practices & Recommendations

  • Avoid SecurityContext.NONE unless Markdown is from a trusted source.
  • Conditionally enable Store DevTools only in dev mode for smaller bundles.
  • Lazy-load PrismJS if bundle size matters.
  • Verify darkModeSelector — ensure it’s boolean or valid CSS selector per PrimeNG docs.
  • Split providers logically (UI, State, Markdown) for easier maintenance.

Summary

The app.config.ts in Angular 19 is the heart of your standalone app.
It centralizes:

  • Routing (provideRouter)
  • Animations (provideAnimationsAsync)
  • PrimeNG theming (providePrimeNG)
  • HTTP Client (provideHttpClient(withFetch))
  • Markdown rendering (provideMarkdown)
  • Syntax highlighting (PrismJS)
  • State management (NgRx)

This approach is cleaner, faster, and easier to maintain — fully embracing the new Angular standalone paradigm.

Final Thoughts

With this setup, you’re not just configuring an app — you’re modernizing your Angular architecture for the standalone era.

If you found this breakdown helpful, consider ❤️ reacting and bookmarking it on Dev.to — it helps others discover this guide too!

Top comments (0)