Skip to main content

Create an Angular Application

This quick start will help you create an Angular.js TypeScript application. We'll be using Angular's 'Hello World' project as a starting point, then bringing it under projen management.

To begin, make sure you have the version of NodeJS you want to use set up in your terminal. Running which node in bash/zsh/other POSIX shells, or Get-Command node in Powershell, should print the path to the NodeJS version you want to use. nvm is a popular tool for managing multiple versions of Node on a single machine. To select a version, run nvm use <version>.

Run npm i @angular/cli to install the Angular CLI. Next, run npx ng new --create-application true hello-world to initialize the hello-world project. Then run cd hello-world to enter the project directory.

npm i @angular/cli
npx ng new --create-application true hello-world
cd hello-world

Follow the prompts and within a few minutes, you'll get an Angular project structure with sample code.

Bringing it under projen management

Now that we have a working Angular project, we'll bring it under projen management. We'll start by making a backup of files that will be overwritten by projen:

mv package.json package.json.bak
mv README.md README.md.bak
mv .gitignore .gitignore.bak

To create a new TypeScript project, use npx projen new typescript:

npx projen new typescript

Most of the npx projen default command that runs after project initialization will work, but it will fail when trying to reference packages that are no longer in package.json. We'll fix that next.

In your favorite editor/IDE, open package.json.bak. Open .projenrc.ts in a separate tab or window.

You'll see a TypeScript file that looks like this:

import { typescript } from "projen";
const project = new typescript.TypeScriptProject({
defaultReleaseBranch: "main",
name: "hello-world",
projenrcTs: true,

// deps: [], /* Runtime dependencies of this module. */
// description: undefined, /* The description is just a string that helps people understand the purpose of the package. */
// devDeps: [], /* Build dependencies for this module. */
// packageName: undefined, /* The "name" in package.json. */
});
project.synth();

Uncomment the line starting with // deps: and add the Angular dependencies from package.json.bak. For example, "@angular/animations": "^16.2.0" should become "@angular/animations@^16.2.0". Do the same for devDeps and add them all to the appropriate place in the .projenrc.ts file.

info

Your versions will very likely be different - convert what you get from the CLI to the format shown below.

import { typescript } from "projen";
const project = new typescript.TypeScriptProject({
defaultReleaseBranch: "main",
name: "hello-world",
projenrcTs: true,

deps: [
"@angular/animations@^16.2.0",
"@angular/common@^16.2.0",
"@angular/compiler@^16.2.0",
"@angular/core@^16.2.0",
"@angular/forms@^16.2.0",
"@angular/platform-browser@^16.2.0",
"@angular/platform-browser-dynamic@^16.2.0",
"@angular/router@^16.2.0",
"rxjs@~7.8.0",
"tslib@^2.3.0",
"zone.js@~0.13.0",
],
devDeps: [
"@angular-devkit/build-angular@^16.2.6",
"@angular/cli@^16.2.6",
"@angular/compiler-cli@^16.2.0",
"@types/jasmine@~4.3.0",
"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",
],
});
project.synth();

Run npx projen to install the Angular dependencies.

Set up tasks

Next, we'll set up some task scripts to make it easier to run our Angular application. Above the project.synth() line, add the following:

project.addTask("ng", { exec: "ng", receiveArgs: true });
project.addTask("start", { exec: "ng serve", receiveArgs: true });
// projen already has build, but it calls compile, which is empty
project.tasks.tryFind("compile")?.reset("ng build", { receiveArgs: true });
project.addTask("ng:watch", {
exec: "ng build --watch --configuration development",
receiveArgs: true,
});
project.tasks.tryFind("test")?.reset("ng test", { receiveArgs: true });
project.addTask("e2e", { exec: "ng e2e", receiveArgs: true });

project.synth();

Let's go over the two types of tasks we've added here:

project.addTask()

When you're adding an entirely new task, you'll use project.addTask(). This method takes two arguments: the name of the task, and an object with the task's configuration. The exec property is the command that will be run when you run the task. The receiveArgs property tells projen whether to pass any arguments you provide to the task to the command. For example, if you run npx projen start --port 3000, projen will run ng serve --port 3000.

project.tasks.tryFind()?.reset()

When you're modifying an existing task, you'll use project.tasks.tryFind().reset(). Generally, you'll want to do this when projen already has the task you're looking for defined in the .projen/tasks.json file. If the task doesn't have an exec parameter, you can simply reset it as we've done here. If it does, which is the case with build, it becomes more complicated. Read the docs on tasks for more information on those cases.

info

Challenge yourself - would you use addTask() or reset() to add an ng lint task?

gitignore

Projen offers a way to easily update the contents of .gitignore in the project definition. The gitignore parameter takes an array of strings, each of which will be added to .gitignore. If you'd like to simply append your .gitignore.bak file, split it on newlines and pass it to gitignore. Alternately, you could do a diff between .gitignore and .gitignore.bak and add the new lines to gitignore.

Example:

  gitignore: [
'# 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',
],

Run npx projen and you'll see the contents of .gitignore have been updated.

README.md

README.md is not managed by projen's TypeScript project. Feel free to update it without worrying about projen overwriting it.

That's it! You now have a working Angular application under projen management. Type npx projen start to see the application in your browser.