Course EN
← back to chapter

Draft a README

Paste a one-paragraph description of a project. Get back a README skeleton

Showcase — Draft a README

Paste a one-paragraph description of a project. Get back a README skeleton in Markdown with sections What, Install, Usage, License. One API call, one useful artefact you can drop into a new repo.

Run

bash bootstrap-secrets.sh              # reads ../../../../.env, writes secrets/
docker compose up --build              # default: PROVIDER=openai

Open http://localhost:3000.

To run against Gemini instead:

PROVIDER=gemini docker compose up --build

What's where

  • backend/ai_openai.py — the OpenAI call
  • backend/ai_gemini.py — the Gemini call
  • backend/main.py — identical FastAPI loader
  • frontend/app/page.tsx — textarea + result <pre> for Markdown
  • docker-compose.yml — two services, secrets mounted from ./secrets/

Stop

docker compose down

Ejecútalo en tu máquina

Descarga el proyecto como ZIP y córrelo con Docker. Levanta un backend FastAPI y un frontend Next.js en localhost:3000.

Descargar draft-readme.zip

unzip draft-readme.zip
cd draft-readme
bash bootstrap-secrets.sh   # one-time: pulls API keys into ./secrets
docker compose up --build   # default provider: openai
# or:  PROVIDER=gemini docker compose up --build

Escribe algo, elige un proveedor y ejecuta el mismo código de Código contra la API real. Requiere iniciar sesión.


  

Los mismos módulos que ejecuta el botón Run. El proyecto completo (frontend, Dockerfile, compose) está en el ZIP, pestaña README.

backend/ai_openai.py

"""Week 1 - Showcase 3 (OpenAI): draft a README skeleton.

Reader pastes a one-paragraph project description; gets back a README in
Markdown with sections What, Install, Usage, License. One API call.
"""
from openai import OpenAI

_client = OpenAI()


def run(description: str) -> str:
    prompt = (
        "Given the project description below, write a concise README in Markdown "
        "with these exact top-level sections (in this order): What, Install, "
        "Usage, License. Use sensible placeholder commands when specifics are "
        "missing. Return only the Markdown body; do not wrap it in fences."
        f"\n\n---\n{description}\n---"
    )
    # Cap the response so the model can't run away on us. 2048 tokens
    # is roughly 6k characters — enough for a tight four-section README.
    response = _client.responses.create(
        model="gpt-5.4-nano", input=prompt, max_output_tokens=2048,
    )
    return response.output_text

backend/ai_gemini.py

"""Week 1 - Showcase 3 (Gemini): draft a README skeleton."""
import os

from google import genai
from google.genai import types

_client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])


def run(description: str) -> str:
    prompt = (
        "Given the project description below, write a concise README in Markdown "
        "with these exact top-level sections (in this order): What, Install, "
        "Usage, License. Use sensible placeholder commands when specifics are "
        "missing. Return only the Markdown body; do not wrap it in fences."
        f"\n\n---\n{description}\n---"
    )
    # Cap the response so the model can't run away on us. 2048 tokens
    # is roughly 6k characters — enough for a tight four-section README.
    response = _client.models.generate_content(
        model="gemini-3.1-flash-lite", contents=prompt,
        config=types.GenerateContentConfig(max_output_tokens=2048),
    )
    return response.text

Archivos del proyecto

  • .gitignore
  • README.md
  • backend/Dockerfile
  • backend/ai_gemini.py
  • backend/ai_openai.py
  • backend/main.py
  • backend/requirements.txt
  • bootstrap-secrets.sh
  • docker-compose.yml
  • frontend/Dockerfile
  • frontend/app/layout.tsx
  • frontend/app/page.tsx
  • frontend/next.config.ts
  • frontend/package.json
  • frontend/tsconfig.json