Documentation navigation

Project Generation Pipeline

This page explains how Djass turns user input into a generated project zip.

For the architectural tradeoffs behind that worker setup, read Django Background Tasks: Choose a Queue.

End-to-end flow

  1. User submits the project creation form.
  2. Backend validates input via ProjectCreateForm.
  3. A Project row is created with status=queued and saved payload.
  4. Background task generate_project_artifact is enqueued.
  5. Worker runs Cookiecutter against the bundled starter/ template (or the COOKIECUTTER_TEMPLATE_PATH override) straight from disk, with no clone step.
  6. Generated directory is zipped and stored as ProjectArtifact.
  7. Project status becomes ready (or failed with error details).
  8. User downloads artifact from the dashboard.

Key models

  • Project tracks generation status and input payload.
  • ProjectArtifact stores 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_message with actionable diagnostics for user feedback.

Generated metadata + manifest specification

project-metadata.json

Stable JSON object with:

  • metadata_version
  • project_id
  • project_name
  • project_slug
  • generator_version
  • timestamps (created_at, started_at, finished_at)
  • module_flags (all generator toggles)

djass-manifest.json

Retrieval-oriented JSON object with:

  • manifest_version
  • kind (djass-cookiecutter-generation)
  • generator (name, cookiecutter_version, template; template is django-saas-starter for the bundled template, never a filesystem path)
  • project (id, name, slug)
  • metadata_file (pointer to project-metadata.json)
  • input_payload (normalized payload used for generation)
  • module_flags
  • top_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_PATH controls which template is used. It defaults to the starter/ directory in the Djass repository.
  • MEDIA_ROOT and 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.