diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
deleted file mode 100644
index 50bde36072..0000000000
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-blank_issues_enabled: false
-contact_links:
- - name: Security Contact
- about: Please report security vulnerabilities to security@tiangolo.com
- - name: Question or Problem
- about: Ask a question or ask about a problem in GitHub Discussions.
- url: https://github.com/fastapi/full-stack-fastapi-template/discussions/categories/questions
- - name: Feature Request
- about: To suggest an idea or ask about a feature, please start with a question saying what you would like to achieve. There might be a way to do it already.
- url: https://github.com/fastapi/full-stack-fastapi-template/discussions/categories/questions
diff --git a/.github/ISSUE_TEMPLATE/privileged.yml b/.github/ISSUE_TEMPLATE/privileged.yml
deleted file mode 100644
index 6438848c83..0000000000
--- a/.github/ISSUE_TEMPLATE/privileged.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-name: Privileged
-description: You are @tiangolo or he asked you directly to create an issue here. If not, check the other options. 👇
-body:
- - type: markdown
- attributes:
- value: |
- Thanks for your interest in this project! 🚀
-
- If you are not @tiangolo or he didn't ask you directly to create an issue here, please start the conversation in a [Question in GitHub Discussions](https://github.com/tiangolo/full-stack-fastapi-template/discussions/categories/questions) instead.
- - type: checkboxes
- id: privileged
- attributes:
- label: Privileged issue
- description: Confirm that you are allowed to create an issue here.
- options:
- - label: I'm @tiangolo or he asked me directly to create an issue here.
- required: true
- - type: textarea
- id: content
- attributes:
- label: Issue Content
- description: Add the content of the issue here.
diff --git a/.github/workflows/README.MD b/.github/workflows/README.MD
new file mode 100644
index 0000000000..7e97cdf01d
--- /dev/null
+++ b/.github/workflows/README.MD
@@ -0,0 +1,9 @@
+
+
+# Workflows (portfolio)
+
+Workflows del portfolio:
+- ci.yml: se ejecuta en Pull Requests
+- cd.yml: deploy automático al mergear a main
+
+Se construyen de forma incremental.
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000000..180c63b5a4
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,37 @@
+name: CI
+
+on:
+ pull_request:
+ branches: [ "main" ]
+ push:
+ branches: [ "main" ]
+
+jobs:
+ docker-build:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ strategy:
+ fail-fast: false
+ matrix:
+ service:
+ - name: backend
+ context: ./backend
+ - name: frontend
+ context: ./frontend
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Build ${{ matrix.service.name }}
+ uses: docker/build-push-action@v6
+ with:
+ context: ${{ matrix.service.context }}
+ push: false
+ tags: devops-portfolio/${{ matrix.service.name }}:ci
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
diff --git a/.github/workflows/add-to-project.yml b/.github/workflows_upstream/add-to-project.yml
similarity index 100%
rename from .github/workflows/add-to-project.yml
rename to .github/workflows_upstream/add-to-project.yml
diff --git a/.github/workflows/deploy-production.yml b/.github/workflows_upstream/deploy-production.yml
similarity index 100%
rename from .github/workflows/deploy-production.yml
rename to .github/workflows_upstream/deploy-production.yml
diff --git a/.github/workflows/deploy-staging.yml b/.github/workflows_upstream/deploy-staging.yml
similarity index 100%
rename from .github/workflows/deploy-staging.yml
rename to .github/workflows_upstream/deploy-staging.yml
diff --git a/.github/workflows/detect-conflicts.yml b/.github/workflows_upstream/detect-conflicts.yml
similarity index 100%
rename from .github/workflows/detect-conflicts.yml
rename to .github/workflows_upstream/detect-conflicts.yml
diff --git a/.github/workflows/generate-client.yml b/.github/workflows_upstream/generate-client.yml
similarity index 100%
rename from .github/workflows/generate-client.yml
rename to .github/workflows_upstream/generate-client.yml
diff --git a/.github/workflows/issue-manager.yml b/.github/workflows_upstream/issue-manager.yml
similarity index 100%
rename from .github/workflows/issue-manager.yml
rename to .github/workflows_upstream/issue-manager.yml
diff --git a/.github/workflows/labeler.yml b/.github/workflows_upstream/labeler.yml
similarity index 100%
rename from .github/workflows/labeler.yml
rename to .github/workflows_upstream/labeler.yml
diff --git a/.github/workflows/latest-changes.yml b/.github/workflows_upstream/latest-changes.yml
similarity index 100%
rename from .github/workflows/latest-changes.yml
rename to .github/workflows_upstream/latest-changes.yml
diff --git a/.github/workflows/playwright.yml b/.github/workflows_upstream/playwright.yml
similarity index 100%
rename from .github/workflows/playwright.yml
rename to .github/workflows_upstream/playwright.yml
diff --git a/.github/workflows/pre-commit.yml b/.github/workflows_upstream/pre-commit.yml
similarity index 100%
rename from .github/workflows/pre-commit.yml
rename to .github/workflows_upstream/pre-commit.yml
diff --git a/.github/workflows/smokeshow.yml b/.github/workflows_upstream/smokeshow.yml
similarity index 100%
rename from .github/workflows/smokeshow.yml
rename to .github/workflows_upstream/smokeshow.yml
diff --git a/.github/workflows/test-backend.yml b/.github/workflows_upstream/test-backend.yml
similarity index 100%
rename from .github/workflows/test-backend.yml
rename to .github/workflows_upstream/test-backend.yml
diff --git a/.github/workflows/test-docker-compose.yml b/.github/workflows_upstream/test-docker-compose.yml
similarity index 100%
rename from .github/workflows/test-docker-compose.yml
rename to .github/workflows_upstream/test-docker-compose.yml
diff --git a/README.md b/README.md
index a9049b4779..634b76b5d8 100644
--- a/README.md
+++ b/README.md
@@ -1,233 +1,44 @@
-# Full Stack FastAPI Template
-
-
-
-
-
-## Technology Stack and Features
-
-- ⚡ [**FastAPI**](https://fastapi.tiangolo.com) for the Python backend API.
- - 🧰 [SQLModel](https://sqlmodel.tiangolo.com) for the Python SQL database interactions (ORM).
- - 🔍 [Pydantic](https://docs.pydantic.dev), used by FastAPI, for the data validation and settings management.
- - 💾 [PostgreSQL](https://www.postgresql.org) as the SQL database.
-- 🚀 [React](https://react.dev) for the frontend.
- - 💃 Using TypeScript, hooks, [Vite](https://vitejs.dev), and other parts of a modern frontend stack.
- - 🎨 [Tailwind CSS](https://tailwindcss.com) and [shadcn/ui](https://ui.shadcn.com) for the frontend components.
- - 🤖 An automatically generated frontend client.
- - 🧪 [Playwright](https://playwright.dev) for End-to-End testing.
- - 🦇 Dark mode support.
-- 🐋 [Docker Compose](https://www.docker.com) for development and production.
-- 🔒 Secure password hashing by default.
-- 🔑 JWT (JSON Web Token) authentication.
-- 📫 Email based password recovery.
-- 📬 [Mailcatcher](https://mailcatcher.me) for local email testing during development.
-- ✅ Tests with [Pytest](https://pytest.org).
-- 📞 [Traefik](https://traefik.io) as a reverse proxy / load balancer.
-- 🚢 Deployment instructions using Docker Compose, including how to set up a frontend Traefik proxy to handle automatic HTTPS certificates.
-- 🏭 CI (continuous integration) and CD (continuous deployment) based on GitHub Actions.
-
-### Dashboard Login
-
-[](https://github.com/fastapi/full-stack-fastapi-template)
-
-### Dashboard - Admin
-
-[](https://github.com/fastapi/full-stack-fastapi-template)
-
-### Dashboard - Items
-
-[](https://github.com/fastapi/full-stack-fastapi-template)
-
-### Dashboard - Dark Mode
-
-[](https://github.com/fastapi/full-stack-fastapi-template)
-
-### Interactive API Documentation
-
-[](https://github.com/fastapi/full-stack-fastapi-template)
-
-## How To Use It
-
-You can **just fork or clone** this repository and use it as is.
-
-✨ It just works. ✨
-
-### How to Use a Private Repository
-
-If you want to have a private repository, GitHub won't allow you to simply fork it as it doesn't allow changing the visibility of forks.
-
-But you can do the following:
-
-- Create a new GitHub repo, for example `my-full-stack`.
-- Clone this repository manually, set the name with the name of the project you want to use, for example `my-full-stack`:
-
-```bash
-git clone git@github.com:fastapi/full-stack-fastapi-template.git my-full-stack
-```
-
-- Enter into the new directory:
-
-```bash
-cd my-full-stack
-```
-
-- Set the new origin to your new repository, copy it from the GitHub interface, for example:
-
-```bash
-git remote set-url origin git@github.com:octocat/my-full-stack.git
-```
-
-- Add this repo as another "remote" to allow you to get updates later:
-
-```bash
-git remote add upstream git@github.com:fastapi/full-stack-fastapi-template.git
-```
-
-- Push the code to your new repository:
-
-```bash
-git push -u origin master
-```
-
-### Update From the Original Template
-
-After cloning the repository, and after doing changes, you might want to get the latest changes from this original template.
-
-- Make sure you added the original repository as a remote, you can check it with:
-
-```bash
-git remote -v
-
-origin git@github.com:octocat/my-full-stack.git (fetch)
-origin git@github.com:octocat/my-full-stack.git (push)
-upstream git@github.com:fastapi/full-stack-fastapi-template.git (fetch)
-upstream git@github.com:fastapi/full-stack-fastapi-template.git (push)
-```
-
-- Pull the latest changes without merging:
-
-```bash
-git pull --no-commit upstream master
-```
-
-This will download the latest changes from this template without committing them, that way you can check everything is right before committing.
-
-- If there are conflicts, solve them in your editor.
-
-- Once you are done, commit the changes:
-
-```bash
-git merge --continue
-```
-
-### Configure
-
-You can then update configs in the `.env` files to customize your configurations.
-
-Before deploying it, make sure you change at least the values for:
-
-- `SECRET_KEY`
-- `FIRST_SUPERUSER_PASSWORD`
-- `POSTGRES_PASSWORD`
-
-You can (and should) pass these as environment variables from secrets.
-
-Read the [deployment.md](./deployment.md) docs for more details.
-
-### Generate Secret Keys
-
-Some environment variables in the `.env` file have a default value of `changethis`.
-
-You have to change them with a secret key, to generate secret keys you can run the following command:
-
-```bash
-python -c "import secrets; print(secrets.token_urlsafe(32))"
-```
-
-Copy the content and use that as password / secret key. And run that again to generate another secure key.
-
-## How To Use It - Alternative With Copier
-
-This repository also supports generating a new project using [Copier](https://copier.readthedocs.io).
-
-It will copy all the files, ask you configuration questions, and update the `.env` files with your answers.
-
-### Install Copier
-
-You can install Copier with:
-
-```bash
-pip install copier
-```
-
-Or better, if you have [`pipx`](https://pipx.pypa.io/), you can run it with:
-
-```bash
-pipx install copier
-```
-
-**Note**: If you have `pipx`, installing copier is optional, you could run it directly.
-
-### Generate a Project With Copier
-
-Decide a name for your new project's directory, you will use it below. For example, `my-awesome-project`.
-
-Go to the directory that will be the parent of your project, and run the command with your project's name:
-
-```bash
-copier copy https://github.com/fastapi/full-stack-fastapi-template my-awesome-project --trust
-```
-
-If you have `pipx` and you didn't install `copier`, you can run it directly:
-
-```bash
-pipx run copier copy https://github.com/fastapi/full-stack-fastapi-template my-awesome-project --trust
-```
-
-**Note** the `--trust` option is necessary to be able to execute a [post-creation script](https://github.com/fastapi/full-stack-fastapi-template/blob/master/.copier/update_dotenv.py) that updates your `.env` files.
-
-### Input Variables
-
-Copier will ask you for some data, you might want to have at hand before generating the project.
-
-But don't worry, you can just update any of that in the `.env` files afterwards.
-
-The input variables, with their default values (some auto generated) are:
-
-- `project_name`: (default: `"FastAPI Project"`) The name of the project, shown to API users (in .env).
-- `stack_name`: (default: `"fastapi-project"`) The name of the stack used for Docker Compose labels and project name (no spaces, no periods) (in .env).
-- `secret_key`: (default: `"changethis"`) The secret key for the project, used for security, stored in .env, you can generate one with the method above.
-- `first_superuser`: (default: `"admin@example.com"`) The email of the first superuser (in .env).
-- `first_superuser_password`: (default: `"changethis"`) The password of the first superuser (in .env).
-- `smtp_host`: (default: "") The SMTP server host to send emails, you can set it later in .env.
-- `smtp_user`: (default: "") The SMTP server user to send emails, you can set it later in .env.
-- `smtp_password`: (default: "") The SMTP server password to send emails, you can set it later in .env.
-- `emails_from_email`: (default: `"info@example.com"`) The email account to send emails from, you can set it later in .env.
-- `postgres_password`: (default: `"changethis"`) The password for the PostgreSQL database, stored in .env, you can generate one with the method above.
-- `sentry_dsn`: (default: "") The DSN for Sentry, if you are using it, you can set it later in .env.
-
-## Backend Development
-
-Backend docs: [backend/README.md](./backend/README.md).
-
-## Frontend Development
-
-Frontend docs: [frontend/README.md](./frontend/README.md).
-
-## Deployment
-
-Deployment docs: [deployment.md](./deployment.md).
-
-## Development
-
-General development docs: [development.md](./development.md).
-
-This includes using Docker Compose, custom local domains, `.env` configurations, etc.
-
-## Release Notes
-
-Check the file [release-notes.md](./release-notes.md).
-
-## License
-
-The Full Stack FastAPI Template is licensed under the terms of the MIT license.
+# DevOps Portfolio — FastAPI Template (Docker + Kubernetes + CI/CD + AWS)
+
+Este repositorio es un **portfolio personal DevOps/Cloud**. El objetivo es demostrar prácticas modernas de:
+- Docker
+- Kubernetes (kind en local / k3s en AWS EC2 — **sin EKS**)
+- CI/CD con GitHub Actions
+- Deploy automático al mergear Pull Requests
+
+> La aplicación se utiliza como base open-source. El foco principal es infraestructura, automatización y despliegue.
+
+## Qué vas a encontrar acá
+- `docs/`: arquitectura, decisiones técnicas y guías de ejecución
+- `k8s/portfolio/`: manifiestos Kubernetes creados como parte del portfolio
+- `.github/workflows/`: pipelines del portfolio (CI y CD)
+
+## Arquitectura (resumen)
+- **Local (Docker):** ejecución reproducible con Docker/Compose
+- **Local (Kubernetes):** cluster kind + manifests del portfolio
+- **AWS:** instancia EC2 corriendo k3s + Nginx Ingress Controller
+- **CI/CD:** GitHub Actions:
+ - CI en Pull Requests
+ - CD al mergear a `main`
+
+## Cómo ejecutarlo
+- Local con Docker: ver `docs/runbooks/local-docker.md`
+- Kubernetes local (kind): ver `docs/runbooks/kind.md`
+- AWS (EC2 + k3s): ver `docs/runbooks/aws-k3s.md`
+
+## Skills DevOps demostradas
+- Containerización y buenas prácticas Docker
+- Deploy y troubleshooting en Kubernetes
+- Automatización CI/CD con GitHub Actions
+- Deploy automático a infraestructura en AWS (sin EKS)
+- Documentación técnica orientada a entrevistas
+
+## Roadmap
+- [X] Phase 1: Docker baseline
+- [ ] Phase 2: Kubernetes local (kind)
+- [ ] Phase 3: CI/CD
+- [ ] Phase 4: AWS EC2 + k3s deploy
+
+---
+
+📌 Autor: AlfreMu
diff --git a/docker-compose.portfolio.yml b/docker-compose.portfolio.yml
new file mode 100644
index 0000000000..e030357e34
--- /dev/null
+++ b/docker-compose.portfolio.yml
@@ -0,0 +1,49 @@
+services:
+ db:
+ image: postgres:17
+ restart: unless-stopped
+ environment:
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changethis}
+ POSTGRES_USER: ${POSTGRES_USER:-postgres}
+ POSTGRES_DB: ${POSTGRES_DB:-app}
+ volumes:
+ - db-data:/var/lib/postgresql/data
+ ports:
+ - "5432:5432"
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
+ interval: 10s
+ timeout: 5s
+ retries: 5
+
+ backend:
+ build:
+ context: ./backend
+ restart: unless-stopped
+ env_file:
+ - .env
+ depends_on:
+ db:
+ condition: service_healthy
+ ports:
+ - "8000:8000"
+
+ frontend:
+ build:
+ context: ./frontend
+ restart: unless-stopped
+ depends_on:
+ - backend
+ ports:
+ - "5173:80"
+
+ adminer:
+ image: adminer
+ restart: unless-stopped
+ depends_on:
+ - db
+ ports:
+ - "8080:8080"
+
+volumes:
+ db-data:
diff --git a/docs/arquitectura.md b/docs/arquitectura.md
new file mode 100644
index 0000000000..10f5335409
--- /dev/null
+++ b/docs/arquitectura.md
@@ -0,0 +1,10 @@
+# Arquitectura (Portfolio DevOps)
+
+Este repositorio se utiliza como portfolio profesional DevOps/Cloud.
+
+Objetivo del proyecto:
+- Flujo local con Docker (reproducible)
+- Flujo local con Kubernetes (kind)
+- CI/CD con GitHub Actions
+- Deploy automático al hacer merge a main hacia AWS (EC2 + k3s, sin EKS)
+
diff --git a/docs/decisiones.md b/docs/decisiones.md
new file mode 100644
index 0000000000..cb8288d849
--- /dev/null
+++ b/docs/decisiones.md
@@ -0,0 +1,14 @@
+# Decisiones técnicas
+
+## 0001 - App base: template open-source (código secundario)
+Se utiliza una aplicación open-source existente como base.
+
+**El foco del repositorio es la infraestructura, automatización y despliegue (prácticas DevOps).**
+
+## 0002 - Kubernetes: kind en local, k3s en AWS EC2 (sin EKS)
+Se eligen alternativas livianas para mantener el alcance terminable y ejecutable, evitando complejidad innecesaria.
+
+## 0003 - CI/CD con GitHub Actions
+Se utiliza GitHub Actions para:
+- CI en Pull Requests (checks de calidad)
+- CD al mergear a main (deploy automático)
diff --git a/docs/docstream/README-fastapi-template.md b/docs/docstream/README-fastapi-template.md
new file mode 100644
index 0000000000..a9049b4779
--- /dev/null
+++ b/docs/docstream/README-fastapi-template.md
@@ -0,0 +1,233 @@
+# Full Stack FastAPI Template
+
+
+
+
+
+## Technology Stack and Features
+
+- ⚡ [**FastAPI**](https://fastapi.tiangolo.com) for the Python backend API.
+ - 🧰 [SQLModel](https://sqlmodel.tiangolo.com) for the Python SQL database interactions (ORM).
+ - 🔍 [Pydantic](https://docs.pydantic.dev), used by FastAPI, for the data validation and settings management.
+ - 💾 [PostgreSQL](https://www.postgresql.org) as the SQL database.
+- 🚀 [React](https://react.dev) for the frontend.
+ - 💃 Using TypeScript, hooks, [Vite](https://vitejs.dev), and other parts of a modern frontend stack.
+ - 🎨 [Tailwind CSS](https://tailwindcss.com) and [shadcn/ui](https://ui.shadcn.com) for the frontend components.
+ - 🤖 An automatically generated frontend client.
+ - 🧪 [Playwright](https://playwright.dev) for End-to-End testing.
+ - 🦇 Dark mode support.
+- 🐋 [Docker Compose](https://www.docker.com) for development and production.
+- 🔒 Secure password hashing by default.
+- 🔑 JWT (JSON Web Token) authentication.
+- 📫 Email based password recovery.
+- 📬 [Mailcatcher](https://mailcatcher.me) for local email testing during development.
+- ✅ Tests with [Pytest](https://pytest.org).
+- 📞 [Traefik](https://traefik.io) as a reverse proxy / load balancer.
+- 🚢 Deployment instructions using Docker Compose, including how to set up a frontend Traefik proxy to handle automatic HTTPS certificates.
+- 🏭 CI (continuous integration) and CD (continuous deployment) based on GitHub Actions.
+
+### Dashboard Login
+
+[](https://github.com/fastapi/full-stack-fastapi-template)
+
+### Dashboard - Admin
+
+[](https://github.com/fastapi/full-stack-fastapi-template)
+
+### Dashboard - Items
+
+[](https://github.com/fastapi/full-stack-fastapi-template)
+
+### Dashboard - Dark Mode
+
+[](https://github.com/fastapi/full-stack-fastapi-template)
+
+### Interactive API Documentation
+
+[](https://github.com/fastapi/full-stack-fastapi-template)
+
+## How To Use It
+
+You can **just fork or clone** this repository and use it as is.
+
+✨ It just works. ✨
+
+### How to Use a Private Repository
+
+If you want to have a private repository, GitHub won't allow you to simply fork it as it doesn't allow changing the visibility of forks.
+
+But you can do the following:
+
+- Create a new GitHub repo, for example `my-full-stack`.
+- Clone this repository manually, set the name with the name of the project you want to use, for example `my-full-stack`:
+
+```bash
+git clone git@github.com:fastapi/full-stack-fastapi-template.git my-full-stack
+```
+
+- Enter into the new directory:
+
+```bash
+cd my-full-stack
+```
+
+- Set the new origin to your new repository, copy it from the GitHub interface, for example:
+
+```bash
+git remote set-url origin git@github.com:octocat/my-full-stack.git
+```
+
+- Add this repo as another "remote" to allow you to get updates later:
+
+```bash
+git remote add upstream git@github.com:fastapi/full-stack-fastapi-template.git
+```
+
+- Push the code to your new repository:
+
+```bash
+git push -u origin master
+```
+
+### Update From the Original Template
+
+After cloning the repository, and after doing changes, you might want to get the latest changes from this original template.
+
+- Make sure you added the original repository as a remote, you can check it with:
+
+```bash
+git remote -v
+
+origin git@github.com:octocat/my-full-stack.git (fetch)
+origin git@github.com:octocat/my-full-stack.git (push)
+upstream git@github.com:fastapi/full-stack-fastapi-template.git (fetch)
+upstream git@github.com:fastapi/full-stack-fastapi-template.git (push)
+```
+
+- Pull the latest changes without merging:
+
+```bash
+git pull --no-commit upstream master
+```
+
+This will download the latest changes from this template without committing them, that way you can check everything is right before committing.
+
+- If there are conflicts, solve them in your editor.
+
+- Once you are done, commit the changes:
+
+```bash
+git merge --continue
+```
+
+### Configure
+
+You can then update configs in the `.env` files to customize your configurations.
+
+Before deploying it, make sure you change at least the values for:
+
+- `SECRET_KEY`
+- `FIRST_SUPERUSER_PASSWORD`
+- `POSTGRES_PASSWORD`
+
+You can (and should) pass these as environment variables from secrets.
+
+Read the [deployment.md](./deployment.md) docs for more details.
+
+### Generate Secret Keys
+
+Some environment variables in the `.env` file have a default value of `changethis`.
+
+You have to change them with a secret key, to generate secret keys you can run the following command:
+
+```bash
+python -c "import secrets; print(secrets.token_urlsafe(32))"
+```
+
+Copy the content and use that as password / secret key. And run that again to generate another secure key.
+
+## How To Use It - Alternative With Copier
+
+This repository also supports generating a new project using [Copier](https://copier.readthedocs.io).
+
+It will copy all the files, ask you configuration questions, and update the `.env` files with your answers.
+
+### Install Copier
+
+You can install Copier with:
+
+```bash
+pip install copier
+```
+
+Or better, if you have [`pipx`](https://pipx.pypa.io/), you can run it with:
+
+```bash
+pipx install copier
+```
+
+**Note**: If you have `pipx`, installing copier is optional, you could run it directly.
+
+### Generate a Project With Copier
+
+Decide a name for your new project's directory, you will use it below. For example, `my-awesome-project`.
+
+Go to the directory that will be the parent of your project, and run the command with your project's name:
+
+```bash
+copier copy https://github.com/fastapi/full-stack-fastapi-template my-awesome-project --trust
+```
+
+If you have `pipx` and you didn't install `copier`, you can run it directly:
+
+```bash
+pipx run copier copy https://github.com/fastapi/full-stack-fastapi-template my-awesome-project --trust
+```
+
+**Note** the `--trust` option is necessary to be able to execute a [post-creation script](https://github.com/fastapi/full-stack-fastapi-template/blob/master/.copier/update_dotenv.py) that updates your `.env` files.
+
+### Input Variables
+
+Copier will ask you for some data, you might want to have at hand before generating the project.
+
+But don't worry, you can just update any of that in the `.env` files afterwards.
+
+The input variables, with their default values (some auto generated) are:
+
+- `project_name`: (default: `"FastAPI Project"`) The name of the project, shown to API users (in .env).
+- `stack_name`: (default: `"fastapi-project"`) The name of the stack used for Docker Compose labels and project name (no spaces, no periods) (in .env).
+- `secret_key`: (default: `"changethis"`) The secret key for the project, used for security, stored in .env, you can generate one with the method above.
+- `first_superuser`: (default: `"admin@example.com"`) The email of the first superuser (in .env).
+- `first_superuser_password`: (default: `"changethis"`) The password of the first superuser (in .env).
+- `smtp_host`: (default: "") The SMTP server host to send emails, you can set it later in .env.
+- `smtp_user`: (default: "") The SMTP server user to send emails, you can set it later in .env.
+- `smtp_password`: (default: "") The SMTP server password to send emails, you can set it later in .env.
+- `emails_from_email`: (default: `"info@example.com"`) The email account to send emails from, you can set it later in .env.
+- `postgres_password`: (default: `"changethis"`) The password for the PostgreSQL database, stored in .env, you can generate one with the method above.
+- `sentry_dsn`: (default: "") The DSN for Sentry, if you are using it, you can set it later in .env.
+
+## Backend Development
+
+Backend docs: [backend/README.md](./backend/README.md).
+
+## Frontend Development
+
+Frontend docs: [frontend/README.md](./frontend/README.md).
+
+## Deployment
+
+Deployment docs: [deployment.md](./deployment.md).
+
+## Development
+
+General development docs: [development.md](./development.md).
+
+This includes using Docker Compose, custom local domains, `.env` configurations, etc.
+
+## Release Notes
+
+Check the file [release-notes.md](./release-notes.md).
+
+## License
+
+The Full Stack FastAPI Template is licensed under the terms of the MIT license.
diff --git a/docs/runbooks/aws-k3s.md b/docs/runbooks/aws-k3s.md
new file mode 100644
index 0000000000..7eab1cd14e
--- /dev/null
+++ b/docs/runbooks/aws-k3s.md
@@ -0,0 +1,5 @@
+# Runbook — AWS (EC2 + k3s)
+
+> Pendiente: se completará en Phase 4 (AWS deploy).
+
+Objetivo: desplegar automáticamente al mergear a main hacia un cluster k3s corriendo en EC2.
diff --git a/docs/runbooks/kind.md b/docs/runbooks/kind.md
new file mode 100644
index 0000000000..86f455c300
--- /dev/null
+++ b/docs/runbooks/kind.md
@@ -0,0 +1,5 @@
+# Runbook — Kubernetes local (kind)
+
+> Pendiente: se completará en Phase 2 (Kubernetes local).
+
+Objetivo: levantar el stack en un cluster kind y acceder vía Ingress.
diff --git a/docs/runbooks/local-docker.md b/docs/runbooks/local-docker.md
new file mode 100644
index 0000000000..68acd4d242
--- /dev/null
+++ b/docs/runbooks/local-docker.md
@@ -0,0 +1,5 @@
+# Runbook — Local (Docker)
+
+> Pendiente: se completará en Phase 1 (Docker baseline).
+
+Objetivo: levantar el stack localmente con Docker/Compose de forma reproducible.
diff --git a/k8s/portfolio/README.md b/k8s/portfolio/README.md
new file mode 100644
index 0000000000..36044ba5cd
--- /dev/null
+++ b/k8s/portfolio/README.md
@@ -0,0 +1,8 @@
+# Manifiestos Kubernetes (portfolio)
+
+En esta carpeta van a vivir los manifiestos Kubernetes creados como parte del portfolio.
+
+Principios:
+- Separar el “trabajo propio” del contenido upstream del template
+- Mantenerlo incremental por fases
+- Minimizar complejidad: primero kind (local), luego k3s (AWS)
diff --git a/k8s/portfolio/backend/deployment.yaml b/k8s/portfolio/backend/deployment.yaml
new file mode 100644
index 0000000000..e490d1ad3f
--- /dev/null
+++ b/k8s/portfolio/backend/deployment.yaml
@@ -0,0 +1,30 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: backend
+ labels:
+ app: backend
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: backend
+ template:
+ metadata:
+ labels:
+ app: backend
+ spec:
+ containers:
+ - name: backend
+ image: devops-portfolio-fastapi-backend:latest
+ imagePullPolicy: IfNotPresent
+ ports:
+ - containerPort: 8000
+ env:
+ - name: PORT
+ value: "8000"
+ envFrom:
+ - configMapRef:
+ name: backend-config
+ - secretRef:
+ name: backend-secret
diff --git a/k8s/portfolio/backend/env/configmap.yaml b/k8s/portfolio/backend/env/configmap.yaml
new file mode 100644
index 0000000000..70254adaeb
--- /dev/null
+++ b/k8s/portfolio/backend/env/configmap.yaml
@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: backend-config
+data:
+ PROJECT_NAME: "DevOps Portfolio FastAPI"
+ POSTGRES_SERVER: "postgres"
+ POSTGRES_PORT: "5432"
+ POSTGRES_DB: "app"
+ POSTGRES_USER: "postgres"
+ BACKEND_CORS_ORIGINS: '["http://localhost:5173","http://localhost:18000"]'
diff --git a/k8s/portfolio/backend/env/secret.yaml b/k8s/portfolio/backend/env/secret.yaml
new file mode 100644
index 0000000000..074bd4664d
--- /dev/null
+++ b/k8s/portfolio/backend/env/secret.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: backend-secret
+type: Opaque
+stringData:
+ POSTGRES_PASSWORD: "postgres"
+ FIRST_SUPERUSER: "admin@example.com"
+ FIRST_SUPERUSER_PASSWORD: "admin123"
diff --git a/k8s/portfolio/backend/service.yaml b/k8s/portfolio/backend/service.yaml
new file mode 100644
index 0000000000..b54c3595d4
--- /dev/null
+++ b/k8s/portfolio/backend/service.yaml
@@ -0,0 +1,12 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: backend
+spec:
+ type: NodePort
+ selector:
+ app: backend
+ ports:
+ - port: 8000
+ targetPort: 8000
+ nodePort: 30080
diff --git a/k8s/portfolio/postgres/deployment.yaml b/k8s/portfolio/postgres/deployment.yaml
new file mode 100644
index 0000000000..1c71439f30
--- /dev/null
+++ b/k8s/portfolio/postgres/deployment.yaml
@@ -0,0 +1,31 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: postgres
+ labels:
+ app: postgres
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: postgres
+ template:
+ metadata:
+ labels:
+ app: postgres
+ spec:
+ containers:
+ - name: postgres
+ image: postgres:17
+ ports:
+ - containerPort: 5432
+ envFrom:
+ - secretRef:
+ name: postgres-secret
+ volumeMounts:
+ - name: postgres-data
+ mountPath: /var/lib/postgresql/data
+ volumes:
+ - name: postgres-data
+ persistentVolumeClaim:
+ claimName: postgres-pvc
diff --git a/k8s/portfolio/postgres/pvc.yaml b/k8s/portfolio/postgres/pvc.yaml
new file mode 100644
index 0000000000..23afd37855
--- /dev/null
+++ b/k8s/portfolio/postgres/pvc.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: postgres-pvc
+spec:
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 1Gi
diff --git a/k8s/portfolio/postgres/secret.yaml b/k8s/portfolio/postgres/secret.yaml
new file mode 100644
index 0000000000..fd11573938
--- /dev/null
+++ b/k8s/portfolio/postgres/secret.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: postgres-secret
+type: Opaque
+stringData:
+ POSTGRES_DB: app
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: postgres
diff --git a/k8s/portfolio/postgres/service.yaml b/k8s/portfolio/postgres/service.yaml
new file mode 100644
index 0000000000..e78c91e198
--- /dev/null
+++ b/k8s/portfolio/postgres/service.yaml
@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: postgres
+spec:
+ type: ClusterIP
+ selector:
+ app: postgres
+ ports:
+ - port: 5432
+ targetPort: 5432
diff --git a/kind-config.yaml b/kind-config.yaml
new file mode 100644
index 0000000000..f64b87e8e2
--- /dev/null
+++ b/kind-config.yaml
@@ -0,0 +1,4 @@
+kind: Cluster
+apiVersion: kind.x-k8s.io/v1alpha4
+nodes:
+ - role: control-plane