lords.temnorid.com

Angular Landing Template (SSR + Prerender)

Modern Angular 22 starter template for building fast landing pages with SSR prerendering, TailwindCSS, and GitHub Pages deployment.

This template is optimized for static landing sites where pages are rendered at build time for SEO and performance.


Acknowledge

The project builds both:

dist/app/browser
dist/app/server

But deployment uses the browser prerendered output, making it perfect for static hosting.


Project Structure

src/
  app/
    app.component.ts
    app.config.ts
    app.config.server.ts
    app.routes.ts
    app.routes.server.ts
    layouts/
    pages/
  assets/
  environments/
  i18n/
  styles/
  styles.scss

SSR configuration lives in:

app.config.server.ts
app.routes.server.ts

Development

Start the development server:

npm start

or

ng serve

Application runs at http://localhost:4200

Development mode runs as a normal Angular SPA.


Build

Build the project:

npm run build

This generates:

dist/app/browser
dist/app/server

Pages are prerendered at build time using Angular SSR.


Running the SSR server (optional)

After npm run build, the generated SSR server can be run manually:

node dist/app/server/server.mjs

For most landing pages this is not required, because prerendered HTML is already generated.


Prerender configuration

All routes are prerendered by default:

src/app/app.routes.server.ts
RenderMode.Prerender
export const serverRoutes: ServerRoute[] = [
	{
		path: '**',
		renderMode: RenderMode.Prerender,
	},
];

This makes Angular generate static HTML for every route during build.


Bootstrap Data

The app includes a small bootstrap data flow for company profile data.

Main files:

src/app/app.config.ts
src/app/feature/bootstrap/bootstrap.service.ts
src/app/feature/bootstrap/bootstrap.interface.ts
src/app/feature/company/company.data.ts
src/app/feature/company/company.service.ts
src/data/company/company.json
src/environments/environment.prod.ts

How it works:

Bootstrap payload shape:

export interface BootstrapData {
	company?: Partial<Company> | null;
}

Environment keys involved:

Current fallback behavior in code:

This keeps SSR and prerender safe while still allowing the app to hydrate with API data when it exists.

For future component or page-level async reads, prefer signal-based resources. Use ngxResource() from @wawjs/ngx-core for persisted or generic async reads, especially when StoreService caching is useful. Keep bootstrap initialization, migrations, and startup fallback flows as direct imperative async code when a resource state object would make the flow less clear.

For theme preferences, keep mode, density, radius, and persistence centralized in ThemeService from @wawjs/ngx-ui. Do not add duplicate localStorage or document attribute logic for theme state in app components.


TailwindCSS

Tailwind is configured via:

.postcssrc.json

Tailwind should be used as much as possible for everyday UI work.

Prefer Tailwind utilities for:

Use SCSS only when Tailwind is not the right tool, for example:

Global styles live in:

src/styles.scss

Icons

This template includes Material Symbols Outlined and those should be used as the default icon set across the project.

Loaded in:

src/index.html

Use icons directly in HTML like this:

<span class="material-symbols-outlined" aria-hidden="true">arrow_forward</span>

For accessible buttons, keep the icon decorative and provide a text label or aria-label on the button itself:

<button type="button" aria-label="Open menu">
	<span class="material-symbols-outlined" aria-hidden="true">menu</span>
</button>

Translations And Languages

UI translations live in:

src/i18n/<code>.json

Language metadata lives in:

src/environments/environment.prod.ts

Translation bootstrap starts in:

src/app/app.config.ts

The app uses the @wawjs/ngx-translate translation stack:

When adding or updating translations:

Supported usage patterns:

Examples:

<span translate>Default source text</span>
<button translate [translate]="{ ariaLabel: 'Default aria label' }" type="button"></button>
private readonly _translateService = inject(TranslateService);

protected readonly toggleLabel = computed(() =>
	this._translateService.translate('Default source text')(),
);

SCSS Conventions

Use SCSS in a way that matches modern Angular defaults:

Recommended split:

src/styles.scss           -> global entry point
src/app/**/**/*.scss      -> component-local styles
src/styles/_theme.scss    -> shared theme CSS variables

Environments

This template includes Angular environment files and they can be used for different runtime setups such as local development and production builds.

Available files:

src/environments/environment.ts
src/environments/environment.prod.ts

Typical use cases:

Production builds replace environment.ts with environment.prod.ts through Angular file replacements.

Keep environment files limited to public front-end configuration. Do not store secrets in them.


Deployment

Deployment is handled automatically via GitHub Actions.

Workflow:

.github/workflows/deploy.yml

Steps:

  1. Install dependencies
  2. Build Angular app
  3. Copy CNAME
  4. Push build output to gh-pages

The deployed folder is:

dist/app/browser

Domain

Custom domain which you should adjust to your own domain so it works properly, any subdomain of *.itkamianets.com in case it’s not used before on our github org.

ngx.itkamianets.com

Configured via:

CNAME

Code Style

Formatting is handled by:

Key conventions:


AI Usage

If you use AI outside the IDE and it does not automatically read repository instructions, copy the contents of AGENTS.md into the AI prompt/context first.

This ensures the AI follows the same project-specific rules that Codex uses inside the IDE.


MCP Servers For Codex, Copilot, And Gemini

This project uses these MCP servers:

[mcp_servers.angular-cli]
command = "npx"
args = ["-y", "@angular/cli", "mcp"]

[mcp_servers.context7]
command = "npx"
args = ["-y", "@upstash/context7-mcp"]

[mcp_servers.typescript-lsp]
command = "npx"
args = ["-y", "ts-lsp-mcp", "serve", "--stdio"]

Use the following setup depending on the client.

Codex

Codex supports both user-level config and repo-level config through TOML files:

Codex CLI and the Codex IDE extension share the same MCP configuration.

Codex global config

Add this to ~/.codex/config.toml:

[mcp_servers.angular-cli]
command = "npx"
args = ["-y", "@angular/cli", "mcp"]

[mcp_servers.context7]
command = "npx"
args = ["-y", "@upstash/context7-mcp"]

[mcp_servers.typescript-lsp]
command = "npx"
args = ["-y", "ts-lsp-mcp", "serve", "--stdio"]

Codex project-local config

Create .codex/config.toml in the repository root and add the same block:

[mcp_servers.angular-cli]
command = "npx"
args = ["-y", "@angular/cli", "mcp"]

[mcp_servers.context7]
command = "npx"
args = ["-y", "@upstash/context7-mcp"]

[mcp_servers.typescript-lsp]
command = "npx"
args = ["-y", "ts-lsp-mcp", "serve", "--stdio"]

If Codex does not load project-local MCP config, mark the repo as trusted in your user config:

[projects.'\\?\C:\Users\YOUR_USER\work\itkp.ngx-default']
trust_level = "trusted"

Codex CLI commands

You can add the same servers with the CLI instead of editing TOML manually:

codex mcp add angular-cli -- npx -y @angular/cli mcp
codex mcp add context7 -- npx -y @upstash/context7-mcp
codex mcp add typescript-lsp -- npx -y ts-lsp-mcp serve --stdio

Useful checks:

codex mcp --help
codex mcp list

GitHub Copilot

For GitHub Copilot in VS Code, MCP servers are configured with mcp.json:

The project-local file is the easiest way to share MCP setup with everyone working in the repo.

Copilot project-local config

Create .vscode/mcp.json:

{
	"servers": {
		"angular-cli": {
			"command": "npx",
			"args": ["-y", "@angular/cli", "mcp"]
		},
		"context7": {
			"command": "npx",
			"args": ["-y", "@upstash/context7-mcp"]
		},
		"typescript-lsp": {
			"command": "npx",
			"args": ["-y", "ts-lsp-mcp", "serve", "--stdio"]
		}
	}
}

Copilot global config

Open the Command Palette in VS Code and run:

MCP: Open User Configuration

Then add the same JSON shown above.

You can also use:

MCP: Add Server

and choose either Workspace or Global.

Copilot notes

Gemini CLI

Gemini CLI supports both user and project scope through settings.json:

Gemini global config

Add this to ~/.gemini/settings.json:

{
	"mcpServers": {
		"angular-cli": {
			"command": "npx",
			"args": ["-y", "@angular/cli", "mcp"]
		},
		"context7": {
			"command": "npx",
			"args": ["-y", "@upstash/context7-mcp"]
		},
		"typescript-lsp": {
			"command": "npx",
			"args": ["-y", "ts-lsp-mcp", "serve", "--stdio"]
		}
	}
}

Gemini project-local config

Create .gemini/settings.json in the repo root and add the same JSON:

{
	"mcpServers": {
		"angular-cli": {
			"command": "npx",
			"args": ["-y", "@angular/cli", "mcp"]
		},
		"context7": {
			"command": "npx",
			"args": ["-y", "@upstash/context7-mcp"]
		},
		"typescript-lsp": {
			"command": "npx",
			"args": ["-y", "ts-lsp-mcp", "serve", "--stdio"]
		}
	}
}

Gemini CLI commands

Gemini CLI can write either scope directly:

gemini mcp add -s user angular-cli npx -y @angular/cli mcp
gemini mcp add -s user context7 npx -y @upstash/context7-mcp
gemini mcp add -s user typescript-lsp npx -y ts-lsp-mcp serve --stdio
gemini mcp add -s project angular-cli npx -y @angular/cli mcp
gemini mcp add -s project context7 npx -y @upstash/context7-mcp
gemini mcp add -s project typescript-lsp npx -y ts-lsp-mcp serve --stdio

Useful checks:

gemini mcp list

Recommendation

For this repository:

Use global config only when you want the same MCP servers in every project.

References


NPM Scripts

Start development:

npm start

Build project:

npm run build

Requirements

Recommended environment:

Node.js 20+
npm 11+

Code structure guide

Pages

Application pages should be created inside:

src/app/pages/

Each page should have its own folder and its own component file.

Example:

src/app/pages/home/home.component.ts
src/app/pages/about/about.component.ts

Generate a page component with Angular CLI:

ng generate component pages/home

or shorter:

ng g c pages/home

Pages should be lazy loaded from src/app/app.routes.ts.

Example route config:

import { Routes } from '@angular/router';

export const routes: Routes = [
	{
		path: '',
		loadComponent: () => import('./pages/home/home.component').then((m) => m.HomeComponent),
	},
	{
		path: 'about',
		loadComponent: () => import('./pages/about/about.component').then((m) => m.AboutComponent),
	},
];

Feature structure for back-end connected modules

If a part of the app needs its own business logic and back-end integration, create a dedicated feature folder inside:

src/app/feature/

Each feature should keep its own internal structure.

Example:

src/app/feature/user/
src/app/feature/user/components/
src/app/feature/user/directives/
src/app/feature/user/interfaces/
src/app/feature/user/pages/
src/app/feature/user/pipes/
src/app/feature/user/services/

Example service location:

src/app/feature/user/services/user.service.ts

Suggested CLI commands:

Create feature page:

ng g c feature/user/pages/user-profile

Create feature component:

ng g c feature/user/components/user-card

Create feature directive:

ng g d feature/user/directives/user-focus

Create feature pipe:

ng g p feature/user/pipes/user-name

Create feature service:

ng g s feature/user/services/user

Interfaces are usually created manually:

src/app/feature/user/interfaces/user.interface.ts
src/app/feature/user/interfaces/user-response.interface.ts

For small focused features, colocated files like feature/language/language.type.ts, language.interface.ts, language.const.ts, and language.service.ts are also valid when that structure keeps the feature simpler.


Generic shared code

Generic reusable code that is not tied to one specific feature can live directly under src/app.

Example shared folders:

src/app/components/
src/app/directives/
src/app/interfaces/
src/app/pipes/
src/app/services/

Example shared pipe location:

src/app/pipes/phone.pipe.ts

Suggested CLI commands:

Create shared component:

ng g c components/page-header

Create shared directive:

ng g d directives/autofocus

Create shared pipe:

ng g p pipes/phone

Create shared service:

ng g s services/api

Interfaces are usually created manually:

src/app/interfaces/api-response.interface.ts
src/app/interfaces/select-option.interface.ts

Development summary

Use these locations by default:

Create a new project from this template

Clone the default repository into a new folder with your project name (replace PROJECT_NAME with your project name):

git clone https://github.com/WebArtWork/ngx-default.git PROJECT_NAME
cd PROJECT_NAME
npm i
npm run start

What these commands do

After that, open the local URL shown in the terminal, usually http://localhost:4200

Initialize your own git repository

If you want to start fresh instead of keeping the template git history, remove the existing .git folder, initialize a new repository, and create the first commit.

Example:

rm -rf .git
git init
git remote add origin https://github.com/WebArtWork/PROJECT_NAME.git
git add .
git commit -m "chore(init): bootstrap project from ngx-default template"

git remote add origin ... connects your local repository to the remote GitHub repository so future git push and git pull commands know where your main project lives.

Use a Conventional Commit message for the first commit as well. A good default is:

chore(init): bootstrap project from ngx-default template

Adapting The Template To A Real Business

After cloning and installing the project, use the Angular Default Web Art Work Custom GPT to adapt the template to a real business:

Angular Default Web Art Work on ChatGPT

The GPT operates in two phases:

Phase 1 — Implementation prompt Provide a Google Maps place URL and the new domain. The GPT researches the business from public sources (Maps, website, socials, reviews, directories), gathers confirmed facts, and outputs one compact ready-to-run prompt for a coding agent. The coding agent applies branding, content, SEO, theme, company data, and environment config in a single pass.

Phase 2 — Page cleanup After Phase 1 is applied, trigger cleanup with phrases like “cleanup” or “remove unused pages”. The GPT reviews each page one at a time, suggests keep or remove based on the business type, collects your decision, and generates a targeted removal prompt.


License

MIT