A full-stack CRUD template for students with related photos.
This project was built with focus on building and deploying a full-stack application, including a Dockerized backend and database, API design, persistent file storage on the host file system, and an ASP.NET Core Web API + React + PostgreSQL stack.
Features:
- Create, update, view, and delete entities
- Server-side validation
- File uploads
- Keeping uploaded files on the server filesystem
- Pagination
- Sorting
- Search with debounced API requests (after the user stops typing)
- Responsive UI (mobile-friendly layout)
- Running backend and database using Docker containers
Backend
- ASP.NET Core Web API
- Entity Framework Core
- PostgreSQL
- RESTful API design
- File upload & storage (local filesystem)
Frontend
- React (Vite)
- JavaScript
- Bootstrap 5
Infrastructure
- Docker
- docker-compose
- Nginx (reverse proxy)
- Linux server deployment
students-fullstack/
│
├── backend/
│ └── StudentsApi/
│ ├── Controllers/
│ │ ├── StudentsController.cs
│ │ ├── StudentPhotosController.cs
│ │ └── DebugFileController.cs
│ │
│ ├── Data/
│ │ └── ApplicationDbContext.cs
│ │
│ ├── Domain/
│ │ └── Entities/
│ │ ├── Student.cs
│ │ ├── PhotoAvatar.cs
│ │ └── PhotoEnclosure.cs
│ │
│ ├── Dtos/
│ │ ├── StudentCreateDto.cs
│ │ ├── StudentUpdateDto.cs
│ │ ├── StudentReadDto.cs
│ │ ├── PagedResultDto.cs
│ │ └── Photos/
│ │ ├── UploadAvatarRequest.cs
│ │ └── UploadEnclosuresRequest.cs
│ │
│ ├── Services/
│ │ ├── Students/
│ │ │ ├── IStudentService.cs
│ │ │ └── StudentService.cs
│ │ │
│ │ ├── Photos/
│ │ │ ├── IStudentPhotoService.cs
│ │ │ └── StudentPhotoService.cs
│ │ │
│ │ └── Storage/
│ │ ├── IFileStorage.cs
│ │ ├── LocalFileStorage.cs
│ │ └── FileStorageOptions.cs
│ │
│ ├── Migrations/
│ ├── Program.cs
│ └── appsettings.json
│
├── frontend/
│ └── students-app/
│ ├── src/
│ │ ├── api/
│ │ │ └── studentsApi.js
│ │ │
│ │ ├── components/
│ │ │ └── students/
│ │ │ ├── StudentTable.jsx
│ │ │ ├── StudentForm.jsx
│ │ │ ├── StudentSearchBar.jsx
│ │ │ └── PaginationBar.jsx
│ │ │
│ │ ├── pages/
│ │ │ └── students/
│ │ │ ├── StudentsAll.jsx
│ │ │ ├── StudentCreate.jsx
│ │ │ ├── StudentDetails.jsx
│ │ │ └── StudentUpdate.jsx
│ │ │
│ │ ├── App.jsx
│ │ └── main.jsx
│ │
│ ├── index.html
│ ├── package.json
│ └── vite.config.js
│
├── docker-compose.yml
├── .env
├── .env.example
└── README.md
Uploaded files are stored outside containers on the host filesystem:
/var/www/uploads/students-fullstack/
└── students/
└── {studentId}/
└── enclosures/
The directory is mounted in the API container:
volumes:
- /var/www/uploads/students-fullstack:/uploads
- GET /api/students — paginated, sortable, searchable list
- POST /api/students — create student
- PUT /api/students/{id} — update student
- DELETE /api/students/{id} — delete student
- POST /api/students/{id}/avatar — upload avatar
- POST /api/students/{id}/enclosures — upload multiple files
- GET /api/students/{id}/enclosures — list enclosures
- GET /api/students/{id}/enclosures/{enclosureId} — download file
The backend and database run in containers, frontend is served as static files.
docker-compose up -d --build
Containers:
- students-api — ASP.NET Core Web API
- students-postgres — PostgreSQL database


