Feature/add blog (#218)
* Setup blog * Add german blog post * Add english blog post * Update changelog
This commit is contained in:
parent
61e667213e
commit
1c65599a16
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Added
|
||||
|
||||
- Added the date range component to the positions tab
|
||||
- Added a blog
|
||||
|
||||
## 1.29.0 - 26.07.2021
|
||||
|
||||
|
@ -28,6 +28,10 @@ export class InfoService {
|
||||
|
||||
const globalPermissions: string[] = [];
|
||||
|
||||
if (this.configurationService.get('ENABLE_FEATURE_BLOG')) {
|
||||
globalPermissions.push(permissions.enableBlog);
|
||||
}
|
||||
|
||||
if (this.configurationService.get('ENABLE_FEATURE_IMPORT')) {
|
||||
globalPermissions.push(permissions.enableImport);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ export class ConfigurationService {
|
||||
ALPHA_VANTAGE_API_KEY: str({ default: '' }),
|
||||
CACHE_TTL: num({ default: 1 }),
|
||||
DATA_SOURCES: json({ default: JSON.stringify([DataSource.YAHOO]) }),
|
||||
ENABLE_FEATURE_BLOG: bool({ default: false }),
|
||||
ENABLE_FEATURE_CUSTOM_SYMBOLS: bool({ default: false }),
|
||||
ENABLE_FEATURE_FEAR_AND_GREED_INDEX: bool({ default: false }),
|
||||
ENABLE_FEATURE_IMPORT: bool({ default: !environment.production }),
|
||||
|
@ -5,6 +5,7 @@ export interface Environment extends CleanedEnvAccessors {
|
||||
ALPHA_VANTAGE_API_KEY: string;
|
||||
CACHE_TTL: number;
|
||||
DATA_SOURCES: string | string[]; // string is not correct, error in envalid?
|
||||
ENABLE_FEATURE_BLOG: boolean;
|
||||
ENABLE_FEATURE_CUSTOM_SYMBOLS: boolean;
|
||||
ENABLE_FEATURE_FEAR_AND_GREED_INDEX: boolean;
|
||||
ENABLE_FEATURE_IMPORT: boolean;
|
||||
|
@ -33,6 +33,20 @@ const routes: Routes = [
|
||||
loadChildren: () =>
|
||||
import('./pages/auth/auth-page.module').then((m) => m.AuthPageModule)
|
||||
},
|
||||
{
|
||||
path: 'de/blog/2021/07/hallo-ghostfolio',
|
||||
loadChildren: () =>
|
||||
import(
|
||||
'./pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.module'
|
||||
).then((m) => m.HalloGhostfolioPageModule)
|
||||
},
|
||||
{
|
||||
path: 'en/blog/2021/07/hello-ghostfolio',
|
||||
loadChildren: () =>
|
||||
import(
|
||||
'./pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.module'
|
||||
).then((m) => m.HelloGhostfolioPageModule)
|
||||
},
|
||||
{
|
||||
path: 'home',
|
||||
loadChildren: () =>
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
a {
|
||||
color: rgba(var(--palette-primary-500), 1);
|
||||
font-weight: bold;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,8 @@ import { UserService } from '../services/user/user.service';
|
||||
export class AuthGuard implements CanActivate {
|
||||
private static PUBLIC_PAGE_ROUTES = [
|
||||
'/about',
|
||||
'/de/blog',
|
||||
'/en/blog',
|
||||
'/pricing',
|
||||
'/register',
|
||||
'/resources'
|
||||
@ -43,7 +45,11 @@ export class AuthGuard implements CanActivate {
|
||||
if (route.queryParams?.utm_source) {
|
||||
this.router.navigate(['/register']);
|
||||
resolve(false);
|
||||
} else if (AuthGuard.PUBLIC_PAGE_ROUTES.includes(state.url)) {
|
||||
} else if (
|
||||
AuthGuard.PUBLIC_PAGE_ROUTES.filter((publicPageRoute) =>
|
||||
state.url.startsWith(publicPageRoute)
|
||||
)?.length > 0
|
||||
) {
|
||||
resolve(true);
|
||||
return EMPTY;
|
||||
} else if (state.url !== '/start') {
|
||||
|
@ -17,7 +17,9 @@ import { environment } from '../../../environments/environment';
|
||||
})
|
||||
export class AboutPageComponent implements OnDestroy, OnInit {
|
||||
public baseCurrency = baseCurrency;
|
||||
public hasPermissionForBlog: boolean;
|
||||
public hasPermissionForStatistics: boolean;
|
||||
public hasPermissionForSubscription: boolean;
|
||||
public isLoggedIn: boolean;
|
||||
public lastPublish = environment.lastPublish;
|
||||
public statistics: Statistics;
|
||||
@ -40,11 +42,22 @@ export class AboutPageComponent implements OnDestroy, OnInit {
|
||||
*/
|
||||
public ngOnInit() {
|
||||
const { globalPermissions, statistics } = this.dataService.fetchInfo();
|
||||
|
||||
this.hasPermissionForBlog = hasPermission(
|
||||
globalPermissions,
|
||||
permissions.enableBlog
|
||||
);
|
||||
|
||||
this.hasPermissionForStatistics = hasPermission(
|
||||
globalPermissions,
|
||||
permissions.enableStatistics
|
||||
);
|
||||
|
||||
this.hasPermissionForSubscription = hasPermission(
|
||||
globalPermissions,
|
||||
permissions.enableSubscription
|
||||
);
|
||||
|
||||
this.statistics = statistics;
|
||||
|
||||
this.userService.stateChanged
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div class="mb-5 row">
|
||||
<div class="col">
|
||||
<h3 class="d-flex justify-content-center mb-3" i18n>About Ghostfolio</h3>
|
||||
<mat-card>
|
||||
<mat-card class="about-container">
|
||||
<mat-card-content>
|
||||
<p>
|
||||
<strong>Ghostfolio</strong> is a lightweight wealth management
|
||||
@ -56,7 +56,10 @@
|
||||
<ion-icon name="logo-github" size="large"></ion-icon>
|
||||
</a>
|
||||
</p>
|
||||
<div class="d-flex justify-content-center">
|
||||
<div
|
||||
*ngIf="hasPermissionForSubscription"
|
||||
class="d-flex justify-content-center"
|
||||
>
|
||||
<div
|
||||
class="independent-and-bootstrapped-logo mb-2"
|
||||
title="Ghostfolio is an independent & bootstrapped business"
|
||||
@ -101,6 +104,54 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="hasPermissionForBlog" class="mb-5 row">
|
||||
<div class="col">
|
||||
<h3 class="mb-3 text-center" i18n>Blog</h3>
|
||||
<mat-card class="blog-container">
|
||||
<mat-card-content>
|
||||
<div class="container p-0">
|
||||
<div class="flex-nowrap mb-3 no-gutters row">
|
||||
<a
|
||||
class="d-flex w-100"
|
||||
[routerLink]="['/en', 'blog', '2021', '07', 'hello-ghostfolio']"
|
||||
>
|
||||
<div class="flex-grow-1">
|
||||
<div class="h6 m-0 text-truncate">Hello Ghostfolio</div>
|
||||
<div class="d-flex text-muted">31.07.2021</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 class="flex-nowrap no-gutters row">
|
||||
<a
|
||||
class="d-flex w-100"
|
||||
[routerLink]="['/de', 'blog', '2021', '07', 'hallo-ghostfolio']"
|
||||
>
|
||||
<div class="flex-grow-1">
|
||||
<div class="h6 m-0 text-truncate">Hallo Ghostfolio</div>
|
||||
<div class="d-flex text-muted">31.07.2021</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 class="mb-5 row">
|
||||
<div class="col">
|
||||
<h3 class="mb-3 text-center" i18n>Changelog</h3>
|
||||
|
@ -7,6 +7,18 @@
|
||||
}
|
||||
|
||||
.mat-card {
|
||||
&.about-container,
|
||||
&.changelog {
|
||||
a {
|
||||
color: rgba(var(--palette-primary-500), 1);
|
||||
font-weight: 500;
|
||||
|
||||
&:hover {
|
||||
color: rgba(var(--palette-primary-300), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.changelog {
|
||||
::ng-deep {
|
||||
markdown {
|
||||
@ -30,15 +42,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: rgba(var(--palette-primary-500), 1);
|
||||
font-weight: bold;
|
||||
|
||||
&:hover {
|
||||
color: rgba(var(--palette-primary-300), 1);
|
||||
}
|
||||
}
|
||||
|
||||
.independent-and-bootstrapped-logo {
|
||||
background-image: url('/assets/bootstrapped-dark.svg');
|
||||
background-position: center;
|
||||
|
@ -35,7 +35,7 @@ export class AccountPageComponent implements OnDestroy, OnInit {
|
||||
public couponId: string;
|
||||
public currencies: Currency[] = [];
|
||||
public defaultDateFormat = DEFAULT_DATE_FORMAT;
|
||||
public hasPermissionForSubscription;
|
||||
public hasPermissionForSubscription: boolean;
|
||||
public hasPermissionToUpdateViewMode: boolean;
|
||||
public hasPermissionToUpdateUserSettings: boolean;
|
||||
public price: number;
|
||||
|
@ -0,0 +1,19 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
|
||||
|
||||
import { HalloGhostfolioPageComponent } from './hallo-ghostfolio-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: HalloGhostfolioPageComponent,
|
||||
canActivate: [AuthGuard]
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class HalloGhostfolioPageRoutingModule {}
|
@ -0,0 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'gf-hallo-ghostfolio-page',
|
||||
templateUrl: './hallo-ghostfolio-page.html'
|
||||
})
|
||||
export class HalloGhostfolioPageComponent {}
|
@ -0,0 +1,194 @@
|
||||
<div class="blog container">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<article>
|
||||
<div class="mb-4 text-center">
|
||||
<h1 class="mb-1" i18n>Hallo Ghostfolio 👋</h1>
|
||||
<div class="text-muted"><small>31.07.2021</small></div>
|
||||
</div>
|
||||
<section class="mb-4">
|
||||
<p>
|
||||
In diesem Artikel möchte ich mein neues Open Source Projekt näher
|
||||
vorstellen: <a href="https://ghostfol.io">Ghostfolio</a>, eine
|
||||
web-basierte Software für das Management der persönlichen Finanzen.
|
||||
</p>
|
||||
</section>
|
||||
<section class="mb-4">
|
||||
<h2 class="h4">Welches Problem löst Ghostfolio?</h2>
|
||||
<p>
|
||||
Aufgrund der steigenden Inflation und den Negativzinsen befasse ich
|
||||
mich seit einiger Zeit, wie ich mein Vermögen möglichst
|
||||
diversifiziert anlegen kann. Konkret verfolge ich eine
|
||||
<a [routerLink]="['/resources']">Buy and Hold Strategie</a> mit
|
||||
Investitionen in verschiedene Anlageklassen verteilt auf
|
||||
unterschiedliche Plattformen. Deshalb suchte ich nach einer App, die
|
||||
mein Portfolio ganzheitlich zusammenfasst. Bei meiner
|
||||
Internetrecherche und Suche in App Stores habe ich mehrere Lösungen
|
||||
ausprobiert, doch keine hat mich vollkommen überzeugt: Zu
|
||||
kompliziert, zu überladen, nicht optimiert für Smartphones oder zu
|
||||
wenig umfassend.
|
||||
</p>
|
||||
</section>
|
||||
<section class="mb-4">
|
||||
<h2 class="h4">Die Vision</h2>
|
||||
<p>
|
||||
Besonders wichtig ist mir, dass ich in Echtzeit die Übersicht über
|
||||
mein gesamtes Vermögen erhalte. Bisher hatte ich nur einmal im Jahr,
|
||||
beim Abschluss der Steuererklärung, die aufbereiteten Zahlen zur
|
||||
Verfügung. Zum Gesamtbild gehören neben Cash auf dem Sparkonto auch
|
||||
länderspezifische Besonderheiten wie beispielsweise die freiwillige
|
||||
Altersvorsorge (Säule 3a) in der Schweiz.
|
||||
</p>
|
||||
<p>
|
||||
In der Zwischenzeit habe ich mit vielen Kollegen gesprochen, die
|
||||
schon länger investieren. Nicht wenige haben aus denselben
|
||||
Überlegungen über die Zeit ein komplexes Spreadsheet angelegt. Ich
|
||||
finde, dass dies im Jahr 2021 besser gehen muss.
|
||||
</p>
|
||||
<div class="container my-4">
|
||||
<div class="row">
|
||||
<div class="col-md-10 offset-md-1">
|
||||
<blockquote class="blockquote m-0">
|
||||
<p class="mb-0">
|
||||
Ghostfolio zeigt das Gesamtbild des Vermögens, um
|
||||
bestmögliche Anlage-Entscheidungen zu treffen.
|
||||
</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
Ghostfolio soll eine simple Wealth Management Software sein. Diese
|
||||
präsentiert jederzeit das aktuelle Vermögen und unterstützt bei
|
||||
zukünftigen Investments. Sei es beim Rebalancing des Portfolios in
|
||||
Anlageklassen (Aktien, Cryptocurrencies, ETFs, etc.) oder der
|
||||
Finanzierung einer Wohnung, Ghostfolio bietet eine solide,
|
||||
datengestützte Entscheidungshilfe.
|
||||
</p>
|
||||
<p>
|
||||
Ich lege grossen Wert auf Datenschutz. Als
|
||||
<a href="https://github.com/ghostfolio/ghostfolio"
|
||||
>Open Source Software</a
|
||||
>
|
||||
(OSS) kann Ghostfolio vollständig anonym genutzt werden, ohne die
|
||||
gierigen Blicke von Grossbanken oder Big Tech.
|
||||
</p>
|
||||
</section>
|
||||
<section class="mb-4">
|
||||
<h2 class="h4">Von der Idee zur Umsetzung</h2>
|
||||
<p>
|
||||
Vor diesem Hintergrund habe ich das ambitionierte Projekt gestartet
|
||||
und in kleinen Schritten eine Software programmiert, die ich rasch
|
||||
selbst nutzen konnte. Als Stack habe ich mich für moderne
|
||||
Web-Technologien entschieden, die mich persönlich besonders
|
||||
interessieren beziehungsweise die ich gerne erlernen und vertiefen
|
||||
möchte. Dazu zählen <a href="https://www.docker.com">Docker</a>,
|
||||
<a href="https://nx.dev">Nx</a> für das Management des Monorepos,
|
||||
<a href="https://nestjs.com">NestJS</a> für das Backend und
|
||||
<a href="https://www.postgresql.org">PostgreSQL</a> als Datenbank.
|
||||
Der Code ist sowohl im Frontend als auch im Backend in
|
||||
<a href="https://www.typescriptlang.org">TypeScript</a>
|
||||
geschrieben.
|
||||
</p>
|
||||
<p>
|
||||
Da ich bei einigen Kalkulationen an meine Grenzen gestossen bin,
|
||||
habe ich mit verschiedenen Möglichkeiten auseinandergesetzt, um
|
||||
Unterstützung zu bekommen. In der Hoffnung, dass andere Leute
|
||||
ebenfalls von der Lösung profitieren und bei Interesse mit
|
||||
Verbesserungen beitragen können, habe ich den bestehenden Code als
|
||||
Open Source Software veröffentlicht. Schon nach kurzer Zeit haben
|
||||
<a
|
||||
href="https://github.com/ghostfolio/ghostfolio/graphs/contributors"
|
||||
>andere Entwickler</a
|
||||
>
|
||||
mit tollen Erweiterungen an Ghostfolio mitgewirkt.
|
||||
</p>
|
||||
</section>
|
||||
<section class="mb-4">
|
||||
<h2 class="h4">Wie kann ich das Projekt unterstützen?</h2>
|
||||
<p>
|
||||
Bist du ebenfalls besessen von einer maximal diversifizierten
|
||||
Anlagestrategie? Ich freue mich über alle, die Ghostfolio
|
||||
ausprobieren. Bist du überzeugt vom Potential der Software? Jede
|
||||
Unterstützung für Ghostfolio ist willkommen. Sei es mit einer
|
||||
<a href="https://ghostfol.io/pricing">Ghostfolio Premium</a>
|
||||
Subscription zur Finanzierung des Hostings, einem positiven Rating
|
||||
im
|
||||
<a
|
||||
href="https://play.google.com/store/apps/details?id=ch.dotsilver.ghostfolio.twa"
|
||||
>Google Play Store</a
|
||||
>, einem Sternchen auf
|
||||
<a href="https://github.com/ghostfolio/ghostfolio">GitHub</a>,
|
||||
Feedback, Bug Reports, Feature Requests und natürlich Contributions!
|
||||
</p>
|
||||
<p>
|
||||
Du erreichst mich per E-Mail unter
|
||||
<a href="mailto:hi@ghostfol.io">hi@ghostfol.io</a> oder auf Twitter
|
||||
<a href="https://twitter.com/ghostfolio_">@ghostfolio_</a>.
|
||||
</p>
|
||||
<p>
|
||||
Ich freue mich, von dir zu hören.<br />
|
||||
Thomas von Ghostfolio
|
||||
</p>
|
||||
</section>
|
||||
<section class="my-5">
|
||||
<ul class="list-inline">
|
||||
<li class="h5">
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Aktie</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Altersvorsorge</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Anlage</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2">App</span>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Cryptocurrency</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2">ETF</span>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Feedback</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Fintech</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Ghostfolio</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Investition</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Open Source</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2">OSS</span>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Portfolio</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Software</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Strategie</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Trading</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>TypeScript</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Vermögen</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Wealth Management</span
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,15 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { HalloGhostfolioPageRoutingModule } from './hallo-ghostfolio-page-routing.module';
|
||||
import { HalloGhostfolioPageComponent } from './hallo-ghostfolio-page.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [HalloGhostfolioPageComponent],
|
||||
exports: [],
|
||||
imports: [CommonModule, HalloGhostfolioPageRoutingModule, RouterModule],
|
||||
providers: [],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class HalloGhostfolioPageModule {}
|
@ -0,0 +1,19 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
|
||||
|
||||
import { HelloGhostfolioPageComponent } from './hello-ghostfolio-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: HelloGhostfolioPageComponent,
|
||||
canActivate: [AuthGuard]
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class HelloGhostfolioPageRoutingModule {}
|
@ -0,0 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'gf-hello-ghostfolio-page',
|
||||
templateUrl: './hello-ghostfolio-page.html'
|
||||
})
|
||||
export class HelloGhostfolioPageComponent {}
|
@ -0,0 +1,173 @@
|
||||
<div class="blog container">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<article>
|
||||
<div class="mb-4 text-center">
|
||||
<h1 class="mb-1" i18n>Hello Ghostfolio 👋</h1>
|
||||
<div class="text-muted"><small>31.07.2021</small></div>
|
||||
</div>
|
||||
<section class="mb-4">
|
||||
<p>
|
||||
In this article I would like to introduce my new open source project
|
||||
in more detail: <a href="https://ghostfol.io">Ghostfolio</a>, a
|
||||
web-based personal finance management software.
|
||||
</p>
|
||||
</section>
|
||||
<section class="mb-4">
|
||||
<h2 class="h4">What problem does Ghostfolio solve?</h2>
|
||||
<p>
|
||||
Due to rising inflation and negative interest rates, I have been
|
||||
looking for some time at how I can invest my assets in the most
|
||||
diversified way possible. Specifically, I follow a
|
||||
<a [routerLink]="['/resources']">buy and hold strategy</a> with
|
||||
investments in different asset classes spread across different
|
||||
platforms. Therefore, I was looking for an app that would
|
||||
holistically aggregate my portfolio. During my research on the
|
||||
internet and in app stores, I have tried several solutions, but none
|
||||
of them has convinced me completely: too complicated, too cluttered,
|
||||
not optimized for smartphones or not comprehensive enough.
|
||||
</p>
|
||||
</section>
|
||||
<section class="mb-4">
|
||||
<h2 class="h4">The vision</h2>
|
||||
<p>
|
||||
It is particularly important to me that I get an overview of all my
|
||||
assets in real time. Previously, I only had the prepared figures
|
||||
available once a year, when I had completed my annual tax
|
||||
declaration. In addition to the cash balance in the savings account,
|
||||
the overall picture also includes country-specific traits such as
|
||||
the voluntary pension plan (pillar 3a) in Switzerland.
|
||||
</p>
|
||||
<p>
|
||||
In the meantime, I have talked to many colleagues who have been
|
||||
investing for a longer time. Quite a few have created complex
|
||||
spreadsheets from the same considerations. I think that should be
|
||||
better in 2021.
|
||||
</p>
|
||||
<div class="container my-4">
|
||||
<div class="row">
|
||||
<div class="col-md-10 offset-md-1">
|
||||
<blockquote class="blockquote m-0">
|
||||
<p class="mb-0">
|
||||
Ghostfolio presents the big picture of assets to make the
|
||||
best possible investment decisions.
|
||||
</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
Ghostfolio is supposed to be a simple wealth management software. It
|
||||
presents the current assets at any time and supports the decision
|
||||
making of future investments. Whether rebalancing the portfolio in
|
||||
asset classes (stocks, cryptocurrencies, ETFs, etc.) or financing an
|
||||
apartment, Ghostfolio offers solid, data-driven decision support.
|
||||
</p>
|
||||
<p>
|
||||
As I value privacy, data protection is an integral part of
|
||||
Ghostfolio. As
|
||||
<a href="https://github.com/ghostfolio/ghostfolio"
|
||||
>open source software</a
|
||||
>
|
||||
(OSS), Ghostfolio can be used completely anonymously, without the
|
||||
greedy eyes of big banks or big tech.
|
||||
</p>
|
||||
</section>
|
||||
<section class="mb-4">
|
||||
<h2 class="h4">From idea to implementation</h2>
|
||||
<p>
|
||||
With this background I have started the ambitious project and
|
||||
programmed with small steps a software that I could quickly use for
|
||||
myself. As a stack, I chose modern web technologies that are
|
||||
personally of particular interest or that I would like to learn and
|
||||
deepen. These include <a href="https://www.docker.com">Docker</a>,
|
||||
<a href="https://nx.dev">Nx</a> for the management of the monorepo,
|
||||
<a href="https://nestjs.com">NestJS</a> for the backend and
|
||||
<a href="https://www.postgresql.org">PostgreSQL</a> as a database.
|
||||
The code of the frontend and backend is written in
|
||||
<a href="https://www.typescriptlang.org">TypeScript</a>.
|
||||
</p>
|
||||
<p>
|
||||
Since I have shortly reached my limits with some calculations, I
|
||||
have looked into different possibilities to get valuable support.
|
||||
Hoping that other people could also benefit from the solution and
|
||||
contribute with improvements if interested, I have released the
|
||||
existing code as open source software. Very soon, other
|
||||
<a
|
||||
href="https://github.com/ghostfolio/ghostfolio/graphs/contributors"
|
||||
>developers</a
|
||||
>
|
||||
contributed to Ghostfolio with great enhancements.
|
||||
</p>
|
||||
</section>
|
||||
<section class="mb-4">
|
||||
<h2 class="h4">How can I support the project?</h2>
|
||||
<p>
|
||||
Are you also obsessed with a maximally diversified investment
|
||||
strategy? I'm happy for everyone who tries Ghostfolio. Are you
|
||||
convinced of its potential? Any support for Ghostfolio is welcome.
|
||||
Be it with a
|
||||
<a href="https://ghostfol.io/pricing">Ghostfolio Premium</a>
|
||||
Subscription to finance the hosting, a positive rating in the
|
||||
<a
|
||||
href="https://play.google.com/store/apps/details?id=ch.dotsilver.ghostfolio.twa"
|
||||
>Google Play Store</a
|
||||
>, a star on
|
||||
<a href="https://github.com/ghostfolio/ghostfolio">GitHub</a>,
|
||||
feedback, bug reports, feature requests and of course contributions!
|
||||
</p>
|
||||
<p>
|
||||
You can reach me by email at
|
||||
<a href="mailto:hi@ghostfol.io">hi@ghostfol.io</a> or on Twitter
|
||||
<a href="https://twitter.com/ghostfolio_">@ghostfolio_</a>.
|
||||
</p>
|
||||
<p>
|
||||
I look forward to hearing from you.<br />
|
||||
Thomas from Ghostfolio
|
||||
</p>
|
||||
</section>
|
||||
<section class="my-5">
|
||||
<ul class="list-inline">
|
||||
<li class="h5">
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Cryptocurrency</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2">ETF</span>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Fintech</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Ghostfolio</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Investment</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Open Source</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2">OSS</span>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Portfolio</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Software</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Stock</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Strategy</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Wealth</span
|
||||
>
|
||||
<span class="badge badge-light font-weight-normal mr-2"
|
||||
>Wealth Management</span
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,15 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { HelloGhostfolioPageRoutingModule } from './hello-ghostfolio-page-routing.module';
|
||||
import { HelloGhostfolioPageComponent } from './hello-ghostfolio-page.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [HelloGhostfolioPageComponent],
|
||||
exports: [],
|
||||
imports: [CommonModule, HelloGhostfolioPageRoutingModule, RouterModule],
|
||||
providers: [],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class HelloGhostfolioPageModule {}
|
@ -4,7 +4,7 @@
|
||||
|
||||
a {
|
||||
color: rgba(var(--palette-primary-500), 1);
|
||||
font-weight: bold;
|
||||
font-weight: 500;
|
||||
|
||||
&:hover {
|
||||
color: rgba(var(--palette-primary-300), 1);
|
||||
|
@ -5,7 +5,7 @@
|
||||
.mat-card {
|
||||
a {
|
||||
color: rgba(var(--palette-primary-500), 1);
|
||||
font-weight: bold;
|
||||
font-weight: 500;
|
||||
|
||||
&:hover {
|
||||
color: rgba(var(--palette-primary-300), 1);
|
||||
|
@ -42,7 +42,7 @@
|
||||
|
||||
a {
|
||||
color: rgba(var(--palette-primary-500), 1);
|
||||
font-weight: bold;
|
||||
font-weight: 500;
|
||||
|
||||
&:hover {
|
||||
color: rgba(var(--palette-primary-300), 1);
|
||||
|
@ -6,22 +6,30 @@
|
||||
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
|
||||
<url>
|
||||
<loc>https://ghostfol.io</loc>
|
||||
<lastmod>2021-06-03T00:00:00+00:00</lastmod>
|
||||
<lastmod>2021-07-31T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/about</loc>
|
||||
<lastmod>2021-06-03T00:00:00+00:00</lastmod>
|
||||
<lastmod>2021-07-31T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/de/blog/2021/07/hallo-ghostfolio</loc>
|
||||
<lastmod>2021-07-31T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/en/blog/2021/07/hello-ghostfolio</loc>
|
||||
<lastmod>2021-07-31T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/pricing</loc>
|
||||
<lastmod>2021-06-03T00:00:00+00:00</lastmod>
|
||||
<lastmod>2021-07-31T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/register</loc>
|
||||
<lastmod>2021-06-03T00:00:00+00:00</lastmod>
|
||||
<lastmod>2021-07-31T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://ghostfol.io/resources</loc>
|
||||
<lastmod>2021-06-03T00:00:00+00:00</lastmod>
|
||||
<lastmod>2021-07-31T00:00:00+00:00</lastmod>
|
||||
</url>
|
||||
</urlset>
|
||||
|
@ -28,6 +28,22 @@ body {
|
||||
|
||||
a {
|
||||
color: var(--dark-primary-text);
|
||||
|
||||
&:hover {
|
||||
color: unset;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.blog {
|
||||
a {
|
||||
color: rgba(var(--palette-primary-500), 1);
|
||||
font-weight: 500;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-dark-theme {
|
||||
@ -82,11 +98,6 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: unset;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
button:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ export const permissions = {
|
||||
deleteOrder: 'deleteOrder',
|
||||
deleteUser: 'deleteUser',
|
||||
enableImport: 'enableImport',
|
||||
enableBlog: 'enableBlog',
|
||||
enableSocialLogin: 'enableSocialLogin',
|
||||
enableStatistics: 'enableStatistics',
|
||||
enableSubscription: 'enableSubscription',
|
||||
|
Loading…
x
Reference in New Issue
Block a user