Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
cb34426
fix(nx-plugin): order analog before tailwind plugin
benpsnyder Apr 6, 2026
ae795e6
fix(create-analog): order analog before tailwind plugin
benpsnyder Apr 6, 2026
8fb2979
docs(vite-plugin-angular): align tailwind guidance with generated setup
benpsnyder Apr 6, 2026
18799fc
docs: add PR review and description agent skills
brandonroberts Apr 6, 2026
74617db
docs: add test coverage and build artifact checks to review-pr skill
brandonroberts Apr 6, 2026
95387db
feat(platform): add generic style-pipeline hooks for community plugin…
benpsnyder Apr 6, 2026
e0df473
chore: release 3.0.0-alpha.26 [skip ci]
semantic-release-bot Apr 6, 2026
2537f41
refactor: retire root tsconfig paths and move workspace linking to pa…
benpsnyder Apr 12, 2026
20acf90
Merge branch 'alpha' into fix/tailwind-csr
benpsnyder Apr 12, 2026
7a29bbc
fix: reorder plugins in generator configuration for improved compatib…
benpsnyder Apr 12, 2026
874419d
docs: clarify Angular HMR requirements and compatibility for versions…
benpsnyder Apr 12, 2026
4a7ec54
docs: update link format for HMR migration guidance in Tailwind integ…
benpsnyder Apr 12, 2026
e0b4fba
test: add coverage for analog registration in vite.config.ts templates
benpsnyder Apr 12, 2026
3326eca
Merge remote-tracking branch 'origin/alpha' into fix/tailwind-csr
benpsnyder Apr 14, 2026
94c2f5b
refactor: update Angular live-reload configuration and Tailwind integ…
benpsnyder Apr 14, 2026
75ffacd
refactor: remove hmr compatibility alias and streamline live-reload c…
benpsnyder Apr 14, 2026
87af10d
Merge branch 'alpha' into fix/tailwind-csr
brandonroberts Apr 14, 2026
792e785
chore: update tsconfig path in live reload test
brandonroberts Apr 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions MAINTAINER.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Contributing (Maintainer)

## Debugging

Repo-local debugging guidance for Analog package development lives in [docs/debugging.md](docs/debugging.md).

## Adding and updating an package

Adding or updating a package requires some extra step if its part of `dependencies` or `devDependencies`.
Expand Down
22 changes: 12 additions & 10 deletions apps/docs-app/docs/guides/debugging.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ sidebar_position: 4

# Debugging

Analog includes structured debug logging powered by [obug](https://www.npmjs.com/package/obug). Debug output can be enabled through the `debug` option in your Vite config or via the `DEBUG` environment variable.
Analog includes structured debug logging powered by [obug](https://www.npmjs.com/package/obug). You can enable debug output through the `debug` option in your Vite config or via the `DEBUG` environment variable.

The examples below use `npm`, but the same `DEBUG` values work with any package manager.

## Enabling Debug Output

Expand Down Expand Up @@ -91,20 +93,20 @@ analog({
});
```

You can mix immediate and deferred entries — entries without `mode` enable immediately for both commands:
You can mix immediate and deferred entries. Entries without `mode` enable immediately for both commands:

```ts
analog({
debug: [
{ scopes: ['analog:platform'] }, // both commands
{ scopes: ['analog:angular:hmr'], mode: 'dev' }, // dev only
{ scopes: ['analog:platform:typed-router'], mode: 'build' }, // build only
{ scopes: ['analog:platform'] },
{ scopes: ['analog:angular:hmr'], mode: 'dev' },
{ scopes: ['analog:platform:typed-router'], mode: 'build' },
],
});
```

:::tip
To enable debug output for **both** build and dev, simply omit `mode`. Any form without `mode` — `true`, a `string[]`, or `{ scopes }` — outputs in both commands.
To enable debug output for both build and dev, omit `mode`. Any form without `mode` outputs in both commands.
:::

### Environment variable
Expand All @@ -113,13 +115,13 @@ The `DEBUG` environment variable works independently of the config option and is

```bash
# All Analog scopes
DEBUG=analog:* pnpm dev
DEBUG=analog:* npm run dev

# Specific scopes
DEBUG=analog:platform:routes,analog:angular:compiler pnpm build
DEBUG=analog:platform:routes,analog:angular:compiler npm run build

# All platform scopes
DEBUG=analog:platform:* pnpm dev
DEBUG=analog:platform:* npm run dev
```

## Debugging a local Analog checkout from another pnpm workspace
Expand Down Expand Up @@ -248,7 +250,7 @@ import angular from '@analogjs/vite-plugin-angular';
export default defineConfig({
plugins: [
angular({
debug: true, // enables analog:angular:* scopes
debug: true,
}),
],
});
Expand Down
2 changes: 1 addition & 1 deletion apps/docs-app/docs/guides/migrating-v2-to-v3.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,4 +158,4 @@ Keep automated migration tooling focused on the breaking changes above:
- rewrite only the legacy `@analogjs/vite-plugin-angular/setup-vitest` setup import
- flag `@analogjs/trpc` as a removed package that needs a manual migration plan
- flag `experimental.useAnalogCompiler`, `analogCompilationMode`, and `@analogjs/angular-compiler` as unsupported on the current v3 alpha line rather than removed outright
- treat optional helpers such as `withTypedRouter`, `withRouteContext`, `withLoaderCaching`, `withDebugRoutes`, and compatibility aliases such as `liveReload` as opt-in rather than mandatory rewrites
- treat optional helpers such as `withTypedRouter`, `withRouteContext`, `withLoaderCaching`, `withDebugRoutes`, and `liveReload` as opt-in rather than mandatory rewrites
11 changes: 7 additions & 4 deletions apps/docs-app/docs/guides/migrating.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,11 @@ export default defineConfig(({ mode }) => ({

## Enabling HMR

Angular supports HMR where in most cases components can be updated without a full page reload. In Analog, prefer the `hmr` option. `liveReload` is still accepted as a compatibility alias, but `hmr` is the primary API.
Analog requires Angular v19 or newer for `hmr` / `liveReload` to work. On Angular v17-v18, `hmr` and its `liveReload` alias are forcibly disabled at runtime with a console warning, so HMR is unavailable on those versions.
Angular supports HMR where in most cases components can be updated without a full page reload. In Analog, use `liveReload` to control the Angular live-reload pipeline.

This is separate from Vite's `server.hmr` option, which configures the HMR websocket transport. You can use `server.hmr` together with `liveReload` when you need custom host, port, or path settings.

Analog requires Angular v19 or newer for `liveReload` to work. On Angular v17-v18, `liveReload` is forcibly disabled at runtime with a console warning, so HMR is unavailable on those versions.

```ts
/// <reference types="vitest" />
Expand All @@ -204,7 +207,7 @@ export default defineConfig(({ mode }) => ({
// .. other configuration
plugins: [
analog({
hmr: true,
liveReload: true,
}),
],
}));
Expand All @@ -223,7 +226,7 @@ import tailwindcss from '@tailwindcss/vite';
export default defineConfig(() => ({
plugins: [
analog({
hmr: true,
liveReload: true,
vite: {
tailwindCss: {
rootStylesheet: resolve(import.meta.dirname, 'src/styles.css'),
Expand Down
8 changes: 5 additions & 3 deletions apps/docs-app/docs/integrations/storybook/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ const config: StorybookConfig = {
export default config;
```

For current Analog projects, prefer `framework.options.hmr` if you need to configure Angular HMR. `liveReload` is still accepted as a compatibility alias, but `hmr` is the recommended option.
For current Analog projects, use `framework.options.liveReload` to control Analog's Angular live-reload behavior.

This is separate from Vite's `server.hmr` option, which configures the HMR websocket transport. You can use `server.hmr` together with `framework.options.liveReload` when Storybook needs custom host, port, or path settings.

Remove the existing `webpackFinal` config function if present.

Expand Down Expand Up @@ -177,7 +179,7 @@ If your project uses Tailwind v4, keep Storybook aligned with the same opinionat
- one root stylesheet such as `src/styles.css`
- `@import 'tailwindcss';` in that stylesheet
- `framework.options.tailwindCss.rootStylesheet` pointing at that stylesheet
- `framework.options.hmr` for Angular HMR behavior
- `framework.options.liveReload` for Angular reload behavior

```ts
import { resolve } from 'node:path';
Expand All @@ -187,7 +189,7 @@ const config: StorybookConfig = {
framework: {
name: '@analogjs/storybook-angular',
options: {
hmr: true,
liveReload: true,
tailwindCss: {
rootStylesheet: resolve(__dirname, '../src/styles.css'),
},
Expand Down
146 changes: 146 additions & 0 deletions apps/docs-app/docs/integrations/tailwind/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# Tailwind CSS v4

Analog does not replace Tailwind's installation guides. Start with one Tailwind setup that matches your project:

- [Install Tailwind with Vite](https://tailwindcss.com/docs/installation/using-vite)
- [Install Tailwind with PostCSS](https://tailwindcss.com/docs/installation/using-postcss)
- [Install Tailwind with Angular](https://tailwindcss.com/docs/installation/framework-guides/angular)

Once Tailwind is installed, Analog adds the Angular-specific part: component stylesheet handling for `@apply` and Tailwind-aware `@reference` injection.

## What Analog adds

Use Analog's `tailwindCss.rootStylesheet` option when you want Tailwind utilities inside Angular component styles.

That option lets Analog:

- detect component stylesheets that use Tailwind utilities
- inject the correct `@reference` to your root stylesheet
- keep component styles aligned with your root Tailwind theme, prefixes, and plugins
- avoid manual `@reference` directives in every component stylesheet

If you only use Tailwind utilities in templates and a global stylesheet, you can follow Tailwind's install docs and keep your generated scaffold defaults without adding extra Analog configuration.

## Component Styles Setup

When you enable `tailwindCss.rootStylesheet`, keep Tailwind wired through Vite for the component stylesheet path:

```ts
/// <reference types="vitest" />

import { resolve } from 'node:path';
import { defineConfig } from 'vite';
import analog from '@analogjs/platform';
import tailwindcss from '@tailwindcss/vite';

export default defineConfig(() => ({
plugins: [
analog({
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should flow through the analog plugin to the Vite plugin.

vite: {
tailwindCss: {
rootStylesheet: resolve(__dirname, 'src/styles.css'),
},
},
}),
tailwindcss(),
],
}));
```

If you are using `@analogjs/vite-plugin-angular` directly instead of `@analogjs/platform`, the same option lives on the Angular plugin:

```ts
import { resolve } from 'node:path';
import { defineConfig } from 'vite';
import angular from '@analogjs/vite-plugin-angular';
import tailwindcss from '@tailwindcss/vite';

export default defineConfig(() => ({
plugins: [
angular({
tailwindCss: {
rootStylesheet: resolve(__dirname, 'src/styles.css'),
},
}),
tailwindcss(),
],
}));
```

List `analog()` before `tailwindcss()` in your Vite config. Current generators now scaffold that order.

## Root Stylesheet

In `src/styles.css`:

```css
@import 'tailwindcss';
```

You can keep your theme, `@source`, plugins, and prefixes there as well:

```css
@import 'tailwindcss' prefix(tw);

@source './src';

@theme {
--color-primary: #3b82f6;
}
```

Use an absolute `rootStylesheet` path. Analog may serve component styles through virtual stylesheet ids during dev, so relative `@reference` paths are not reliable there.

## How Component Styles Work

Angular compiles component styles in isolation. When a component stylesheet contains `@apply`, Tailwind still needs access to the root stylesheet that defines prefixes, theme values, and plugins.

Analog handles that by:

- detecting Tailwind usage in component CSS
- injecting `@reference` to the configured root stylesheet
- routing those component styles through the Vite CSS pipeline when needed

That means you should not manually add `@reference` to every component stylesheet in the normal setup.

## Prefixes

If your component styles use custom-prefixed utilities, configure `prefixes` so Analog knows which stylesheets need Tailwind `@reference` injection:

```ts
analog({
vite: {
tailwindCss: {
rootStylesheet: resolve(__dirname, 'src/styles.css'),
prefixes: ['tw:'],
},
},
});
```

Without `prefixes`, Analog falls back to its default Tailwind usage detection for component styles.

## HMR

Use `liveReload` when you need to configure Analog's Angular live-reload behavior explicitly.

Vite's `server.hmr` option is separate. It controls the HMR websocket transport, so you can use `server.hmr` together with `liveReload` when your dev server needs custom host, port, or path settings.

Angular HMR requires Angular v19 or newer. On Angular v17-v18, `liveReload` is intentionally disabled at runtime and emits a console warning, so HMR is unavailable on those versions. For broader migration guidance, see the [migration guide](/docs/guides/migrating).

Tailwind support does not require you to enable HMR manually. The stylesheet pipeline is handled independently from whether Angular can produce a hot component update for a given edit.

## Generated Apps

Current `create-analog` and Nx app scaffolds already:

- import Tailwind in `src/styles.css`
- register Tailwind in `vite.config.ts`
- keep the generated Vite plugin order aligned with the current Analog templates

Some templates may also include additional Tailwind tooling config files. Treat the generated scaffold as your project default, and only diverge after validating your own dev and build behavior.

## Related

- [Using CSS Pre-processors](/docs/packages/vite-plugin-angular/css-preprocessors)
- [create-analog](/docs/packages/create-analog/overview)
9 changes: 3 additions & 6 deletions apps/docs-app/docs/packages/create-analog/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,11 @@ pnpm create analog

### Tailwind v4

`create-analog` scaffolds Tailwind v4 with the Vite plugin by default for the current Analog templates. Generated projects use `@tailwindcss/vite`, add `@import 'tailwindcss';` to `src/styles.css`, and also generate a `postcss.config.mjs` with `@tailwindcss/postcss` so the build path and tool integrations use the same Tailwind setup.
`create-analog` scaffolds Tailwind v4 for the current Analog templates. Generated projects import Tailwind in `src/styles.css` and wire the Tailwind-related Vite config the template expects.

This is the recommended Analog v3 direction:
If you only need Tailwind utilities in templates and global styles, keep the scaffold defaults.

- Keep one root stylesheet, usually `src/styles.css`, that contains `@import 'tailwindcss';`
- Keep `@tailwindcss/vite` enabled in `vite.config.ts`
- Let Analog handle component-level `@reference` injection through its Tailwind-aware stylesheet pipeline instead of adding `@reference` directives manually in every component stylesheet
- Prefer the `hmr` option over `liveReload` when you need to configure Angular HMR explicitly
If you also want `@apply` inside Angular component styles, add Analog's `tailwindCss.rootStylesheet` option and follow the [Tailwind CSS guide](/docs/integrations/tailwind).

If you do not want Tailwind in the generated app, pass `--skipTailwind true`. The default Tailwind v4 flow expects a plain CSS entry file for global styles.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ title: 'Using CSS Pre-processors'

The Vite Plugin supports CSS pre-processing using external `styleUrls` and inline `styles` in the Component decorator metadata.

## Recommended Tailwind v4 setup
## Tailwind v4 component styles

If your app uses Tailwind v4, the recommended Analog setup is opinionated:
Tailwind installation itself should follow Tailwind's docs. The Analog-specific configuration below is for Angular component styles that use Tailwind utilities such as `@apply`.

- keep a single root stylesheet such as `src/styles.css`
- put `@import 'tailwindcss';` in that root stylesheet
Expand All @@ -15,6 +15,8 @@ If your app uses Tailwind v4, the recommended Analog setup is opinionated:

This lets Analog preprocess component stylesheets and inject the correct `@reference` directive automatically for component CSS that uses Tailwind utilities.

For the broader Tailwind + Analog overview, see the [Tailwind CSS guide](/docs/integrations/tailwind).

```ts
/// <reference types="vitest" />

Expand All @@ -29,7 +31,7 @@ export default defineConfig(() => ({
tailwindCss: {
rootStylesheet: resolve(__dirname, 'src/styles.css'),
},
hmr: true,
liveReload: true,
}),
tailwindcss(),
],
Expand All @@ -44,8 +46,12 @@ And in `src/styles.css`:

Use an absolute path for `rootStylesheet`. Analog serves some component styles through virtual stylesheet ids during dev, so relative `@reference` paths are not reliable there.

Use `liveReload` to control Analog's Angular reload behavior. Vite's top-level `server.hmr` option remains available when you need to configure the HMR websocket transport separately.

You only need `tailwindCss.prefixes` when your component styles use custom-prefixed utilities and you want Analog to look for those prefixes instead of the default `@apply` detection.

If you only use Tailwind utilities in templates and a global stylesheet, you can keep your Tailwind install path and skip `tailwindCss.rootStylesheet`.

External `styleUrls` can be used without any additional configuration.

An example with `styleUrls`:
Expand Down
Loading
Loading