Full Code of enten/angular-universal for AI

main 1dddc6ac8390 cached
34 files
47.5 KB
17.8k tokens
21 symbols
1 requests
Download .txt
Repository: enten/angular-universal
Branch: main
Commit: 1dddc6ac8390
Files: 34
Total size: 47.5 KB

Directory structure:
gitextract_8f690w8e/

├── .editorconfig
├── .gitignore
├── .vscode/
│   ├── extensions.json
│   ├── launch.json
│   └── tasks.json
├── README.md
├── angular.json
├── package.json
├── src/
│   ├── api/
│   │   └── index.ts
│   ├── app/
│   │   ├── app-routes.spa.ts
│   │   ├── app-routes.ts
│   │   ├── app-routing.module.ts
│   │   ├── app.browser.module.ts
│   │   ├── app.component.ts
│   │   ├── app.module.ts
│   │   ├── app.server.module.ts
│   │   ├── hello/
│   │   │   ├── hello-routing.module.ts
│   │   │   ├── hello.component.html
│   │   │   ├── hello.component.scss
│   │   │   ├── hello.component.spec.ts
│   │   │   ├── hello.component.ts
│   │   │   └── hello.module.ts
│   │   └── not-found.component.ts
│   ├── assets/
│   │   └── .gitkeep
│   ├── environments/
│   │   ├── environment.prod.ts
│   │   └── environment.ts
│   ├── index.html
│   ├── main.ts
│   ├── server.ts
│   └── styles.scss
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.server.json
└── tsconfig.spec.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
# 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


================================================
FILE: .gitignore
================================================
# 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
.sass-cache/
/connect.lock
/coverage
/libpeerconnection.log
testem.log
/typings

# System files
.DS_Store
Thumbs.db


================================================
FILE: .vscode/extensions.json
================================================
{
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
  "recommendations": ["angular.ng-template"]
}


================================================
FILE: .vscode/launch.json
================================================
{
  // 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:4000/"
    },
    {
      "name": "ng test",
      "type": "chrome",
      "request": "launch",
      "preLaunchTask": "npm: test",
      "url": "http://localhost:9876/debug.html"
    }
  ]
}


================================================
FILE: .vscode/tasks.json
================================================
{
  // 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"
          }
        }
      }
    }
  ]
}


================================================
FILE: README.md
================================================
# Angular Universal 100% powered by Angular CLI

This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 16.1.3.

### Fast, Unopinionated, Minimalist starter kit for [Angular Universal][angulario-ssr] 100% powered by [Angular CLI][angular-cli].

Unlike the [Official Angular Universal starter kit][official-universal-kit] and other [Awesome Universal Seed Projects][awesome-angular], this starter kit is **universal 100% which means you developing for both browser and server at the same time**.

The main other difference is that **you only need [Angular CLI](https://angular.io/cli)** to kick off your next [Angular Universal][angulario-ssr] project:

* `ng build` - Building browser and server bundles ;
* `ng serve` - Running [ssr dev server][ssr-dev-server] ;
* `ng serve -c spa` - Running [ssr dev server][ssr-dev-server] with server side rendering disabled of routes only.

In other words, this starter kit gives superpower for those who want develop universal application fastly with no pain. Just keep in mind with great power comes [great responsibility (Universal Gotcha's)][universal-gotchas].

## Getting started

```shell
git clone https://github.com/enten/angular-universal
cd angular-universal
npm install
ng serve
```

## Development server

Run `ng serve` for a [ssr dev server][ssr-dev-server]. Navigate to `http://localhost:4000/`. The app will automatically reload if you change any of the source files.

Tip: run `ng serve -c spa` to disable server side rendering of routes only.

## Code scaffolding

Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.

## Build

Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.

Run `node dist/app/server/main.js` to start application built.

## Running unit tests

Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).

## Running end-to-end tests

Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.

## Further help

To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.

[angulario-ssr]: https://angular.io/guide/universal
[angular-cli]: https://github.com/angular/angular-cli
[awesome-angular]: https://github.com/PatrickJS/awesome-angular#universal-seed-projects
[official-universal-kit]: https://github.com/angular/universal-starter
[ssr-dev-server]: https://github.com/angular/universal/tree/main/modules/builders/src/ssr-dev-server
[universal-gotchas]: https://github.com/angular/universal/blob/main/docs/gotchas.md
[webpack-concept-hmr]: https://webpack.js.org/concepts/hot-module-replacement/


================================================
FILE: angular.json
================================================
{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "app": {
      "projectType": "application",
      "schematics": {
        "@schematics/angular:component": {
          "style": "scss"
        },
        "@schematics/angular:application": {
          "strict": true
        }
      },
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-devkit/architect:concat",
          "options": {
            "targets": [
              { "target": "app:browser" },
              { "target": "app:server" }
            ]
          },
          "configurations": {
            "production": {
              "targets": [
                { "target": "app:browser:production" },
                { "target": "app:server:production" }
              ]
            },
            "watch": {
              "targets": [
                { "target": "app:browser:watch" },
                { "target": "app:server:watch" }
              ]
            }
          },
          "defaultConfiguration": "production"
        },
        "browser": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/app/browser",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": [
              "zone.js"
            ],
            "tsConfig": "tsconfig.app.json",
            "inlineStyleLanguage": "scss",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.scss"
            ],
            "sourceMap": true,
            "scripts": []
          },
          "configurations": {
            "production": {
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "500kb",
                  "maximumError": "1mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "2kb",
                  "maximumError": "4kb"
                }
              ],
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "buildOptimizer": true,
              "optimization": true,
              "outputHashing": "all",
              "extractLicenses": true,
              "namedChunks": true,
              "vendorChunk": true
            },
            "development": {
              "buildOptimizer": false,
              "optimization": false,
              "vendorChunk": true,
              "extractLicenses": false,
              "namedChunks": true
            },
            "watch": {
              "buildOptimizer": false,
              "optimization": false,
              "vendorChunk": true,
              "extractLicenses": false,
              "namedChunks": true,
              "watch": true
            }
          },
          "defaultConfiguration": "production"
        },
        "server": {
          "builder": "@angular-devkit/build-angular:server",
          "options": {
            "outputPath": "dist/app/server",
            "main": "src/server.ts",
            "tsConfig": "tsconfig.server.json",
            "inlineStyleLanguage": "scss",
            "namedChunks": true,
            "sourceMap": true
          },
          "configurations": {
            "production": {
              "buildOptimizer": true,
              "optimization": true,
              "extractLicenses": true,
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "outputHashing": "media"
            },
            "development": {
              "buildOptimizer": false,
              "optimization": false,
              "extractLicenses": false,
              "vendorChunk": true
            },
            "spa": {
              "buildOptimizer": false,
              "optimization": false,
              "extractLicenses": false,
              "vendorChunk": true,
              "fileReplacements": [
                {
                  "replace": "src/app/app-routes.ts",
                  "with": "src/app/app-routes.spa.ts"
                }
              ]
            },
            "watch": {
              "buildOptimizer": false,
              "optimization": false,
              "extractLicenses": false,
              "watch": true,
              "vendorChunk": true
            }
          },
          "defaultConfiguration": "production"
        },
        "serve": {
          "builder": "@nguniversal/builders:ssr-dev-server",
          "options": {
            "browserTarget": "app:browser",
            "serverTarget": "app:server",
            "port": 4000
          },
          "configurations": {
            "production": {
              "browserTarget": "app:browser:production",
              "serverTarget": "app:server:production"
            },
            "development": {
              "browserTarget": "app:browser:development",
              "serverTarget": "app:server:development"
            },
            "spa": {
              "serverTarget": "app:server:spa"
            }
          },
          "defaultConfiguration": "development"
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "polyfills": [
              "zone.js",
              "zone.js/testing"
            ],
            "tsConfig": "tsconfig.spec.json",
            "inlineStyleLanguage": "scss",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.scss"
            ],
            "scripts": []
          }
        }
      }
    }
  }
}


================================================
FILE: package.json
================================================
{
  "name": "app",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "watch": "ng build -c watch",
    "test": "ng test"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^16.1.0",
    "@angular/common": "^16.1.0",
    "@angular/compiler": "^16.1.0",
    "@angular/core": "^16.1.0",
    "@angular/forms": "^16.1.0",
    "@angular/platform-browser": "^16.1.0",
    "@angular/platform-browser-dynamic": "^16.1.0",
    "@angular/platform-server": "^16.1.0",
    "@angular/router": "^16.1.0",
    "@nguniversal/express-engine": "^16.1.0",
    "express": "^4.18.2",
    "rxjs": "~7.8.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.13.0"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^16.1.3",
    "@angular/cli": "~16.1.3",
    "@angular/compiler-cli": "^16.1.0",
    "@nguniversal/builders": "^16.1.0",
    "@types/express": "~4.17.17",
    "@types/jasmine": "~4.3.0",
    "@types/node": "^14.18.0",
    "@types/webpack-env": "~1.18.1",
    "jasmine-core": "~4.6.0",
    "karma": "~6.4.0",
    "karma-chrome-launcher": "~3.2.0",
    "karma-coverage": "~2.2.0",
    "karma-jasmine": "~5.1.0",
    "karma-jasmine-html-reporter": "~2.1.0",
    "typescript": "~5.1.3"
  }
}


================================================
FILE: src/api/index.ts
================================================
import { APP_BASE_HREF } from '@angular/common';
import { NgSetupOptions, ngExpressEngine } from '@nguniversal/express-engine';
import * as express from 'express';


export interface ServerAPIOptions {
  distPath: string;
  ngSetup: NgSetupOptions;
  hideSourceMap: boolean;
}


export function createApi(options: ServerAPIOptions): express.Express {
  const router = express();

  // Example Express Rest API endpoints
  // router.get('/api/**', (req, res) => { });

  // Ensures source maps aren't readable on production
  if (options.hideSourceMap) {
    router.get('*.(cs|j)s.map', (req, res) => res.sendStatus(404));
  }

  router.use(createNgRenderMiddleware(options.distPath, options.ngSetup));

  return router;
}


export function createNgRenderMiddleware(distPath: string, ngSetup: NgSetupOptions): express.Express {
  const router = express();

  router.set('view engine', 'html');
  router.set('views', distPath);

  // Server static files from distPath
  router.get('*.*', express.static(distPath, { maxAge: '1y' }), (req, res, next) => {
    if (/\.\w+$/.test(req.path)) {
      res.sendStatus(404);
    } else {
      next();
    }
  });

  // Our Universal express-engine (found @ https://github.com/angular/universal/tree/main/modules/express-engine)
  router.engine('html', ngExpressEngine(ngSetup));

  // All regular routes use the Universal engine
  router.get('*', (req, res) => res.render('index', {
    req,
    res,
    providers: [
      {
        provide: APP_BASE_HREF,
        useValue: req.baseUrl,
      },
    ],
  }));

  return router;
}


================================================
FILE: src/app/app-routes.spa.ts
================================================
import { Routes } from '@angular/router';

// Using an empty array of routes will render an empty <router-outlet> in AppComponent.
export const APP_ROUTES: Routes = [];


================================================
FILE: src/app/app-routes.ts
================================================
import { Routes } from '@angular/router';

import { NotFoundComponent } from './not-found.component';


export const APP_ROUTES: Routes = [
  { path: '', loadChildren: () => import('./hello/hello.module').then(m => m.HelloModule) },
  { path: '**', component: NotFoundComponent },
];


================================================
FILE: src/app/app-routing.module.ts
================================================
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';

import { APP_ROUTES } from './app-routes';


@NgModule({
  imports: [
    RouterModule.forRoot(APP_ROUTES, {
      initialNavigation: 'enabledBlocking',
    }),
  ],
  exports: [RouterModule],
})
export class AppRoutingModule { }


================================================
FILE: src/app/app.browser.module.ts
================================================
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { AppModule } from './app.module';


@NgModule({
  imports: [AppModule],
  bootstrap: [AppComponent],
})
export class AppBrowserModule { }


================================================
FILE: src/app/app.component.ts
================================================
import { ChangeDetectionStrategy, Component, ElementRef, Renderer2 } from '@angular/core';

import { environment } from '../environments/environment';


@Component({
  selector: 'app-root',
  template: '<router-outlet></router-outlet>',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {
  constructor(
    private elementRef: ElementRef<HTMLElement>,
    private renderer: Renderer2,
  ) { }

  ngOnInit(): void {
    if (environment.production) {
      this.renderer.removeAttribute(this.elementRef.nativeElement, 'ng-version');
    }
  }
}


================================================
FILE: src/app/app.module.ts
================================================
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { NotFoundComponent } from './not-found.component';


@NgModule({
  declarations: [
    AppComponent,
    NotFoundComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule { }


================================================
FILE: src/app/app.server.module.ts
================================================
import { NgModule } from '@angular/core';
import { ServerModule } from '@angular/platform-server';

import { AppComponent } from './app.component';
import { AppModule } from './app.module';


@NgModule({
  imports: [
    // The AppServerModule should import your AppModule followed
    // by the ServerModule from @angular/platform-server.
    AppModule,
    ServerModule,
  ],
  // Since the bootstrapped component is not inherited from your
  // imported AppModule, it needs to be repeated here.
  bootstrap: [ AppComponent ],
})
export class AppServerModule { }


================================================
FILE: src/app/hello/hello-routing.module.ts
================================================
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { HelloComponent } from './hello.component';


const routes: Routes = [
  { path: '', component: HelloComponent },
];


@NgModule({
  declarations: [ HelloComponent ],
  imports: [
    CommonModule,
    RouterModule.forChild(routes),
  ],
  exports: [ RouterModule ],
})
export class HelloRoutingModule { }


================================================
FILE: src/app/hello/hello.component.html
================================================
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * * The content below * * * * * * * * * * * -->
<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * -->
<!-- * * * * * * * * * * and can be replaced. * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * Delete the template below * * * * * * * * * * -->
<!-- * * * * * * * to get started with your project! * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->

<style>
  :host {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
    font-size: 14px;
    color: #333;
    box-sizing: border-box;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }

  h1,
  h2,
  h3,
  h4,
  h5,
  h6 {
    margin: 8px 0;
  }

  p {
    margin: 0;
  }

  .spacer {
    flex: 1;
  }

  .toolbar {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 60px;
    display: flex;
    align-items: center;
    background-color: #1976d2;
    color: white;
    font-weight: 600;
  }

  .toolbar img {
    margin: 0 16px;
  }

  .toolbar #twitter-logo {
    height: 40px;
    margin: 0 8px;
  }

  .toolbar #youtube-logo {
    height: 40px;
    margin: 0 16px;
  }

  .toolbar #twitter-logo:hover,
  .toolbar #youtube-logo:hover {
    opacity: 0.8;
  }

  .content {
    display: flex;
    margin: 82px auto 32px;
    padding: 0 16px;
    max-width: 960px;
    flex-direction: column;
    align-items: center;
  }

  svg.material-icons {
    height: 24px;
    width: auto;
  }

  svg.material-icons:not(:last-child) {
    margin-right: 8px;
  }

  .card svg.material-icons path {
    fill: #888;
  }

  .card-container {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    margin-top: 16px;
  }

  .card {
    all: unset;
    border-radius: 4px;
    border: 1px solid #eee;
    background-color: #fafafa;
    height: 40px;
    width: 200px;
    margin: 0 8px 16px;
    padding: 16px;
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    transition: all 0.2s ease-in-out;
    line-height: 24px;
  }

  .card-container .card:not(:last-child) {
    margin-right: 0;
  }

  .card.card-small {
    height: 16px;
    width: 168px;
  }

  .card-container .card:not(.highlight-card) {
    cursor: pointer;
  }

  .card-container .card:not(.highlight-card):hover {
    transform: translateY(-3px);
    box-shadow: 0 4px 17px rgba(0, 0, 0, 0.35);
  }

  .card-container .card:not(.highlight-card):hover .material-icons path {
    fill: rgb(105, 103, 103);
  }

  .card.highlight-card {
    background-color: #1976d2;
    color: white;
    font-weight: 600;
    border: none;
    width: auto;
    min-width: 30%;
    position: relative;
  }

  .card.card.highlight-card span {
    margin-left: 60px;
  }

  svg#rocket {
    width: 80px;
    position: absolute;
    left: -10px;
    top: -24px;
  }

  svg#rocket-smoke {
    height: calc(100vh - 95px);
    position: absolute;
    top: 10px;
    right: 180px;
    z-index: -10;
  }

  a,
  a:visited,
  a:hover {
    color: #1976d2;
    text-decoration: none;
  }

  a:hover {
    color: #125699;
  }

  .terminal {
    position: relative;
    width: 80%;
    max-width: 600px;
    border-radius: 6px;
    padding-top: 45px;
    margin-top: 8px;
    overflow: hidden;
    background-color: rgb(15, 15, 16);
  }

  .terminal::before {
    content: "\2022 \2022 \2022";
    position: absolute;
    top: 0;
    left: 0;
    height: 4px;
    background: rgb(58, 58, 58);
    color: #c2c3c4;
    width: 100%;
    font-size: 2rem;
    line-height: 0;
    padding: 14px 0;
    text-indent: 4px;
  }

  .terminal pre {
    font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;
    color: white;
    padding: 0 1rem 1rem;
    margin: 0;
  }

  .circle-link {
    height: 40px;
    width: 40px;
    border-radius: 40px;
    margin: 8px;
    background-color: white;
    border: 1px solid #eeeeee;
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
    transition: 1s ease-out;
  }

  .circle-link:hover {
    transform: translateY(-0.25rem);
    box-shadow: 0px 3px 15px rgba(0, 0, 0, 0.2);
  }

  footer {
    margin-top: 8px;
    display: flex;
    align-items: center;
    line-height: 20px;
  }

  footer a {
    display: flex;
    align-items: center;
  }

  .github-star-badge {
    color: #24292e;
    display: flex;
    align-items: center;
    font-size: 12px;
    padding: 3px 10px;
    border: 1px solid rgba(27,31,35,.2);
    border-radius: 3px;
    background-image: linear-gradient(-180deg,#fafbfc,#eff3f6 90%);
    margin-left: 4px;
    font-weight: 600;
  }

  .github-star-badge:hover {
    background-image: linear-gradient(-180deg,#f0f3f6,#e6ebf1 90%);
    border-color: rgba(27,31,35,.35);
    background-position: -.5em;
  }

  .github-star-badge .material-icons {
    height: 16px;
    width: 16px;
    margin-right: 4px;
  }

  svg#clouds {
    position: fixed;
    bottom: -160px;
    left: -230px;
    z-index: -10;
    width: 1920px;
  }

  /* Responsive Styles */
  @media screen and (max-width: 767px) {
    .card-container > *:not(.circle-link) ,
    .terminal {
      width: 100%;
    }

    .card:not(.highlight-card) {
      height: 16px;
      margin: 8px 0;
    }

    .card.highlight-card span {
      margin-left: 72px;
    }

    svg#rocket-smoke {
      right: 120px;
      transform: rotate(-5deg);
    }
  }

  @media screen and (max-width: 575px) {
    svg#rocket-smoke {
      display: none;
      visibility: hidden;
    }
  }
</style>

<!-- Toolbar -->
<div class="toolbar" role="banner">
  <img
    width="40"
    alt="Angular Logo"
    src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg=="
  />
  <span>Welcome</span>
    <div class="spacer"></div>
    <a aria-label="Angular on twitter" target="_blank" rel="noopener" href="https://twitter.com/angular" title="Twitter">
      <svg id="twitter-logo" height="24" data-name="Logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400">
        <rect width="400" height="400" fill="none"/>
        <path d="M153.62,301.59c94.34,0,145.94-78.16,145.94-145.94,0-2.22,0-4.43-.15-6.63A104.36,104.36,0,0,0,325,122.47a102.38,102.38,0,0,1-29.46,8.07,51.47,51.47,0,0,0,22.55-28.37,102.79,102.79,0,0,1-32.57,12.45,51.34,51.34,0,0,0-87.41,46.78A145.62,145.62,0,0,1,92.4,107.81a51.33,51.33,0,0,0,15.88,68.47A50.91,50.91,0,0,1,85,169.86c0,.21,0,.43,0,.65a51.31,51.31,0,0,0,41.15,50.28,51.21,51.21,0,0,1-23.16.88,51.35,51.35,0,0,0,47.92,35.62,102.92,102.92,0,0,1-63.7,22A104.41,104.41,0,0,1,75,278.55a145.21,145.21,0,0,0,78.62,23" fill="#fff"/>
      </svg>
    </a>
    <a aria-label="Angular on YouTube" target="_blank" rel="noopener" href="https://youtube.com/angular" title="YouTube">
      <svg id="youtube-logo" height="24" width="24" data-name="Logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#fff">
        <path d="M0 0h24v24H0V0z" fill="none"/>
        <path d="M21.58 7.19c-.23-.86-.91-1.54-1.77-1.77C18.25 5 12 5 12 5s-6.25 0-7.81.42c-.86.23-1.54.91-1.77 1.77C2 8.75 2 12 2 12s0 3.25.42 4.81c.23.86.91 1.54 1.77 1.77C5.75 19 12 19 12 19s6.25 0 7.81-.42c.86-.23 1.54-.91 1.77-1.77C22 15.25 22 12 22 12s0-3.25-.42-4.81zM10 15V9l5.2 3-5.2 3z"/>
      </svg>
    </a>
</div>

<div class="content" role="main">

  <!-- Highlight Card -->
  <div class="card highlight-card card-small">

    <svg id="rocket" xmlns="http://www.w3.org/2000/svg" width="101.678" height="101.678" viewBox="0 0 101.678 101.678">
      <title>Rocket Ship</title>
      <g id="Group_83" data-name="Group 83" transform="translate(-141 -696)">
        <circle id="Ellipse_8" data-name="Ellipse 8" cx="50.839" cy="50.839" r="50.839" transform="translate(141 696)" fill="#dd0031"/>
        <g id="Group_47" data-name="Group 47" transform="translate(165.185 720.185)">
          <path id="Path_33" data-name="Path 33" d="M3.4,42.615a3.084,3.084,0,0,0,3.553,3.553,21.419,21.419,0,0,0,12.215-6.107L9.511,30.4A21.419,21.419,0,0,0,3.4,42.615Z" transform="translate(0.371 3.363)" fill="#fff"/>
          <path id="Path_34" data-name="Path 34" d="M53.3,3.221A3.09,3.09,0,0,0,50.081,0,48.227,48.227,0,0,0,18.322,13.437c-6-1.666-14.991-1.221-18.322,7.218A33.892,33.892,0,0,1,9.439,25.1l-.333.666a3.013,3.013,0,0,0,.555,3.553L23.985,43.641a2.9,2.9,0,0,0,3.553.555l.666-.333A33.892,33.892,0,0,1,32.647,53.3c8.55-3.664,8.884-12.326,7.218-18.322A48.227,48.227,0,0,0,53.3,3.221ZM34.424,9.772a6.439,6.439,0,1,1,9.106,9.106,6.368,6.368,0,0,1-9.106,0A6.467,6.467,0,0,1,34.424,9.772Z" transform="translate(0 0.005)" fill="#fff"/>
        </g>
      </g>
    </svg>

    <span>{{ title }} app is running!</span>

    <svg id="rocket-smoke" xmlns="http://www.w3.org/2000/svg" width="516.119" height="1083.632" viewBox="0 0 516.119 1083.632">
      <title>Rocket Ship Smoke</title>
      <path id="Path_40" data-name="Path 40" d="M644.6,141S143.02,215.537,147.049,870.207s342.774,201.755,342.774,201.755S404.659,847.213,388.815,762.2c-27.116-145.51-11.551-384.124,271.9-609.1C671.15,139.365,644.6,141,644.6,141Z" transform="translate(-147.025 -140.939)" fill="#f5f5f5"/>
    </svg>

  </div>

  <!-- Resources -->
  <h2>Resources</h2>
  <p>Here are some links to help you get started:</p>

  <div class="card-container">
    <a class="card" target="_blank" rel="noopener" href="https://angular.io/tutorial">
      <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M5 13.18v4L12 21l7-3.82v-4L12 17l-7-3.82zM12 3L1 9l11 6 9-4.91V17h2V9L12 3z"/></svg>
      <span>Learn Angular</span>
      <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>    </a>

    <a class="card" target="_blank" rel="noopener" href="https://angular.io/cli">
      <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"/></svg>
      <span>CLI Documentation</span>
      <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>
    </a>

    <a class="card" target="_blank" rel="noopener" href="https://material.angular.io">
      <svg xmlns="http://www.w3.org/2000/svg" style="margin-right: 8px" width="21.813" height="23.453" viewBox="0 0 179.2 192.7"><path fill="#ffa726" d="M89.4 0 0 32l13.5 118.4 75.9 42.3 76-42.3L179.2 32 89.4 0z"/><path fill="#fb8c00" d="M89.4 0v192.7l76-42.3L179.2 32 89.4 0z"/><path fill="#ffe0b2" d="m102.9 146.3-63.3-30.5 36.3-22.4 63.7 30.6-36.7 22.3z"/><path fill="#fff3e0" d="M102.9 122.8 39.6 92.2l36.3-22.3 63.7 30.6-36.7 22.3z"/><path fill="#fff" d="M102.9 99.3 39.6 68.7l36.3-22.4 63.7 30.6-36.7 22.4z"/></svg>
      <span>Angular Material</span>
      <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>
    </a>

    <a class="card" target="_blank" rel="noopener" href="https://blog.angular.io/">
      <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M13.5.67s.74 2.65.74 4.8c0 2.06-1.35 3.73-3.41 3.73-2.07 0-3.63-1.67-3.63-3.73l.03-.36C5.21 7.51 4 10.62 4 14c0 4.42 3.58 8 8 8s8-3.58 8-8C20 8.61 17.41 3.8 13.5.67zM11.71 19c-1.78 0-3.22-1.4-3.22-3.14 0-1.62 1.05-2.76 2.81-3.12 1.77-.36 3.6-1.21 4.62-2.58.39 1.29.59 2.65.59 4.04 0 2.65-2.15 4.8-4.8 4.8z"/></svg>
      <span>Angular Blog</span>
      <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>
    </a>

    <a class="card" target="_blank" rel="noopener" href="https://angular.io/devtools/">
      <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><g><path d="M14.73,13.31C15.52,12.24,16,10.93,16,9.5C16,5.91,13.09,3,9.5,3S3,5.91,3,9.5C3,13.09,5.91,16,9.5,16 c1.43,0,2.74-0.48,3.81-1.27L19.59,21L21,19.59L14.73,13.31z M9.5,14C7.01,14,5,11.99,5,9.5S7.01,5,9.5,5S14,7.01,14,9.5 S11.99,14,9.5,14z"/><polygon points="10.29,8.44 9.5,6 8.71,8.44 6.25,8.44 8.26,10.03 7.49,12.5 9.5,10.97 11.51,12.5 10.74,10.03 12.75,8.44"/></g></g></svg>
      <span>Angular DevTools</span>
      <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>
    </a>

  </div>

  <!-- Next Steps -->
  <h2>Next Steps</h2>
  <p>What do you want to do next with your app?</p>

  <input type="hidden" #selection>

  <div class="card-container">
    <button class="card card-small" (click)="selection.value = 'component'" tabindex="0">
      <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
      <span>New Component</span>
    </button>

    <button class="card card-small" (click)="selection.value = 'material'" tabindex="0">
      <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
      <span>Angular Material</span>
    </button>

    <button class="card card-small" (click)="selection.value = 'pwa'" tabindex="0">
      <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
      <span>Add PWA Support</span>
    </button>

    <button class="card card-small" (click)="selection.value = 'dependency'" tabindex="0">
      <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
      <span>Add Dependency</span>
    </button>

    <button class="card card-small" (click)="selection.value = 'test'" tabindex="0">
      <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
      <span>Run and Watch Tests</span>
    </button>

    <button class="card card-small" (click)="selection.value = 'build'" tabindex="0">
      <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
      <span>Build for Production</span>
    </button>
  </div>

  <!-- Terminal -->
  <div class="terminal" [ngSwitch]="selection.value">
      <pre *ngSwitchDefault>ng generate component xyz</pre>
      <pre *ngSwitchCase="'material'">ng add @angular/material</pre>
      <pre *ngSwitchCase="'pwa'">ng add @angular/pwa</pre>
      <pre *ngSwitchCase="'dependency'">ng add _____</pre>
      <pre *ngSwitchCase="'test'">ng test</pre>
      <pre *ngSwitchCase="'build'">ng build</pre>
  </div>

  <!-- Links -->
  <div class="card-container">
    <a class="circle-link" title="Find a Local Meetup" href="https://www.meetup.com/find/?keywords=angular" target="_blank" rel="noopener">
      <svg xmlns="http://www.w3.org/2000/svg" width="24.607" height="23.447" viewBox="0 0 24.607 23.447">
        <title>Meetup Logo</title>
        <path id="logo--mSwarm" d="M21.221,14.95A4.393,4.393,0,0,1,17.6,19.281a4.452,4.452,0,0,1-.8.069c-.09,0-.125.035-.154.117a2.939,2.939,0,0,1-2.506,2.091,2.868,2.868,0,0,1-2.248-.624.168.168,0,0,0-.245-.005,3.926,3.926,0,0,1-2.589.741,4.015,4.015,0,0,1-3.7-3.347,2.7,2.7,0,0,1-.043-.38c0-.106-.042-.146-.143-.166a3.524,3.524,0,0,1-1.516-.69A3.623,3.623,0,0,1,2.23,14.557a3.66,3.66,0,0,1,1.077-3.085.138.138,0,0,0,.026-.2,3.348,3.348,0,0,1-.451-1.821,3.46,3.46,0,0,1,2.749-3.28.44.44,0,0,0,.355-.281,5.072,5.072,0,0,1,3.863-3,5.028,5.028,0,0,1,3.555.666.31.31,0,0,0,.271.03A4.5,4.5,0,0,1,18.3,4.7a4.4,4.4,0,0,1,1.334,2.751,3.658,3.658,0,0,1,.022.706.131.131,0,0,0,.1.157,2.432,2.432,0,0,1,1.574,1.645,2.464,2.464,0,0,1-.7,2.616c-.065.064-.051.1-.014.166A4.321,4.321,0,0,1,21.221,14.95ZM13.4,14.607a2.09,2.09,0,0,0,1.409,1.982,4.7,4.7,0,0,0,1.275.221,1.807,1.807,0,0,0,.9-.151.542.542,0,0,0,.321-.545.558.558,0,0,0-.359-.534,1.2,1.2,0,0,0-.254-.078c-.262-.047-.526-.086-.787-.138a.674.674,0,0,1-.617-.75,3.394,3.394,0,0,1,.218-1.109c.217-.658.509-1.286.79-1.918a15.609,15.609,0,0,0,.745-1.86,1.95,1.95,0,0,0,.06-1.073,1.286,1.286,0,0,0-1.051-1.033,1.977,1.977,0,0,0-1.521.2.339.339,0,0,1-.446-.042c-.1-.092-.2-.189-.307-.284a1.214,1.214,0,0,0-1.643-.061,7.563,7.563,0,0,1-.614.512A.588.588,0,0,1,10.883,8c-.215-.115-.437-.215-.659-.316a2.153,2.153,0,0,0-.695-.248A2.091,2.091,0,0,0,7.541,8.562a9.915,9.915,0,0,0-.405.986c-.559,1.545-1.015,3.123-1.487,4.7a1.528,1.528,0,0,0,.634,1.777,1.755,1.755,0,0,0,1.5.211,1.35,1.35,0,0,0,.824-.858c.543-1.281,1.032-2.584,1.55-3.875.142-.355.28-.712.432-1.064a.548.548,0,0,1,.851-.24.622.622,0,0,1,.185.539,2.161,2.161,0,0,1-.181.621c-.337.852-.68,1.7-1.018,2.552a2.564,2.564,0,0,0-.173.528.624.624,0,0,0,.333.71,1.073,1.073,0,0,0,.814.034,1.22,1.22,0,0,0,.657-.655q.758-1.488,1.511-2.978.35-.687.709-1.37a1.073,1.073,0,0,1,.357-.434.43.43,0,0,1,.463-.016.373.373,0,0,1,.153.387.7.7,0,0,1-.057.236c-.065.157-.127.316-.2.469-.42.883-.846,1.763-1.262,2.648A2.463,2.463,0,0,0,13.4,14.607Zm5.888,6.508a1.09,1.09,0,0,0-2.179.006,1.09,1.09,0,0,0,2.179-.006ZM1.028,12.139a1.038,1.038,0,1,0,.01-2.075,1.038,1.038,0,0,0-.01,2.075ZM13.782.528a1.027,1.027,0,1,0-.011,2.055A1.027,1.027,0,0,0,13.782.528ZM22.21,6.95a.882.882,0,0,0-1.763.011A.882.882,0,0,0,22.21,6.95ZM4.153,4.439a.785.785,0,1,0,.787-.78A.766.766,0,0,0,4.153,4.439Zm8.221,18.22a.676.676,0,1,0-.677.666A.671.671,0,0,0,12.374,22.658ZM22.872,12.2a.674.674,0,0,0-.665.665.656.656,0,0,0,.655.643.634.634,0,0,0,.655-.644A.654.654,0,0,0,22.872,12.2ZM7.171-.123A.546.546,0,0,0,6.613.43a.553.553,0,1,0,1.106,0A.539.539,0,0,0,7.171-.123ZM24.119,9.234a.507.507,0,0,0-.493.488.494.494,0,0,0,.494.494.48.48,0,0,0,.487-.483A.491.491,0,0,0,24.119,9.234Zm-19.454,9.7a.5.5,0,0,0-.488-.488.491.491,0,0,0-.487.5.483.483,0,0,0,.491.479A.49.49,0,0,0,4.665,18.936Z" transform="translate(0 0.123)" fill="#f64060"/>
      </svg>
    </a>

    <a class="circle-link" title="Join the Conversation on Discord" href="https://discord.gg/angular" target="_blank" rel="noopener">
      <svg xmlns="http://www.w3.org/2000/svg" width="26" height="26" viewBox="0 0 245 240">
        <title>Discord Logo</title>
        <path d="M104.4 103.9c-5.7 0-10.2 5-10.2 11.1s4.6 11.1 10.2 11.1c5.7 0 10.2-5 10.2-11.1.1-6.1-4.5-11.1-10.2-11.1zM140.9 103.9c-5.7 0-10.2 5-10.2 11.1s4.6 11.1 10.2 11.1c5.7 0 10.2-5 10.2-11.1s-4.5-11.1-10.2-11.1z"/>
        <path d="M189.5 20h-134C44.2 20 35 29.2 35 40.6v135.2c0 11.4 9.2 20.6 20.5 20.6h113.4l-5.3-18.5 12.8 11.9 12.1 11.2 21.5 19V40.6c0-11.4-9.2-20.6-20.5-20.6zm-38.6 130.6s-3.6-4.3-6.6-8.1c13.1-3.7 18.1-11.9 18.1-11.9-4.1 2.7-8 4.6-11.5 5.9-5 2.1-9.8 3.5-14.5 4.3-9.6 1.8-18.4 1.3-25.9-.1-5.7-1.1-10.6-2.7-14.7-4.3-2.3-.9-4.8-2-7.3-3.4-.3-.2-.6-.3-.9-.5-.2-.1-.3-.2-.4-.3-1.8-1-2.8-1.7-2.8-1.7s4.8 8 17.5 11.8c-3 3.8-6.7 8.3-6.7 8.3-22.1-.7-30.5-15.2-30.5-15.2 0-32.2 14.4-58.3 14.4-58.3 14.4-10.8 28.1-10.5 28.1-10.5l1 1.2c-18 5.2-26.3 13.1-26.3 13.1s2.2-1.2 5.9-2.9c10.7-4.7 19.2-6 22.7-6.3.6-.1 1.1-.2 1.7-.2 6.1-.8 13-1 20.2-.2 9.5 1.1 19.7 3.9 30.1 9.6 0 0-7.9-7.5-24.9-12.7l1.4-1.6s13.7-.3 28.1 10.5c0 0 14.4 26.1 14.4 58.3 0 0-8.5 14.5-30.6 15.2z"/>
      </svg>
    </a>
  </div>

  <!-- Footer -->
  <footer>
      Love Angular?&nbsp;
      <a href="https://github.com/angular/angular" target="_blank" rel="noopener"> Give our repo a star.
        <div class="github-star-badge">
            <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/></svg>
          Star
        </div>
      </a>
      <a href="https://github.com/angular/angular" target="_blank" rel="noopener">
        <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" fill="#1976d2"/><path d="M0 0h24v24H0z" fill="none"/></svg>
      </a>
  </footer>

  <svg id="clouds" xmlns="http://www.w3.org/2000/svg" width="2611.084" height="485.677" viewBox="0 0 2611.084 485.677">
    <title>Gray Clouds Background</title>
    <path id="Path_39" data-name="Path 39" d="M2379.709,863.793c10-93-77-171-168-149-52-114-225-105-264,15-75,3-140,59-152,133-30,2.83-66.725,9.829-93.5,26.25-26.771-16.421-63.5-23.42-93.5-26.25-12-74-77-130-152-133-39-120-212-129-264-15-54.084-13.075-106.753,9.173-138.488,48.9-31.734-39.726-84.4-61.974-138.487-48.9-52-114-225-105-264,15a162.027,162.027,0,0,0-103.147,43.044c-30.633-45.365-87.1-72.091-145.206-58.044-52-114-225-105-264,15-75,3-140,59-152,133-53,5-127,23-130,83-2,42,35,72,70,86,49,20,106,18,157,5a165.625,165.625,0,0,0,120,0c47,94,178,113,251,33,61.112,8.015,113.854-5.72,150.492-29.764a165.62,165.62,0,0,0,110.861-3.236c47,94,178,113,251,33,31.385,4.116,60.563,2.495,86.487-3.311,25.924,5.806,55.1,7.427,86.488,3.311,73,80,204,61,251-33a165.625,165.625,0,0,0,120,0c51,13,108,15,157-5a147.188,147.188,0,0,0,33.5-18.694,147.217,147.217,0,0,0,33.5,18.694c49,20,106,18,157,5a165.625,165.625,0,0,0,120,0c47,94,178,113,251,33C2446.709,1093.793,2554.709,922.793,2379.709,863.793Z" transform="translate(142.69 -634.312)" fill="#eee"/>
  </svg>

</div>

<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * * The content above * * * * * * * * * * * -->
<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * -->
<!-- * * * * * * * * * * and can be replaced. * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * End of Placeholder * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->


================================================
FILE: src/app/hello/hello.component.scss
================================================


================================================
FILE: src/app/hello/hello.component.spec.ts
================================================
import { TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { RouterTestingModule } from '@angular/router/testing';

import { HelloComponent } from './hello.component';


describe('HelloComponent', () => {
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [
        RouterTestingModule,
      ],
      declarations: [
        HelloComponent,
      ],
    }).compileComponents();
  });

  it('should create the app', () => {
    const fixture = TestBed.createComponent(HelloComponent);
    const app = fixture.debugElement.componentInstance;
    expect(app).toBeTruthy();
  });

  it(`should have as title 'angular'`, () => {
    const fixture = TestBed.createComponent(HelloComponent);
    const app = fixture.debugElement.componentInstance;
    expect(app.title).toEqual('angular');
  });

  it('should render title as rocket message', () => {
    const fixture = TestBed.createComponent(HelloComponent);
    fixture.detectChanges();
    const rocketMessage = fixture.debugElement.query(By.css('.content span'))?.nativeElement;
    expect(rocketMessage?.textContent).toContain('angular app is running!');
  });
});


================================================
FILE: src/app/hello/hello.component.ts
================================================
import { ChangeDetectionStrategy, Component } from '@angular/core';


@Component({
  selector: 'app-welcome',
  templateUrl: './hello.component.html',
  styleUrls: ['./hello.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HelloComponent {
  title = 'angular';
}


================================================
FILE: src/app/hello/hello.module.ts
================================================
import { NgModule } from '@angular/core';

import { HelloRoutingModule } from './hello-routing.module';


@NgModule({
  declarations: [],
  imports: [
    HelloRoutingModule,
  ],
})
export class HelloModule { }


================================================
FILE: src/app/not-found.component.ts
================================================
import { Component, Inject, OnInit, Optional } from '@angular/core';
import { RESPONSE } from '@nguniversal/express-engine/tokens';


interface PartialResponse {
  status(code: number): this;
}


@Component({
  selector: 'app-not-found',
  template: '<h1>Page Not Found</h1>',
})
export class NotFoundComponent implements OnInit {
  constructor(
    @Optional() @Inject(RESPONSE) private response: PartialResponse,
  ) {}

  ngOnInit(): void {
    if (this.response) {
      this.response.status(404);
    }
  }
}


================================================
FILE: src/assets/.gitkeep
================================================


================================================
FILE: src/environments/environment.prod.ts
================================================
export const environment = {
  production: true
};


================================================
FILE: src/environments/environment.ts
================================================
// This file can be replaced during build by using the `fileReplacements` array.
// `ng build` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.

export const environment = {
  production: false
};

/*
 * For easier debugging in development mode, you can import the following file
 * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
 *
 * This import should be commented out in production mode because it will have a negative impact
 * on performance if an error is thrown.
 */
// import 'zone.js/plugins/zone-error';  // Included with Angular CLI.


================================================
FILE: src/index.html
================================================
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>App</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-root></app-root>
</body>
</html>


================================================
FILE: src/main.ts
================================================
import { ApplicationRef, NgModuleRef } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppBrowserModule } from './app/app.browser.module';


async function main(): Promise<NgModuleRef<AppBrowserModule>> {
  const ngModuleRef = await platformBrowserDynamic().bootstrapModule(AppBrowserModule);
  const appRef = ngModuleRef.injector.get(ApplicationRef);

  console.log('AppBrowserModule boostraped!', { appRef, ngModuleRef });

  return ngModuleRef;
}


if (document.readyState === 'complete') {
  main().catch(console.error);
} else {
  document.addEventListener('DOMContentLoaded', main);
}


================================================
FILE: src/server.ts
================================================
// These are important and needed before anything else
import 'zone.js/node';

/***************************************************************************************************
 * Initialize the server environment - for example, adding DOM built-in types to the global scope.
 *
 * NOTE:
 * This import must come before any imports (direct or transitive) that rely on DOM built-ins being
 * available, such as `@angular/elements`.
 */
import '@angular/platform-server/init';


import { createServer } from 'node:http';
import { join } from 'node:path';

import { Type } from '@angular/core';

import { ServerAPIOptions, createApi } from './api';
import { AppServerModule } from './app/app.server.module';
import { environment } from './environments/environment';


// WARN: don't remove export of AppServerModule.
// Removing export below will break replaceServerBootstrap() transformer.
export { AppServerModule } from './app/app.server.module';


// WARN: keep in mind that __filename ends with dist/app/server/main.js during runtime.
// WARN: keep in mind that __dirname ends with dist/app/server during runtime.
export const BROWSER_DIST_PATH = join(__dirname, '..', 'browser');

export const getServerAPIOptions = (bootstrap: Type<{}>): ServerAPIOptions => ({
  distPath: BROWSER_DIST_PATH,
  ngSetup: {
    bootstrap,
    providers: [],
  },
  hideSourceMap: environment.production,
});


let requestListener = createApi(getServerAPIOptions(AppServerModule));

// Create the Node server
const server = createServer((req, res) => {
  requestListener(req, res);
});


// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const moduleFilename = mainModule && mainModule.filename || '';
if (
  moduleFilename === __filename
  || moduleFilename.includes('iisnode')
) {
  const PORT = process.env['PORT'] ? +process.env['PORT'] : 4000;

  server.listen(PORT, () => {
    console.log(`Server listening -- http://localhost:${PORT}`);
  });
}


export default server;


================================================
FILE: src/styles.scss
================================================
/* You can add global styles to this file, and also import other style files */


================================================
FILE: tsconfig.app.json
================================================
/* 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"
  ],
  "include": [
    "src/**/*.d.ts"
  ],
  "exclude": [
    "**/*.spec.ts",
    "**/*.stories.ts",
    "e2e/**",
    "src/api/**",
    "src/app/app.server.module.ts",
    "src/server.ts",
    "src/stories/**",
    "src/test.ts"
  ]
}

================================================
FILE: tsconfig.json
================================================
/* 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": "node",
    "importHelpers": true,
    "target": "ES2022",
    "module": "ES2022",
    "useDefineForClassFields": false,
    "lib": [
      "ES2022",
      "dom"
    ]
  },
  "angularCompilerOptions": {
    "enableI18nLegacyMessageIdFormat": false,
    "strictInjectionParameters": true,
    "strictInputAccessModifiers": true,
    "strictTemplates": true
  }
}


================================================
FILE: tsconfig.server.json
================================================
{
  "extends": "./tsconfig.app.json",
  "compilerOptions": {
    "outDir": "./out-tsc/server",
    "target": "es2019",
    "types": ["node"]
  },
  "angularCompilerOptions": {
    "entryModule": "./src/app/app.server.module#AppServerModule"
  },
  "files": [
    "src/server.ts"
  ],
  "exclude": [
    "**/*.spec.ts",
    "**/*.stories.ts",
    "e2e/**",
    "src/app/app.browser.module.ts",
    "src/main.ts",
    "src/stories/**"
  ]
}


================================================
FILE: tsconfig.spec.json
================================================
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./out-tsc/spec",
    "types": [
      "jasmine"
    ]
  },
  "include": [
    "src/**/*.spec.ts",
    "src/**/*.d.ts"
  ]
}
Download .txt
gitextract_8f690w8e/

├── .editorconfig
├── .gitignore
├── .vscode/
│   ├── extensions.json
│   ├── launch.json
│   └── tasks.json
├── README.md
├── angular.json
├── package.json
├── src/
│   ├── api/
│   │   └── index.ts
│   ├── app/
│   │   ├── app-routes.spa.ts
│   │   ├── app-routes.ts
│   │   ├── app-routing.module.ts
│   │   ├── app.browser.module.ts
│   │   ├── app.component.ts
│   │   ├── app.module.ts
│   │   ├── app.server.module.ts
│   │   ├── hello/
│   │   │   ├── hello-routing.module.ts
│   │   │   ├── hello.component.html
│   │   │   ├── hello.component.scss
│   │   │   ├── hello.component.spec.ts
│   │   │   ├── hello.component.ts
│   │   │   └── hello.module.ts
│   │   └── not-found.component.ts
│   ├── assets/
│   │   └── .gitkeep
│   ├── environments/
│   │   ├── environment.prod.ts
│   │   └── environment.ts
│   ├── index.html
│   ├── main.ts
│   ├── server.ts
│   └── styles.scss
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.server.json
└── tsconfig.spec.json
Download .txt
SYMBOL INDEX (21 symbols across 14 files)

FILE: src/api/index.ts
  type ServerAPIOptions (line 6) | interface ServerAPIOptions {
  function createApi (line 13) | function createApi(options: ServerAPIOptions): express.Express {
  function createNgRenderMiddleware (line 30) | function createNgRenderMiddleware(distPath: string, ngSetup: NgSetupOpti...

FILE: src/app/app-routes.spa.ts
  constant APP_ROUTES (line 4) | const APP_ROUTES: Routes = [];

FILE: src/app/app-routes.ts
  constant APP_ROUTES (line 6) | const APP_ROUTES: Routes = [

FILE: src/app/app-routing.module.ts
  class AppRoutingModule (line 15) | class AppRoutingModule { }

FILE: src/app/app.browser.module.ts
  class AppBrowserModule (line 11) | class AppBrowserModule { }

FILE: src/app/app.component.ts
  class AppComponent (line 11) | class AppComponent {
    method constructor (line 12) | constructor(
    method ngOnInit (line 17) | ngOnInit(): void {

FILE: src/app/app.module.ts
  class AppModule (line 21) | class AppModule { }

FILE: src/app/app.server.module.ts
  class AppServerModule (line 19) | class AppServerModule { }

FILE: src/app/hello/hello-routing.module.ts
  class HelloRoutingModule (line 21) | class HelloRoutingModule { }

FILE: src/app/hello/hello.component.ts
  class HelloComponent (line 10) | class HelloComponent {

FILE: src/app/hello/hello.module.ts
  class HelloModule (line 12) | class HelloModule { }

FILE: src/app/not-found.component.ts
  type PartialResponse (line 5) | interface PartialResponse {
  class NotFoundComponent (line 14) | class NotFoundComponent implements OnInit {
    method constructor (line 15) | constructor(
    method ngOnInit (line 19) | ngOnInit(): void {

FILE: src/main.ts
  function main (line 7) | async function main(): Promise<NgModuleRef<AppBrowserModule>> {

FILE: src/server.ts
  constant BROWSER_DIST_PATH (line 31) | const BROWSER_DIST_PATH = join(__dirname, '..', 'browser');
Condensed preview — 34 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (53K chars).
[
  {
    "path": ".editorconfig",
    "chars": 274,
    "preview": "# Editor configuration, see https://editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size ="
  },
  {
    "path": ".gitignore",
    "chars": 548,
    "preview": "# See http://help.github.com/ignore-files/ for more about ignoring files.\n\n# Compiled output\n/dist\n/tmp\n/out-tsc\n/bazel-"
  },
  {
    "path": ".vscode/extensions.json",
    "chars": 130,
    "preview": "{\n  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846\n  \"recommendations\": [\"angular.ng-tem"
  },
  {
    "path": ".vscode/launch.json",
    "chars": 470,
    "preview": "{\n  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387\n  \"version\": \"0.2.0\",\n  \"configuratio"
  },
  {
    "path": ".vscode/tasks.json",
    "chars": 938,
    "preview": "{\n  // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558\n  \"version\": \"2.0.0\",\n  \"tasks\": [\n  "
  },
  {
    "path": "README.md",
    "chars": 2906,
    "preview": "# Angular Universal 100% powered by Angular CLI\n\nThis project was generated with [Angular CLI](https://github.com/angula"
  },
  {
    "path": "angular.json",
    "chars": 6134,
    "preview": "{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"version\": 1,\n  \"newProjectRoot\": \"projects\",\n  \""
  },
  {
    "path": "package.json",
    "chars": 1264,
    "preview": "{\n  \"name\": \"app\",\n  \"version\": \"0.0.0\",\n  \"scripts\": {\n    \"ng\": \"ng\",\n    \"start\": \"ng serve\",\n    \"build\": \"ng build\""
  },
  {
    "path": "src/api/index.ts",
    "chars": 1572,
    "preview": "import { APP_BASE_HREF } from '@angular/common';\nimport { NgSetupOptions, ngExpressEngine } from '@nguniversal/express-e"
  },
  {
    "path": "src/app/app-routes.spa.ts",
    "chars": 169,
    "preview": "import { Routes } from '@angular/router';\n\n// Using an empty array of routes will render an empty <router-outlet> in App"
  },
  {
    "path": "src/app/app-routes.ts",
    "chars": 284,
    "preview": "import { Routes } from '@angular/router';\n\nimport { NotFoundComponent } from './not-found.component';\n\n\nexport const APP"
  },
  {
    "path": "src/app/app-routing.module.ts",
    "chars": 321,
    "preview": "import { NgModule } from '@angular/core';\nimport { RouterModule } from '@angular/router';\n\nimport { APP_ROUTES } from '."
  },
  {
    "path": "src/app/app.browser.module.ts",
    "chars": 237,
    "preview": "import { NgModule } from '@angular/core';\n\nimport { AppComponent } from './app.component';\nimport { AppModule } from './"
  },
  {
    "path": "src/app/app.component.ts",
    "chars": 574,
    "preview": "import { ChangeDetectionStrategy, Component, ElementRef, Renderer2 } from '@angular/core';\n\nimport { environment } from "
  },
  {
    "path": "src/app/app.module.ts",
    "chars": 479,
    "preview": "import { NgModule } from '@angular/core';\nimport { BrowserModule } from '@angular/platform-browser';\n\nimport { AppRoutin"
  },
  {
    "path": "src/app/app.server.module.ts",
    "chars": 565,
    "preview": "import { NgModule } from '@angular/core';\nimport { ServerModule } from '@angular/platform-server';\n\nimport { AppComponen"
  },
  {
    "path": "src/app/hello/hello-routing.module.ts",
    "chars": 461,
    "preview": "import { CommonModule } from '@angular/common';\nimport { NgModule } from '@angular/core';\nimport { RouterModule, Routes "
  },
  {
    "path": "src/app/hello/hello.component.html",
    "chars": 23082,
    "preview": "<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->\n<!-- * * * * * * * * * * * The content below * * "
  },
  {
    "path": "src/app/hello/hello.component.scss",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/app/hello/hello.component.spec.ts",
    "chars": 1195,
    "preview": "import { TestBed } from '@angular/core/testing';\nimport { By } from '@angular/platform-browser';\nimport { RouterTestingM"
  },
  {
    "path": "src/app/hello/hello.component.ts",
    "chars": 299,
    "preview": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\n\n@Component({\n  selector: 'app-welcome',\n  template"
  },
  {
    "path": "src/app/hello/hello.module.ts",
    "chars": 212,
    "preview": "import { NgModule } from '@angular/core';\n\nimport { HelloRoutingModule } from './hello-routing.module';\n\n\n@NgModule({\n  "
  },
  {
    "path": "src/app/not-found.component.ts",
    "chars": 514,
    "preview": "import { Component, Inject, OnInit, Optional } from '@angular/core';\nimport { RESPONSE } from '@nguniversal/express-engi"
  },
  {
    "path": "src/assets/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/environments/environment.prod.ts",
    "chars": 51,
    "preview": "export const environment = {\n  production: true\n};\n"
  },
  {
    "path": "src/environments/environment.ts",
    "chars": 658,
    "preview": "// This file can be replaced during build by using the `fileReplacements` array.\n// `ng build` replaces `environment.ts`"
  },
  {
    "path": "src/index.html",
    "chars": 289,
    "preview": "<!doctype html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <title>App</title>\n  <base href=\"/\">\n  <meta name=\"vi"
  },
  {
    "path": "src/main.ts",
    "chars": 651,
    "preview": "import { ApplicationRef, NgModuleRef } from '@angular/core';\nimport { platformBrowserDynamic } from '@angular/platform-b"
  },
  {
    "path": "src/server.ts",
    "chars": 2225,
    "preview": "// These are important and needed before anything else\nimport 'zone.js/node';\n\n/****************************************"
  },
  {
    "path": "src/styles.scss",
    "chars": 80,
    "preview": "/* You can add global styles to this file, and also import other style files */\n"
  },
  {
    "path": "tsconfig.app.json",
    "chars": 454,
    "preview": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n  \"extends\": \"./tsconfig.json\",\n  \"compil"
  },
  {
    "path": "tsconfig.json",
    "chars": 901,
    "preview": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n  \"compileOnSave\": false,\n  \"compilerOpti"
  },
  {
    "path": "tsconfig.server.json",
    "chars": 439,
    "preview": "{\n  \"extends\": \"./tsconfig.app.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./out-tsc/server\",\n    \"target\": \"es2019\",\n "
  },
  {
    "path": "tsconfig.spec.json",
    "chars": 273,
    "preview": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n  \"extends\": \"./tsconfig.json\",\n  \"compil"
  }
]

About this extraction

This page contains the full source code of the enten/angular-universal GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 34 files (47.5 KB), approximately 17.8k tokens, and a symbol index with 21 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!