Week 8 of 16

Stretch Goals & Feature Ideas

You've shipped Phase 1. Here's what Phase 2 could look like — pick one thing and build it.

Day 39 60 minutes Build (optional)

Day 39 of 80

You've Shipped Phase 1

Take a moment to recognize what you've built in 8 weeks:

This is a real tool. Today is about extending it — but only the feature that would genuinely make it more useful for you.

Pick One

Do not try to build all six features below. Pick the single feature you would actually use. Build just that. Finish it. One complete feature is worth more than five half-built ones.

Optional Features to Add

Feature 1: Prompt Tags

Add a tags array to each prompt, then filter the library by tag. This makes the vault useful as it grows beyond 30-40 prompts.

Data structure change — prompts.json JSON
{
  "platform": "Kling",
  "shot": "aerial establishing shot",
  "prompt": "Wide drone shot ascending over misty mountains...",
  "tags": ["aerial", "establishing", "nature"],
  "created_at": "2025-01-15T10:30:00"
}

Add a tags input to the generation form. Split by commas: tags = request.form.get("tags", "").split(","). In the template, show clickable tag badges that trigger a filter by tag.

Feature 2: Favorites

Add a favorited boolean field to each prompt. A star button toggles it. A "Favorites Only" filter shows just favorited prompts.

vault.py — favorite toggle route Python
@app.route("/favorite/<int:index>", methods=["POST"])
def toggle_favorite(index):
    prompts = load_prompts()
    if 0 <= index < len(prompts):
        current = prompts[index].get("favorited", False)
        prompts[index]["favorited"] = not current
        save_prompts(prompts)
    return redirect(url_for("index"))

In the template, add a small form button for each prompt: a star (★/☆) that POSTs to this route. The favorited value determines which star you show.

Feature 3: Bulk Export

A route that returns all prompts as a downloadable .txt file — useful for copying into video production docs or sharing with collaborators.

vault.py — export route Python
from flask import Response

@app.route("/export")
def export_prompts():
    prompts = load_prompts()
    lines = []
    for i, p in enumerate(prompts, 1):
        lines.append(f"--- Prompt {i} ---")
        lines.append(f"Platform: {p['platform']}")
        lines.append(f"Shot:     {p['shot']}")
        lines.append(f"Prompt:   {p['prompt']}")
        lines.append("")

    content = "\n".join(lines)
    return Response(
        content,
        mimetype="text/plain",
        headers={"Content-Disposition": "attachment; filename=prompt-vault-export.txt"}
    )

The Content-Disposition: attachment header tells the browser to download the file rather than display it. Add an "Export All" button to your template pointing to /export.

Feature 4: Prompt Editing

Add an edit route that loads a single prompt into a pre-filled form, then saves the changes back to the same index position.

vault.py — edit route sketch Python
@app.route("/edit/<int:index>", methods=["GET", "POST"])
def edit_prompt(index):
    prompts = load_prompts()
    prompt = prompts[index]

    if request.method == "POST":
        prompts[index]["prompt"] = request.form.get("prompt_text")
        prompts[index]["shot"]   = request.form.get("shot")
        save_prompts(prompts)
        return redirect(url_for("index"))

    return render_template("edit.html", prompt=prompt, index=index)

You'll need a new template edit.html with a form pre-populated with {{ prompt.shot }} and {{ prompt.prompt }}. The GET loads the form; the POST saves it.

Feature 5: Stats Dashboard

A simple stats page showing a breakdown of prompts by platform. You can render this with a basic HTML bar chart or use Chart.js for something visual.

vault.py — stats route Python
@app.route("/stats")
def stats():
    prompts = load_prompts()
    counts = {}
    for p in prompts:
        platform = p.get("platform", "Unknown")
        counts[platform] = counts.get(platform, 0) + 1

    total = len(prompts)
    return render_template("stats.html", counts=counts, total=total)

In the template, loop over counts.items() to show platform names and counts. For Chart.js, pass the data as JSON and let JavaScript render the chart. This is a great introduction to passing data from Python to a frontend library.

Feature 6: Multi-User Support (Advanced Preview)

Adding real user accounts requires Flask-Login — a library you'll cover in Week 12. For now, you could add basic HTTP Basic Auth as a simple password gate, or just note this as a future milestone.

Simple password protection — not production-grade Python
from functools import wraps
from flask import request, Response

def require_auth(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        auth = request.authorization
        if not auth or auth.password != os.environ.get("APP_PASSWORD"):
            return Response("Unauthorized", 401,
                {"WWW-Authenticate": 'Basic realm="Prompt Vault"'})
        return f(*args, **kwargs)
    return decorated

# Then decorate your index route:
@app.route("/")
@require_auth
def index(): ...

This is a decorator pattern — Python wrapping a function with extra behavior. You'll study decorators formally in Week 10. This is a sneak peek at how Flask uses them.

How to Tackle Any Feature

The Feature-Building Process
  1. Plan on paper first. What does the user do? What data is involved? What route handles it?
  2. Identify the route. Is it GET (display something) or POST (change something)?
  3. Write the route in vault.py first. Hard-code the return value to confirm the route works.
  4. Build the template. Get the HTML right before worrying about dynamic data.
  5. Wire them together. Replace hardcoded values with template variables. Test the full flow.

End of Day Checklist

Tomorrow

Day 40 is a reflection day — no new code. You'll look back at where you started and forward at what Part 2 brings. It's also a good day to write down what you'd do differently if you rebuilt the Prompt Vault from scratch with everything you now know.