This commit is contained in:
Timo Knuth 2026-02-03 14:34:43 +01:00
parent 27aebcab38
commit 2aeebb8d39
16 changed files with 134 additions and 88 deletions

View File

@ -26,7 +26,9 @@
"Bash(ls:*)",
"WebFetch(domain:angular.dev)",
"Bash(killall:*)",
"Bash(echo:*)"
"Bash(echo:*)",
"Bash(npm run build:*)",
"Bash(npx tsc:*)"
]
}
}

View File

@ -18,7 +18,7 @@ interface SitemapIndexEntry {
@Injectable()
export class SitemapService {
private readonly baseUrl = 'https://biz-match.com';
private readonly baseUrl = 'https://www.bizmatch.net';
private readonly URLS_PER_SITEMAP = 10000; // Google best practice
constructor(@Inject(PG_CONNECTION) private readonly db: NodePgDatabase<typeof schema>) { }

View File

@ -1,14 +1,17 @@
import { Routes } from '@angular/router';
// Core components (eagerly loaded - needed for initial navigation)
import { LogoutComponent } from './components/logout/logout.component';
import { NotFoundComponent } from './components/not-found/not-found.component';
import { TestSsrComponent } from './components/test-ssr/test-ssr.component';
import { EmailAuthorizedComponent } from './components/email-authorized/email-authorized.component';
import { EmailVerificationComponent } from './components/email-verification/email-verification.component';
import { LoginRegisterComponent } from './components/login-register/login-register.component';
// Guards
import { AuthGuard } from './guards/auth.guard';
import { ListingCategoryGuard } from './guards/listing-category.guard';
import { UserListComponent } from './pages/admin/user-list/user-list.component';
// Public pages (eagerly loaded - high traffic)
import { DetailsBusinessListingComponent } from './pages/details/details-business-listing/details-business-listing.component';
import { DetailsCommercialPropertyListingComponent } from './pages/details/details-commercial-property-listing/details-commercial-property-listing.component';
import { DetailsUserComponent } from './pages/details/details-user/details-user.component';
@ -16,16 +19,12 @@ import { HomeComponent } from './pages/home/home.component';
import { BrokerListingsComponent } from './pages/listings/broker-listings/broker-listings.component';
import { BusinessListingsComponent } from './pages/listings/business-listings/business-listings.component';
import { CommercialPropertyListingsComponent } from './pages/listings/commercial-property-listings/commercial-property-listings.component';
import { AccountComponent } from './pages/subscription/account/account.component';
import { EditBusinessListingComponent } from './pages/subscription/edit-business-listing/edit-business-listing.component';
import { EditCommercialPropertyListingComponent } from './pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component';
import { EmailUsComponent } from './pages/subscription/email-us/email-us.component';
import { FavoritesComponent } from './pages/subscription/favorites/favorites.component';
import { MyListingComponent } from './pages/subscription/my-listing/my-listing.component';
import { SuccessComponent } from './pages/success/success.component';
import { TermsOfUseComponent } from './pages/legal/terms-of-use.component';
import { PrivacyStatementComponent } from './pages/legal/privacy-statement.component';
// Note: Account, Edit, Admin, Favorites, MyListing, and EmailUs components are now lazy-loaded below
export const routes: Routes = [
{
path: 'test-ssr',
@ -99,58 +98,58 @@ export const routes: Routes = [
component: DetailsUserComponent,
},
// #########
// User edit
// User edit (lazy-loaded)
{
path: 'account',
component: AccountComponent,
loadComponent: () => import('./pages/subscription/account/account.component').then(m => m.AccountComponent),
canActivate: [AuthGuard],
},
{
path: 'account/:id',
component: AccountComponent,
loadComponent: () => import('./pages/subscription/account/account.component').then(m => m.AccountComponent),
canActivate: [AuthGuard],
},
// #########
// Create, Update Listings
// Create, Update Listings (lazy-loaded)
{
path: 'editBusinessListing/:id',
component: EditBusinessListingComponent,
loadComponent: () => import('./pages/subscription/edit-business-listing/edit-business-listing.component').then(m => m.EditBusinessListingComponent),
canActivate: [AuthGuard],
},
{
path: 'createBusinessListing',
component: EditBusinessListingComponent,
loadComponent: () => import('./pages/subscription/edit-business-listing/edit-business-listing.component').then(m => m.EditBusinessListingComponent),
canActivate: [AuthGuard],
},
{
path: 'editCommercialPropertyListing/:id',
component: EditCommercialPropertyListingComponent,
loadComponent: () => import('./pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component').then(m => m.EditCommercialPropertyListingComponent),
canActivate: [AuthGuard],
},
{
path: 'createCommercialPropertyListing',
component: EditCommercialPropertyListingComponent,
loadComponent: () => import('./pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component').then(m => m.EditCommercialPropertyListingComponent),
canActivate: [AuthGuard],
},
// #########
// My Listings
// My Listings (lazy-loaded)
{
path: 'myListings',
component: MyListingComponent,
loadComponent: () => import('./pages/subscription/my-listing/my-listing.component').then(m => m.MyListingComponent),
canActivate: [AuthGuard],
},
// #########
// My Favorites
// My Favorites (lazy-loaded)
{
path: 'myFavorites',
component: FavoritesComponent,
loadComponent: () => import('./pages/subscription/favorites/favorites.component').then(m => m.FavoritesComponent),
canActivate: [AuthGuard],
},
// #########
// EMAil Us
// Email Us (lazy-loaded)
{
path: 'emailUs',
component: EmailUsComponent,
loadComponent: () => import('./pages/subscription/email-us/email-us.component').then(m => m.EmailUsComponent),
// canActivate: [AuthGuard],
},
// #########
@ -174,9 +173,11 @@ export const routes: Routes = [
path: 'success',
component: SuccessComponent,
},
// #########
// Admin Pages (lazy-loaded)
{
path: 'admin/users',
component: UserListComponent,
loadComponent: () => import('./pages/admin/user-list/user-list.component').then(m => m.UserListComponent),
canActivate: [AuthGuard],
},
// #########

View File

@ -81,7 +81,7 @@
<h1 class="text-[1.55rem] sm:text-4xl md:text-5xl lg:text-6xl font-extrabold tracking-tight leading-tight drop-shadow-[0_2px_6px_rgba(0,0,0,0.55)]">Buy & Sell Businesses and Commercial Properties</h1>
<p class="mt-3 sm:mt-4 text-base sm:text-lg md:text-xl lg:text-2xl font-medium text-white/90 drop-shadow-[0_1.5px_4px_rgba(0,0,0,0.6)]">
Find profitable businesses for sale, commercial real estate, and franchise opportunities across the United States
Buy profitable businesses for sale or sell your business to qualified buyers. Browse commercial real estate and franchise opportunities across the United States.
</p>
</div>
</section>

View File

@ -1,5 +1,5 @@
import { CommonModule } from '@angular/common';
import { ChangeDetectorRef, Component, ElementRef, ViewChild } from '@angular/core';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, ViewChild } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { NgSelectModule } from '@ng-select/ng-select';
@ -27,6 +27,7 @@ import { map2User } from '../../utils/utils';
imports: [CommonModule, FormsModule, RouterModule, NgSelectModule, FaqComponent],
templateUrl: './home.component.html',
styleUrl: './home.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HomeComponent {
placeholders: string[] = ['Property close to Houston less than 10M', 'Franchise business in Austin price less than 500K'];
@ -130,14 +131,10 @@ export class HomeComponent {
type: 'website'
});
// Add Organization schema for brand identity and FAQ schema for AEO
// Add Organization schema for brand identity
// NOTE: FAQ schema removed because FAQ section is hidden (violates Google's visible content requirement)
// FAQ content is preserved in component for future use when FAQ section is made visible
const organizationSchema = this.seoService.generateOrganizationSchema();
const faqSchema = this.seoService.generateFAQPageSchema(
this.faqItems.map(item => ({
question: item.question,
answer: item.answer
}))
);
// Add HowTo schema for buying a business
const howToSchema = this.seoService.generateHowToSchema({
@ -175,7 +172,8 @@ export class HomeComponent {
// Add SearchBox schema for Sitelinks Search
const searchBoxSchema = this.seoService.generateSearchBoxSchema();
this.seoService.injectMultipleSchemas([organizationSchema, faqSchema, howToSchema, searchBoxSchema]);
// Inject schemas (FAQ schema excluded - content not visible to users)
this.seoService.injectMultipleSchemas([organizationSchema, howToSchema, searchBoxSchema]);
// Clear all filters and sort options on initial load
this.filterStateService.resetCriteria('businessListings');

View File

@ -21,7 +21,7 @@
Policy.
</p>
<p class="mb-4">
We may update our Privacy Policy from time to time. Our Privacy Policy was last updated in Febuary 2018 and is effective upon acceptance for new users. By continuing to use our websites or otherwise
We may update our Privacy Policy from time to time. Our Privacy Policy was last updated in February 2018 and is effective upon acceptance for new users. By continuing to use our websites or otherwise
continuing to deal with us, you accept this Privacy Policy.
</p>
<p class="font-bold mb-4 mt-6">Collection of personal information</p>

View File

@ -17,6 +17,9 @@
<h1 class="text-3xl md:text-4xl font-bold text-neutral-900 mb-2">Professional Business Brokers & Advisors</h1>
<p class="text-lg text-neutral-600">Connect with licensed business brokers, CPAs, attorneys, and other
professionals across the United States.</p>
<div class="mt-4 text-base text-neutral-700 max-w-4xl">
<p>BizMatch connects business buyers and sellers with experienced professionals. Find qualified business brokers to help with your business sale or acquisition. Our platform features verified professionals including business brokers, M&A advisors, CPAs, and attorneys specializing in business transactions across the United States. Whether you're looking to buy or sell a business, our network of professionals can guide you through the process.</p>
</div>
</div>
<!-- Mobile Filter Button -->

View File

@ -1,5 +1,5 @@
import { CommonModule, NgOptimizedImage } from '@angular/common';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { UntilDestroy } from '@ngneat/until-destroy';
@ -29,6 +29,7 @@ import { assignProperties, resetUserListingCriteria, map2User } from '../../../u
imports: [CommonModule, FormsModule, RouterModule, PaginatorComponent, CustomerSubTypeComponent, BreadcrumbsComponent, SearchModalBrokerComponent],
templateUrl: './broker-listings.component.html',
styleUrls: ['./broker-listings.component.scss', '../../pages.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class BrokerListingsComponent implements OnInit, OnDestroy {
private destroy$ = new Subject<void>();

View File

@ -17,6 +17,9 @@
<h1 class="text-3xl md:text-4xl font-bold text-neutral-900 mb-2">Businesses for Sale</h1>
<p class="text-lg text-neutral-600">Discover profitable business opportunities across the United States. Browse
verified listings from business owners and brokers.</p>
<div class="mt-4 text-base text-neutral-700 max-w-4xl">
<p>BizMatch features thousands of businesses for sale across all industries and price ranges. Browse restaurants, retail stores, franchises, service businesses, e-commerce operations, and manufacturing companies. Each listing includes financial details, years established, location information, and seller contact details. Our marketplace connects business buyers with sellers and brokers nationwide, making it easy to find your next business opportunity.</p>
</div>
</div>
<!-- Loading Skeleton -->

View File

@ -1,5 +1,5 @@
import { CommonModule } from '@angular/common';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { UntilDestroy } from '@ngneat/until-destroy';
@ -31,6 +31,7 @@ import { map2User } from '../../../utils/utils';
imports: [CommonModule, FormsModule, RouterModule, PaginatorComponent, SearchModalComponent, LazyLoadImageDirective, BreadcrumbsComponent],
templateUrl: './business-listings.component.html',
styleUrls: ['./business-listings.component.scss', '../../pages.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class BusinessListingsComponent implements OnInit, OnDestroy {
private destroy$ = new Subject<void>();

View File

@ -16,6 +16,9 @@
<div class="mb-6">
<h1 class="text-3xl md:text-4xl font-bold text-neutral-900 mb-2">Commercial Properties for Sale</h1>
<p class="text-lg text-neutral-600">Find office buildings, retail spaces, warehouses, and industrial properties across the United States. Investment opportunities from verified sellers and commercial real estate brokers.</p>
<div class="mt-4 text-base text-neutral-700 max-w-4xl">
<p>BizMatch showcases commercial real estate listings including office buildings, retail spaces, warehouses, and industrial properties for sale or lease. Browse investment properties across the United States with detailed information on square footage, zoning, pricing, and location. Our platform connects property buyers and investors with sellers and commercial real estate brokers. Find shopping centers, medical buildings, land parcels, and mixed-use developments in your target market.</p>
</div>
</div>
@if(listings?.length > 0) {

View File

@ -1,5 +1,5 @@
import { CommonModule } from '@angular/common';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { UntilDestroy } from '@ngneat/until-destroy';
@ -30,6 +30,7 @@ import { map2User } from '../../../utils/utils';
imports: [CommonModule, FormsModule, RouterModule, PaginatorComponent, SearchModalCommercialComponent, LazyLoadImageDirective, BreadcrumbsComponent],
templateUrl: './commercial-property-listings.component.html',
styleUrls: ['./commercial-property-listings.component.scss', '../../pages.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CommercialPropertyListingsComponent implements OnInit, OnDestroy {
private destroy$ = new Subject<void>();

View File

@ -23,9 +23,9 @@ export class SeoService {
private platformId = inject(PLATFORM_ID);
private isBrowser = isPlatformBrowser(this.platformId);
private readonly defaultImage = 'https://biz-match.com/assets/images/bizmatch-og-image.jpg';
private readonly defaultImage = 'https://www.bizmatch.net/assets/images/bizmatch-og-image.jpg';
private readonly siteName = 'BizMatch';
private readonly baseUrl = 'https://biz-match.com';
private readonly baseUrl = 'https://www.bizmatch.net';
/**
* Get the base URL for SEO purposes
@ -418,6 +418,7 @@ export class SeoService {
/**
* Generate Organization schema for the company
* Enhanced for Knowledge Graph and entity verification
*/
generateOrganizationSchema(): object {
return {
@ -427,18 +428,47 @@ export class SeoService {
'url': this.baseUrl,
'logo': `${this.baseUrl}/assets/images/bizmatch-logo.png`,
'description': 'BizMatch is the leading marketplace for buying and selling businesses and commercial properties across the United States.',
// Physical address for entity verification
'address': {
'@type': 'PostalAddress',
'streetAddress': '1001 Blucher Street',
'addressLocality': 'Corpus Christi',
'addressRegion': 'TX',
'postalCode': '78401',
'addressCountry': 'US'
},
// Contact information (E.164 format)
'telephone': '+1-800-840-6025',
'email': 'info@bizmatch.net',
// Social media and entity verification
'sameAs': [
'https://www.facebook.com/bizmatch',
'https://www.linkedin.com/company/bizmatch',
'https://twitter.com/bizmatch'
// Future: Add Wikidata, Crunchbase, Wikipedia when available
],
// Enhanced contact point
'contactPoint': {
'@type': 'ContactPoint',
'telephone': '+1-800-BIZ-MATCH',
'telephone': '+1-800-840-6025',
'contactType': 'Customer Service',
'areaServed': 'US',
'availableLanguage': 'English'
}
'availableLanguage': 'English',
'email': 'info@bizmatch.net'
},
// Business details for Knowledge Graph
'foundingDate': '2020',
'knowsAbout': [
'Business Brokerage',
'Commercial Real Estate',
'Business Valuation',
'Franchise Opportunities'
]
};
}

View File

@ -11,7 +11,7 @@ export interface SitemapUrl {
providedIn: 'root'
})
export class SitemapService {
private readonly baseUrl = 'https://biz-match.com';
private readonly baseUrl = 'https://www.bizmatch.net';
/**
* Generate XML sitemap content

View File

@ -1,6 +1,6 @@
// Build information, automatically generated by `the_build_script` :zwinkern:
const build = {
timestamp: "GER: 06.01.2026 22:33 | TX: 01/06/2026 3:33 PM"
timestamp: "GER: 03.02.2026 12:44 | TX: 02/03/2026 5:44 AM"
};
export default build;

View File

@ -1,6 +1,6 @@
# robots.txt for BizMatch - Business Marketplace
# https://biz-match.com
# Last updated: 2026-01-02
# https://www.bizmatch.net
# Last updated: 2026-02-03
# ===========================================
# Default rules for all crawlers
@ -37,6 +37,9 @@ Disallow: /emailUs
Disallow: /api/
Disallow: /bizmatch/
# Disallow Cloudflare internal paths (prevents 404 errors in crawl reports)
Disallow: /cdn-cgi/
# Disallow search result pages with parameters (to avoid duplicate content)
Disallow: /*?*sortBy=
Disallow: /*?*page=
@ -127,14 +130,14 @@ Disallow: /
# Sitemap locations
# ===========================================
# Main sitemap index (dynamically generated, contains all sub-sitemaps)
Sitemap: https://biz-match.com/bizmatch/sitemap.xml
Sitemap: https://www.bizmatch.net/bizmatch/sitemap.xml
# Individual sitemaps (auto-listed in sitemap index)
# - https://biz-match.com/bizmatch/sitemap/static.xml
# - https://biz-match.com/bizmatch/sitemap/business-1.xml
# - https://biz-match.com/bizmatch/sitemap/commercial-1.xml
# - https://www.bizmatch.net/bizmatch/sitemap/static.xml
# - https://www.bizmatch.net/bizmatch/sitemap/business-1.xml
# - https://www.bizmatch.net/bizmatch/sitemap/commercial-1.xml
# ===========================================
# Host directive (for Yandex)
# ===========================================
Host: https://biz-match.com
Host: https://www.bizmatch.net