Thoughts about Projen
Tags: aws, cdk, typescript, python
Published: 2023-04-27 19:20:13

## Introduction
[Projen](https://github.com/projen/projen), an open-source project generator, was created by Elad Ben-Israel, who also built [AWS CDK](https://aws.amazon.com/cdk/). It offers modern software engineering practices like linting, prettier, test runners, Github actions, and more when starting a new project.
![chatgpt-question-1.png](https://jolo-dev-blog-images.s3.amazonaws.com/chatgpt-question-1.png)You might assume that Projen is only compatible with CDK, just like ChatGPT. However, after reviewing their documentation, it became apparent that Projen also handles generating project files, managing dependencies, and configuring build tools. This means that developers can concentrate on writing code instead of worrying about these tasks. Projen can be used to bootstrap various projects, including `React` and `mvn` apps, as listed on [their website](https://github.com/projen/projen#project-types). While Projen is compatible with any project, it particularly shines when used with AWS CDK. When creating a CDK project using `cdk init app` you won't have all the necessary tooling at first. Projen provides these tools, letting you focus on developing infrastructure rather than setting up the project.

In this blog post, we will explore the 'battery includes' of Projen and evaluate its outcome.

## What's inside?

We will have a look at bootstrapping a CDK with [Typescript](https://projen.io/api/API.html#projen-awscdk-awscdktypescriptapp) and [Python]([awscdk-app-py](https://projen.io/api/API.html#projen-awscdk-awscdkpythonapp)), [React with Typescript](https://projen.io/api/API.html#projen-web-reacttypescriptproject), and a blank [Python](https://projen.io/api/API.html#projen-python-pythonproject) project.

### AWS CDK Typescript

To start with AWS CDK in Typescript, you simply run `npx projen new awscdk-app-ts`

```sh
👾 Project definition file was created at /Users/jolo/Development/projen-demo/.projenrc.ts
👾 Installing dependencies...
👾 install | yarn install --check-files
yarn install v1.22.19
info No lockfile found.
[1/4] 🔍  Resolving packages...
warning npm-check-updates > pacote > @npmcli/run-script > node-gyp > make-fetch-happen > cacache > @npmcli/move-file@2.0.1: This functionality has been moved to @npmcli/fs
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...
success Saved lockfile.
✨  Done in 37.05s.
👾 Installing dependencies...
👾 install | yarn install --check-files
yarn install v1.22.19
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...
success Saved lockfile.
✨  Done in 4.80s.> projen-demo@0.0.0 eslint
> npx projen eslintInitialized empty Git repository in /Users/jolo/Development/projen-demo/.git/
[main (root-commit) 53e6677] chore: project created with projen
 22 files changed, 6925 insertions(+)
 create mode 100644 .eslintrc.json
 create mode 100644 .gitattributes
 create mode 100644 .github/pull_request_template.md
 create mode 100644 .github/workflows/build.yml
 create mode 100644 .github/workflows/pull-request-lint.yml
 create mode 100644 .github/workflows/upgrade.yml
 create mode 100644 .gitignore
 create mode 100644 .mergify.yml
 create mode 100644 .npmignore
 create mode 100644 .projen/deps.json
 create mode 100644 .projen/files.json
 create mode 100644 .projen/tasks.json
 create mode 100644 .projenrc.ts
 create mode 100644 LICENSE
 create mode 100644 README.md
 create mode 100644 cdk.json
 create mode 100644 package.json
 create mode 100644 src/main.ts
 create mode 100644 test/main.test.ts
 create mode 100644 tsconfig.dev.json
 create mode 100644 tsconfig.json
 create mode 100644 yarn.lock
```
When working with Node.js projects, you'll find that it generates certain files for linting (using [ESLint](https://eslint.org/)), Typescript (using `tsconfig.json`), testing (using [Jest](https://jestjs.io/)), and even GitHub actions for CI/CD. To configure your project, you'll need to use the `.projenrc.ts` file. However, the documentation for this can be difficult to understand. Thankfully, using Typescript can help with auto-suggestions for available configuration options. If you prefer to use [`pnpm`](https://pnpm.io/) over [`yarn`](https://yarnpkg.com/), you can run `npx projen new awscdk-app-ts --package-manager PNPM` or add it to the `.projenrc.ts` file, although this is not clearly explained in the documentation.

#### Evaluation

The CDK Typescript app that is bootstrapped contains all the necessary tools for development, including linting rules, a testing framework, Typescript configuration, and even GitHub actions for CI/CD. Although `cdk init app --language typescript` only comes equipped with `jest`, in my opinion, these tools are sufficient to get started.

If you prefer a different tool, such as [vitest](https://vitest.dev/), you can disable jest by configuring it in `.projenrc.ts`. However, it is important to note that packages installed via `npm` must also be added to this file to avoid being overwritten. I have made the mistake of forgetting to add a package and then having it overwritten when I ran `pnpm install my-npm-package`.
Additionally, the documentation is very bad.

## AWS CDK Python

To bootstrap your AWS CDK python, run `npx projen new awscdk-app-py`.

```sh
[main (root-commit) 68e75df] chore: project created with projen
 16 files changed, 434 insertions(+)
 create mode 100644 .gitattributes
 create mode 100644 .github/workflows/pull-request-lint.yml
 create mode 100644 .gitignore
 create mode 100644 .projen/deps.json
 create mode 100644 .projen/files.json
 create mode 100644 .projen/tasks.json
 create mode 100644 .projenrc.py
 create mode 100644 README.md
 create mode 100644 app.py
 create mode 100644 cdk.json
 create mode 100644 projen_demo/__init__.py
 create mode 100644 projen_demo/main.py
 create mode 100644 requirements-dev.txt
 create mode 100644 requirements.txt
 create mode 100644 tests/__init__.py
 create mode 100644 tests/test_example.py
 ```
The `.projenrc.py` file is equivalent to the `.projenrc.ts` file used in the Typescript app discussed earlier. The virtual environment is established through the use of `.env`, although I prefer to name it `.venv`. Unfortunately, I have not been able to locate an option to change the name. While [`pytest`](https://docs.pytest.org/en/7.3.x/) is set to `True`, it is not included in `requirements-dev.txt`, so you will have to add it manually to the `.projenrc.py` file. However, the file does include the necessary GitHub actions for CI/CD.

#### Evaluation

I have encountered some issues with missing linting and formatting tools like [flake8](https://github.com/pycqa/flake8) or [black](https://github.com/psf/black). Additionally, I faced difficulties while using [poetry](https://python-poetry.org/). When I added `pytest` in `.projenrc.py` as `dev_deps`, the `npx projen` did not include the dependencies in the `poetry.toml`. As a result, I had to manually add `pytest`, which was unexpected.
It is also important to note that installing Node.js is necessary to execute `npx projen`.
Considering all these issues, I would not recommend using this for your Python application. If you prefer using CDK with Python, it is better to use the standard [CDK-CLI](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-python.html) and add your developer tools there. Finally, I also do not recommend using the blank Python-projen.

### React Typescript

Let's see what's included in the React app, `npx projen new react-ts --package-manager PNPM`.
```sh
👾 Project definition file was created at /Users/jolo/Development/projen-demo/.projenrc.ts
👾 Installing dependencies...
👾 install | pnpm i --no-frozen-lockfile
Downloading registry.npmjs.org/typescript/4.9.5: 11.6 MB/11.6 MB, done
 WARN  deprecated svgo@1.3.2: This SVGO version is no longer supported. Upgrade to v2.x.x.
 WARN  deprecated rollup-plugin-terser@7.0.2: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser
 WARN  deprecated stable@0.1.8: Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility
 WARN  deprecated sourcemap-codec@1.4.8: Please use @jridgewell/sourcemap-codec instead
 WARN  deprecated w3c-hr-time@1.0.2: Use your platform's native performance.now() and performance.timeOrigin.
 WARN  deprecated @npmcli/move-file@2.0.1: This functionality has been moved to @npmcli/fs
Packages: +1423
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Packages are hard linked from the content-addressable store to the virtual store.
  Content-addressable store is at: /Users/foo/Library/pnpm/store/v3
  Virtual store is at:             node_modules/.pnpm
Progress: resolved 1423, reused 959, downloaded 464, added 1423, done
node_modules/.pnpm/core-js-pure@3.30.1/node_modules/core-js-pure: Running postinstall script, done in 39ms
node_modules/.pnpm/core-js@3.30.1/node_modules/core-js: Running postinstall script, done in 38msdependencies:
+ react 18.2.0
+ react-dom 18.2.0
+ react-scripts 5.0.1
+ web-vitals 3.3.1devDependencies:
+ @testing-library/jest-dom 5.16.5
+ @testing-library/react 14.0.0
+ @testing-library/user-event 14.4.3
+ @types/jest 29.5.1
+ @types/node 16.18.25 (18.16.1 is available)
+ @types/react 18.2.0
+ @types/react-dom 18.2.1
+ @typescript-eslint/eslint-plugin 5.59.1
+ @typescript-eslint/parser 5.59.1
+ eslint 8.39.0
+ eslint-import-resolver-node 0.3.7
+ eslint-import-resolver-typescript 3.5.5
+ eslint-plugin-import 2.27.5
+ npm-check-updates 16.10.9
+ projen 0.71.27
+ ts-node 10.9.1
+ typescript 4.9.5 (5.0.4 is available)The integrity of 6434 files was checked. This might have caused installation to take longer.
Done in 15.9s
👾 Installing dependencies...
👾 install | pnpm i --no-frozen-lockfile
 WARN  deprecated svgo@1.3.2: This SVGO version is no longer supported. Upgrade to v2.x.x.
 WARN  deprecated rollup-plugin-terser@7.0.2: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser
 WARN  deprecated stable@0.1.8: Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility
 WARN  deprecated @npmcli/move-file@2.0.1: This functionality has been moved to @npmcli/fs
 WARN  deprecated sourcemap-codec@1.4.8: Please use @jridgewell/sourcemap-codec instead
 WARN  deprecated w3c-hr-time@1.0.2: Use your platform's native performance.now() and performance.timeOrigin.
Already up to date
Progress: resolved 1423, reused 1423, downloaded 0, added 0, done
Done in 3.7s> projen-demo@0.0.0 eslint
> npx projen eslintInitialized empty Git repository in /Users/jolo/Development/projen-demo/.git/
[main (root-commit) ca3f2aa] chore: project created with projen
 35 files changed, 13095 insertions(+)
 create mode 100644 .eslintrc.json
 create mode 100644 .gitattributes
 create mode 100644 .github/pull_request_template.md
 create mode 100644 .github/workflows/build.yml
 create mode 100644 .github/workflows/pull-request-lint.yml
 create mode 100644 .github/workflows/upgrade.yml
 create mode 100644 .gitignore
 create mode 100644 .mergify.yml
 create mode 100644 .npmignore
 create mode 100644 .npmrc
 create mode 100644 .projen/deps.json
 create mode 100644 .projen/files.json
 create mode 100644 .projen/tasks.json
 create mode 100644 .projenrc.ts
 create mode 100644 LICENSE
 create mode 100644 README.md
 create mode 100644 package.json
 create mode 100644 pnpm-lock.yaml
 create mode 100644 public/favicon.ico
 create mode 100644 public/index.html
 create mode 100644 public/logo192.png
 create mode 100644 public/logo512.png
 create mode 100644 public/manifest.json
 create mode 100644 public/robots.txt
 create mode 100644 src/App.css
 create mode 100644 src/App.test.tsx
 create mode 100644 src/App.tsx
 create mode 100644 src/index.css
 create mode 100644 src/index.tsx
 create mode 100644 src/logo.svg
 create mode 100644 src/react-app-env.d.ts
 create mode 100644 src/reportWebVitals.ts
 create mode 100644 src/setupTests.ts
 create mode 100644 tsconfig.dev.json
 create mode 100644 tsconfig.json
```

The app includes linting with ESLint, testing with Jest and [testing library](https://testing-library.com/docs/react-testing-library/intro/), Typescript configs, and GitHub Actions for CI/CD. The setup is like the AWS CDK Typescript, which means that all the dependencies need to be placed in the `.projenrc.ts`.

#### Evaluation

Upon inspection, I noticed that the React app uses `create-react-app` and was last updated on April 12th, 2022. However, it is not mentioned in the official documentation on [react.dev](https://react.dev/learn/start-a-new-react-project). Additionally, I find it inconvenient to store my dependencies within the `.projenrc.ts` file. Overall, I believe that most people would choose a better alternative, such as [ViteJS](https://vitejs.dev/), instead of using projen for their React app.

## Conclusion

Projen is a valuable open-source tool designed to simplify the creation and management of software projects for developers. It works exceptionally well with AWS CDK and Typescript, automating repetitive and error-prone tasks and providing an organized project structure, a testing framework, and built-in CI/CD support.

In our blog, we have showcased several project types that Projen can bootstrap, including AWS CDK with Typescript and Python, and React app. However, the entry point file `.projenrc.[ts|py|js|json]` can be frustrating to work with since it requires the manual addition of all dependencies. This is not the standard way of adding dependencies for most developers, who usually copy the `npm install third-party` command from a website and paste it into the terminal. Additionally, the documentation for CDK with Python or creating a React App is not very helpful.

As a tip, you could bootstrap your AWS CDK Typescript app and then delete the `.projenrc.ts` - file. But then you will need to change the permissions of all the configuration files such as `tsconfig.json`, basically any file which contains `~~ Generated by projen. To modify.. ` as they make them read-only.
For the rest, use the basic CDK- CLI and customize it to your need.