Feature/setup personal finance tools pages (#2135)

pull/2136/head
Thomas Kaul 1 year ago committed by GitHub
parent ba220eaee9
commit 2d23c566f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,34 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { PersonalFinanceToolsPageComponent } from './personal-finance-tools-page.component';
import { products } from './products';
const routes: Routes = [
{
canActivate: [AuthGuard],
component: PersonalFinanceToolsPageComponent,
path: '',
title: $localize`Personal Finance Tools`
},
...products
.filter(({ key }) => {
return key !== 'ghostfolio';
})
.map(({ component, key, name }) => {
return {
canActivate: [AuthGuard],
path: `open-source-alternative-to-${key}`,
loadComponent: () =>
import(`./products/${key}-page.component`).then(() => component),
title: `Open Source Alternative to ${name}`
};
})
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class PersonalFinanceToolsPageRoutingModule {}

@ -0,0 +1,25 @@
import { Component, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { products } from './products';
@Component({
host: { class: 'page' },
selector: 'gf-personal-finance-tools-page',
styleUrls: ['./personal-finance-tools-page.scss'],
templateUrl: './personal-finance-tools-page.html'
})
export class PersonalFinanceToolsPageComponent implements OnDestroy {
public products = products.filter(({ key }) => {
return key !== 'ghostfolio';
});
private unsubscribeSubject = new Subject<void>();
public constructor() {}
public ngOnDestroy() {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
}

@ -0,0 +1,53 @@
<div class="container">
<div class="mb-5 row">
<div class="col">
<h3 class="d-none d-sm-block mb-3 text-center" i18n>
Discover Open Source Alternatives for Personal Finance Tools
</h3>
<div class="introduction mb-4">
<p>
This overview page features a curated collection of personal finance
tools compared to the open source alternative
<a [routerLink]="['/about']">Ghostfolio</a>. If you value
transparency, data privacy, and community collaboration, Ghostfolio
provides an excellent opportunity to take control of your financial
management.
</p>
<p>
Explore the links below to compare a variety of personal finance tools
with Ghostfolio.
</p>
</div>
<mat-card
*ngFor="let product of products"
appearance="outlined"
class="mb-3"
>
<mat-card-content>
<div class="container p-0">
<div class="flex-nowrap no-gutters row">
<a
class="d-flex overflow-hidden w-100"
title="Compare Ghostfolio to {{ product.name }}"
[routerLink]="['/resources', 'personal-finance-tools', 'open-source-alternative-to-' + product.key]"
>
<div class="flex-grow-1 overflow-hidden">
<div class="h6 m-0 text-truncate">
Open Source Alternative to {{ product.name }}
</div>
</div>
<div class="align-items-center d-flex">
<ion-icon
class="chevron text-muted"
name="chevron-forward-outline"
size="small"
></ion-icon>
</div>
</a>
</div>
</div>
</mat-card-content>
</mat-card>
</div>
</div>
</div>

@ -0,0 +1,13 @@
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatCardModule } from '@angular/material/card';
import { PersonalFinanceToolsPageRoutingModule } from './personal-finance-tools-page-routing.module';
import { PersonalFinanceToolsPageComponent } from './personal-finance-tools-page.component';
@NgModule({
declarations: [PersonalFinanceToolsPageComponent],
imports: [CommonModule, MatCardModule, PersonalFinanceToolsPageRoutingModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class PersonalFinanceToolsPageModule {}

@ -0,0 +1,19 @@
:host {
color: rgb(var(--dark-primary-text));
display: block;
.introduction {
a {
color: rgba(var(--palette-primary-500), 1);
font-weight: 500;
&:hover {
color: rgba(var(--palette-primary-300), 1);
}
}
}
}
:host-context(.is-dark-theme) {
color: rgb(var(--light-primary-text));
}

@ -0,0 +1,263 @@
<div class="container">
<div class="row">
<div class="col-md-8 offset-md-2">
<article>
<div class="mb-4 text-center">
<h1 class="mb-1">
<strong>Ghostfolio</strong>: The Open Source Alternative to
<strong>{{ product2.name }}</strong>
</h1>
</div>
<section class="mb-4">
<p>
Are you looking for an open source alternative to {{ product2.name
}}? <a [routerLink]="['/about']">Ghostfolio</a> is a powerful
portfolio management tool that provides individuals with a
comprehensive platform to track, analyze, and optimize their
investments. Whether you are an experienced investor or just
starting out, Ghostfolio offers an intuitive user interface and a
<a [routerLink]="['/features']">wide range of functionalities</a>
to help you make informed decisions and take control of your
financial future.
</p>
<p>
Ghostfolio is open source software (OSS) where a community of
developers, contributors, and enthusiasts collaborate to enhance its
capabilities, security, and user experience.
</p>
<p>
Lets dive deeper into the detailed comparison table below to gain a
thorough understanding of how Ghostfolio positions itself relative
to {{ product2.name }}. We will explore various aspects such as
features, data privacy, pricing, and more, allowing you to make a
well-informed choice for your personal requirements.
</p>
</section>
<section class="mb-4">
<table class="gf-table w-100">
<thead>
<tr class="mat-mdc-header-row">
<th class="mat-mdc-header-cell px-1 py-2"></th>
<th class="mat-mdc-header-cell px-1 py-2">Ghostfolio</th>
<th class="mat-mdc-header-cell px-1 py-2">
{{ product2.name }}
</th>
</tr>
</thead>
<tbody>
<tr class="mat-mdc-row">
<td class="mat-mdc-cell px-3 py-2 text-right"></td>
<td class="mat-mdc-cell px-1 py-2">{{ product1.slogan }}</td>
<td class="mat-mdc-cell px-1 py-2">{{ product2.slogan }}</td>
</tr>
<tr class="mat-mdc-row">
<td class="mat-mdc-cell px-3 py-2 text-right" i18n>Founded</td>
<td class="mat-mdc-cell px-1 py-2">{{ product1.founded }}</td>
<td class="mat-mdc-cell px-1 py-2">{{ product2.founded }}</td>
</tr>
<tr class="mat-mdc-row">
<td class="mat-mdc-cell px-3 py-2 text-right" i18n>Origin</td>
<td class="mat-mdc-cell px-1 py-2">{{ product1.origin }}</td>
<td class="mat-mdc-cell px-1 py-2">{{ product2.origin }}</td>
</tr>
<tr class="mat-mdc-row">
<td class="mat-mdc-cell px-3 py-2 text-right" i18n>Region</td>
<td class="mat-mdc-cell px-1 py-2">{{ product1.region }}</td>
<td class="mat-mdc-cell px-1 py-2">{{ product2.region }}</td>
</tr>
<tr class="mat-mdc-row">
<td class="mat-mdc-cell px-3 py-2 text-right" i18n>
Available in
</td>
<td class="mat-mdc-cell px-1 py-2">{{ product1.languages }}</td>
<td class="mat-mdc-cell px-1 py-2">{{ product2.languages }}</td>
</tr>
<tr class="mat-mdc-row">
<td class="mat-mdc-cell px-3 py-2 text-right" i18n>
Open Source Software
</td>
<td class="mat-mdc-cell px-1 py-2">
<ng-container *ngIf="product1.isOpenSource === true" i18n
>✅ Yes</ng-container
><ng-container *ngIf="product1.isOpenSource === false" i18n
>❌ No</ng-container
>
</td>
<td class="mat-mdc-cell px-1 py-2">
<ng-container *ngIf="product2.isOpenSource === true" i18n
>✅ Yes</ng-container
><ng-container *ngIf="product2.isOpenSource === false" i18n
>❌ No
</ng-container>
</td>
</tr>
<tr class="mat-mdc-row">
<td class="mat-mdc-cell px-3 py-2 text-right" i18n>
Self-Hosting
</td>
<td class="mat-mdc-cell px-1 py-2">
<ng-container
*ngIf="product1.hasSelfHostingAbility === true"
i18n
>✅ Yes</ng-container
><ng-container
*ngIf="product1.hasSelfHostingAbility === false"
i18n
>❌ No</ng-container
>
</td>
<td class="mat-mdc-cell px-1 py-2">
<ng-container
*ngIf="product2.hasSelfHostingAbility === true"
i18n
>✅ Yes</ng-container
><ng-container
*ngIf="product2.hasSelfHostingAbility === false"
i18n
>❌ No</ng-container
>
</td>
</tr>
<tr class="mat-mdc-row">
<td class="mat-mdc-cell px-3 py-2 text-right" i18n>
Free Plan
</td>
<td class="mat-mdc-cell px-1 py-2">
<ng-container *ngIf="product1.hasFreePlan === true" i18n
>✅ Yes</ng-container
><ng-container *ngIf="product1.hasFreePlan === false" i18n
>❌ No</ng-container
>
</td>
<td class="mat-mdc-cell px-1 py-2">
<ng-container *ngIf="product2.hasFreePlan === true" i18n
>✅ Yes</ng-container
><ng-container *ngIf="product2.hasFreePlan === false" i18n
>❌ No</ng-container
>
</td>
</tr>
<tr class="mat-mdc-row">
<td class="mat-mdc-cell px-3 py-2 text-right" i18n>Pricing</td>
<td class="mat-mdc-cell px-1 py-2">
Starting from {{ product1.pricingPerYear }} / year
</td>
<td class="mat-mdc-cell px-1 py-2">
<ng-container *ngIf="product2.pricingPerYear"
>Starting from {{ product2.pricingPerYear }} /
year</ng-container
>
</td>
</tr>
<tr *ngIf="product1.note || product2.note" class="mat-mdc-row">
<td class="mat-mdc-cell px-3 py-2 text-right" i18n>Notes</td>
<td class="mat-mdc-cell px-1 py-2">{{ product1.note }}</td>
<td class="mat-mdc-cell px-1 py-2">{{ product2.note }}</td>
</tr>
</tbody>
</table>
</section>
<section class="mb-4 py-3">
<h2 class="h4 mb-0 text-center">
Ready to take your <strong>investments</strong> to the
<strong>next level</strong>?
</h2>
<p class="lead mb-2 text-center" i18n>
Effortlessly track, analyze, and visualize your wealth with
Ghostfolio.
</p>
<div class="text-center">
<a color="primary" href="https://ghostfol.io" mat-flat-button>
Get Started
</a>
</div>
</section>
<section class="mb-4">
<small>
Please note that the information provided is based on our
independent research and analysis. This website is not affiliated
with {{ product2.name }} or any other product mentioned in the
comparison. As the landscape of personal finance tools evolves, it
is essential to verify any specific details or changes directly from
the respective product page. Data needs a refresh? Help us maintain
accurate data on
<a href="https://github.com/ghostfolio/ghostfolio">GitHub</a>.
</small>
</section>
<section class="mb-4">
<ul class="list-inline">
<li class="list-inline-item">
<span class="badge badge-light">{{ product1.name }}</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">{{ product2.name }}</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Alternative</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">App</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Community</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Fintech</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Investment</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Investor</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Open Source</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">OSS</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Personal Finance</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Privacy</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Portfolio</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Software</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Tool</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">User Experience</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Wealth</span>
</li>
<li class="list-inline-item">
<span class="badge badge-light">Wealth Management</span>
</li>
</ul>
</section>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a i18n [routerLink]="['/resources', 'personal-finance-tools']"
>Personal Finance Tools</a
>
</li>
<li
aria-current="page"
class="active breadcrumb-item text-truncate"
>
{{ product2.name }}
</li>
</ol>
</nav>
</article>
</div>
</div>
</div>

@ -0,0 +1,17 @@
:host {
color: rgb(var(--dark-primary-text));
display: block;
a {
color: rgba(var(--palette-primary-500), 1);
font-weight: 500;
&:hover {
color: rgba(var(--palette-primary-300), 1);
}
}
}
:host-context(.is-dark-theme) {
color: rgb(var(--light-primary-text));
}

@ -0,0 +1,280 @@
import { Product } from '@ghostfolio/common/interfaces';
import { AltooPageComponent } from './products/altoo-page.component';
import { DivvyDiaryPageComponent } from './products/divvydiary-page.component';
import { ExirioPageComponent } from './products/exirio-page.component';
import { FolisharePageComponent } from './products/folishare-page.component';
import { GetquinPageComponent } from './products/getquin-page.component';
import { JustEtfPageComponent } from './products/justetf-page.component';
import { KuberaPageComponent } from './products/kubera-page.component';
import { MaybeFinancePageComponent } from './products/maybe-finance-page.component';
import { MonsePageComponent } from './products/monse-page.component';
import { ParqetPageComponent } from './products/parqet-page.component';
import { PortfolioDividendTrackerPageComponent } from './products/portfolio-dividend-tracker-page.component';
import { PortseidoPageComponent } from './products/portseido-page.component';
import { SeekingAlphaPageComponent } from './products/seeking-alpha-page.component';
import { SharesightPageComponent } from './products/sharesight-page.component';
import { SimplePortfolioPageComponent } from './products/simple-portfolio-page.component';
import { SnowballAnalyticsPageComponent } from './products/snowball-analytics-page.component';
import { SumioPageComponent } from './products/sumio-page.component';
import { UtlunaPageComponent } from './products/utluna-page.component';
import { YeekateePageComponent } from './products/yeekatee-page.component';
import { ProjectionLabPageComponent } from './products/projectionlab-page.component';
export const products: Product[] = [
{
component: undefined,
founded: 2021,
hasFreePlan: true,
hasSelfHostingAbility: true,
isOpenSource: true,
key: 'ghostfolio',
languages: 'Dutch, English, French, German, Italian, Portuguese, Spanish',
name: 'Ghostfolio',
origin: 'Switzerland',
pricingPerYear: '$19',
region: 'Global',
slogan: 'Open Source Wealth Management'
},
{
component: AltooPageComponent,
founded: 2017,
hasSelfHostingAbility: false,
isOpenSource: false,
key: 'altoo',
name: 'Altoo Wealth Platform',
origin: 'Switzerland',
slogan: 'Simplicity for Complex Wealth'
},
{
component: DivvyDiaryPageComponent,
founded: 2019,
hasFreePlan: true,
hasSelfHostingAbility: false,
isOpenSource: false,
key: 'divvydiary',
languages: 'English, German',
name: 'DivvyDiary',
origin: 'Germany',
pricingPerYear: '€65',
slogan: 'Your personal Dividend Calendar'
},
{
component: ExirioPageComponent,
founded: 2020,
hasFreePlan: true,
hasSelfHostingAbility: false,
isOpenSource: false,
key: 'exirio',
name: 'Exirio',
origin: 'United States',
pricingPerYear: '$100',
slogan: 'All your wealth, in one place.'
},
{
component: FolisharePageComponent,
hasFreePlan: true,
hasSelfHostingAbility: false,
isOpenSource: false,
key: 'folishare',
languages: 'English, German',
name: 'folishare',
origin: 'Austria',
pricingPerYear: '$65',
slogan: 'Take control over your investments'
},
{
component: GetquinPageComponent,
founded: 2020,
hasFreePlan: true,
hasSelfHostingAbility: false,
isOpenSource: false,
key: 'getquin',
languages: 'English, German',
name: 'getquin',
origin: 'Germany',
pricingPerYear: '€48',
slogan: 'Portfolio Tracker, Analysis & Community'
},
{
component: JustEtfPageComponent,
founded: 2011,
hasFreePlan: true,
hasSelfHostingAbility: false,
isOpenSource: false,
key: 'justetf',
name: 'justETF',
origin: 'Germany',
pricingPerYear: '€119',
slogan: 'ETF portfolios made simple'
},
{
component: KuberaPageComponent,
founded: 2019,
hasFreePlan: false,
hasSelfHostingAbility: false,
isOpenSource: false,
key: 'kubera',
name: 'Kubera®',
origin: 'United States',
pricingPerYear: '$150',
slogan: 'The Time Machine for your Net Worth'
},
{
component: MaybeFinancePageComponent,
founded: 2021,
hasSelfHostingAbility: false,
isOpenSource: false,
key: 'maybe-finance',
languages: 'English',
name: 'Maybe Finance',
note: 'Sunset in 2023',
origin: 'United States',
pricingPerYear: '$145',
region: 'United States',
slogan: 'Your financial future, in your control'
},
{
component: MonsePageComponent,
hasFreePlan: false,
hasSelfHostingAbility: false,
isOpenSource: false,
key: 'monse',
name: 'Monse',
pricingPerYear: '$60',
slogan: 'Gain financial control and keep your data private.'
},
{
component: ParqetPageComponent,
founded: 2020,
hasSelfHostingAbility: false,
hasFreePlan: true,
isOpenSource: false,
key: 'parqet',
name: 'Parqet',
note: 'Originally named as Tresor One',
origin: 'Germany',
pricingPerYear: '€88',
region: 'Austria, Germany, Switzerland',
slogan: 'Dein Vermögen immer im Blick'
},
{
component: PortfolioDividendTrackerPageComponent,
hasFreePlan: false,
hasSelfHostingAbility: false,
isOpenSource: false,
key: 'portfolio-dividend-tracker',
languages: 'English, Dutch',
name: 'Portfolio Dividend Tracker',
origin: 'Netherlands',
pricingPerYear: '€60',
slogan: 'Manage all your portfolios'
},
{
component: PortseidoPageComponent,
founded: 2021,
hasFreePlan: true,
hasSelfHostingAbility: false,
isOpenSource: false,
key: 'portseido',
languages: 'Dutch, English, French, German',
name: 'Portseido',
origin: 'Thailand',
pricingPerYear: '$96',
slogan: 'Portfolio Performance and Dividend Tracker'
},
{
component: ProjectionLabPageComponent,
founded: 2021,
hasFreePlan: true,
hasSelfHostingAbility: true,
isOpenSource: false,
key: 'projectionlab',
name: 'ProjectionLab',
origin: 'United States',
pricingPerYear: '$108',
slogan: 'Build Financial Plans You Love.'
},
{
component: SeekingAlphaPageComponent,
founded: 2004,
hasFreePlan: false,
hasSelfHostingAbility: false,
isOpenSource: false,
key: 'seeking-alpha',
name: 'Seeking Alpha',
origin: 'United States',
pricingPerYear: '$239',
slogan: 'Stock Market Analysis & Tools for Investors'
},
{
component: SharesightPageComponent,
founded: 2007,
hasFreePlan: true,
hasSelfHostingAbility: false,
isOpenSource: false,
key: 'sharesight',
name: 'Sharesight',
origin: 'New Zealand',
pricingPerYear: '$135',
region: 'Global',
slogan: 'Stock Portfolio Tracker'
},
{
component: SimplePortfolioPageComponent,
hasFreePlan: true,
hasSelfHostingAbility: false,
isOpenSource: false,
key: 'simple-portfolio',
name: 'Simple Portfolio',
origin: 'Czech Republic',
pricingPerYear: '€80',
slogan: 'Stock Portfolio Tracker'
},
{
component: SnowballAnalyticsPageComponent,
founded: 2021,
hasFreePlan: true,
hasSelfHostingAbility: false,
isOpenSource: false,
key: 'snowball-analytics',
name: 'Snowball Analytics',
origin: 'France',
pricingPerYear: '$80',
slogan: 'Simple and powerful portfolio tracker'
},
{
component: SumioPageComponent,
hasFreePlan: true,
hasSelfHostingAbility: false,
isOpenSource: false,
key: 'sumio',
name: 'Sumio',
origin: 'Czech Republic',
pricingPerYear: '$20',
slogan: 'Sum up and build your wealth.'
},
{
component: UtlunaPageComponent,
hasFreePlan: true,
hasSelfHostingAbility: false,
isOpenSource: false,
key: 'utluna',
languages: 'English, French, German',
name: 'Utluna',
origin: 'Switzerland',
pricingPerYear: '$300',
slogan: 'Your Portfolio. Revealed.'
},
{
component: YeekateePageComponent,
founded: 2021,
hasSelfHostingAbility: false,
isOpenSource: false,
key: 'yeekatee',
name: 'yeekatee',
origin: 'Switzerland',
region: 'Switzerland',
slogan: 'Connect. Share. Invest.'
}
];

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-altoo-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class AltooPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'altoo';
});
}

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-divvy-diary-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class DivvyDiaryPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'divvydiary';
});
}

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-exirio-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class ExirioPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'exirio';
});
}

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-folishare-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class FolisharePageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'folishare';
});
}

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-getquin-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class GetquinPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'getquin';
});
}

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-justetf-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class JustEtfPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'justetf';
});
}

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-kubera-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class KuberaPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'kubera';
});
}

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-maybe-finance-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class MaybeFinancePageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'maybe-finance';
});
}

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-monse-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class MonsePageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'monse';
});
}

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-parqet-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class ParqetPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'parqet';
});
}

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-portfolio-dividend-tracker-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class PortfolioDividendTrackerPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'portfolio-dividend-tracker';
});
}

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-portseido-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class PortseidoPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'portseido';
});
}

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-projection-lab-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class ProjectionLabPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'projectionlab';
});
}

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-seeking-alpha-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class SeekingAlphaPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'seeking-alpha';
});
}

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-sharesight-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class SharesightPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'sharesight';
});
}

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-simple-portfolio-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class SimplePortfolioPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'simple-portfolio';
});
}

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-snowball-analytics-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class SnowballAnalyticsPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'snowball-analytics';
});
}

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-sumio-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class SumioPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'sumio';
});
}

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-utluna-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class UtlunaPageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'utluna';
});
}

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
import { products } from '../products';
@Component({
host: { class: 'page' },
imports: [CommonModule, MatButtonModule, RouterModule],
selector: 'gf-yeekatee-page',
standalone: true,
styleUrls: ['../product-page-template.scss'],
templateUrl: '../product-page-template.html'
})
export class YeekateePageComponent {
public product1 = products.find(({ key }) => {
return key === 'ghostfolio';
});
public product2 = products.find(({ key }) => {
return key === 'yeekatee';
});
}

@ -10,7 +10,14 @@ const routes: Routes = [
component: ResourcesPageComponent,
path: '',
title: $localize`Resources`
}
},
...['personal-finance-tools'].map((path) => ({
path,
loadChildren: () =>
import(
'./personal-finance-tools/personal-finance-tools-page.module'
).then((m) => m.PersonalFinanceToolsPageModule)
}))
];
@NgModule({

@ -2,7 +2,7 @@
<div class="row">
<div class="col">
<h1 class="d-none d-sm-block h3 mb-3 text-center" i18n>Resources</h1>
<h2 class="h4 mb-3">Guides</h2>
<h2 class="h4 mb-3" i18n>Guides</h2>
<div class="mb-5">
<div class="mb-4 media">
<div class="media-body">
@ -36,7 +36,7 @@
</div>
</div>
</div>
<h2 class="h4 mb-3">Market</h2>
<h2 class="h4 mb-3" i18n>Markets</h2>
<div class="mb-5">
<div class="mb-4 media">
<div class="media-body">
@ -72,7 +72,7 @@
</div>
</div>
</div>
<h2 class="h4 mb-3">Glossary</h2>
<h2 class="h4 mb-3" i18n>Glossary</h2>
<div>
<div class="mb-4 media">
<div class="media-body">
@ -170,6 +170,21 @@
</div>
</div>
</div>
<div class="mb-4 media">
<div class="media-body">
<h3 class="h5 mt-0">Personal Finance Tools</h3>
<div class="mb-1">
Personal finance tools are software applications that help
individuals manage their money, track expenses, set budgets,
monitor investments, and make informed financial decisions.
</div>
<div>
<a i18n [routerLink]="['/resources', 'personal-finance-tools']"
>Personal Finance Tools →</a
>
</div>
</div>
</div>
<div class="mb-4 media">
<div class="media-body">
<h3 class="h5 mt-0">Stagflation</h3>

@ -6,410 +6,494 @@
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<url>
<loc>https://ghostfol.io/de</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/de/blog</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/de/blog/2021/07/hallo-ghostfolio</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/de/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/de/features</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/de/haeufig-gestellte-fragen</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/de/maerkte</loc>
<changefreq>daily</changefreq>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/de/open</loc>
<changefreq>daily</changefreq>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/de/preise</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/de/registrierung</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/de/ressourcen</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/de/ueber-uns</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/de/ueber-uns/changelog</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/de/ueber-uns/datenschutzbestimmungen</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/de/ueber-uns/lizenz</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/about</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/about/changelog</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/about/license</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2021/07/hello-ghostfolio</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2022/01/ghostfolio-first-months-in-open-source</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2022/07/ghostfolio-meets-internet-identity</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2022/07/how-do-i-get-my-finances-in-order</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2022/08/500-stars-on-github</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2022/10/hacktoberfest-2022</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2022/11/black-friday-2022</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2022/12/the-importance-of-tracking-your-personal-finances</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2023/02/ghostfolio-meets-umbrel</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2023/03/ghostfolio-reaches-1000-stars-on-github</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2023/05/unlock-your-financial-potential-with-ghostfolio</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2023/07/exploring-the-path-to-fire</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/faq</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/features</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/markets</loc>
<changefreq>daily</changefreq>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/open</loc>
<changefreq>daily</changefreq>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/pricing</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/register</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-altoo</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-divvydiary</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-exirio</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-folishare</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-getquin</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-justetf</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-kubera</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-maybe-finance</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-monse</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-parqet</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-portfolio-dividend-tracker</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-portseido</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-projectionlab</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-seeking-alpha</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-sharesight</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-simple-portfolio</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-snowball-analytics</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-sumio</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-utluna</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources/personal-finance-tools/open-source-alternative-to-yeekatee</loc>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/es</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/es/funcionalidades</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/es/mercados</loc>
<changefreq>daily</changefreq>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/es/open</loc>
<changefreq>daily</changefreq>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/es/precios</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/es/preguntas-mas-frecuentes</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/es/recursos</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/es/registro</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/es/sobre</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/es/sobre/changelog</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/es/sobre/licencia</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/es/sobre/politica-de-privacidad</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/fr</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/fr/a-propos</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/fr/a-propos/changelog</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/fr/a-propos/licence</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/fr/a-propos/politique-de-confidentialite</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/fr/enregistrement</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/fr/fonctionnalites</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/fr/foire-aux-questions</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/fr/marches</loc>
<changefreq>daily</changefreq>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/fr/open</loc>
<changefreq>daily</changefreq>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/fr/prix</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/fr/ressources</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/it</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/it/domande-piu-frequenti</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/it/funzionalita</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/it/informazioni-su</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/it/informazioni-su/changelog</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/it/informazioni-su/licenza</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/it/informazioni-su/informativa-sulla-privacy</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/it/iscrizione</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/it/mercati</loc>
<changefreq>daily</changefreq>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/it/open</loc>
<changefreq>daily</changefreq>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/it/prezzi</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/it/risorse</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/nl</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/nl/bronnen</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/nl/kenmerken</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/nl/markten</loc>
<changefreq>daily</changefreq>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/nl/open</loc>
<changefreq>daily</changefreq>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/nl/over</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/nl/over/changelog</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/nl/over/licentie</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/nl/over/privacybeleid</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/nl/prijzen</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/nl/registratie</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/nl/vaak-gestelde-vragen</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/pt/blog</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/pt/funcionalidades</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/pt/mercados</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/pt/open</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/pt/perguntas-mais-frequentes</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/pt/precos</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/pt/recursos</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/pt/registo</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/pt/sobre</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/pt/sobre/changelog</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/pt/sobre/licenca</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/pt/sobre/politica-de-privacidade</loc>
<lastmod>2023-07-01T00:00:00+00:00</lastmod>
<lastmod>2023-07-07T00:00:00+00:00</lastmod>
</url>
</urlset>

@ -32,6 +32,7 @@ import type { PortfolioReportRule } from './portfolio-report-rule.interface';
import type { PortfolioReport } from './portfolio-report.interface';
import type { PortfolioSummary } from './portfolio-summary.interface';
import type { Position } from './position.interface';
import type { Product } from './product';
import type { BenchmarkResponse } from './responses/benchmark-response.interface';
import type { ResponseError } from './responses/errors.interface';
import type { ImportResponse } from './responses/import-response.interface';
@ -83,6 +84,7 @@ export {
PortfolioReportRule,
PortfolioSummary,
Position,
Product,
ResponseError,
ScraperConfiguration,
Statistics,

@ -0,0 +1,15 @@
export interface Product {
component: any;
founded?: number;
hasFreePlan?: boolean;
hasSelfHostingAbility?: boolean;
isOpenSource: boolean;
key: string;
languages?: string;
name: string;
note?: string;
origin?: string;
pricingPerYear?: string;
region?: string;
slogan?: string;
}
Loading…
Cancel
Save