Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
db2b7bf
documentation
xalbd Mar 12, 2026
013bf4a
write a bunch more documentation
xalbd Mar 12, 2026
ec12374
shadcn addition
xalbd Mar 12, 2026
24c5880
get shadcn working
xalbd Mar 13, 2026
102e0db
some styling
xalbd Mar 13, 2026
2e5dc42
homepage + claude md
xalbd Mar 13, 2026
eafef17
add some frontend skills
xalbd Mar 13, 2026
6eda516
change to vega
xalbd Mar 13, 2026
a0b14c0
initial feedback form skeleton
xalbd Mar 13, 2026
a211779
refactor
xalbd Mar 13, 2026
399255f
fix bug
xalbd Mar 13, 2026
f0f187b
some UI improvements
xalbd Mar 13, 2026
007be92
comboboxes
xalbd Mar 13, 2026
bf86b0a
some more text changes
xalbd Mar 14, 2026
27a3ea8
move to radix and change everything to a big form
xalbd Mar 14, 2026
2dbe292
move to subfolder
xalbd Mar 14, 2026
0a443a6
bunch more refactoring
xalbd Mar 14, 2026
81372e6
useHook only for type (???) removed, thank you claude code for that h…
xalbd Mar 14, 2026
b148a68
finally split the form correctly, thank you claude code for doing the…
xalbd Mar 14, 2026
fb53e0f
fix the gender selection + constants
xalbd Mar 14, 2026
c5d6fd1
ta feedback + start uncooking constants
xalbd Mar 14, 2026
bcba44d
head la feedback
xalbd Mar 14, 2026
3493fb2
schema fixes
xalbd Mar 15, 2026
5d227ca
finally finish la to head la and fix schema x5
xalbd Mar 15, 2026
7cf81e6
claude update
xalbd Mar 15, 2026
0dd9396
add observation form
xalbd Mar 15, 2026
c40b5bb
3xl width maybe
xalbd Mar 15, 2026
a137237
set vercel api URL through action
xalbd Mar 16, 2026
d5fcf07
test
xalbd Mar 16, 2026
051ab2e
attempt fix again
xalbd Mar 16, 2026
8370f01
whoops
xalbd Mar 16, 2026
d94e2d3
test again
xalbd Mar 16, 2026
13e7dd9
again
xalbd Mar 16, 2026
24a4ca8
claude md updates
xalbd Mar 16, 2026
bc24f3d
not found
xalbd Mar 16, 2026
ff4cc3d
another github action fix
xalbd Mar 16, 2026
d9d3974
remove agent files
xalbd Mar 16, 2026
f17fe5d
fix gitignore
xalbd Mar 16, 2026
ae49b0f
mroe gitignore notes
xalbd Mar 16, 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
4 changes: 3 additions & 1 deletion .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
name: "Production Deployment"
on:
push:
branches: [main]
pull_request:
branches: [main]
types: [closed]
Expand Down Expand Up @@ -34,7 +36,7 @@ jobs:
- name: Destroy Preview Terraform Deployment
working-directory: ./terraform/dev
run: |
if terraform workspace show | grep -q "pr${{ github.event.number }}"; then
if terraform workspace list | grep -q "pr${{ github.event.number }}"; then
terraform workspace select pr${{ github.event.number }}
terraform destroy -auto-approve -no-color
terraform workspace select default
Expand Down
47 changes: 43 additions & 4 deletions .github/workflows/terraform-pr-preview.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ env:
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
TF_IN_AUTOMATION: true

defaults:
run:
working-directory: ./terraform/dev

jobs:
terraform:
name: "Terraform PR Preview Deployment"
defaults:
run:
working-directory: ./terraform/dev
runs-on: ubuntu-latest
permissions:
contents: read
Expand Down Expand Up @@ -106,3 +105,43 @@ jobs:
body
});
}

vercel-preview:
name: "Update Vercel Preview Environment"
runs-on: ubuntu-latest
needs: terraform
if: ${{ needs.terraform.outputs.api_url != '' }}
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
outputs:
skip_redeploy: ${{ steps.apply_api_url.outputs.skip_redeploy }}

steps:
- name: Install Vercel CLI
run: npm install -g vercel

- name: Check and update NEXT_PUBLIC_API_URL
id: apply_api_url
run: |
BRANCH="${{ github.head_ref }}"
API_URL="${{ needs.terraform.outputs.api_url }}"
vercel env pull --environment preview --git-branch "$BRANCH" --token="$VERCEL_TOKEN" --no-color
CURRENT=$(cat .env.local | grep "NEXT_PUBLIC_API_URL" || true)

if [ "$CURRENT" = "NEXT_PUBLIC_API_URL=$API_URL" ]; then
echo "NEXT_PUBLIC_API_URL already set to correct value, skipping."
echo "skip_redeploy=true" >> $GITHUB_OUTPUT
exit 0
fi

echo "$API_URL" | vercel env add NEXT_PUBLIC_API_URL preview "$BRANCH" --token="$VERCEL_TOKEN" --force --no-color
echo "Set NEXT_PUBLIC_API_URL=$API_URL for branch $BRANCH"

- name: Redeploy Vercel preview
if: ${{ steps.apply_api_url.outputs.skip_redeploy != 'true' }}
run: |
BRANCH="${{ github.head_ref }}"
DEPLOYMENT_URL="laprogram-git-$BRANCH-xalbd-team.vercel.app"
vercel redeploy "$DEPLOYMENT_URL" --token="$VERCEL_TOKEN" --scope xalbd-team --no-color --no-wait
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Remove LLM skills as they are too large and clog commits
# Perhaps find a better way to share these later; at the moment simply
# use skills-lock.json to get the current skills.
.agents/
.claude/
56 changes: 56 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Overview

Monorepo for the UCLA Learning Assistant Program web app (<https://www.laprogramucla.com>). Used by LAs and PDT to manage the feedback and observation cycle each quarter. Three top-level directories: `frontend/`, `backend/`, `terraform/`.

## Commands

### Frontend

```bash
cd frontend
npm i # install deps
npm run dev # dev server at localhost:3000
npm run build # production build (catches type errors)
npm run lint # ESLint
```

### Backend

No local dev server. Deploy and test backend routes by opening a PR — GitHub Actions will provision a test environment and post environment variable instructions as a PR comment. Set `NEXT_PUBLIC_API_URL` in the frontend to point at the test API URL.

## Architecture

### Frontend (`frontend/`)

- **Next.js 16** (App Router), React 19, TypeScript, Tailwind CSS v4, shadcn/ui, TanStack Form, Zod 4
- `app/` — file-based routing. Current routes:
- `/` — landing page (hero with CTA links to `/feedback` and `/login`)
- `/feedback` — multi-variant feedback form (the main feature)
- `/login` — email-based OTP login (stub — `handleSubmit` is a server action that currently just logs)
- `components/ui/` — shadcn components. Add new ones with `npx shadcn add <component>`. Never copy-paste component source manually.

#### Feedback form (`app/feedback/`)

The feedback form is the most complex part of the frontend. It conditionally renders different sections based on role (`student`, `la`, `ta`) and feedback type.

- **Schema** (`schema.ts`): validation uses nested `z.discriminatedUnion` — first on `role`, then on `feedback_type` (and `la_head_type` for LA→Head LA). Shared field groups (`headerFields`, `closingFields`, `mqFields`, `eqFields`, `laPedFields`, `laLccFields`, `obsFields`, `taFields`, etc.) are defined once and spread into both variant schemas and `baseSchema`. `baseSchema` exists only for type inference (`FeedbackFormValues`) and generating `defaultValues` — it is built from the field groups, not maintained manually. When adding a new field, add it to the relevant field group; it will flow into `baseSchema`, `defaultValues`, and the variant schema automatically.
- **Constants** (`constants.ts`): all dropdown/radio options and question lists. Courses and LAs are currently hardcoded (will eventually be fetched from backend).
- The exported `feedbackFormSchema` is cast to `z.ZodType<FeedbackFormValues, FeedbackFormValues>` because the discriminated union's inferred type is narrower than the flat `FeedbackFormValues` that TanStack Form expects. This cast is safe — runtime validation is correct.

### Backend (`backend/`)

- Python 3.14. Each `.py` file = one Lambda function = one API route.
- Lambdas use AWS Lambda format 2.0 payload. Each handler parses HTTP method, path, body, etc. from the `event` dict directly.
- No shared runtime or framework — each file is standalone.

### Infrastructure (`terraform/`)

- Avoid changing Terraform files; they should only be edited by humans. Only read Terraform files to figure out how to properly access AWS resources for backend routes.
- Two Terraform modules: `deploy` (per-PR, duplicatable: API Gateway + Lambdas) and `prod` (production-only: domain, TLS cert).
- Two configs: `terraform/dev/` (PR previews, one workspace per PR named e.g. `pr150`) and `terraform/release/` (production, `default` workspace).
- Terraform state is in S3; AWS credentials are in GitHub Secrets.
- `deploy` automatically provisions a Lambda for every `.py` file found in `backend/`.
38 changes: 31 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,36 @@
# UCLA Learning Assistant Website
LA Program site for observations and feedback.

## Development Requirements
This monorepo contains the code for the Learning Assistant website at UCLA. This is not an informational website; it is actively used by both LAs and PDT to manage the feedback and observation cycle each quarter.

### Terraform
Install Terraform: refer to the [Terraform installation documentation](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli)
Please visit <https://www.laprogramucla.com> to see the production website.

### AWS
1. Install AWS CLI: refer to the [AWS CLI installation documentation](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
2. Obtain LA Program's AWS credentials and account (TODO)
## Development Requirements/Tech Stack

- Node.js (preferably LTS)
- Python 3.14

We use:

- Next.js on the frontend deployed through Vercel
- Python on the backend run through AWS Lambdas
- AWS for infrastructure, managed using Terraform

### Frontend/Backend

To develop the app, run:

```bash
cd frontend
npm i
npm run dev
```

This starts a Next.js development server in the `frontend` directory at <http://localhost:3000>. You can see any changes you make in real time here. For more information, including in-depth development patterns, please read [frontend/README.md](frontend/README.md) before proceeding.

To develop API routes, make any changes you wish to make to `backend`, then make a PR targeting `main`. Please refer to [backend/README.md](backend/README.md) for more information on how to access AWS resources in a way that allows for both test and production deployments with the same code.

Once the Github Actions pipelines run, check the PR for a comment with instructions on how to set your environment variables properly to allow your locally hosted app to access a testing version of the API; this will let you test front-end and back-end changes together without affecting production data.

### Infrastructure

Please refer to [terraform/README.md](terraform/README.md) for more information. This should not need to be edited more than roughly once a quarter (for new database deployments).
17 changes: 0 additions & 17 deletions amplify.yml

This file was deleted.

18 changes: 18 additions & 0 deletions backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Backend

## Technical Guide

All back-end API routes are deployed as AWS Lambdas (serverless functions). Each route is associated with exactly one `.py` file. These are served through an HTTP API using API Gateway.

For instance, creating an API on the `/test` route can be accomplished by creating a `test.py` file in the `backend` folder. Thus, each `.py` file needs to parse for HTTP method, etc, individually.

Please read the AWS documentation if you have questions after looking at existing routes. For reference:

- [Defining Python Lambda handlers](https://docs.aws.amazon.com/lambda/latest/dg/python-handler.html)
- [Lambda Payload Documentation](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html) - note: we use format 2.0

## AWS Resource Access

We need to support both production and test deployments on one codebase; this means that unless a resource is global (i.e. shared between production and test deployments), we can not completely hardcode information like database names.

To accomplish this, please: TODO
1 change: 1 addition & 0 deletions frontend/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NEXT_PUBLIC_API_URL=
1 change: 1 addition & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ yarn-error.log*

# env files (can opt-in for committing if needed)
.env*
!.env.example

# vercel
.vercel
Expand Down
50 changes: 30 additions & 20 deletions frontend/README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,46 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
# Frontend

This is a [Next.js](https://nextjs.org/docs) project.

## Technical Guide

We use a subset of Next.js features in order to ease development and reduce cost. These include that we:

- use the App Router
- do not use Vercel for anything other than front-end deployment (all API routes are deployed through Lambdas)
- minimize usage of Next.js Route Handlers
- minimize usage of SSR (server-side rendering) as this app does not require SEO optimization and we wish to minimize requests to Vercel

In addition, we use [shadcn](https://ui.shadcn.com/docs/components) as our component/styling library. We aim to minimize custom styling to ease development.

## Getting Started

First, run the development server:
First, install dependencies.

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
cd frontend
npm i
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
Run the development server:

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
```bash
npm run dev
```

This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

## Learn More
Edit the `page.tsx` files in `/app` to change the site's contents. Please read the codebase and the [Next.js docs](https://nextjs.org/docs) for more information.

To learn more about Next.js, take a look at the following resources:
## API Access

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
> [!WARNING]
> Do not hardcode API routes. Instead, set the `NEXT_PUBLIC_API_ROUTE` environment variable while developing. This ensures your API calls will work on the production deployment as this URL changes between test and production deployments.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
You can get a test API URL by making a PR on Github. More information is in [the root README.md](../README.md).

## Deploy on Vercel
You can set the environment variable by making a copy of `.env.example`, naming it `.env`, and setting the environment variable there. Next.js automatically loads this variable upon starting the development server.

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
## Styling

Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
Use shadcn to add components. Use the `npx` command listed in the component documentation to add it to the project.
29 changes: 0 additions & 29 deletions frontend/app/[slug]/route.ts

This file was deleted.

Loading