vccs
Vue 3용 차트 컴포넌트 모음, Recharts에서 포팅
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Read-only operational dashboard over BigQuery for the EXP programme (Educate!).
FastAPI backend + React 19 / Vite SPA, deployed to DigitalOcean Kubernetes.
--reload can crash on Windows — run without it and restart manually.
Smoke test: curl http://localhost:8000/health, open http://localhost:3000,
API docs at http://localhost:8000/docs.
Env-file footgun: Vite prefers .env.local over .env. Do not create
`frontend/.eREADME 전문 보기 ↗Read-only operational dashboard over BigQuery for the EXP programme (Educate!). FastAPI backend + React 19 / Vite SPA, deployed to DigitalOcean Kubernetes.
educate-data-warehouse-test.gold_exp.exp_ai_dashboard_modelBigQuery (gold_exp.exp_ai_dashboard_model)
↓ service-account key (BigQuery Data Viewer + Job User)
FastAPI backend (Python 3.14) → single replica / single process
│ /api/auth/* email+password or Google SSO → JWT (carries access scope)
│ /api/overview/* CU + school rows, row-level access-scoped
│ /api/cu CU drilldown (school rows)
│ every /api/* needs a valid JWT + the X-Exp-Client header
↓ REST JSON (Bearer JWT + CORS allowlist + X-Exp-Client)
React 19 + Vite SPA (nginx) → single replica
├── CLAUDE.md project conventions (thin)
├── docs/ ONBOARDING · CONTEXT · ARCHITECTURE · DECISION · FLOW
├── .github/workflows/ deploy.yml (digest-pinned) · secret-scan.yml (gitleaks)
├── backend/ FastAPI app (app/core, app/routers, tests)
├── frontend/ React 19 + Vite SPA
├── k8s/ backend + frontend manifests
└── legacy/ dashboard-v1.html — the original single-file app (reference)
--reload can crash on Windows — run without it and restart manually.
# Terminal 1 — backend
cd backend
python -m venv venv; venv\Scripts\Activate.ps1
pip install -r requirements-dev.txt
copy .env.example .env # then fill secrets + BQ config
gcloud auth application-default login # BigQuery as your own Google identity
uvicorn app.main:app --port 8000
# Terminal 2 — frontend
cd frontend
npm install
copy .env.example .env.local # VITE_API_URL=http://localhost:8000
npm run dev
Smoke test: curl http://localhost:8000/health, open http://localhost:3000,
API docs at http://localhost:8000/docs.
Env-file footgun: Vite prefers
.env.localover.env. Do not createfrontend/.env— a stale one has previously made local dev silently hit prod.
Generate secrets: python -c "import secrets; print(secrets.token_hex(32))".
Leave GOOGLE_SERVICE_ACCOUNT_KEY empty and run:
gcloud auth application-default login
gcloud auth application-default set-quota-project educate-data-warehouse-test
The backend then reaches BigQuery as you, under your own IAM grants, and no
service-account key ever lands on the laptop — the SA key is meant to live only
in the k8s Secret (docs/CONTEXT.md). You need BigQuery Data Viewer + Job User
on educate-data-warehouse-test. Setting GOOGLE_SERVICE_ACCOUNT_KEY to a JSON
path still works and still takes precedence; that is how the cluster runs.
backend/.envBQ_PROJECT_ID / BQ_DATASET / BQ_TABLE, JWT_SECRET, DASHBOARD_PASSWORD,
the client-header token, and FRONTEND_URL
(GOOGLE_SERVICE_ACCOUNT_KEY is optional — see above). Google OAuth vars are optional locally (email+password works
without them). See backend/.env.example.
One JWT scheme (HS256, 8h, sessionStorage, Authorization: Bearer). The UI
offers Google SSO as the primary sign-in; the password path is retained as a
hidden break-glass fallback (revealed by a link on the login screen):
@experienceeducate.org) → /api/auth/google/login → Google →
/api/auth/google/callback → redirects to FRONTEND_URL/#token=<jwt> (or
/#error=<code> on failure); the SPA reads the fragment and stores the token.POST /api/auth/login. Also the only
path for the few non-@experienceeducate.org FOA accounts in ACCESS_CONFIG,
which SSO's domain check rejects.Both resolve the email to an access scope (national / regional / cu)
via ACCESS_CONFIG, embedded in the JWT. Row-level filtering is server-side
(core/access.py + core/sql.py::access_clause). Unknown emails get no access.
SSO needs a Google OAuth 2.0 client. In the Google Cloud console for the project:
https://exp-dashboard-api.educateapps.work/api/auth/google/callback (prod)http://localhost:8000/api/auth/google/callback (local dev)GOOGLE_CLIENT_ID /
GOOGLE_CLIENT_SECRET — in the exp-dashboard-credentials k8s Secret for prod,
and backend/.env for local dev. Ensure FRONTEND_URL matches the SPA origin
the callback should return to.The source model is a wide "one-big-table" with a level column (cu /
school). Full metric formulas, RAG thresholds, and the field catalogue are in
docs/METRICS.md (the EXP Dashboard Metrics Reference). See
docs/ARCHITECTURE.md for the grouped field list, docs/FLOW.md for how a
request becomes a scoped BigQuery query, and docs/DROPPED_SECTIONS.md for the
parity gap analysis vs. the legacy dashboard.
Push to main auto-builds changed images and digest-pins the rollout (see
.github/workflows/deploy.yml). k8s manifest changes are applied manually with
kubectl apply — see docs/CONTEXT.md → Deployment for the ordering rules.
cd backend; python -m pytest