Important information for working with this codebase.
CRITICAL: XSLT stylesheets are stored in the Django database, not just as files on disk.
- Detail stylesheet:
xslt/detail_stylesheet.xsl(at repo root) - List stylesheet:
xslt/list_stylesheet.xsl(at repo root)
-
Edit the XSL file in
xslt/ -
Update the database (REQUIRED - changes won't appear otherwise):
# From the deployment directory:
cd deployment
source dev-commands.sh
dev-update-xslt # Updates both detail and list stylesheets
# OR
dev-update-xslt-detail # Updates only detail_stylesheet.xsl
dev-update-xslt-list # Updates only list_stylesheet.xslThe update script (deployment/scripts/update-xslt.sh) automatically:
- Loads the XSL file from the mounted
xslt/directory - Patches the
datasetBaseUrlandpreviewBaseUrlvariables using environment variables - Updates the stylesheet in the Django database
- Verifies the changes were applied
URLs in XSLT are patched from environment variables:
XSLT_DATASET_BASE_URL- Base URL for instrument data filesXSLT_PREVIEW_BASE_URL- Base URL for preview images/metadata
These are configured in your .env file (defaults for development):
XSLT_DATASET_BASE_URL=https://files.nexuslims-dev.localhost/instrument-dataXSLT_PREVIEW_BASE_URL=https://files.nexuslims-dev.localhost/data
- Just editing the file is NOT enough - you must update the database
- The XSLT transforms XML records to HTML for display in the browser
- The init script loads these on initial setup but doesn't auto-reload on changes
- Template files use placeholders:
https://CHANGE.THIS.VALUE - Update script automatically patches URLs based on your
.envconfiguration - For production, update the environment variables to match your production domains
The NexusLIMS XML schema file defines the structure for experiment records in CDCS.
File Location: deployment/schemas/nexus-experiment.xsd
Canonical Source: https://github.com/datasophos/NexusLIMS/blob/main/nexusLIMS/schemas/nexus-experiment.xsd
The schema file is tracked in this repository for self-contained deployments, but the canonical version lives in the main NexusLIMS repository. When the upstream schema is updated, you need to sync it here.
Automatic Update:
cd deployment
bash scripts/update-schema.shThis script:
- Downloads the latest schema from the NexusLIMS repository
- Saves it to
deployment/schemas/nexus-experiment.xsd - Verifies the download was successful
Manual Update:
curl -L -o deployment/schemas/nexus-experiment.xsd \
https://raw.githubusercontent.com/datasophos/NexusLIMS/main/nexusLIMS/schemas/nexus-experiment.xsdAfter updating the schema file, you must update it in the database:
Development Environment:
cd deployment
dev-down && dev-up # Restart to apply changesProduction Environment:
docker exec <container-name> python /srv/scripts/init_environment.py- The schema file is mounted into containers at
/srv/nexuslims/schemas/nexus-experiment.xsd - During initialization,
init_environment.pyreads this file and uploads it to the CDCS database - The database stores the schema for validating and rendering XML records
- Just updating the file on disk doesn't change the database - you must re-run initialization
init_environment.pyis idempotent and safely skips items that already exist
This project uses UV for Python dependency management. UV provides fast, reliable dependency resolution with reproducible builds via lockfiles.
CRITICAL RULES:
- ALWAYS commit
uv.lock- The lockfile ensures reproducible builds across dev, staging, and production - NEVER edit
uv.lockmanually - It's generated frompyproject.tomlviauv lock - Update
pyproject.tomlfirst, then regenerate lockfile - This is the proper workflow - Rebuild Docker after dependency changes - Use
dev-build-cleanto apply changes
pyproject.toml- Single source of truth for all dependencies- Main dependencies: Core application packages (celery, Django, django-redis)
[project.optional-dependencies.core]: CDCS/MDCS packages pinned to2.20.*[project.optional-dependencies.server]: Production servers (psycopg2-binary, uwsgi, gunicorn)
uv.lock- Lockfile with exact versions (MUST be committed).python-version- Required Python version (3.13)
For main application dependencies:
cd /path/to/NexusLIMS-CDCS # Repository root
uv add package-name
# This automatically updates pyproject.toml and uv.lockFor optional group dependencies (manual edit required):
# 1. Edit pyproject.toml manually to add to the appropriate group
# 2. Regenerate lockfile
uv lockApply changes to Docker:
cd deployment
source dev-commands.sh
dev-build-clean # Clean rebuild with new dependencies
dev-up # Start servicesFor local development (outside Docker):
# Install/sync dependencies locally
uv sync
# Or use the convenience alias from deployment directory
cd deployment
source dev-commands.sh
dev-uv-syncUpdate all packages (respecting version constraints):
uv lock --upgradeUpdate a specific package:
uv lock --upgrade-package package-nameIMPORTANT: After updating, commit both pyproject.toml and uv.lock.
CDCS core packages are strictly pinned to 2.20.* for stability. To upgrade to a new CDCS version:
-
Edit
pyproject.toml- Update allcore_*_apppackages to new version:[project.optional-dependencies] core = [ "core_main_app[auth]==2.21.*", # Changed from 2.20.* "core_composer_app==2.21.*", # Changed from 2.20.* # ... update all 21 core packages ]
-
Regenerate lockfile with upgraded packages:
uv lock --upgrade
-
Review changes:
git diff uv.lock # Review what changed -
Test thoroughly in development:
cd deployment dev-build-clean dev-up # Run tests, migrations, verify functionality
-
Commit changes:
git add pyproject.toml uv.lock git commit -m "chore: upgrade CDCS core packages to 2.19.*"
Problem: "Package not found" during Docker build
- Ensure
uv.lockis committed and up to date - Run
uv lockto regenerate lockfile - Check for typos in
pyproject.toml
Problem: Version conflicts
- Review CDCS package version pins in
pyproject.toml - Use
uv lock --upgrade-package package-nameto upgrade specific packages - Check upstream CDCS release notes for compatibility
Problem: Docker build fails after dependency change
- Clear Docker cache:
dev-build-clean - Verify lockfile is committed:
git status - Check Dockerfile syntax if you modified it
The Dockerfile uses native UV commands for optimal performance:
# Copy dependency files (separate layer for caching)
COPY pyproject.toml uv.lock ./
# Install from lockfile (no dependency resolution needed - fast!)
RUN uv sync --frozenFlags explained:
--frozen: Use exact versions from lockfile (fail if lockfile is outdated)
- Speed: 10-100x faster than pip for dependency resolution
- Reproducibility: Lockfile ensures identical builds everywhere
- Modern: Follows Python packaging standards (PEP 621, PEP 631)
- Reliable: Better conflict resolution than pip
- Efficient: Shared cache across projects, parallel downloads
Tests use runtests.py at the repo root, which runs Django tests with an in-memory SQLite database (no Docker or external services required).
# From the repo root, with uv:
uv run python runtests.py
# Or with a local venv:
python runtests.py- Uses
tests/test_settings.pyas the Django settings module - Runs
migrateautomatically before tests (in-memory SQLite) - Discovers and runs all tests in the
tests/directory - Exits with a non-zero code if any tests fail
- Uses an in-memory SQLite database (
:memory:) - no external DB needed - Loads
.envviapython-dotenvif present INSTALLED_APPSincludesnexuslims_annotateandtestsROOT_URLCONFpoints totests.urls
All planning and analysis documents should be stored in this repository, not in the user's home directory:
- Plans: Store in
.claude/plans/folder - Progress tracking: Each plan should have a corresponding progress document in
.claude/plan-progress/
This ensures plans and progress are version-controlled with the codebase and accessible to all developers. Format progress documents as {plan-name}-progress.md to establish a clear relationship with their corresponding plans.