I know in advance that I'm gonna get lynched over this but I've tried to find a solution for many moons now and I'm still struggling with this. Here's the deal: I have an Angular App that I created with the CLI and I chose to activate SSR for this project for SEO purposes. Great thing with Angular18 and SSR is that it gets setup automatically and fast. I'm using for this project, Firebase (particularly the emulator for dev purposes) and Firestore to store some blog articles. To handle fetching these documents, without SSR, I would typically use AngularFire calling "collectionData()" to get an Observable. I've setup a basic "test" project to try to find a solution easily (congrats to me for that: No solution in sight): Basic service: import { inject, Injectable } from '@angular/core'; import { collection, collectionData, Firestore } from '@angular/fire/firestore'; @Injectable({ providedIn: 'root' }) export class TestServiceService { private firestore = inject(Firestore); constructor() { } getTests(){ return collectionData(collection(this.firestore, 'tests')); } } to app.component.ts: import { Component, inject, OnInit, signal } from '@angular/core'; import { RouterOutlet } from '@angular/router'; import { TestServiceService } from './test-service.service'; import { JsonPipe } from '@angular/common'; @Component({ selector: 'app-root', standalone: true, imports: [RouterOutlet, JsonPipe], templateUrl: './app.component.html', styleUrl: './app.component.scss' }) export class AppComponent implements OnInit { private testService = inject(TestServiceService); tests = signal<any[]>([]); ngOnInit() { this.testService.getTests().subscribe((tests: any) => { this.tests.set(tests); }); } } With the config file on the client: import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; import { provideClientHydration } from '@angular/platform-browser'; import { initializeApp, provideFirebaseApp } from '@angular/fire/app'; import { getAuth, provideAuth } from '@angular/fire/auth'; import { getFirestore, provideFirestore } from '@angular/fire/firestore'; import { getFunctions, provideFunctions } from '@angular/fire/functions'; import { getStorage, provideStorage } from '@angular/fire/storage'; import { environment } from '../environments/environment'; export const appConfig: ApplicationConfig = { providers: [ provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideClientHydration(), provideFirebaseApp(() => initializeApp(environment.firebaseConfig)), provideAuth(() => getAuth()), provideFirestore(() => getFirestore()), provideFunctions(() => getFunctions()), provideStorage(() => getStorage()) ] }; On the server: import { mergeApplicationConfig, ApplicationConfig } from '@angular/core'; import { provideServerRendering } from '@angular/platform-server'; import { appConfig } from './app.config'; const serverConfig: ApplicationConfig = { providers: [ provideServerRendering(), ] }; export const config = mergeApplicationConfig(appConfig, serverConfig); Instead of subscribing in the component I've tried also to resolve through the route: import { Routes } from '@angular/router'; import { AppComponent } from './app.component'; export const routes: Routes = [ { path: '', component: AppComponent, // resolve: { // tests: () => inject(TestServiceService).getTests() // } } ]; But I get this error in firestore: ERROR FirebaseError: Missing or insufficient permissions. Followed after a while by this warning: [2024-09-23T15:32:16.455Z] @firebase/firestore: Firestore (10.13.2): GrpcConnection RPC 'Listen' stream 0x1b30eee5 error. Code: 1 Message: 1 CANCELLED: Disconnecting idle stream. Timed out waiting for new target My firestore rules are supposedly sufficiently opened: service cloud.firestore { match /databases/{database}/documents { match /{document=**} { // This rule allows anyone with your database reference to view, edit, // and delete all data in your database. It is useful for getting // started, but it is configured to expire after 30 days because it // leaves your app open to attackers. At that time, all client // requests to your database will be denied. // // Make sure to write security rules for your app before that time, or // else all client requests to your database will be denied until you // update your rules. allow read, write: if request.time < timestamp.date(2024, 10, 22); } } } I've tried then to use the AdminSDK but it's worse. I've got some error message from "vite" [vite] that says that the modules are not accessible... Here's the server.ts (automatically generated by the CLI): import { APP_BASE_HREF } from '@angular/common'; import { CommonEngine } from '@angular/ssr'; import express from 'express'; import { fileURLToPath } from 'node:url'; import { dirname, join, resolve } from 'nodeath'; import bootstrap from './src/main.server'; // The Express app is exported so that it can be used by serverless Functions. export function app(): express.Express { const server = express(); const serverDistFolder = dirname(fileURLToPath(import.meta.url)); const browserDistFolder = resolve(serverDistFolder, '../browser'); const indexHtml = join(serverDistFolder, 'index.server.html'); const commonEngine = new CommonEngine(); server.set('view engine', 'html'); server.set('views', browserDistFolder); // Example Express Rest API endpoints // server.get('/api/**', (req, res) => { }); // Serve static files from /browser server.get('**', express.static(browserDistFolder, { maxAge: '1y', index: 'index.html', })); // All regular routes use the Angular engine server.get('**', (req, res, next) => { const { protocol, originalUrl, baseUrl, headers } = req; commonEngine .render({ bootstrap, documentFilePath: indexHtml, url: `${protocol}://${headers.host}${originalUrl}`, publicPath: browserDistFolder, providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }], }) .then((html) => res.send(html)) .catch((err) => next(err)); }); return server; } function run(): void { const port = process.env['PORT'] || 4000; // Start up the Node server const server = app(); server.listen(port, () => { console.log(`Node Express server listening on http://localhost:${port}`); }); } run(); And the 2 mains: Client: import { bootstrapApplication } from '@angular/platform-browser'; import { appConfig } from './app/app.config'; import { AppComponent } from './app/app.component'; bootstrapApplication(AppComponent, appConfig) .catch((err) => console.error(err)); Server: import { bootstrapApplication } from '@angular/platform-browser'; import { AppComponent } from './app/app.component'; import { config } from './app/app.config.server'; const bootstrap = () => bootstrapApplication(AppComponent, config); export default bootstrap; Can someone please point me in the right direction for this? Continue reading...