Porto Angular 22 Template Documentation
Porto is a multipurpose, elegant and responsive Angular 22 website template built with Bootstrap 5, SCSS and TypeScript. It suits portfolio landing pages, app landing pages, SaaS and software promotion, digital agencies, startups, business websites and blogs.
Every homepage is assembled from reusable standalone Angular components such as header, banner, about, services, work, pricing, team, testimonials, blog and contact. Content such as text, prices, team members and portfolio items lives in typed data files, so you can turn the demo into your own website without rewriting layout code.
This guide covers installation, project structure, routes, menus, theme colors, the PHP contact form, SEO settings, deployment and the change log. Porto is also available as a NextJS version and a Bootstrap 5 HTML version.
- Angular 22
- Bootstrap 5.3
- SCSS
- TypeScript
What's included
15+ homepages
Portfolio, app, SaaS, agency, startup, corporate and parallax layouts, each lazy loaded on its own route.
16+ supportive pages
Six blog layouts, contact, login, register, confirm, lock screen and coming soon pages.
Menu variations
Sticky and normal headers, centered logo, button nav and slide-in sidebar menus.
Lightbox & sorting
PhotoSwipe image lightbox and Shuffle.js category filtering for portfolio galleries.
PHP contact form
A validated Angular form that posts to a bundled PHP mail script.
Modern Angular
Standalone components, no NgModules, zoneless setup, prerendering and Vitest unit tests.
Quick start
npm install
npm startOpen http://localhost:4200/. The full steps are in the Installation section.
Who this guide is for
Developers with basic Angular and npm knowledge who want to install Porto, change its content and colors, and publish it. You do not need to edit component templates to change most text, prices and images.
Requirements
Install these tools before you start.
| Tool | Version |
|---|---|
| Node.js | ^22.22.3, ^24.15.0 or >=26 (required by Angular 22) |
| npm | 8 or newer (the project pins npm 11.13.0 in packageManager) |
| Angular CLI | 22.x (also available through npx ng) |
| PHP hosting | Only needed for the contact form, with mail() enabled |
Installation
Get Porto running locally in four steps.
1. Install Angular CLI
npm install -g @angular/cli2. Open the template folder
cd porto-angular-223. Install dependencies
npm install4. Start the development server
npm startOpen http://localhost:4200/ in your browser. The app reloads automatically whenever you change a source file.
Available scripts
| Command | What it does |
|---|---|
npm start | Runs the dev server on port 4200 |
npm run build | Production build with prerendered pages in dist/porto-angular-22 |
npm run build:file | Build that opens straight from disk (file://) in dist/porto-angular-22-file |
npm run watch | Development build that rebuilds on every change |
npm test | Runs unit tests with Vitest |
Tip: keep your own changes in the data files and a custom SCSS file so future template updates are easy to merge.
Project Structure
Pages, layout parts and reusable sections are kept in separate folders.
porto-angular-22/
├── public/ favicon
├── scripts/ build:file post-processing script
├── src/
│ ├── app/
│ │ ├── core/layout/ headers, sidebars, footers, preloader, scroll to top, page banners
│ │ ├── pages/ one folder per route (index ... index15, blog, login, contact ...)
│ │ ├── shared/
│ │ │ ├── components/ homes, abouts, services, works, pricings, teams, blogs, contact-us ...
│ │ │ ├── directives/ scrollspy, counter, skills, input
│ │ │ ├── models/ seo.json, interfaces, footer link data
│ │ │ ├── services/ SeoService, NavlinkService
│ │ │ └── utils/ animated headlines, velocity typings
│ │ ├── app.config.ts providers (router, HTTP client, hydration)
│ │ ├── app.routes.ts all routes (lazy loaded)
│ │ └── app.routes.server.ts prerender settings
│ └── assets/
│ ├── css/ third-party CSS (animate.min.css)
│ ├── fonts/ icons/ icon fonts and font files
│ ├── images/ logos, backgrounds, blog, team, work images
│ ├── php/contact.php contact form mail script
│ └── scss/ theme, components, sections, shared, pages, plugins
├── angular.json
└── package.jsonPages & Routes
Porto ships with 15 homepages and 16 supportive pages. Each is a standalone component registered in src/app/app.routes.ts and loaded lazily.
Homepages
The empty path redirects to /index, and unknown paths redirect there too.
| Route | Component | Header / menu | Theme file |
|---|---|---|---|
/index | IndexComponent | Header (top nav) | theme-1 |
/index2 | Index2Component | Header 2 (centered logo) | theme-2 |
/index3 | Index3Component | Header 3 + sidebar | theme-3 |
/index4 | Index4Component | Header 2 (centered logo) | theme-4 |
/index5 | Index5Component | Header 3 | theme-4 |
/index6 | Index6Component | Header 3 | app |
/index7 | Index7Component | Sidebar menu | theme-3 |
/index8 | Index8Component | App header + sidebar | theme-5 |
/index9 | Index9Component | Header 3 | theme-4 |
/index10 | Index10Component | Header (top nav) | theme-1 |
/index11 | Index11Component | Header 2 (centered logo) | theme-2 |
/index12 | Index12Component | Header 4 (parallax) + sidebar | none |
/index13 | Index13Component | Header 3 | theme-4 |
/index14 | Index14Component | Header 3 + sidebar | app-2 |
/index15 | Index15Component | Header (top nav) | theme-6 |
To change the default homepage, edit the redirectTo value of the empty path (and of the ** path) in app.routes.ts.
Supportive pages
| Route | Page |
|---|---|
/blog-full-page | Blog list, full width |
/blog-left-sidebar | Blog list with left sidebar |
/blog-right-sidebar | Blog list with right sidebar |
/blog-details-full-width/:id | Blog post, full width |
/blog-details-left-sidebar/:id | Blog post with left sidebar |
/blog-details-right-sidebar/:id | Blog post with right sidebar |
/contact-us | Contact page with working form |
/login, /login2 | Sign in pages |
/register, /register2 | Sign up pages |
/confirm | Email confirmation page |
/lockscreen, /lockscreen-2 | Lock screens |
/coming-soon, /coming-soon-2 | Coming soon pages |
Note: the authentication pages are front-end layouts with form validation. Connect them to your own backend before using them in production. The blog :id is the index of the post in BlogList.
Customization
Most content can be changed from data files, images and SCSS, without touching component templates.
Edit content from data files
Each section reads its content from a typed data.ts file next to the section components.
| Content | File |
|---|---|
| Services | src/app/shared/components/services/data.ts |
| Features | src/app/shared/components/features/data.ts |
| Portfolio / work | src/app/shared/components/works/data.ts |
| Pricing plans | src/app/shared/components/pricings/data.ts |
| Team members | src/app/shared/components/teams/data.ts |
| Testimonials | src/app/shared/components/testimonials/data.ts |
| Blog posts | src/app/shared/components/blogs/data.ts |
| Facts / counters | src/app/shared/components/facts/data.ts |
| Contact details | src/app/shared/components/contact-us/data.ts |
| Footer links | src/app/shared/models/data.ts |
Headings and short intro texts that are not in a data file live in the section component template, for example home1.component.html.
Replace images and logo
- Images are in
src/assets/images(backgrounds inbg, blog posts inblog, work items inworks, testimonials intesti). - Keep the same file name to replace an image everywhere, or update the path in the matching data file.
- The header uses two logos:
logo.png(white, over banners) andlogo-blk.png(dark, on a solid header). - Replace
public/favicon.icowith your own icon.
Fonts and icons
Fonts (Roboto, Poppins, Barlow, Open Sans and Roboto Slab) are imported from Google Fonts in src/assets/scss/fonts/_fonts.scss. Change the import there, and the font stacks in _variables.scss. Icon fonts are in src/assets/fonts and src/assets/icons, wired up in icons.scss.
Demo images are for preview purposes only. Replace them with your own before publishing.
Theme Colors & SCSS
Colors, fonts and spacing are controlled from a few SCSS files.
Global variables
Edit src/assets/scss/_variables.scss. The main brand color is $theme-color-1 (#3584A7), and the Bootstrap color map (primary, secondary, success and so on) is built from the variables in the same file.
$theme-color-1: #3584A7;
$warning: #fab758;
$success: #45c4a0;Per-homepage themes
Each homepage loads one theme file from src/assets/scss/themes through styleUrls in its component, for example theme-1.scss for /index. Theme files set CSS custom properties such as --app-theme-color and the gradients used for buttons and overlays.
:root {
--app-theme-color: #4e5aff;
--app-btn-gred: linear-gradient(to right, #4e5aff 0%, #800fee 51%, #2540f0 100%);
}Change the values in the theme file used by the homepage you want to recolor. Because page styles are loaded with ViewEncapsulation.None, theme changes apply to the whole page.
SCSS organization
| Folder | Contents |
|---|---|
components/ | Buttons, forms, modals, pagination, backgrounds, text |
sections/ | Styles for about, services, portfolio, pricing, teams, testimonials, blogs, contact and more |
shared/ | Header, sidebar, footer, preloader, scroll to top, animations |
pages/ | Login, auth, blog, contact and coming soon page styles |
plugins/ | Swiper, Owl Carousel, AOS, PhotoSwipe, parallax and animated headline styles |
themes/ | Color themes used by the homepages |
Add a New Page
Create your own page from existing sections in four steps.
Porto pages are standalone components, so a new page only needs a component, a route and an SEO entry. The easiest start is to copy an existing page folder, for example src/app/pages/index10.
- Copy the page folder and rename the component, selector and class (for example
my-pageandMyPageComponent). - Edit the template to keep, remove or reorder section tags, and update the
importsarray to match. - Register a lazy loaded route in
src/app/app.routes.ts, above the**route:
{
path: 'my-page',
loadComponent: () =>
import('./pages/my-page/my-page.component').then((m) => m.MyPageComponent),
},- Add an entry with the same key (
my-page) toseo.jsonwith a title, description and breadcrumb.
Because the build prerenders routes, the new page is generated as static HTML the next time you run npm run build.
Contact Form (PHP)
The contact form posts to a bundled PHP script that validates the fields and sends an email.
The form component (contact-us-form) sends firstName, lastName, email, phone and message to assets/php/contact.php. The script checks the name and email and then calls PHP mail().
Set it up
- Open
src/assets/php/contact.php. - Set
$recipientto your own email address. In the demo it is set to the sender's address, so replace it or you will not receive messages. - Remove or replace the demo address in
$bcc. - Deploy the built site to PHP hosting so that
assets/php/contact.phpis served by PHP.
$recipient = "you@yourdomain.com";
$bcc = ""; // optionalPHP 8 note: the script calls get_magic_quotes_gpc(), which was removed in PHP 8. On PHP 8 or newer, delete that if block (it only calls stripslashes) or the form will fail.
The form does not work from npm start because the Angular dev server does not run PHP. Test it on PHP hosting or a local PHP server.
SEO Settings
Page titles, descriptions and structured data come from a single JSON file.
Edit src/app/shared/models/seo.json. The site block holds the site name, URL, default image and product details. The pages block has a title, description and breadcrumb for each route key (index, index2, contact-us and so on). SeoService applies them to each route, including during prerendering.
Before you publish: change site.siteUrl from https://example.com to your real domain, and update the site name and image.
SEO checklist before launch
- Write a unique title (about 50 to 60 characters) and description (about 150 to 160 characters) for every route in
seo.json. - Replace demo images and give every image a descriptive
alttext. - Keep one
h1per page and use headings in order. - Add a
robots.txtand asitemap.xmlto thepublicfolder so they are copied into the build output. - Serve the site over HTTPS and submit the sitemap in Google Search Console.
Browser Support
Porto is responsive and works across modern browsers and mobile devices.
Angular 22 targets the current versions of Chrome, Edge, Firefox and Safari, on desktop as well as on iOS and Android. Older browsers that do not support modern JavaScript features are not supported. Layouts use the Bootstrap 5 grid, so pages adapt to phones, tablets and desktops without extra setup.
Some animations (AOS scroll effects) are switched off on tablet and smaller screens by design, which keeps scrolling smooth on mobile devices.
Dependencies
Everything is installed with npm install.
Packages
| Package | Purpose |
|---|---|
| @angular/* 22 | Framework, router, forms, SSR and prerendering |
| bootstrap, @popperjs/core, @ng-bootstrap/ng-bootstrap | Grid, components, collapse and modals |
| swiper, ngx-owl-carousel-o | Sliders and carousels |
| photoswipe, shufflejs | Image lightbox and portfolio sorting |
| aos, typed.js, velocity-animate, vivus | Scroll animations, typed text, animated headlines and SVG drawing |
| jarallax, parallax-js, ngx-smooth-parallax | Parallax backgrounds |
| ng-particles, tsparticles, tsparticles-engine | Animated particle banners |
| ngx-page-scroll | Smooth scrolling to sections |
| rxjs, tslib | Reactive utilities and TypeScript helpers |
Dev packages
@angular/cli,@angular/build,@angular/compiler-cli: build toolingtypescript6,vitest,jsdom: language and unit testsprettier: code formatting (see.prettierrc)
Security audit (known vulnerabilities)
Last checked with npm audit on October 19, 2026, across 500 installed packages (164 production, 336 development). No known vulnerabilities were reported.
| Level | npm severity | Found |
|---|---|---|
| Major | Critical and high | 0 |
| Minor | Moderate | 0 |
| Low | Low and info | 0 |
New advisories are published over time, so run the audit yourself before you deploy:
npm audit
npm audit fixNote: avoid npm audit fix --force. It can install breaking major versions of Angular or other packages.
Build & Deploy
Create an optimized build and upload it to any static host.
npm run buildThe production build prerenders every route, including each blog post, so the output in dist/porto-angular-22/browser is plain static files that work on any web host.
Hosting options
- Static hosting: upload the contents of
dist/porto-angular-22/browserto Netlify, Vercel, GitHub Pages, S3 or a shared host. - PHP hosting: use the same upload if you want the contact form to work.
- Open from disk:
npm run build:filecreates a build indist/porto-angular-22-file/browserthat opens by double-clickingindex.html. It uses hash URLs (for exampleindex.html#/index2).
Server rewrite rule
If you deploy without prerendered files, send unknown paths to index.html. Nginx example:
location / {
try_files $uri $uri/ /index.html;
}Testing
npm testUnit tests run with Vitest through the Angular CLI.
Troubleshooting
Fixes for the most common problems.
npm install fails or the build errors out
Check node -v against the versions in Requirements. Delete node_modules and package-lock.json only as a last resort, then run npm install again.
Port 4200 is already in use
npm start -- --port 4300Page shows 404 after refresh on the live site
Upload the full contents of the browser folder, including the prerendered route folders, or add the server rewrite rule from Build & Deploy.
Contact form shows an error or nothing happens
Make sure the site is on PHP hosting with mail() enabled, set $recipient, and on PHP 8 remove the get_magic_quotes_gpc() block. See Contact Form (PHP).
Changes to SCSS variables do not appear
Restart npm start. If a homepage still shows old colors, check the theme file that page loads in its styleUrls, since theme files override global variables.
Images are not showing
Image paths are relative to src/assets. Check the spelling and letter case of the file name and path.
FAQ
Which Node.js version does Porto need?
Porto uses Angular 22, which requires Node.js ^22.22.3, ^24.15.0 or >=26 with npm 8 or newer.
How do I change the theme colors?
Edit the brand variables in src/assets/scss/_variables.scss, and the CSS custom properties in the theme file a homepage loads (src/assets/scss/themes). Then restart the dev server.
How do I edit services, pricing, team and portfolio content?
Each section reads its content from a typed data.ts file inside src/app/shared/components, so you can change text, prices and images without touching the templates.
How do I make the contact form send email to me?
Open src/assets/php/contact.php, set $recipient to your email address, and deploy the site to PHP hosting with mail() enabled. On PHP 8 remove the get_magic_quotes_gpc() block.
How do I fix 404 errors after refreshing the live site?
Upload the full contents of dist/porto-angular-22/browser including the prerendered folders, or configure your server to serve index.html for unknown paths, for example try_files $uri $uri/ /index.html in Nginx.
How do I add a new page?
Copy an existing folder in src/app/pages, register a lazy loaded route in app.routes.ts and add an entry with the same key to seo.json. See the Add a New Page section.
Does Porto work with server side rendering?
Yes. The production build prerenders every route, including each blog post, and the project includes the Angular SSR packages and a serve:ssr:porto-angular-22 script.
How do I change the logo and favicon?
Replace logo.png and logo-blk.png in src/assets/images and the favicon.ico in the public folder, keeping the same file names.
Is Porto available for NextJS or plain Bootstrap?
Yes. See the NextJS version at https://lettstartdesign.com/theme/porto-react-nextjs-website-templates and the Bootstrap 5 version at https://lettstartdesign.com/theme/porto-bootstrap-website-templates.
Change Log
Version 1.0.0
Added
- Angular 22 release with Bootstrap 5.3, SCSS and TypeScript 6
- Standalone components with lazy loaded routes, no NgModules
- Prerendering of all routes and blog posts
- Central SEO configuration in
seo.json
Credits
Porto uses these open source libraries.
- Angular, Bootstrap, ng-bootstrap, Popper
- Swiper, ngx-owl-carousel-o, PhotoSwipe, Shuffle.js
- AOS, Typed.js, Velocity, Vivus, Jarallax, parallax.js, tsParticles
- Google Fonts: Roboto, Poppins, Barlow, Open Sans, Roboto Slab
Demo images are for preview purposes only. Replace them with your own before publishing.
Support
Need help with Porto? Start here before you get in touch.
Check the troubleshooting and FAQ sections first. Your purchase includes one year of free premium support and unlimited updates. Contact LettstartDesign through the support link on your purchase page, and include your template version and a short description of the issue.