diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 97f1456fb..11c7a2568 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,10 +1,6 @@
name: ci
on:
- push:
- branches:
- - beta
- - main
pull_request: {}
env:
diff --git a/.github/workflows/test-release.yml b/.github/workflows/test-release.yml
index c7e8ca253..d9b8b1061 100644
--- a/.github/workflows/test-release.yml
+++ b/.github/workflows/test-release.yml
@@ -1,8 +1,11 @@
name: Release Test
+permissions:
+ contents: read
+
on:
release:
- types: [released, prereleased]
+ types: [published]
workflow_dispatch:
inputs:
analog_build_tag:
diff --git a/package.json b/package.json
index d08c54f7f..23bed5953 100644
--- a/package.json
+++ b/package.json
@@ -43,17 +43,17 @@
},
"private": true,
"dependencies": {
- "@angular/animations": "19.2.4",
- "@angular/cdk": "19.2.7",
- "@angular/common": "19.2.4",
- "@angular/compiler": "19.2.4",
- "@angular/core": "19.2.4",
- "@angular/forms": "19.2.4",
- "@angular/material": "19.2.7",
- "@angular/platform-browser": "19.2.4",
- "@angular/platform-browser-dynamic": "19.2.4",
- "@angular/platform-server": "19.2.4",
- "@angular/router": "19.2.4",
+ "@angular/animations": "20.0.0-rc.2",
+ "@angular/cdk": "20.0.0-rc.2",
+ "@angular/common": "20.0.0-rc.2",
+ "@angular/compiler": "20.0.0-rc.2",
+ "@angular/core": "20.0.0-rc.2",
+ "@angular/forms": "20.0.0-rc.2",
+ "@angular/material": "20.0.0-rc.2",
+ "@angular/platform-browser": "20.0.0-rc.2",
+ "@angular/platform-browser-dynamic": "20.0.0-rc.2",
+ "@angular/platform-server": "20.0.0-rc.2",
+ "@angular/router": "20.0.0-rc.2",
"@astrojs/mdx": "^3.0.1",
"@astrojs/react": "^3.0.0",
"@babel/core": "^7.21.8",
@@ -84,17 +84,17 @@
"zone.js": "^0.15.0"
},
"devDependencies": {
- "@angular-devkit/architect": "0.1902.5",
- "@angular-devkit/build-angular": "19.2.5",
- "@angular-devkit/core": "19.2.5",
- "@angular-devkit/schematics": "19.2.5",
+ "@angular-devkit/architect": "0.2000.0-rc.3",
+ "@angular-devkit/build-angular": "20.0.0-rc.3",
+ "@angular-devkit/core": "20.0.0-rc.3",
+ "@angular-devkit/schematics": "20.0.0-rc.3",
"@angular-eslint/eslint-plugin": "19.3.0",
"@angular-eslint/eslint-plugin-template": "19.3.0",
"@angular-eslint/template-parser": "19.3.0",
- "@angular/build": "19.2.5",
- "@angular/cli": "~19.2.0",
- "@angular/compiler-cli": "19.2.4",
- "@angular/language-service": "19.2.4",
+ "@angular/build": "20.0.0-rc.3",
+ "@angular/cli": "20.0.0-rc.3",
+ "@angular/compiler-cli": "20.0.0-rc.2",
+ "@angular/language-service": "20.0.0-rc.2",
"@astrojs/markdown-component": "^1.0.5",
"@commitlint/cli": "^17.4.2",
"@commitlint/config-conventional": "^17.4.2",
@@ -162,7 +162,7 @@
"marked-mangle": "^1.1.10",
"marked-shiki": "^1.1.0",
"minimist": "^1.2.7",
- "ng-packagr": "19.2.0",
+ "ng-packagr": "20.0.0-rc.1",
"nitropack": "^2.11.0",
"nx": "21.0.3",
"playwright": "^1.49.1",
@@ -188,7 +188,7 @@
"ts-jest": "29.1.0",
"ts-morph": "^21.0.1",
"ts-node": "10.9.1",
- "typescript": "5.7.3",
+ "typescript": "~5.8.0",
"vfile": "^6.0.3",
"vite": "6.2.3",
"vite-plugin-eslint": "^1.8.1",
@@ -198,5 +198,20 @@
"vitest": "^3.0.5",
"webpack-bundle-analyzer": "^4.7.0",
"xmlbuilder2": "^3.0.2"
+ },
+ "pnpm": {
+ "ignoredBuiltDependencies": [
+ "cypress"
+ ],
+ "onlyBuiltDependencies": [
+ "@swc/core",
+ "core-js",
+ "core-js-pure",
+ "esbuild",
+ "lmdb",
+ "msgpackr-extract",
+ "nx",
+ "sharp"
+ ]
}
}
diff --git a/packages/content/og/src/lib/og.ts b/packages/content/og/src/lib/og.ts
index b915b02b2..dd3ac115a 100644
--- a/packages/content/og/src/lib/og.ts
+++ b/packages/content/og/src/lib/og.ts
@@ -4,7 +4,7 @@ import satori from 'satori';
import { html as toReactElement } from 'satori-html';
import sharp from 'sharp';
-import { ImageResponseOptions } from './options.js';
+import { ImageResponseOptions } from './options';
export const generateImage = async (
element: string,
diff --git a/packages/content/package.json b/packages/content/package.json
index 4253f1cfd..ac1092848 100644
--- a/packages/content/package.json
+++ b/packages/content/package.json
@@ -23,10 +23,10 @@
"url": "https://github.com/sponsors/brandonroberts"
},
"peerDependencies": {
- "@angular/common": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
- "@angular/core": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
- "@angular/platform-browser": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
- "@angular/router": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "@angular/common": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0",
+ "@angular/core": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0",
+ "@angular/platform-browser": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0",
+ "@angular/router": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0",
"@nx/devkit": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0",
"front-matter": "^4.0.2",
"marked": "^15.0.7",
diff --git a/packages/create-analog/index.js b/packages/create-analog/index.js
index 54a0665a2..e4c45c641 100755
--- a/packages/create-analog/index.js
+++ b/packages/create-analog/index.js
@@ -441,10 +441,10 @@ function setComponentFormat(root, filesDir, write, template, useAnalogSFC) {
__APP_COMPONENT__: useAnalogSFC ? 'App' : 'AppComponent',
__APP_COMPONENT_IMPORT__: useAnalogSFC
? "import App from './app/app-root.ag';"
- : "import { AppComponent } from './app/app.component';",
+ : "import { AppComponent } from './app/app';",
});
- const cmpForDelete = useAnalogSFC ? 'app.component' : 'app-root';
+ const cmpForDelete = useAnalogSFC ? 'app' : 'app-root';
const deleteExt = useAnalogSFC ? 'ts' : 'ag';
deleteFiles(root, [
useAnalogSFC ? `src/app/${cmpForDelete}.ts` : `src/app/${cmpForDelete}.ag`,
diff --git a/packages/create-analog/template-angular-v19/.editorconfig b/packages/create-analog/template-angular-v19/.editorconfig
new file mode 100644
index 000000000..59d9a3a3e
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/.editorconfig
@@ -0,0 +1,16 @@
+# Editor configuration, see https://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.ts]
+quote_type = single
+
+[*.md]
+max_line_length = off
+trim_trailing_whitespace = false
diff --git a/packages/create-analog/template-angular-v19/.vscode/extensions.json b/packages/create-analog/template-angular-v19/.vscode/extensions.json
new file mode 100644
index 000000000..e4679f326
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/.vscode/extensions.json
@@ -0,0 +1,4 @@
+{
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
+ "recommendations": ["angular.ng-template", "analogjs.vscode-analog"]
+}
diff --git a/packages/create-analog/template-angular-v19/.vscode/launch.json b/packages/create-analog/template-angular-v19/.vscode/launch.json
new file mode 100644
index 000000000..57dbf761e
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/.vscode/launch.json
@@ -0,0 +1,19 @@
+{
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "ng serve",
+ "type": "chrome",
+ "request": "launch",
+ "preLaunchTask": "npm: start",
+ "url": "http://localhost:5173/"
+ },
+ {
+ "name": "ng test",
+ "type": "chrome",
+ "request": "launch",
+ "preLaunchTask": "npm: test"
+ }
+ ]
+}
diff --git a/packages/create-analog/template-angular-v19/.vscode/tasks.json b/packages/create-analog/template-angular-v19/.vscode/tasks.json
new file mode 100644
index 000000000..a298b5bd8
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/.vscode/tasks.json
@@ -0,0 +1,42 @@
+{
+ // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "type": "npm",
+ "script": "start",
+ "isBackground": true,
+ "problemMatcher": {
+ "owner": "typescript",
+ "pattern": "$tsc",
+ "background": {
+ "activeOnStart": true,
+ "beginsPattern": {
+ "regexp": "(.*?)"
+ },
+ "endsPattern": {
+ "regexp": "bundle generation complete"
+ }
+ }
+ }
+ },
+ {
+ "type": "npm",
+ "script": "test",
+ "isBackground": true,
+ "problemMatcher": {
+ "owner": "typescript",
+ "pattern": "$tsc",
+ "background": {
+ "activeOnStart": true,
+ "beginsPattern": {
+ "regexp": "(.*?)"
+ },
+ "endsPattern": {
+ "regexp": "bundle generation complete"
+ }
+ }
+ }
+ }
+ ]
+}
diff --git a/packages/create-analog/template-angular-v19/README.md b/packages/create-analog/template-angular-v19/README.md
new file mode 100644
index 000000000..e98b397bb
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/README.md
@@ -0,0 +1,26 @@
+# __PROJECT_TITLE__
+
+This project was generated with [Analog](https://analogjs.org), the fullstack meta-framework for Angular.
+
+## Setup
+
+Run `npm install` to install the application dependencies.
+
+## Development
+
+Run `npm start` for a dev server. Navigate to `http://localhost:5173/`. The application automatically reloads if you change any of the source files.
+
+## Build
+
+Run `npm run build` to build the client/server project. The client build artifacts are located in the `dist/analog/public` directory. The server for the API build artifacts are located in the `dist/analog/server` directory.
+
+## Test
+
+Run `npm run test` to run unit tests with [Vitest](https://vitest.dev).
+
+## Community
+
+- Visit and Star the [GitHub Repo](https://github.com/analogjs/analog)
+- Join the [Discord](https://chat.analogjs.org)
+- Follow us on [Twitter](https://twitter.com/analogjs)
+- Become a [Sponsor](https://github.com/sponsors/brandonroberts)
diff --git a/packages/create-analog/template-angular-v19/_gitignore b/packages/create-analog/template-angular-v19/_gitignore
new file mode 100644
index 000000000..bf149eb7c
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/_gitignore
@@ -0,0 +1,44 @@
+# See http://help.github.com/ignore-files/ for more about ignoring files.
+
+# Compiled output
+/dist
+/tmp
+/out-tsc
+/bazel-out
+
+# Node
+/node_modules
+npm-debug.log
+yarn-error.log
+
+# IDEs and editors
+.idea/
+.project
+.classpath
+.c9/
+*.launch
+.settings/
+*.sublime-workspace
+
+# Visual Studio Code
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+.history/*
+
+# Miscellaneous
+/.angular/cache
+/.nx/cache
+/.nx/workspace-data
+.sass-cache/
+/connect.lock
+/coverage
+/libpeerconnection.log
+testem.log
+/typings
+
+# System files
+.DS_Store
+Thumbs.db
diff --git a/packages/create-analog/template-angular-v19/angular.json b/packages/create-analog/template-angular-v19/angular.json
new file mode 100644
index 000000000..60b166f35
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/angular.json
@@ -0,0 +1,54 @@
+{
+ "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
+ "version": 1,
+ "newProjectRoot": "projects",
+ "projects": {
+ "my-app": {
+ "projectType": "application",
+ "root": ".",
+ "sourceRoot": "src",
+ "prefix": "app",
+ "architect": {
+ "build": {
+ "builder": "@analogjs/platform:vite",
+ "options": {
+ "configFile": "vite.config.ts",
+ "main": "src/main.ts",
+ "outputPath": "dist/client",
+ "tsConfig": "tsconfig.app.json"
+ },
+ "defaultConfiguration": "production",
+ "configurations": {
+ "development": {
+ "mode": "development"
+ },
+ "production": {
+ "sourcemap": false,
+ "mode": "production"
+ }
+ }
+ },
+ "serve": {
+ "builder": "@analogjs/platform:vite-dev-server",
+ "defaultConfiguration": "development",
+ "options": {
+ "buildTarget": "my-app:build",
+ "port": 5173
+ },
+ "configurations": {
+ "development": {
+ "buildTarget": "my-app:build:development",
+ "hmr": true
+ },
+ "production": {
+ "buildTarget": "my-app:build:production"
+ }
+ }
+ },
+ "test": {
+ "builder": "@analogjs/vitest-angular:test"
+ }
+ }
+ }
+ }
+}
diff --git a/packages/create-analog/template-angular-v19/index.html b/packages/create-analog/template-angular-v19/index.html
new file mode 100644
index 000000000..e91f5f547
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+ __PROJECT_TITLE__
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/create-analog/template-angular-v19/package.json b/packages/create-analog/template-angular-v19/package.json
new file mode 100644
index 000000000..fc79d593b
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/package.json
@@ -0,0 +1,53 @@
+{
+ "name": "my-app",
+ "version": "0.0.0",
+ "type": "module",
+ "engines": {
+ "node": ">=18.19.1"
+ },
+ "scripts": {
+ "ng": "ng",
+ "dev": "ng serve",
+ "start": "ng serve",
+ "build": "ng build",
+ "watch": "ng build --watch --configuration development",
+ "test": "ng test"
+ },
+ "private": true,
+ "dependencies": {
+ "@analogjs/content": "^1.17.0-beta.6",
+ "@analogjs/router": "^1.17.0-beta.6",
+ "@angular/animations": "^19.0.0",
+ "@angular/common": "^19.0.0",
+ "@angular/compiler": "^19.0.0",
+ "@angular/core": "^19.0.0",
+ "@angular/forms": "^19.0.0",
+ "@angular/platform-browser": "^19.0.0",
+ "@angular/platform-browser-dynamic": "^19.0.0",
+ "@angular/platform-server": "^19.0.0",
+ "@angular/router": "^19.0.0",
+ "front-matter": "^4.0.2",
+ "marked": "^15.0.7",
+ "marked-gfm-heading-id": "^4.1.1",
+ "marked-highlight": "^2.2.1",
+ "marked-mangle": "^1.1.10",
+ "prismjs": "^1.29.0",
+ "rxjs": "~7.8.0",
+ "tslib": "^2.3.0",
+ "zone.js": "~0.15.0"
+ },
+ "devDependencies": {
+ "@analogjs/platform": "^1.17.0-beta.6",
+ "@analogjs/vite-plugin-angular": "^1.17.0-beta.6",
+ "@analogjs/vitest-angular": "^1.17.0-beta.6",
+ "@angular-devkit/build-angular": "^19.0.0",
+ "@angular/build": "^19.0.0",
+ "@angular/cli": "^19.0.0",
+ "@angular/compiler-cli": "^19.0.0",
+ "jsdom": "^22.0.0",
+ "typescript": "~5.8.0",
+ "vite": "^6.0.0",
+ "vite-tsconfig-paths": "^4.2.0",
+ "vitest": "^3.0.0"
+ }
+}
diff --git a/packages/create-analog/template-angular-v19/public/.gitkeep b/packages/create-analog/template-angular-v19/public/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/packages/create-analog/template-angular-v19/public/analog.svg b/packages/create-analog/template-angular-v19/public/analog.svg
new file mode 100644
index 000000000..e4f555aa7
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/public/analog.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/create-analog/template-angular-v19/public/favicon.ico b/packages/create-analog/template-angular-v19/public/favicon.ico
new file mode 100644
index 000000000..997406ad2
Binary files /dev/null and b/packages/create-analog/template-angular-v19/public/favicon.ico differ
diff --git a/packages/create-analog/template-angular-v19/public/vite.svg b/packages/create-analog/template-angular-v19/public/vite.svg
new file mode 100644
index 000000000..e7b8dfb1b
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/create-analog/template-angular-v19/src/app/app-root.ag b/packages/create-analog/template-angular-v19/src/app/app-root.ag
new file mode 100644
index 000000000..08f108322
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/src/app/app-root.ag
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/packages/create-analog/template-angular-v19/src/app/app-root.spec.ts b/packages/create-analog/template-angular-v19/src/app/app-root.spec.ts
new file mode 100644
index 000000000..381dfd390
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/src/app/app-root.spec.ts
@@ -0,0 +1,20 @@
+import { TestBed } from '@angular/core/testing';
+import { provideRouter } from '@angular/router';
+import { provideLocationMocks } from '@angular/common/testing';
+
+import App from './app-root.ag';
+
+describe('App', () => {
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [App],
+ providers: [provideRouter([]), provideLocationMocks()],
+ }).compileComponents();
+ });
+
+ it('should create the app', () => {
+ const fixture = TestBed.createComponent(App);
+ const app = fixture.componentInstance;
+ expect(app).toBeTruthy();
+ });
+});
diff --git a/packages/create-analog/template-blog/src/app/app.component.spec.ts b/packages/create-analog/template-angular-v19/src/app/app.component.spec.ts
similarity index 100%
rename from packages/create-analog/template-blog/src/app/app.component.spec.ts
rename to packages/create-analog/template-angular-v19/src/app/app.component.spec.ts
diff --git a/packages/create-analog/template-latest/src/app/app.component.ts b/packages/create-analog/template-angular-v19/src/app/app.component.ts
similarity index 94%
rename from packages/create-analog/template-latest/src/app/app.component.ts
rename to packages/create-analog/template-angular-v19/src/app/app.component.ts
index 5dab86b4d..fa46e6be0 100644
--- a/packages/create-analog/template-latest/src/app/app.component.ts
+++ b/packages/create-analog/template-angular-v19/src/app/app.component.ts
@@ -3,7 +3,6 @@ import { RouterOutlet } from '@angular/router';
@Component({
selector: 'app-root',
- standalone: true,
imports: [RouterOutlet],
template: ``,
styles: `
diff --git a/packages/create-analog/template-angular-v19/src/app/app.config.server.ts b/packages/create-analog/template-angular-v19/src/app/app.config.server.ts
new file mode 100644
index 000000000..0da63b09b
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/src/app/app.config.server.ts
@@ -0,0 +1,10 @@
+import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';
+import { provideServerRendering } from '@angular/platform-server';
+
+import { appConfig } from './app.config';
+
+const serverConfig: ApplicationConfig = {
+ providers: [provideServerRendering()],
+};
+
+export const config = mergeApplicationConfig(appConfig, serverConfig);
diff --git a/packages/create-analog/template-angular-v19/src/app/app.config.ts b/packages/create-analog/template-angular-v19/src/app/app.config.ts
new file mode 100644
index 000000000..a1a58ee8f
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/src/app/app.config.ts
@@ -0,0 +1,20 @@
+import {
+ provideHttpClient,
+ withFetch,
+ withInterceptors,
+} from '@angular/common/http';
+import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
+import { provideClientHydration } from '@angular/platform-browser';
+import { provideFileRouter, requestContextInterceptor } from '@analogjs/router';
+
+export const appConfig: ApplicationConfig = {
+ providers: [
+ provideZoneChangeDetection({ eventCoalescing: true }),
+ provideFileRouter(),
+ provideHttpClient(
+ withFetch(),
+ withInterceptors([requestContextInterceptor])
+ ),
+ provideClientHydration(),
+ ],
+};
diff --git a/packages/create-analog/template-angular-v19/src/app/pages/index.page.ag b/packages/create-analog/template-angular-v19/src/app/pages/index.page.ag
new file mode 100644
index 000000000..fd85cac98
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/src/app/pages/index.page.ag
@@ -0,0 +1,53 @@
+
+
+
+
+
+ Analog
+
+ The fullstack meta-framework for Angular!
+
+
+
+
+
+
+ Docs |
+ GitHub |
+
+ Sponsor
+
+
+
+
+
diff --git a/packages/create-analog/template-angular-v19/src/app/pages/index.page.ts b/packages/create-analog/template-angular-v19/src/app/pages/index.page.ts
new file mode 100644
index 000000000..fcbc53d11
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/src/app/pages/index.page.ts
@@ -0,0 +1,54 @@
+import { Component, signal } from '@angular/core';
+
+@Component({
+ selector: 'app-home',
+ template: `
+
+
+ Analog
+
+ The fullstack meta-framework for Angular!
+
+
+
+
+
+
+ Docs |
+ GitHub |
+
+ Sponsor
+
+
+ `,
+ styles: `
+ .logo {
+ will-change: filter;
+ }
+
+ .logo:hover {
+ filter: drop-shadow(0 0 2em #646cffaa);
+ }
+
+ .read-the-docs > * {
+ color: #fff;
+ }
+
+ @media (prefers-color-scheme: light) {
+ .read-the-docs > * {
+ color: #213547;
+ }
+ }
+ `,
+})
+export default class HomeComponent {
+ count = signal(0);
+
+ increment() {
+ this.count.update((count) => count + 1);
+ }
+}
diff --git a/packages/create-analog/template-angular-v19/src/main.server.ts b/packages/create-analog/template-angular-v19/src/main.server.ts
new file mode 100644
index 000000000..d3f23684e
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/src/main.server.ts
@@ -0,0 +1,8 @@
+import 'zone.js/node';
+import '@angular/platform-server/init';
+import { render } from '@analogjs/router/server';
+
+__APP_COMPONENT_IMPORT__
+import { config } from './app/app.config.server';
+
+export default render(__APP_COMPONENT__, config);
diff --git a/packages/create-analog/template-angular-v19/src/main.ts b/packages/create-analog/template-angular-v19/src/main.ts
new file mode 100644
index 000000000..4b0822a08
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/src/main.ts
@@ -0,0 +1,7 @@
+import 'zone.js';
+import { bootstrapApplication } from '@angular/platform-browser';
+
+__APP_COMPONENT_IMPORT__
+import { appConfig } from './app/app.config';
+
+bootstrapApplication(__APP_COMPONENT__, appConfig);
diff --git a/packages/create-analog/template-angular-v19/src/server/routes/api/v1/hello.ts b/packages/create-analog/template-angular-v19/src/server/routes/api/v1/hello.ts
new file mode 100644
index 000000000..594c5d716
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/src/server/routes/api/v1/hello.ts
@@ -0,0 +1,3 @@
+import { defineEventHandler } from 'h3';
+
+export default defineEventHandler(() => ({ message: 'Hello World' }));
diff --git a/packages/create-analog/template-angular-v19/src/styles.css b/packages/create-analog/template-angular-v19/src/styles.css
new file mode 100644
index 000000000..e35981187
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/src/styles.css
@@ -0,0 +1,80 @@
+/* You can add global styles to this file, and also import other style files */
+:root {
+ font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
+ font-size: 16px;
+ line-height: 24px;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-text-size-adjust: 100%;
+}
+
+a {
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
+}
+
+a:hover {
+ color: #535bf2;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+
+button:hover {
+ border-color: #646cff;
+}
+
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+.card {
+ padding: 2em;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+
+ a:hover {
+ color: #747bff;
+ }
+
+ button {
+ background-color: #f9f9f9;
+ }
+}
diff --git a/packages/create-analog/template-angular-v19/src/test-setup.ts b/packages/create-analog/template-angular-v19/src/test-setup.ts
new file mode 100644
index 000000000..318c3b9d7
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/src/test-setup.ts
@@ -0,0 +1,12 @@
+import '@analogjs/vitest-angular/setup-zone';
+
+import {
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting,
+} from '@angular/platform-browser-dynamic/testing';
+import { getTestBed } from '@angular/core/testing';
+
+getTestBed().initTestEnvironment(
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting()
+);
diff --git a/packages/create-analog/template-angular-v19/src/vite-env.d.ts b/packages/create-analog/template-angular-v19/src/vite-env.d.ts
new file mode 100644
index 000000000..11f02fe2a
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/packages/create-analog/template-angular-v19/tsconfig.app.json b/packages/create-analog/template-angular-v19/tsconfig.app.json
new file mode 100644
index 000000000..ad965f67d
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/tsconfig.app.json
@@ -0,0 +1,14 @@
+/* To learn more about this file see: https://angular.io/config/tsconfig. */
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "./out-tsc/app",
+ "types": []
+ },
+ "files": ["src/main.ts", "src/main.server.ts"],
+ "include": [
+ "src/**/*.d.ts",
+ "src/app/pages/**/*.page.ts",
+ "src/server/middleware/**/*.ts"
+ ]
+}
diff --git a/packages/create-analog/template-angular-v19/tsconfig.json b/packages/create-analog/template-angular-v19/tsconfig.json
new file mode 100644
index 000000000..b35e861f6
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/tsconfig.json
@@ -0,0 +1,32 @@
+/* To learn more about this file see: https://angular.io/config/tsconfig. */
+{
+ "compileOnSave": false,
+ "compilerOptions": {
+ "baseUrl": "./",
+ "outDir": "./dist/out-tsc",
+ "forceConsistentCasingInFileNames": true,
+ "strict": true,
+ "noImplicitOverride": true,
+ "noPropertyAccessFromIndexSignature": true,
+ "noImplicitReturns": true,
+ "noFallthroughCasesInSwitch": true,
+ "sourceMap": true,
+ "declaration": false,
+ "downlevelIteration": true,
+ "experimentalDecorators": true,
+ "moduleResolution": "bundler",
+ "isolatedModules": true,
+ "importHelpers": true,
+ "target": "ES2022",
+ "module": "ES2022",
+ "lib": ["ES2022", "dom"],
+ "useDefineForClassFields": false,
+ "skipLibCheck": true
+ },
+ "angularCompilerOptions": {
+ "enableI18nLegacyMessageIdFormat": false,
+ "strictInjectionParameters": true,
+ "strictInputAccessModifiers": true,
+ "strictTemplates": true
+ }
+}
diff --git a/packages/create-analog/template-angular-v19/tsconfig.spec.json b/packages/create-analog/template-angular-v19/tsconfig.spec.json
new file mode 100644
index 000000000..06eb7cae6
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/tsconfig.spec.json
@@ -0,0 +1,11 @@
+/* To learn more about this file see: https://angular.io/config/tsconfig. */
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "./out-tsc/spec",
+ "target": "es2016",
+ "types": ["node", "vitest/globals"]
+ },
+ "files": ["src/test-setup.ts"],
+ "include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
+}
diff --git a/packages/create-analog/template-angular-v19/vite.config.ts b/packages/create-analog/template-angular-v19/vite.config.ts
new file mode 100644
index 000000000..2a8fdd9ae
--- /dev/null
+++ b/packages/create-analog/template-angular-v19/vite.config.ts
@@ -0,0 +1,27 @@
+///
+
+import { defineConfig } from 'vite';
+import analog from '@analogjs/platform';__TAILWIND_IMPORT__
+
+// https://vitejs.dev/config/
+export default defineConfig(({ mode }) => ({
+ build: {
+ target: ['es2020'],
+ },
+ resolve: {
+ mainFields: ['module'],
+ },
+ plugins: [
+ analog(__ANALOG_SFC_CONFIG__),__TAILWIND_PLUGIN__
+ ],
+ test: {
+ globals: true,
+ environment: 'jsdom',
+ setupFiles: ['src/test-setup.ts'],
+ include: ['**/*.spec.ts'],
+ reporters: ['default'],
+ },
+ define: {
+ 'import.meta.vitest': mode !== 'production',
+ },
+}));
diff --git a/packages/create-analog/template-blog/package.json b/packages/create-analog/template-blog/package.json
index 770de1d34..76734acdf 100644
--- a/packages/create-analog/template-blog/package.json
+++ b/packages/create-analog/template-blog/package.json
@@ -3,7 +3,7 @@
"version": "0.0.0",
"type": "module",
"engines": {
- "node": ">=18.19.1"
+ "node": ">=20.19.1"
},
"scripts": {
"ng": "ng",
@@ -39,7 +39,6 @@
"@analogjs/platform": "^1.17.0-beta.6",
"@analogjs/vite-plugin-angular": "^1.17.0-beta.6",
"@analogjs/vitest-angular": "^1.17.0-beta.6",
- "@angular-devkit/build-angular": "^19.0.0",
"@angular/build": "^19.0.0",
"@angular/cli": "^19.0.0",
"@angular/compiler-cli": "^19.0.0",
diff --git a/packages/create-analog/template-blog/src/app/app.config.ts b/packages/create-analog/template-blog/src/app/app.config.ts
index 0aa22f6bb..266227dc6 100644
--- a/packages/create-analog/template-blog/src/app/app.config.ts
+++ b/packages/create-analog/template-blog/src/app/app.config.ts
@@ -3,21 +3,26 @@ import {
withFetch,
withInterceptors,
} from '@angular/common/http';
-import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
-import { provideClientHydration } from '@angular/platform-browser';
+import {
+ ApplicationConfig,
+ provideBrowserGlobalErrorListeners,
+ provideZoneChangeDetection
+} from '@angular/core';
+import { provideClientHydration, withEventReplay } from '@angular/platform-browser';
import { provideFileRouter, requestContextInterceptor } from '@analogjs/router';
import { provideContent, withMarkdownRenderer } from '@analogjs/content';
import { __HIGHLIGHTER__ } from '@analogjs/content/__HIGHLIGHTER_ENTRY_POINT__';
export const appConfig: ApplicationConfig = {
providers: [
+ provideBrowserGlobalErrorListeners(),
provideZoneChangeDetection({ eventCoalescing: true }),
provideFileRouter(),
provideHttpClient(
withFetch(),
withInterceptors([requestContextInterceptor])
),
- provideClientHydration(),
+ provideClientHydration(withEventReplay()),
provideContent(withMarkdownRenderer(), __HIGHLIGHTER__()),
],
};
diff --git a/packages/create-analog/template-latest/src/app/app.component.spec.ts b/packages/create-analog/template-blog/src/app/app.spec.ts
similarity index 92%
rename from packages/create-analog/template-latest/src/app/app.component.spec.ts
rename to packages/create-analog/template-blog/src/app/app.spec.ts
index 9a08b4b25..2a78e6087 100644
--- a/packages/create-analog/template-latest/src/app/app.component.spec.ts
+++ b/packages/create-analog/template-blog/src/app/app.spec.ts
@@ -2,7 +2,7 @@ import { TestBed } from '@angular/core/testing';
import { provideRouter } from '@angular/router';
import { provideLocationMocks } from '@angular/common/testing';
-import { AppComponent } from './app.component';
+import { AppComponent } from './app';
describe('AppComponent', () => {
beforeEach(async () => {
diff --git a/packages/create-analog/template-blog/src/app/app.component.ts b/packages/create-analog/template-blog/src/app/app.ts
similarity index 96%
rename from packages/create-analog/template-blog/src/app/app.component.ts
rename to packages/create-analog/template-blog/src/app/app.ts
index ca0e58e80..3f3b6617c 100644
--- a/packages/create-analog/template-blog/src/app/app.component.ts
+++ b/packages/create-analog/template-blog/src/app/app.ts
@@ -3,7 +3,6 @@ import { RouterLink, RouterOutlet } from '@angular/router';
@Component({
selector: 'app-root',
- standalone: true,
imports: [RouterLink, RouterOutlet],
template: `