Project Generation Pipeline
This page explains how Djass turns user input into a generated project zip.
End-to-end flow
- User submits the project creation form.
- Backend validates input via
ProjectCreateForm. - A
Projectrow is created withstatus=queuedand saved payload. - Background task
generate_project_artifactis enqueued. - Worker runs Cookiecutter using
COOKIECUTTER_TEMPLATE_PATH. - Generated directory is zipped and stored as
ProjectArtifact. - Project status becomes
ready(orfailedwith error details). - User downloads artifact from the dashboard.
Key models
Projecttracks generation status and input payload.ProjectArtifactstores generated zip metadata and file.
Both live in apps/core/models.py.
Key implementation points
- Generation is asynchronous by design to avoid blocking web requests.
- Input payload is normalized against known template defaults before generation (stable key set and deterministic defaults).
- Cookiecutter Python API is attempted first, then CLI fallback is used.
- Every generated project includes:
project-metadata.json(standardized metadata envelope),djass-manifest.json(retrieval-friendly manifest for agents/tools).- ZIP packaging is deterministic (sorted traversal + fixed archive timestamps) to reduce output drift.
- Artifacts include SHA-256 and size for integrity and traceability.
- Failures are persisted on
Project.error_messagewith actionable diagnostics for user feedback.
Generated metadata + manifest specification
project-metadata.json
Stable JSON object with:
metadata_versionproject_idproject_nameproject_sluggenerator_versiontimestamps(created_at,started_at,finished_at)module_flags(all generator toggles)
djass-manifest.json
Retrieval-oriented JSON object with:
manifest_versionkind(djass-cookiecutter-generation)generator(name,cookiecutter_version,template)project(id,name,slug)metadata_file(pointer toproject-metadata.json)input_payload(normalized payload used for generation)module_flagstop_level_paths(sorted file/directory names at repository root)timestamps(created_at,started_at,finished_at)
Intentional nondeterminism
The generated output is structurally deterministic for the same normalized payload, but some values remain intentionally time-varying:
- lifecycle timestamps in metadata/manifest (
started_at,finished_at), - project identity fields (
project_id) tied to database rows.
These are preserved for auditability and troubleshooting. Determinism is enforced on payload normalization, manifest shape, module flags, and archive structure.
Configuration knobs
COOKIECUTTER_TEMPLATE_PATHcontrols which template is used.MEDIA_ROOTand storage backend determine where artifacts are stored.- Redis + Q2 config control background execution.
Extension points
Common customizations:
- add more form fields and include them in payload mapping,
- add validation rules for product-specific constraints,
- post-process generated projects before zipping,
- run security/quality checks on generated output before marking ready.