From 0f29b1ba22db0ec93c00fb7447ffddc33904a963 Mon Sep 17 00:00:00 2001 From: OpenClaw Agent Date: Thu, 16 Apr 2026 04:34:39 +0000 Subject: [PATCH] docs: add SPEC.md architecture specification --- SPEC.md | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 SPEC.md diff --git a/SPEC.md b/SPEC.md new file mode 100644 index 0000000..ff8c897 --- /dev/null +++ b/SPEC.md @@ -0,0 +1,212 @@ +# Project: Instagram Clone (SocialPhoto) + +## Overview + +SocialPhoto es un clon minimalista de Instagram que prioriza la simplicidad y velocidad. Permite a usuarios registrarse, subir imágenes, interactuar con publicaciones (likes/dislikes), comentar y seguir a otros usuarios. Ideal para testing de agentes de IA. + +**Principios:** +- Simple de instalar y operar +- Base de datos portable (SQLite) +- API RESTful clara y documentada +- En desarrollo: migrar a PostgreSQL en producción + +--- + +## Architecture + +### Components + +- **FastAPI Backend**: Python 3.11+ REST API +- **SQLite Database**: Almacenamiento local para desarrollo +- **JWT Authentication**: Auth via tokens Bearer +- **Local File Storage**: Imágenes almacenadas en `/uploads` +- **Static Files**: Avatar default, served estáticamente + +### Data Model + +#### Users +| Field | Type | Description | +|-------|------|-------------| +| id | INTEGER | Primary key | +| username | TEXT | Unique, required | +| email | TEXT | Unique, required | +| password_hash | TEXT | bcrypt hashed | +| avatar_url | TEXT | URL to avatar | +| bio | TEXT | User biography | +| created_at | TIMESTAMP | Creation date | + +#### Posts +| Field | Type | Description | +|-------|------|-------------| +| id | INTEGER | Primary key | +| user_id | INTEGER | FK to users | +| image_path | TEXT | Path to uploaded image | +| caption | TEXT | Post caption | +| created_at | TIMESTAMP | Creation date | + +#### Comments +| Field | Type | Description | +|-------|------|-------------| +| id | INTEGER | Primary key | +| post_id | INTEGER | FK to posts | +| user_id | INTEGER | FK to users | +| content | TEXT | Comment text | +| created_at | TIMESTAMP | Creation date | + +#### Likes/Dislikes +| Field | Type | Description | +|-------|------|-------------| +| id | INTEGER | Primary key | +| post_id | INTEGER | FK to posts | +| user_id | INTEGER | FK to users | +| created_at | TIMESTAMP | Creation date | + +#### Follows +| Field | Type | Description | +|-------|------|-------------| +| id | INTEGER | Primary key | +| follower_id | INTEGER | FK to users | +| following_id | INTEGER | FK to users | +| created_at | TIMESTAMP | Creation date | + +--- + +## Tech Stack + +| Component | Technology | +|-----------|-----------| +| **Backend** | Python 3.11+ con FastAPI | +| **Database** | SQLite3 (dev), PostgreSQL (prod) | +| **Auth** | JWT (python-jose) | +| **Password** | bcrypt | +| **Migrations** | Alembic | +| **Testing** | pytest + pytest-asyncio + httpx | +| **Upload** | Local storage in `/uploads` | + +--- + +## API Endpoints + +### Authentication + +| Method | Endpoint | Description | +|--------|----------|-------------| +| POST | `/auth/register` | Register new user | +| POST | `/auth/login` | Login, returns JWT | + +### Users + +| Method | Endpoint | Description | +|--------|----------|-------------| +| GET | `/users/{id}` | Get user profile | +| GET | `/users/{id}/posts` | Get user's posts | +| GET | `/users/{id}/stats` | Get user stats | +| POST | `/users/{id}/follow` | Follow user | +| DELETE | `/users/{id}/follow` | Unfollow user | + +### Posts + +| Method | Endpoint | Description | +|--------|----------|-------------| +| POST | `/posts` | Create post (multipart with image) | +| GET | `/posts` | Global feed | +| GET | `/posts/{id}` | Get post details | +| DELETE | `/posts/{id}` | Delete post (owner only) | +| POST | `/posts/{id}/like` | Like post | +| DELETE | `/posts/{id}/like` | Remove like | +| POST | `/posts/{id}/dislike` | Dislike post | +| DELETE | `/posts/{id}/dislike` | Remove dislike | + +### Comments + +| Method | Endpoint | Description | +|--------|----------|-------------| +| GET | `/posts/{id}/comments` | List comments | +| POST | `/posts/{id}/comments` | Add comment | +| DELETE | `/comments/{id}` | Delete comment (owner only) | + +### Feed + +| Method | Endpoint | Description | +|--------|----------|-------------| +| GET | `/feed` | Personal feed (following) | +| GET | `/feed/global` | Global feed | + +--- + +## Project Structure + +``` +instagram-clone/ +├── app/ +│ ├── __init__.py +│ ├── main.py # FastAPI app entry +│ ├── config.py # Settings +│ ├── database.py # SQLite connection + setup +│ ├── models.py # Pydantic models +│ ├── auth.py # JWT helpers +│ ├── routes/ +│ │ ├── __init__.py +│ │ ├── auth.py # /auth/* endpoints +│ │ ├── users.py # /users/* endpoints +│ │ ├── posts.py # /posts/* endpoints +│ │ └── comments.py # /comments/* endpoints +│ └── services/ +│ ├── __init__.py +│ └── social.py # Social logic (likes, follows) +├── uploads/ # Image storage +├── alembic/ # DB migrations +├── tests/ +│ ├── __init__.py +│ ├── conftest.py +│ ├── test_auth.py +│ ├── test_posts.py +│ └── test_social.py +├── requirements.txt +├── alembic.ini +├── SPEC.md +└── README.md +``` + +--- + +## Acceptance Criteria + +### Auth +- [x] User can register with username, email, password +- [x] User can login and receive JWT +- [x] Protected routes require valid token +- [x] No duplicate username/email allowed + +### Posts +- [x] User can create post with image and caption +- [x] Global feed shows all posts ordered by date +- [x] Personal feed shows only followed users' posts +- [x] User can delete their own posts + +### Likes / Dislikes +- [x] User can like a post +- [x] User can dislike a post +- [x] Like and dislike are mutually exclusive +- [x] Like/dislike counts update in real-time + +### Comments +- [x] User can comment on a post +- [x] User can delete their own comments +- [x] Comments include username and timestamp + +### Follow +- [x] User can follow another user +- [x] User can unfollow +- [x] Cannot follow self +- [x] Stats show followers/following count + +--- + +## Out of Scope + +- No real-time notifications (WebSocket) +- No direct messages +- No stories/reels +- No algorithm-based feed +- No image compression/resizing \ No newline at end of file