From 3040c7e662f6067f77c6affc2fc144cffda572c0 Mon Sep 17 00:00:00 2001 From: jonathoncontact Date: Mon, 28 Sep 2026 12:33:21 -0700 Subject: [PATCH 1/2] Everything has been changed. backend : backend/config frontend : web/ --- .github/workflows/pr-checks.yml | 3 +- AGENTS.md | 16 ++-- README.md | 20 ++--- backend/config/__init__.py | 0 backend/config/asgi.py | 16 ++++ backend/config/settings.py | 123 ++++++++++++++++++++++++++++++ backend/config/urls.py | 22 ++++++ backend/config/wsgi.py | 16 ++++ backend/manage.py | 22 ++++++ web/index.html | 13 ++++ web/package.json | 6 +- web/src/App.tsx | 34 +++++++++ web/src/main.tsx | 11 +++ web/src/styles.css | 131 ++++++++++++++++++++++++++++++++ web/tsconfig.json | 7 +- web/vite.config.ts | 7 ++ 16 files changed, 422 insertions(+), 25 deletions(-) create mode 100644 backend/config/__init__.py create mode 100644 backend/config/asgi.py create mode 100644 backend/config/settings.py create mode 100644 backend/config/urls.py create mode 100644 backend/config/wsgi.py create mode 100755 backend/manage.py create mode 100644 web/index.html create mode 100644 web/src/App.tsx create mode 100644 web/src/main.tsx create mode 100644 web/src/styles.css create mode 100644 web/vite.config.ts diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index f70fba6..1c6f838 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -13,9 +13,8 @@ jobs: steps: - uses: actions/checkout@v4 - uses: gitleaks/gitleaks-action@v2 - //changed here because github told me... env: - GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} + GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} backend: name: Backend tooling diff --git a/AGENTS.md b/AGENTS.md index c1c7c5f..e264877 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,10 +2,10 @@ ## Current status -`infrastructure_plan.md` is the source of truth. The web-only tooling and Docker -foundation are in place, but production application code has not been created. Do not introduce -pages, routes, API handlers, domain models, authentication, or business data -while performing infrastructure work. +`infrastructure_plan.md` is the source of truth. The web tooling, Vite entrypoint, +Docker foundation, and minimal Django project scaffold are in place. Do not +introduce product pages, API handlers, domain models, authentication, or +business data while performing infrastructure work. ## Repository map @@ -14,10 +14,10 @@ while performing infrastructure work. - `docker/backend.Dockerfile`, `docker-compose.yml`, and `.dockerignore` — Docker tooling and local PostgreSQL only. - `scripts/docker-smoke.sh` — infrastructure-owned smoke test. -- `backend/` — Python dependency/tool configuration and infrastructure-only tests; - no Django application package exists yet. -- `web/` — React/Vite dependency/tool configuration and infrastructure-only tests; - no React application entrypoint exists yet. +- `backend/` — Django project scaffold, Python dependency/tool configuration, and + infrastructure-only tests; no API or business application package exists yet. +- `web/` — React/Vite entrypoint, dependency/tool configuration, and + infrastructure-only tests; no product pages or business UI exists yet. - `.github/workflows/pr-checks.yml` — web-only pull-request quality checks. - `.github/workflows/release.yml` — not created; it requires a selected hosting provider. - `docs/` — not created yet. diff --git a/README.md b/README.md index 76b322c..2f43f7e 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ ## Status -The repository has a web-only development foundation: pinned backend and web -tooling, a local PostgreSQL service, and pull-request checks. No production -Django or React application code exists yet. +The repository has minimal Django and React/Vite application scaffolds, a local +PostgreSQL service, and pull-request checks. No production API, domain models, +or product UI exists yet. ## Repository map @@ -14,10 +14,10 @@ Django or React application code exists yet. readiness health check. - `scripts/docker-smoke.sh` — disposable PostgreSQL readiness and `SELECT 1` smoke test. -- `backend/` — Python/Django tooling, locked dependencies, and infrastructure - probes; no Django project or API code exists yet. -- `web/` — React/Vite tooling, locked dependencies, and infrastructure probes; - no page, component, or Vite entrypoint exists yet. +- `backend/` — minimal Django project scaffold, Python/Django tooling, locked + dependencies, and infrastructure probes; no API or business code exists yet. +- `web/` — React/Vite entrypoint, locked dependencies, infrastructure probes, and + the initial application shell; no product page or business UI exists yet. - `.github/workflows/pr-checks.yml` — web-only infrastructure quality checks. - `.github/dependabot.yml` — weekly dependency-update configuration. - `infrastructure_plan.md` — the approved infrastructure plan and source of @@ -70,9 +70,9 @@ The local database is exposed only on `127.0.0.1:5432` by default. Change `POSTGRES_PORT` in an untracked `.env` if that port is occupied. Reset local database data with `docker compose down --volumes`. -Vite builds and Playwright end-to-end tests are intentionally unavailable until -the future React application supplies an entrypoint and workflows. A production -release workflow is also deferred until a hosting provider is selected. +Playwright end-to-end tests are intentionally deferred until the first product +workflow exists. A production release workflow is also deferred until a hosting +provider is selected. ## Troubleshooting diff --git a/backend/config/__init__.py b/backend/config/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/config/asgi.py b/backend/config/asgi.py new file mode 100644 index 0000000..ed7c431 --- /dev/null +++ b/backend/config/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for config project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.2/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') + +application = get_asgi_application() diff --git a/backend/config/settings.py b/backend/config/settings.py new file mode 100644 index 0000000..ae8d871 --- /dev/null +++ b/backend/config/settings.py @@ -0,0 +1,123 @@ +""" +Django settings for config project. + +Generated by 'django-admin startproject' using Django 5.2.17. + +For more information on this file, see +https://docs.djangoproject.com/en/5.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.2/ref/settings/ +""" + +import os +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = os.environ['DJANGO_SECRET_KEY'] + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = os.environ.get('DJANGO_DEBUG', '').lower() == 'true' + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'config.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'config.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/5.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.2/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.2/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/backend/config/urls.py b/backend/config/urls.py new file mode 100644 index 0000000..35a0802 --- /dev/null +++ b/backend/config/urls.py @@ -0,0 +1,22 @@ +""" +URL configuration for config project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/5.2/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] diff --git a/backend/config/wsgi.py b/backend/config/wsgi.py new file mode 100644 index 0000000..e2fbd58 --- /dev/null +++ b/backend/config/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for config project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') + +application = get_wsgi_application() diff --git a/backend/manage.py b/backend/manage.py new file mode 100755 index 0000000..8e7ac79 --- /dev/null +++ b/backend/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/web/index.html b/web/index.html new file mode 100644 index 0000000..4f19898 --- /dev/null +++ b/web/index.html @@ -0,0 +1,13 @@ + + + + + + + Medcheck + + +
+ + + diff --git a/web/package.json b/web/package.json index 1e69afb..d08e073 100644 --- a/web/package.json +++ b/web/package.json @@ -3,18 +3,20 @@ "version": "0.0.0", "private": true, "packageManager": "pnpm@10.4.1", - "description": "Infrastructure-only web tooling for Medcheck.", + "description": "React web client for Medcheck.", "engines": { "node": ">=22 <23", "pnpm": ">=10 <11" }, "scripts": { + "dev": "vite", "format:check": "prettier --check .", "lint": "eslint . --max-warnings=0", "typecheck": "tsc --noEmit --project tsconfig.json", "test": "jest --coverage", "test:e2e": "playwright test", - "build": "echo 'A Vite build is unavailable until the web application entrypoint is implemented.' >&2; exit 1" + "build": "vite build", + "preview": "vite preview" }, "dependencies": { "react": "^19.0.0", diff --git a/web/src/App.tsx b/web/src/App.tsx new file mode 100644 index 0000000..9fde9d6 --- /dev/null +++ b/web/src/App.tsx @@ -0,0 +1,34 @@ +export function App() { + return ( +
+
+

Personal health workspace

+ + +
+ +
+

Medcheck

+

A clear starting point for your health records.

+

+ The React and Vite foundation is ready. Your first workflow will have + a focused home here once the product details are defined. +

+
+ +
+

Next step

+

Define the first user workflow

+

+ This shell is intentionally small: it proves the browser entrypoint, + styling pipeline, and accessible React mount without inventing + application behavior. +

+
+
+ ); +} diff --git a/web/src/main.tsx b/web/src/main.tsx new file mode 100644 index 0000000..15c5a1c --- /dev/null +++ b/web/src/main.tsx @@ -0,0 +1,11 @@ +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; + +import { App } from "./App"; +import "./styles.css"; + +createRoot(document.getElementById("root")!).render( + + + , +); diff --git a/web/src/styles.css b/web/src/styles.css new file mode 100644 index 0000000..5ed634b --- /dev/null +++ b/web/src/styles.css @@ -0,0 +1,131 @@ +:root { + color: #1f2a27; + background: #f7f5f0; + font-family: + Inter, + ui-sans-serif, + system-ui, + -apple-system, + BlinkMacSystemFont, + "Segoe UI", + sans-serif; + font-synthesis: none; + text-rendering: optimizeLegibility; +} + +* { + box-sizing: border-box; +} + +body { + min-width: 320px; + min-height: 100vh; + margin: 0; +} + +body::before { + position: fixed; + inset: 0; + z-index: -1; + background: radial-gradient(circle at 85% 15%, #dce9df 0, transparent 32rem); + content: ""; +} + +.shell { + width: min(100% - 3rem, 72rem); + margin: 0 auto; + padding: 2rem 0 5rem; +} + +.masthead { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + border-bottom: 1px solid #d9ddd5; + padding-bottom: 1.25rem; +} + +.eyebrow, +.kicker, +.card-label { + margin: 0; + color: #557267; + font-size: 0.75rem; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; +} + +.status { + display: inline-flex; + align-items: center; + gap: 0.5rem; + color: #557267; + font-size: 0.875rem; +} + +.status span { + width: 0.5rem; + height: 0.5rem; + border-radius: 50%; + background: #4d8b69; +} + +.intro { + max-width: 48rem; + padding: clamp(5rem, 15vw, 10rem) 0 4rem; +} + +.intro h1 { + max-width: 13ch; + margin: 1rem 0 1.5rem; + color: #203c34; + font-size: clamp(2.75rem, 7vw, 5.5rem); + font-weight: 650; + letter-spacing: -0.06em; + line-height: 0.98; +} + +.summary { + max-width: 34rem; + margin: 0; + color: #60716b; + font-size: clamp(1rem, 2vw, 1.25rem); + line-height: 1.6; +} + +.next-step { + max-width: 36rem; + border-top: 3px solid #92b49b; + padding: 1.5rem 0 0; +} + +.next-step h2 { + margin: 0.75rem 0; + color: #203c34; + font-size: 1.25rem; + letter-spacing: -0.02em; +} + +.next-step p:last-child { + margin: 0; + color: #60716b; + line-height: 1.6; +} + +@media (max-width: 600px) { + .shell { + width: min(100% - 2rem, 72rem); + padding-top: 1.25rem; + } + + .masthead { + align-items: flex-start; + flex-direction: column; + } + + .intro { + padding-top: 5rem; + } +} diff --git a/web/tsconfig.json b/web/tsconfig.json index 02088a2..3f7c7a1 100644 --- a/web/tsconfig.json +++ b/web/tsconfig.json @@ -1,11 +1,12 @@ { "compilerOptions": { "target": "ES2023", - "module": "NodeNext", - "moduleResolution": "NodeNext", + "module": "ESNext", + "moduleResolution": "Bundler", + "jsx": "react-jsx", "strict": true, "noEmit": true, "skipLibCheck": true }, - "files": ["tests/infrastructure/toolchain.ts"] + "include": ["src", "vite.config.ts", "tests/infrastructure/toolchain.ts"] } diff --git a/web/vite.config.ts b/web/vite.config.ts new file mode 100644 index 0000000..99a600b --- /dev/null +++ b/web/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; + +export default defineConfig({ + server: { + port: 5173, + }, +}); From 1d56935800a2a9328856e8cae405e4b0fb7caddd Mon Sep 17 00:00:00 2001 From: jonathoncontact Date: Mon, 28 Sep 2026 12:48:04 -0700 Subject: [PATCH 2/2] codex fixed? --- .github/workflows/pr-checks.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 1c6f838..cedd849 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -59,13 +59,12 @@ jobs: working-directory: web steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: pnpm/action-setup@v4 with: - node-version: 22.14.0 - - name: Enable Corepack - run: corepack enable + version: 10.4.1 - uses: actions/setup-node@v4 with: + node-version: 22.14.0 cache: pnpm cache-dependency-path: web/pnpm-lock.yaml - name: Install locked dependencies