Compare commits
1 Commits
task-001-f
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f29b1ba22 |
212
SPEC.md
Normal file
212
SPEC.md
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user