Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
323 changes: 217 additions & 106 deletions app/interactives/present-value-calculator-v2/page.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>
);
}
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