Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
caf6222
IFDM-153: Set up a staging site
imonroe May 26, 2026
1478c0e
Client feedback changes
jenbreese Jun 5, 2026
b01395d
fixup
jenbreese Jun 8, 2026
67ed153
Time Value of Money client feedback updates
jenbreese Jun 8, 2026
e7f87ad
Merge branch '1.x' into dev
imonroe Jun 9, 2026
8e0f34f
Updated yarn script
imonroe Jun 9, 2026
fc5a850
Updated documentation
imonroe Jun 9, 2026
a696c87
fixup
jenbreese Jun 9, 2026
61b8e75
Testing dev branch flow
jenbreese Jun 9, 2026
1033a8c
Merge pull request #124 from SU-SWS/IFDM-153--testing
jenbreese Jun 9, 2026
773c6fa
Merge pull request #121 from SU-SWS/present-val-v2
jenbreese Jun 9, 2026
c43cce1
Fixups to questions and added errors
jenbreese Jun 9, 2026
bfdd454
feedback
jenbreese Jun 10, 2026
2276b69
Fixed edgecase bug if pmt === 0, typo
imonroe Jun 10, 2026
c8616e5
Fixes from spreadsheet to three calculators
jenbreese Jun 10, 2026
d310a74
Merge pull request #122 from SU-SWS/time-value-cal-0608
jenbreese Jun 11, 2026
a6b948a
Merge branch 'dev' into misc-cals-fixes
jenbreese Jun 11, 2026
218691e
retirement
jenbreese Jun 11, 2026
220db99
fixup
jenbreese Jun 11, 2026
2b49c8f
fixup
jenbreese Jun 11, 2026
bc073d3
Error states for compounding frequency calculator
imonroe Jun 11, 2026
f089a03
Error states and cleanup for present-value-v2
imonroe Jun 11, 2026
043cb38
fixups
jenbreese Jun 11, 2026
3f3943c
two little fixes
imonroe Jun 11, 2026
574ad7d
Merge pull request #126 from SU-SWS/compounding-frequency-errors
imonroe Jun 12, 2026
c50dd86
Merge pull request #127 from SU-SWS/present-value-error-states
imonroe Jun 12, 2026
f888b91
Merge pull request #125 from SU-SWS/misc-cals-fixes
jenbreese Jun 12, 2026
87454ee
Fixed the build error and the text color
jenbreese Jun 12, 2026
4db95bb
Merge pull request #128 from SU-SWS/build-fix
jenbreese Jun 12, 2026
9313d07
Added in changes requested in UX Error and Warning states
jenbreese Jun 12, 2026
cdf47a7
Fixes on UAT testing tab from 6-15-26
jenbreese Jun 15, 2026
88285f5
styling fixups
imonroe Jun 16, 2026
8297a34
Merge pull request #129 from SU-SWS/retirement-ux-warning-states
jenbreese Jun 16, 2026
0f565d0
fixup to use the new color variable
imonroe Jun 16, 2026
f606c05
Merge pull request #130 from SU-SWS/fixes-6-15-2026
jenbreese Jun 16, 2026
b3346a8
Fixes for the Present Value and Compounding Calculators
jenbreese Jun 17, 2026
2aa5676
fixups
jenbreese Jun 18, 2026
1bd1a5c
Merge pull request #131 from SU-SWS/uat-fixes-061726
jenbreese Jun 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,32 @@ This repository serves as source/hosting for an interactive learning tool. The g

---

## Deployment
## Environments

Please see documentation on deployment and embedding here: [deployment.md](docs/deployment.md)
| Environment | URL | Branch | Deploy command |
|---|---|---|---|
| Production | https://ifdm-learning.stanford.edu/ | `1.x` | `yarn deploy` |
| Staging | https://su-sws.github.io/ifdm_learning_apps_staging/ | `dev` | `yarn deploy:staging` |

### Development workflow

New features are developed on feature branches, reviewed via pull request, then deployed to staging for QA before going to production:

```
feature/my-branch → PR into dev → yarn deploy:staging → review on staging
↓ approved
PR into 1.x → yarn deploy → production
```

1. Create a feature branch off `dev` (or `1.x` for urgent fixes)
2. Open a PR targeting `dev`
3. After merge, deploy to staging and verify: `git checkout dev && git pull && yarn deploy:staging`
4. Once staging looks good, open a PR from `dev` into `1.x`
5. After merge, deploy to production: `git checkout 1.x && git pull && yarn deploy`

The deploy scripts enforce branch — `yarn deploy` will fail if you're not on `1.x`, and `yarn deploy:staging` will fail if you're not on `dev`.

For full deployment details and troubleshooting, see [docs/deployment.md](docs/deployment.md).

## Local Setup

Expand Down
314 changes: 228 additions & 86 deletions app/interactives/compounding-frequency-calculator/page.tsx

Large diffs are not rendered by default.

240 changes: 45 additions & 195 deletions app/interactives/debt-payoff-calculator/page.tsx

Large diffs are not rendered by default.

1,837 changes: 1,095 additions & 742 deletions app/interactives/mortgage-calculator-v2/page.tsx

Large diffs are not rendered by default.

211 changes: 112 additions & 99 deletions app/interactives/mortgage-refinancing-calculator-v2/page.tsx

Large diffs are not rendered by default.

723 changes: 571 additions & 152 deletions app/interactives/present-value-calculator-v2/page.tsx

Large diffs are not rendered by default.

785 changes: 540 additions & 245 deletions app/interactives/retirement-calculator/page.tsx

Large diffs are not rendered by default.

483 changes: 357 additions & 126 deletions app/interactives/time-value-money-calculator/app.tsx

Large diffs are not rendered by default.

83 changes: 38 additions & 45 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
import fs from 'fs';
import path from 'path';
import Link from 'next/link';
import React from 'react';
import "@/app/ui/globals.css";
import React from 'react';

// Function to get all page routes from the app directory
function getPageRoutes() {
Expand Down Expand Up @@ -48,52 +47,46 @@ export default function HomePage() {
const routes = getPageRoutes();

return (
<div className="min-h-screen p-8 bg-gray-50">
<div className="max-w-4xl mx-auto">
<h1 className="text-4xl font-bold text-gray-900 mb-8">
Welcome to The IFDM Lessons and Games
</h1>
<div>
<p className="text-lg text-gray-600 mb-8 leading-relaxed max-w-2xl">
This page helps developers find the pages they are working on quicker.
</p>
</div>
<div className="min-h-screen p-8 bg-gray-50">
<div className="max-w-4xl mx-auto">
<h1 className="text-4xl font-bold text-gray-900 mb-8">
Welcome to The IFDM Lessons and Games
</h1>

<div className="bg-white rounded-lg shadow-md p-6">
<h2 className="text-2xl font-semibold text-gray-800 mb-6">
Available Pages
</h2>
<div className="bg-white rounded-lg shadow-md p-6">
<h2 className="text-2xl font-semibold text-gray-800 mb-6">
Available Pages
</h2>

{routes.length > 0 ? (
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
{routes.map((route) => (
<Link
key={route.path}
href={route.path}
className="block p-4 border border-gray-200 rounded-lg hover:border-blue-400 hover:shadow-md transition-all duration-200 group"
>
<h3 className="text-lg font-medium text-gray-900 group-hover:text-blue-600">
{route.name}
</h3>
<p className="text-sm text-gray-500 mt-1">
{route.path}
</p>
</Link>
))}
</div>
) : (
<p className="text-gray-600">
No pages found. Create some pages in the app directory!
</p>
)}
</div>
{routes.length > 0 ? (
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
{routes.map((route) => (
<Link
key={route.path}
href={route.path}
className="block p-4 border border-gray-200 rounded-lg hover:border-blue-400 hover:shadow-md transition-all duration-200 group"
>
<h3 className="text-lg font-medium text-gray-900 group-hover:text-blue-600">
{route.name}
</h3>
<p className="text-sm text-gray-500 mt-1">{route.path}</p>
</Link>
))}
</div>
) : (
<p className="text-gray-600">
No pages found. Create some pages in the app directory!
</p>
)}
</div>

<div className="mt-8 text-center">
<p className="text-gray-600">
This page automatically updates when you add new pages to your app directory.
</p>
</div>
</div>
<div className="mt-8 text-center">
<p className="text-gray-600">
This page automatically updates when you add new pages to your app
directory.
</p>
</div>
</div>
</div>
);
}
2 changes: 1 addition & 1 deletion app/ui/components/popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export default function InfoPopover({
>
<X className="w-6 h-6 text-[var(--color-teal)] font-bold" />
</a>
<h3 id="info-popover-title" className="font-semibold text-sm mb-1 text-[var(--foreground)]">
<h3 id="info-popover-title" className="sr-only font-semibold text-sm mb-1 text-[var(--foreground)]">
{title}
</h3>
<div id="info-popover-body" className="text-sm text-[var(--foreground)]">
Expand Down
2 changes: 2 additions & 0 deletions app/ui/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@
--color-teal: rgba(0, 124, 146, 1);
--color-symbols: #616877;
--color-inline-error: #8C1515;
--color-inline-warning: #C74632;
--results-card-empty: rgba(102, 112, 133, 1);
--info-popup-background: rgba(239, 255, 252, 1);
}
Expand Down Expand Up @@ -181,6 +182,7 @@
--color-teal: rgba(74, 203, 225, 1);
--color-symbols: oklch(0.985 0 0);
--color-inline-error: #F4795B;
--color-inline-warning: #E98300;
--results-card-empty: oklch(0.985 0 0);
--info-popup-background: rgba(35, 35, 35, 1);
}
Expand Down
107 changes: 87 additions & 20 deletions docs/deployment.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,110 @@
# Instructions for deployment and embedding
# Instructions for deployment and embedding

## Deployment
## Environments

The app deploys to https://ifdm-learning.stanford.edu/ via GitHub Pages and the `gh-pages` branch. The deploy script will automatically run the build step and generate the static files based on your local `1.x` branch code. Make sure you are on the latest `1.x` branch before deploying.
| Environment | Branch | URL | Command |
|---|---|---|---|
| Production | `1.x` | https://ifdm-learning.stanford.edu/ | `yarn deploy` |
| Staging | `dev` | https://su-sws.github.io/ifdm_learning_apps_staging/ | `yarn deploy:staging` |

### Deployment Steps
---

## Development workflow

1. Ensure you are on the latest `1.x` branch code:
- `git checkout 1.x && git fetch && git pull`
2. Make sure you are using the correct Node version:
- If you use nvm and are not already on the correct version, run: `nvm use`
3. (Optional) Test the build locally before deploying:
- `yarn build`
4. Deploy to GitHub Pages:
- `yarn deploy`
5. After deploying, verify the deployment:
- Visit https://github.com/SU-SWS/ifdm_learning_apps/deployments to confirm the deployment ran successfully.
Feature branches are developed and reviewed via pull request, then merged in two stages:

```
feature/my-branch → PR → dev → yarn deploy:staging → QA on staging
↓ approved
PR to 1.x → yarn deploy → production
```

1. Open a PR from your feature branch targeting `dev`
2. After merge, deploy to staging and verify: `yarn deploy:staging`
3. Once staging is confirmed, open a PR from `dev` into `1.x`
4. After merge, deploy to production: `yarn deploy`
Comment on lines +22 to +25

---

### Embedding a Calculator
## Deploying to production

The deploy script enforces that you are on the `1.x` branch before building.

1. Switch to the latest `1.x`:
```
git checkout 1.x && git fetch && git pull
```
2. Confirm the correct Node version is active:
```
nvm use
```
3. Deploy:
```
yarn deploy
```
4. Verify at https://github.com/SU-SWS/ifdm_learning_apps/deployments

---

## Deploying to staging

The staging deploy script enforces that you are on the `dev` branch before building.

1. Switch to the latest `dev`:
```
git checkout dev && git fetch && git pull
```
2. Confirm the correct Node version is active:
```
nvm use
```
3. Deploy:
```
yarn deploy:staging
```
4. Verify at https://github.com/SU-SWS/ifdm_learning_apps_staging/deployments and preview at https://su-sws.github.io/ifdm_learning_apps_staging/

---

## One-time staging setup (already done — for reference)

If the staging environment ever needs to be rebuilt from scratch:

1. Create a new GitHub repo: `SU-SWS/ifdm_learning_apps_staging`
2. In that repo's Settings → Pages, set the source to the `gh-pages` branch
3. Add the staging remote to your local clone:
```
git remote add staging git@github.com:SU-SWS/ifdm_learning_apps_staging.git
```
Note: `yarn deploy:staging` targets this remote directly via `gh-pages -r`; the local remote entry is for reference and manual pushes only.

---

## Embedding a calculator

Example iFrame:

```angular2html
```html
<iframe src="https://ifdm-learning.stanford.edu/interactives/investment-calculator/"></iframe>
```

See below screencast as an example of embedding the iframe:

![Embedding Example](images/embedding-in-mighty.gif)

---

## Troubleshooting

### Changes Not Appearing
### Changes not appearing
1. Clear browser cache
2. Check GitHub Pages deployment status
3. Verify the gh-pages branch updated
2. Check GitHub Pages deployment status in the repo's Deployments tab
3. Verify the `gh-pages` branch updated with a recent commit

### Staging assets not loading (404 on `/_next/` paths)
The staging build sets `basePath=/ifdm_learning_apps_staging` so all asset paths are prefixed correctly for the project URL. If you see 404s on static assets, confirm `build:staging` was used (not the plain `build` command).

### iframe Issues
### iframe issues
- Ensure the source URL is correct
- Check for CORS restrictions
- Test the iframe URL directly in browser
2 changes: 1 addition & 1 deletion next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { NextConfig } from "next";
const nextConfig: NextConfig = {
output: 'export',
trailingSlash: true,
basePath: '',
basePath: process.env.NEXT_BASE_PATH || '',
eslint: {
// Directories to run ESLint on during builds
dirs: ['app'],
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
"dev": "next dev --turbopack",
"build:local": "next build",
"build": "echo \" \" > public/.nojekyll && next build && cp CNAME out/CNAME",
"predeploy": "node scripts/check-branch.js && yarn build",
"deploy": "gh-pages -d out",
"build:staging": "echo \" \" > public/.nojekyll && NEXT_BASE_PATH=/ifdm_learning_apps_staging next build",
"predeploy": "node scripts/check-branch.js 1.x && yarn build",
"deploy": "gh-pages -d out --dotfiles",
"deploy:staging": "node scripts/check-branch.js dev && yarn build:staging && gh-pages -d out --dotfiles -r git@github.com:SU-SWS/ifdm_learning_apps_staging.git",
"start": "next start",
"lint": "next lint"
},
Expand Down
7 changes: 4 additions & 3 deletions scripts/check-branch.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
const { execSync } = require('child_process');

const allowedBranch = process.argv[2] || '1.x';

try {
const branch = execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf8' }).trim();

if (branch !== '1.x') {
console.error(`Build blocked on all branches but 1.x`);
console.error('Builds are not allowed on this branch.');
if (branch !== allowedBranch) {
console.error(`Deploy blocked: must be on branch '${allowedBranch}' (currently on '${branch}').`);
process.exit(1);
}
} catch (error) {
Expand Down