Compare commits
No commits in common. "acec8494281b06438b3ddc5e36fcc6c8053e33c6" and "64669e5f588d8b54013b54e31c5c2ff0b8e651e5" have entirely different histories.
acec849428
...
64669e5f58
15
package-lock.json
generated
15
package-lock.json
generated
@ -17,7 +17,6 @@
|
|||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"lucide-react": "^0.503.0",
|
"lucide-react": "^0.503.0",
|
||||||
"next": "^15.2.3",
|
"next": "^15.2.3",
|
||||||
"next-plausible": "^3.12.4",
|
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-hook-form": "^7.56.1",
|
"react-hook-form": "^7.56.1",
|
||||||
@ -5090,20 +5089,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/next-plausible": {
|
|
||||||
"version": "3.12.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/next-plausible/-/next-plausible-3.12.4.tgz",
|
|
||||||
"integrity": "sha512-cD3+ixJxf8yBYvsideTxqli3fvrB7R4BXcvsNJz8Sm2X1QN039WfiXjCyNWkub4h5++rRs6fHhchUMnOuJokcg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/4lejandrito/next-plausible?sponsor=1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"next": "^11.1.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 ",
|
|
||||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
||||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/next/node_modules/postcss": {
|
"node_modules/next/node_modules/postcss": {
|
||||||
"version": "8.4.31",
|
"version": "8.4.31",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"lucide-react": "^0.503.0",
|
"lucide-react": "^0.503.0",
|
||||||
"next": "^15.2.3",
|
"next": "^15.2.3",
|
||||||
"next-plausible": "^3.12.4",
|
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-hook-form": "^7.56.1",
|
"react-hook-form": "^7.56.1",
|
||||||
|
@ -507,7 +507,7 @@ export default function FireCalculatorForm() {
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{result.yearlyData && result.yearlyData.length > 0 && (
|
{result && result.yearlyData && result.yearlyData.length > 0 && (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Financial Projection</CardTitle>
|
<CardTitle>Financial Projection</CardTitle>
|
||||||
@ -549,7 +549,7 @@ export default function FireCalculatorForm() {
|
|||||||
} else if (value >= 1000) {
|
} else if (value >= 1000) {
|
||||||
return `${(value / 1000).toFixed(0)}K`;
|
return `${(value / 1000).toFixed(0)}K`;
|
||||||
}
|
}
|
||||||
return value.toString();
|
return `${value}`;
|
||||||
}}
|
}}
|
||||||
width={80}
|
width={80}
|
||||||
/>
|
/>
|
||||||
@ -560,7 +560,7 @@ export default function FireCalculatorForm() {
|
|||||||
.payload as (typeof result.yearlyData)[0];
|
.payload as (typeof result.yearlyData)[0];
|
||||||
return (
|
return (
|
||||||
<div className="bg-background border p-2 shadow-sm">
|
<div className="bg-background border p-2 shadow-sm">
|
||||||
<p className="font-medium">{`Year: ${data.year.toString()} (Age: ${data.age.toString()})`}</p>
|
<p className="font-medium">{`Year: ${data.year} (Age: ${data.age})`}</p>
|
||||||
<p className="text-primary">{`Balance: ${formatNumber(data.balance)}`}</p>
|
<p className="text-primary">{`Balance: ${formatNumber(data.balance)}`}</p>
|
||||||
{result.fireNumber && (
|
{result.fireNumber && (
|
||||||
<p className="text-destructive">{`FIRE Number: ${formatNumber(result.fireNumber)}`}</p>
|
<p className="text-destructive">{`FIRE Number: ${formatNumber(result.fireNumber)}`}</p>
|
||||||
|
@ -1,77 +0,0 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import { usePlausible } from "next-plausible";
|
|
||||||
import { useReportWebVitals } from "next/web-vitals";
|
|
||||||
interface Metric {
|
|
||||||
/**
|
|
||||||
* The name of the metric (in acronym form).
|
|
||||||
*/
|
|
||||||
name: "CLS" | "FCP" | "FID" | "INP" | "LCP" | "TTFB";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The current value of the metric.
|
|
||||||
*/
|
|
||||||
value: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The rating as to whether the metric value is within the "good",
|
|
||||||
* "needs improvement", or "poor" thresholds of the metric.
|
|
||||||
*/
|
|
||||||
rating: "good" | "needs-improvement" | "poor";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The delta between the current value and the last-reported value.
|
|
||||||
* On the first report, `delta` and `value` will always be the same.
|
|
||||||
*/
|
|
||||||
delta: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A unique ID representing this particular metric instance. This ID can
|
|
||||||
* be used by an analytics tool to dedupe multiple values sent for the same
|
|
||||||
* metric instance, or to group multiple deltas together and calculate a
|
|
||||||
* total. It can also be used to differentiate multiple different metric
|
|
||||||
* instances sent from the same page, which can happen if the page is
|
|
||||||
* restored from the back/forward cache (in that case new metrics object
|
|
||||||
* get created).
|
|
||||||
*/
|
|
||||||
id: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Any performance entries relevant to the metric value calculation.
|
|
||||||
* The array may also be empty if the metric value was not based on any
|
|
||||||
* entries (e.g. a CLS value of 0 given no layout shifts).
|
|
||||||
*/
|
|
||||||
entries: PerformanceEntry[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The type of navigation.
|
|
||||||
*
|
|
||||||
* This will be the value returned by the Navigation Timing API (or
|
|
||||||
* `undefined` if the browser doesn't support that API), with the following
|
|
||||||
* exceptions:
|
|
||||||
* - 'back-forward-cache': for pages that are restored from the bfcache.
|
|
||||||
* - 'back_forward' is renamed to 'back-forward' for consistency.
|
|
||||||
* - 'prerender': for pages that were prerendered.
|
|
||||||
* - 'restore': for pages that were discarded by the browser and then
|
|
||||||
* restored by the user.
|
|
||||||
*/
|
|
||||||
navigationType:
|
|
||||||
| "navigate"
|
|
||||||
| "reload"
|
|
||||||
| "back-forward"
|
|
||||||
| "back-forward-cache"
|
|
||||||
| "prerender"
|
|
||||||
| "restore";
|
|
||||||
}
|
|
||||||
|
|
||||||
export function WebVitals() {
|
|
||||||
const plausible = usePlausible();
|
|
||||||
useReportWebVitals((metric: Metric) => {
|
|
||||||
plausible("web-vitals", {
|
|
||||||
props: {
|
|
||||||
[metric.name]: metric.rating,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return <></>;
|
|
||||||
}
|
|
@ -1,14 +1,13 @@
|
|||||||
import "@/styles/globals.css";
|
import "@/styles/globals.css";
|
||||||
import PlausibleProvider from "next-plausible";
|
|
||||||
import { type Metadata } from "next";
|
import { type Metadata } from "next";
|
||||||
import { Geist } from "next/font/google";
|
import { Geist } from "next/font/google";
|
||||||
import { WebVitals } from "./components/web-vitals";
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title:
|
title:
|
||||||
"InvestingFIRE Calculator | Plan Your Financial Independence & Early Retirement",
|
"FIRE Calculator - Plan Your Financial Independence & Early Retirement",
|
||||||
description:
|
description:
|
||||||
"Achieve Financial Independence, Retire Early (FIRE) with the InvestingFIRE calculator. Get personalized projections and investing advice to plan your journey.",
|
"Calculate your FIRE number, estimate your retirement age, and plan your path to financial independence with this comprehensive FIRE calculator.",
|
||||||
icons: [{ rel: "icon", url: "/favicon.ico" }],
|
icons: [{ rel: "icon", url: "/favicon.ico" }],
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -22,16 +21,7 @@ export default function RootLayout({
|
|||||||
}: Readonly<{ children: React.ReactNode }>) {
|
}: Readonly<{ children: React.ReactNode }>) {
|
||||||
return (
|
return (
|
||||||
<html lang="en" className={geist.variable}>
|
<html lang="en" className={geist.variable}>
|
||||||
<PlausibleProvider
|
<body>{children}</body>
|
||||||
domain="investingfire.com"
|
|
||||||
customDomain="https://analytics.schulze.network"
|
|
||||||
selfHosted={true}
|
|
||||||
enabled={true}
|
|
||||||
trackOutboundLinks={true}
|
|
||||||
>
|
|
||||||
<WebVitals />
|
|
||||||
<body>{children}</body>
|
|
||||||
</PlausibleProvider>
|
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
156
src/app/page.tsx
156
src/app/page.tsx
@ -9,54 +9,41 @@ import {
|
|||||||
export default function HomePage() {
|
export default function HomePage() {
|
||||||
return (
|
return (
|
||||||
<main className="text-primary-foreground to-destructive from-secondary flex min-h-screen flex-col items-center bg-gradient-to-b p-4">
|
<main className="text-primary-foreground to-destructive from-secondary flex min-h-screen flex-col items-center bg-gradient-to-b p-4">
|
||||||
<div className="container mx-auto flex flex-col items-center justify-center gap-4 px-4 py-16 text-center">
|
<div className="container mx-auto flex flex-col items-center justify-center gap-12 px-4 py-16">
|
||||||
<h1 className="from-primary via-primary-foreground to-primary bg-gradient-to-r bg-clip-text text-5xl font-extrabold tracking-tight text-transparent drop-shadow-md sm:text-[5rem]">
|
<h1 className="text-primary-foreground text-5xl font-extrabold tracking-tight sm:text-[5rem]">
|
||||||
InvestingFIRE
|
FIRE Calculator
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-primary-foreground/90 text-xl font-semibold md:text-2xl">
|
<FireCalculatorForm />
|
||||||
The #1 FIRE Calculator
|
|
||||||
</p>
|
|
||||||
<div className="mt-8 w-full max-w-2xl">
|
|
||||||
<FireCalculatorForm />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Added SEO Content Sections */}
|
{/* Added SEO Content Sections */}
|
||||||
<div className="container mx-auto max-w-4xl px-4 py-8 text-left">
|
<div className="container mx-auto max-w-4xl px-4 py-8 text-left">
|
||||||
<section className="mb-12">
|
<section className="mb-12">
|
||||||
<h2 className="mb-4 text-3xl font-bold">
|
<h2 className="mb-4 text-3xl font-bold">What is FIRE?</h2>
|
||||||
What is FIRE? Understanding Financial Independence and Early
|
|
||||||
Retirement
|
|
||||||
</h2>
|
|
||||||
<p className="mb-4 text-lg leading-relaxed">
|
<p className="mb-4 text-lg leading-relaxed">
|
||||||
FIRE stands for "Financial Independence, Retire Early."
|
FIRE stands for "Financial Independence, Retire Early."
|
||||||
It's a movement focused on aggressive saving and strategic
|
It's a movement focused on aggressive saving and investing to
|
||||||
investing to build a substantial portfolio. The goal is for
|
build a large enough portfolio that the returns can cover living
|
||||||
investment returns to cover living expenses indefinitely, freeing
|
expenses indefinitely. Achieving FIRE means you are no longer
|
||||||
you from traditional employment. Achieving FIRE means gaining the
|
dependent on traditional employment to fund your lifestyle, giving
|
||||||
freedom to pursue passions, travel, or simply enjoy life without
|
you the freedom to pursue passions, travel, or simply enjoy life
|
||||||
needing a regular paycheck. Sound investing advice is crucial for
|
without the need for a regular paycheck.
|
||||||
building the wealth needed.
|
|
||||||
</p>
|
</p>
|
||||||
<p className="text-lg leading-relaxed">
|
<p className="text-lg leading-relaxed">
|
||||||
The core principle involves maximizing your savings rate (often
|
The core principle often involves saving a high percentage of income
|
||||||
50%+) and investing wisely, typically in low-cost, diversified
|
(sometimes 50% or more) and investing it wisely, typically in
|
||||||
assets like index funds. Your "FIRE number" – the capital
|
low-cost index funds. The target amount, often called the "FIRE
|
||||||
needed – is often estimated as 25 times your desired annual
|
number," is usually calculated as 25 times your desired annual
|
||||||
spending, derived from the 4% safe withdrawal rate guideline. This
|
spending, based on the 4% safe withdrawal rate rule.
|
||||||
FIRE calculator helps you personalize this estimate.
|
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section className="mb-12">
|
<section className="mb-12">
|
||||||
<h2 className="mb-4 text-3xl font-bold">
|
<h2 className="mb-4 text-3xl font-bold">How This Calculator Works</h2>
|
||||||
How This FIRE Calculator Provides Investing Insights
|
|
||||||
</h2>
|
|
||||||
<p className="mb-4 text-lg leading-relaxed">
|
<p className="mb-4 text-lg leading-relaxed">
|
||||||
This calculator helps visualize your path to FIRE by projecting
|
This calculator helps you estimate your path to FIRE based on your
|
||||||
investment growth based on your inputs. Understanding these
|
current financial situation and future projections. Here's a
|
||||||
projections is a key piece of investing advice for long-term
|
breakdown of the inputs:
|
||||||
planning. Here's a breakdown of the inputs:
|
|
||||||
</p>
|
</p>
|
||||||
<ul className="mb-4 ml-6 list-disc space-y-2 text-lg">
|
<ul className="mb-4 ml-6 list-disc space-y-2 text-lg">
|
||||||
<li>
|
<li>
|
||||||
@ -91,19 +78,19 @@ export default function HomePage() {
|
|||||||
</ul>
|
</ul>
|
||||||
<p className="text-lg leading-relaxed">
|
<p className="text-lg leading-relaxed">
|
||||||
The calculator simulates your investment growth year by year,
|
The calculator simulates your investment growth year by year,
|
||||||
incorporating monthly contributions, the power of compound growth (a
|
factoring in monthly contributions, compound growth, and
|
||||||
core investing principle), and inflation's impact on your
|
inflation's effect on your target allowance. It then determines
|
||||||
target allowance. It estimates the age at which your capital could
|
the age at which your accumulated capital is sufficient to sustain
|
||||||
sustain your desired, inflation-adjusted monthly spending throughout
|
your desired, inflation-adjusted monthly allowance throughout your
|
||||||
your expected retirement until your specified life expectancy. It
|
expected retirement years until your specified life expectancy. It
|
||||||
calculates your potential "FIRE Number" and the age you
|
estimates your "FIRE Number" (the capital needed at
|
||||||
might reach financial independence.
|
retirement) and the age you might reach it.
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section className="mb-12">
|
<section className="mb-12">
|
||||||
<h2 className="mb-4 text-3xl font-bold">
|
<h2 className="mb-4 text-3xl font-bold">
|
||||||
FIRE & Investing Frequently Asked Questions (FAQ)
|
Frequently Asked Questions (FAQ)
|
||||||
</h2>
|
</h2>
|
||||||
<Accordion type="single" collapsible className="w-full">
|
<Accordion type="single" collapsible className="w-full">
|
||||||
<AccordionItem value="item-1">
|
<AccordionItem value="item-1">
|
||||||
@ -123,16 +110,15 @@ export default function HomePage() {
|
|||||||
|
|
||||||
<AccordionItem value="item-2">
|
<AccordionItem value="item-2">
|
||||||
<AccordionTrigger className="text-xl font-semibold">
|
<AccordionTrigger className="text-xl font-semibold">
|
||||||
Is the Expected Growth Rate realistic? Finding the right
|
Is the Expected Growth Rate realistic?
|
||||||
investing advice often starts here.
|
|
||||||
</AccordionTrigger>
|
</AccordionTrigger>
|
||||||
<AccordionContent className="text-lg leading-relaxed">
|
<AccordionContent className="text-lg leading-relaxed">
|
||||||
Historically, diversified stock market investments have returned
|
Historically, diversified stock market investments have returned
|
||||||
around 7-10% annually long-term (before inflation). A rate of 7%
|
around 7-10% annually over the long term, before inflation. A
|
||||||
(after fees) is common, but remember past performance
|
rate of 7% (after fees) is often used as a reasonable estimate,
|
||||||
doesn't guarantee future results, a fundamental piece of
|
but past performance doesn't guarantee future results.
|
||||||
investing advice. Choose a rate reflecting your risk tolerance
|
It's crucial to choose a rate you feel comfortable with and
|
||||||
and investment strategy.
|
understand the associated risks.
|
||||||
</AccordionContent>
|
</AccordionContent>
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
|
|
||||||
@ -152,15 +138,15 @@ export default function HomePage() {
|
|||||||
|
|
||||||
<AccordionItem value="item-4">
|
<AccordionItem value="item-4">
|
||||||
<AccordionTrigger className="text-xl font-semibold">
|
<AccordionTrigger className="text-xl font-semibold">
|
||||||
Can I really retire early with FIRE?
|
Can I really retire early?
|
||||||
</AccordionTrigger>
|
</AccordionTrigger>
|
||||||
<AccordionContent className="text-lg leading-relaxed">
|
<AccordionContent className="text-lg leading-relaxed">
|
||||||
Retiring significantly early is achievable but demands
|
Retiring significantly earlier than traditional retirement age
|
||||||
discipline, a high savings rate, and smart investing. Success
|
is possible but requires discipline, a high savings rate, and
|
||||||
depends on income, expenses, savings habits, and investment
|
consistent investment growth. The feasibility depends heavily on
|
||||||
returns. Use this FIRE calculator as a planning tool,
|
your income, expenses, savings habits, and investment returns.
|
||||||
understanding it provides estimates based on your assumptions
|
Use this calculator as a tool for planning and motivation, but
|
||||||
and chosen investing approach.
|
remember it provides estimates based on your inputs.
|
||||||
</AccordionContent>
|
</AccordionContent>
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
|
|
||||||
@ -196,24 +182,26 @@ export default function HomePage() {
|
|||||||
{/* Optional: Add a section for relevant resources/links here */}
|
{/* Optional: Add a section for relevant resources/links here */}
|
||||||
<section className="mb-12">
|
<section className="mb-12">
|
||||||
<h2 className="mb-4 text-3xl font-bold">
|
<h2 className="mb-4 text-3xl font-bold">
|
||||||
FIRE Journey & Investing Resources
|
Further Reading & Resources
|
||||||
</h2>
|
</h2>
|
||||||
<p className="mb-6 text-lg leading-relaxed">
|
<p className="mb-6 text-lg leading-relaxed">
|
||||||
Ready to dive deeper into FIRE and solidify your investing strategy?
|
Want to learn more about FIRE and continue your journey to financial
|
||||||
Explore these valuable resources for financial independence planning
|
independence? Here are some valuable resources to explore:
|
||||||
and investing advice:
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="bg-secondary/20 my-8 rounded-md p-4 text-lg">
|
<div className="bg-secondary/20 my-8 rounded-md p-4 text-lg">
|
||||||
<p className="font-semibold">Getting Started with FIRE:</p>
|
<p className="font-semibold">Getting Started with FIRE:</p>
|
||||||
<ol className="ml-6 list-decimal space-y-1">
|
<ol className="ml-6 list-decimal space-y-1">
|
||||||
<li>
|
<li>
|
||||||
Calculate your personal numbers using this FIRE calculator and
|
Read foundational content like Mr. Money Mustache's simple
|
||||||
other tools.
|
math article
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Seek sound investing advice and consider joining communities
|
Calculate your personal numbers using this and other FIRE
|
||||||
like r/Fire for support.
|
calculators
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Join communities like r/Fire to ask questions and find support
|
||||||
</li>
|
</li>
|
||||||
<li>Explore books and podcasts to deepen your understanding</li>
|
<li>Explore books and podcasts to deepen your understanding</li>
|
||||||
</ol>
|
</ol>
|
||||||
@ -221,24 +209,24 @@ export default function HomePage() {
|
|||||||
|
|
||||||
<div className="grid gap-8 md:grid-cols-2">
|
<div className="grid gap-8 md:grid-cols-2">
|
||||||
<div>
|
<div>
|
||||||
<h3 className="mb-3 text-xl font-semibold">
|
<h3 className="mb-3 text-xl font-semibold">Blogs & Websites</h3>
|
||||||
Blogs & Investing Websites
|
|
||||||
</h3>
|
|
||||||
<ul className="ml-6 list-disc space-y-2 text-lg">
|
<ul className="ml-6 list-disc space-y-2 text-lg">
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
href="https://www.mrmoneymustache.com/2012/01/13/the-shockingly-simple-math-behind-early-retirement/"
|
href="https://www.mrmoneymustache.com/2012/01/13/the-shockingly-simple-math-behind-early-retirement/"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
className="text-primary hover:underline"
|
className="text-primary hover:underline"
|
||||||
>
|
>
|
||||||
Mr. Money Mustache - Simple Math Behind Early Retirement &
|
Mr. Money Mustache - The Shockingly Simple Math Behind Early
|
||||||
Investing
|
Retirement
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
href="https://www.playingwithfire.co/resources"
|
href="https://www.playingwithfire.co/resources"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
className="text-primary hover:underline"
|
className="text-primary hover:underline"
|
||||||
>
|
>
|
||||||
Playing With FIRE - Comprehensive Resources
|
Playing With FIRE - Comprehensive Resources
|
||||||
@ -248,6 +236,7 @@ export default function HomePage() {
|
|||||||
<a
|
<a
|
||||||
href="https://www.reddit.com/r/Fire/"
|
href="https://www.reddit.com/r/Fire/"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
className="text-primary hover:underline"
|
className="text-primary hover:underline"
|
||||||
>
|
>
|
||||||
r/Fire Reddit Community
|
r/Fire Reddit Community
|
||||||
@ -257,24 +246,23 @@ export default function HomePage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h3 className="mb-3 text-xl font-semibold">
|
<h3 className="mb-3 text-xl font-semibold">Books & Learning</h3>
|
||||||
Books & Investment Learning
|
|
||||||
</h3>
|
|
||||||
<ul className="ml-6 list-disc space-y-2 text-lg">
|
<ul className="ml-6 list-disc space-y-2 text-lg">
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
href="https://www.amazon.com/Your-Money-Life-Transforming-Relationship/dp/0143115766"
|
href="https://www.amazon.com/Your-Money-Life-Transforming-Relationship/dp/0143115766"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
className="text-primary hover:underline"
|
className="text-primary hover:underline"
|
||||||
>
|
>
|
||||||
Your Money or Your Life - Foundational FIRE & Investing
|
Your Money or Your Life - Vicki Robin & Joe Dominguez
|
||||||
Principles
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
href="https://www.playingwithfire.co/"
|
href="https://www.playingwithfire.co/"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
className="text-primary hover:underline"
|
className="text-primary hover:underline"
|
||||||
>
|
>
|
||||||
Playing With FIRE Documentary
|
Playing With FIRE Documentary
|
||||||
@ -284,10 +272,10 @@ export default function HomePage() {
|
|||||||
<a
|
<a
|
||||||
href="https://podcasts.apple.com/us/podcast/can-you-retire-now-this-fire-calculator-will-tell-you/id1330225136?i=1000683436292"
|
href="https://podcasts.apple.com/us/podcast/can-you-retire-now-this-fire-calculator-will-tell-you/id1330225136?i=1000683436292"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
className="text-primary hover:underline"
|
className="text-primary hover:underline"
|
||||||
>
|
>
|
||||||
BiggerPockets Money Podcast - FIRE Calculators & Investing
|
BiggerPockets Money Podcast - FIRE Calculators
|
||||||
Strategies
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -295,13 +283,14 @@ export default function HomePage() {
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h3 className="mb-3 text-xl font-semibold">
|
<h3 className="mb-3 text-xl font-semibold">
|
||||||
Additional FIRE & Investing Calculators
|
Additional Calculators & Tools
|
||||||
</h3>
|
</h3>
|
||||||
<ul className="ml-6 list-disc space-y-2 text-lg">
|
<ul className="ml-6 list-disc space-y-2 text-lg">
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
href="https://walletburst.com/tools/coast-fire-calculator/"
|
href="https://walletburst.com/tools/coast-fire-calculator/"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
className="text-primary hover:underline"
|
className="text-primary hover:underline"
|
||||||
>
|
>
|
||||||
Coast FIRE Calculator - For those considering a partial
|
Coast FIRE Calculator - For those considering a partial
|
||||||
@ -312,34 +301,26 @@ export default function HomePage() {
|
|||||||
<a
|
<a
|
||||||
href="https://www.empower.com/retirement-calculator"
|
href="https://www.empower.com/retirement-calculator"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
className="text-primary hover:underline"
|
className="text-primary hover:underline"
|
||||||
>
|
>
|
||||||
Empower Retirement Planner - Free portfolio analysis and net
|
Empower Retirement Planner - Free portfolio analysis and net
|
||||||
worth tracking
|
worth tracking
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
href="https://www.investor.gov/financial-tools-calculators/calculators/compound-interest-calculator"
|
|
||||||
target="_blank"
|
|
||||||
className="text-primary hover:underline"
|
|
||||||
>
|
|
||||||
CAGR Compound Interest Calculator - Understand Investment
|
|
||||||
Growth
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h3 className="mb-3 text-xl font-semibold">
|
<h3 className="mb-3 text-xl font-semibold">
|
||||||
Recent Investing & FIRE Articles
|
Recent Articles & Trends
|
||||||
</h3>
|
</h3>
|
||||||
<ul className="ml-6 list-disc space-y-2 text-lg">
|
<ul className="ml-6 list-disc space-y-2 text-lg">
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
href="https://www.businessinsider.com/retiring-tech-early-coast-fire-make-me-millionaire-2025-4"
|
href="https://www.businessinsider.com/retiring-tech-early-coast-fire-make-me-millionaire-2025-4"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
className="text-primary hover:underline"
|
className="text-primary hover:underline"
|
||||||
>
|
>
|
||||||
Coast FIRE: Retiring in your 30s while becoming a
|
Coast FIRE: Retiring in your 30s while becoming a
|
||||||
@ -350,6 +331,7 @@ export default function HomePage() {
|
|||||||
<a
|
<a
|
||||||
href="https://www.businessinsider.com/financial-independence-retire-early-saving-loneliness-retreat-bali-making-friends-2025-2"
|
href="https://www.businessinsider.com/financial-independence-retire-early-saving-loneliness-retreat-bali-making-friends-2025-2"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
className="text-primary hover:underline"
|
className="text-primary hover:underline"
|
||||||
>
|
>
|
||||||
The Social Side of FIRE: Finding Community in Financial
|
The Social Side of FIRE: Finding Community in Financial
|
||||||
|
40
src/env.js
40
src/env.js
@ -1,40 +0,0 @@
|
|||||||
import { createEnv } from "@t3-oss/env-nextjs";
|
|
||||||
import { z } from "zod";
|
|
||||||
|
|
||||||
export const env = createEnv({
|
|
||||||
/**
|
|
||||||
* Specify your server-side environment variables schema here. This way you can ensure the app
|
|
||||||
* isn't built with invalid env vars.
|
|
||||||
*/
|
|
||||||
server: {
|
|
||||||
NODE_ENV: z.enum(["development", "test", "production"]),
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify your client-side environment variables schema here. This way you can ensure the app
|
|
||||||
* isn't built with invalid env vars. To expose them to the client, prefix them with
|
|
||||||
* `NEXT_PUBLIC_`.
|
|
||||||
*/
|
|
||||||
client: {
|
|
||||||
// NEXT_PUBLIC_CLIENTVAR: z.string(),
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g.
|
|
||||||
* middlewares) or client-side so we need to destruct manually.
|
|
||||||
*/
|
|
||||||
runtimeEnv: {
|
|
||||||
NODE_ENV: process.env.NODE_ENV,
|
|
||||||
// NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially
|
|
||||||
* useful for Docker builds.
|
|
||||||
*/
|
|
||||||
skipValidation: !!process.env.SKIP_ENV_VALIDATION,
|
|
||||||
/**
|
|
||||||
* Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and
|
|
||||||
* `SOME_VAR=''` will throw an error.
|
|
||||||
*/
|
|
||||||
emptyStringAsUndefined: true,
|
|
||||||
});
|
|
Loading…
x
Reference in New Issue
Block a user