diff --git a/README.md b/README.md
index cddd09ff3..af669f445 100644
--- a/README.md
+++ b/README.md
@@ -108,7 +108,7 @@ We have three sample apps in this repository:
### Having troubles?
-Get help on our [Q&A board](https://github.com/angular/angularfire/discussions?discussions_q=category%3AQ%26A), the official [Firebase Mailing List](https://groups.google.com/forum/#!forum/firebase-talk), the [Firebase Community Slack](https://firebase.community/) (`#angularfire2`), the [Angular Community Discord](http://discord.gg/angular) (`#firebase`), [Gitter](https://gitter.im/angular/angularfire2), the [Firebase subreddit](https://www.reddit.com/r/firebase), or [Stack Overflow](https://stackoverflow.com/questions/tagged/angularfire2).
+Get help on the [Firebase Community Slack](https://firebase.community/) (`#angularfire2`), the [Angular Community Discord](http://discord.gg/angular) (`#firebase`), [Gitter](https://gitter.im/angular/angularfire2), the [Firebase subreddit](https://www.reddit.com/r/firebase), or [Stack Overflow](https://stackoverflow.com/questions/tagged/angularfire2). The official [Firebase Mailing List](https://groups.google.com/forum/#!forum/firebase-talk) is closed to new discussions but you can read and comment on old discussions.
> **NOTE:** AngularFire is maintained by Googlers but is not a supported Firebase product. Questions on the mailing list and issues filed here are answered on a best-effort basis by maintainers and other community members. If you are able to reproduce a problem with Firebase outside of AngularFire's implementation, please [file an issue on the Firebase JS SDK](https://github.com/firebase/firebase-js-sdk/issues) or reach out to the personalized [Firebase support channel](https://firebase.google.com/support/).
diff --git a/docs/firestore/crud-tutorial.md b/docs/firestore/crud-tutorial.md
new file mode 100644
index 000000000..07af661eb
--- /dev/null
+++ b/docs/firestore/crud-tutorial.md
@@ -0,0 +1,1113 @@
+Updated April 6, 2022.
+
+# AngularFire CRUD Tutorial: "Greatest Computer Scientists"
+
+### 1. Create a new project
+
+In your terminal:
+
+```bash
+npm install -g @angular/cli
+ng new GreatestComputerScientists
+cd GreatestComputerScientists
+```
+
+The Angular CLI's `new` command will set up the latest Angular build in a new project structure. Accept the defaults (no routing, CSS). Start the server:
+
+```bash
+ng serve
+```
+
+Open a browser to `localhost:4200`. You should see the Angular default homepage.
+
+### 2. Install AngularFire and Firebase
+
+Install AngularFire and Firebase from npm.
+
+```bash
+ng add @angular/fire
+```
+
+Deselect `ng deploy -- hosting` and select `Firestore`. This project won't use any other Firebase features.
+
+```bash
+npm install firebase
+```
+
+### 3. Create your Firebase project and add Firebase config to environments variable
+
+Open your Firebase console and make a new project. Call it GreatestComputerScientists.
+
+Open `/src/environments/environment.ts` and add your Firebase configuration. You can find your project configuration in your [Firebase Console](https://console.firebase.google.com). Click the Gear icon next to Project Overview, in the Your Apps section, create a new app and choose the type Web. Give the app a name and copy the config values provided to your `environment.ts` file:
+
+```ts
+export const environment = {
+ production: false,
+ firebase: {
+ apiKey: '',
+ authDomain: '',
+ databaseURL: '',
+ projectId: '',
+ storageBucket: '',
+ messagingSenderId: '',
+ appId: '',
+ measurementId: ''
+ }
+};
+```
+
+### 4. Setup `@NgModule` for the `AngularFireModule`
+
+Open `/src/app/app.module.ts`, inject the Firebase and environment modules, and import your Firebase configuration.
+
+```ts
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { AppComponent } from './app.component';
+
+// Firebase
+import { AngularFireModule } from '@angular/fire/compat';
+import { environment } from '../environments/environment';
+
+@NgModule({
+ declarations: [
+ AppComponent
+ ],
+ imports: [
+ BrowserModule,
+ AngularFireModule.initializeApp(environment.firebase),
+ ],
+ providers: [],
+ bootstrap: [AppComponent]
+})
+export class AppModule { }
+```
+
+Keep an eye on the browser. If the homepage crashes, go back and see what's wrong.
+
+### 5. Setup individual `@NgModule`s
+
+After adding the AngularFireModule you also need to add modules to `app.module.ts` for the individual @NgModules that your application needs.
+
+This application uses the Firestore database. Add `AngularFirestoreModule`. We'll also need the Angular `FormsModule`.
+
+```ts
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { AppComponent } from './app.component';
+
+// Angular
+import { FormsModule } from '@angular/forms';
+
+// Firebase
+import { AngularFireModule } from '@angular/fire/compat';
+import { AngularFirestoreModule } from '@angular/fire/compat/firestore';
+import { environment } from '../environments/environment';
+
+@NgModule({
+ declarations: [
+ AppComponent
+ ],
+ imports: [
+ BrowserModule,
+ FormsModule,
+ AngularFireModule.initializeApp(environment.firebase),
+ AngularFirestoreModule
+ ],
+ providers: [],
+ bootstrap: [AppComponent]
+})
+export class AppModule { }
+```
+
+### 6. Inject `AngularFirestore` into Component Controller
+
+Open `/src/app/app.component.ts` and import `AngularFirestore`. In the `constructor` make a local variable for `AngularFirestore`.
+
+```ts
+import { Component } from '@angular/core';
+import { AngularFirestore } from '@angular/fire/compat/firestore';
+
+@Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.css']
+})
+export class AppComponent {
+ title = 'GreatestComputerScientists';
+
+ constructor(public firestore: AngularFirestore) {}
+}
+```
+
+The constructor makes an instantiation of the `AngularFirestore` class and we call it `firestore` for convenience and clarity. You must specify this as `public`, `protected`, or `private`. It doesn't matter which, they all work. It won't work if you don't specify one of these:
+
+```ts
+ constructor(firestore: AngularFirestore) { // doesn't work
+}
+```
+
+I know what you're thinking, the [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/2/classes.html#public) says
+
+```
+ Because public is already the default visibility modifier, you don’t ever need to write it on a class member.
+```
+
+That's not right, or not right in a way that doesn't require a lot of explaining. Here's a discussion of why we have to [use a visibility modifier here](https://github.com/angular/angularfire/issues/3173).
+
+### 7. Set up Firestore collection
+
+Open your Firebase Console and create your Firestore database, in test mode. Make a `collection` and call it `greatest-computer-scientists`. Firestore will ask you to make one document. Call the document `Charles Babbage` and put in two fields, both strings:
+
+```
+name: Charles Babbage
+accomplishment: Built first computer
+```
+
+### 8. Bind an Observable to the Firestore collection
+
+Import `Observable` from `rxjs`. Then make an instantiation of the `Observable` class.
+
+In `/src/app/app.component.ts`:
+
+```ts
+import { Component } from '@angular/core';
+import { AngularFirestore } from '@angular/fire/compat/firestore';
+import { Observable } from 'rxjs';
+
+@Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.css']
+})
+export class AppComponent {
+ title = 'GreatestComputerScientists';
+
+ scientists: Observable;
+
+ constructor(firestore: AngularFirestore) {
+ this.scientists = firestore.collection('greatest-computer-scientists').valueChanges();
+ }
+}
+```
+
+In the constructor we query our database and store the results in `this.scientists`.
+
+#### 8.1 Making an Interface or Type for a Firebase Collection
+
+Did you notice that we set a type to `any`:
+
+```ts
+scientists: Observable;
+```
+
+TypeScript hates it when we declare `any`. Surely we can declare an `interface` or `type`:
+
+```ts
+export declare interface Scientist {
+ accomplishment: string,
+ name: string,
+}
+
+export class AppComponent {
+ scientists: Observable;
+}
+```
+
+This throws an error:
+
+```
+Type 'Observable' is not assignable to type 'Observable'.
+Type 'unknown[]' is missing the following properties from type 'Scientist': accomplishment, name
+```
+
+This is saying that `Scientist` is a document (an object) but we're observing a collection, which is an array of documents.
+
+Let's try this:
+
+```ts
+scientists: Observable;
+```
+
+The error message changes to
+
+```ts
+Type 'Observable' is not assignable to type 'Observable'.
+```
+
+Apparently collections are not the same as arrays and I don't understand the difference. Firestore has a [Data Converter interface](https://firebase.google.com/docs/reference/js/firestore_.firestoredataconverter) that will make a type from your Firestore query. I haven't studied this. Until I can study this I'll just use `any` as the type for Firebase collections.
+
+```ts
+scientists: Observable;
+```
+
+### 9. Make the HTML view
+
+Now we'll make the view in `app.component.html`. Replace the placeholder view with:
+
+```html
+
Greatest Computer Scientists
+
+
Create
+
+
Read
+
+
Update
+
+
Delete
+```
+
+You can remove `title` from `app.component.ts`.
+
+### 10. READ
+
+Let's start with the `Read` service. Add an `*ngFor` iterator to `app.component.html`:
+
+```html
+
+```
+
+Now you should see `Charles Babbage: Built first computer` in your browser view. This is running Angular's `*ngFor` structural directive to make an unstructured list.
+
+The `| async` pipe is used with an Observable or Promise that binds to an asynchronous source, such as a cloud database.
+
+Firebase has [two types of READ operations](https://firebase.google.com/docs/firestore/query-data/get-data). You can get data once, or set a listener to observe changing data. We'll go into this after we finish the four CRUD operations.
+
+### 11. CREATE in the view
+
+Now we'll add the Create service. Add this to `app.component.html`:
+
+```html
+
+```
+
+We're using an HTML form and the Angular `FormsModule`. The form is within the `` directive.
+
+```html
+
+```
+
+The parentheses around `ngSubmit` creates one-way data binding from the view `app.component.html` to the controller `app.component.ts`. When the `Submit` button is clicked the function `onCreate()` executes in `app.component.ts`. We'll make this function next.
+
+Inside the form we have two text field and a `Submit` button. The first text field has two-way data binding (parenthesis and brackets) using `ngModel` to the variable `name` in the controller. The second text field binds to the variable `accomplishment`.
+
+Clicking the button executes `ngSubmit` and the function `onCreate()`.
+
+### 12. CREATE in the controller
+
+In `app.component.ts` add the two variables and the function:
+
+```ts
+import { Component } from '@angular/core';
+import { AngularFirestore } from '@angular/fire/compat/firestore';
+import { Observable } from 'rxjs';
+
+@Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.css']
+})
+export class AppComponent {
+ scientists: Observable;
+ name: string | null = null;
+ accomplishment: string | null = null;
+
+ constructor(public firestore: AngularFirestore) {
+ this.scientists = firestore.collection('greatest-computer-scientists').valueChanges();
+ }
+
+ onCreate() {
+ console.log(this.name);
+ console.log(this.accomplishment);
+ if (this.name != null) {
+ if (this.accomplishment != null) {
+ this.firestore.collection('greatest-computer-scientists').doc(this.name).set({ name: this.name, accomplishment: this.accomplishment })
+ .then(() => {
+ this.name = null;
+ this.accomplishment = null;
+ console.log("Document successfully written!");
+ })
+ .catch((error) => {
+ console.error("Error writing document: ", error);
+ });
+ } else {
+ console.error("Input 'name' is null.");
+ }
+ }
+ }
+}
+```
+
+The two variables `name` and `accomplishment` are strings or null and are initialized as `null`.
+
+The function `onCreate()` first logs the variables so we can see if the data transferred from the view to the controller. The function then checks if `name` and `accomplishment` are null.
+
+If the data is good then we call Firestore and make a document with the name of the computer scientist and two fields, the first for the scientist's name and the second for their accomplishment. Then we reset the variable to null to cleat the fields. Lastly we log success or throw an error.
+
+Now you should be able to add more great computer scientists. Here are some suggestions:
+
+```
+Ada Lovelace: Wrote first software for Charles Babbage's computer
+Alan Turing: First theorized computers with memory and instructions, i.e., general-purpose computers
+John von Neumann: Built first general-purpose computer with memory and instructions
+Donald Knuth: Father of algorithm analysis
+Jeff Dean: Google's smartest computer scientist
+```
+
+#### 12.1 `add()` vs. `set()`
+
+Firebase `add()` is similar to `set()`. The difference is that `set()` requires that you provide the document name. `add()` creates a document with an auto-generated ID number.
+
+### 13. DELETE in the view
+
+Now we'll implement the Delete service to `app.component.html`:
+
+```html
+