Skip to content

Commit f66c133

Browse files
committed
Initial commit — FitSpec vehicle parts fitment application
Full-stack Angular 19 + ASP.NET Core 9 + SQL Server + MongoDB project with 22 features including AI fitment assistant, product comparison, real-time inventory, VIN decoder, and admin dashboard. Dockerized with 4-container compose setup.
0 parents  commit f66c133

349 files changed

Lines changed: 49807 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: FitSpec CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
build-api:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
- uses: actions/setup-dotnet@v4
15+
with:
16+
dotnet-version: '9.0.x'
17+
- name: Restore
18+
run: dotnet restore
19+
- name: Build
20+
run: dotnet build --no-restore
21+
- name: Test
22+
run: dotnet test --no-build --verbosity normal
23+
24+
build-ui:
25+
runs-on: ubuntu-latest
26+
steps:
27+
- uses: actions/checkout@v4
28+
- uses: actions/setup-node@v4
29+
with:
30+
node-version: '20'
31+
cache: 'npm'
32+
cache-dependency-path: src/fitspec-ui/package-lock.json
33+
- name: Install
34+
run: npm ci
35+
working-directory: src/fitspec-ui
36+
- name: Build
37+
run: npx ng build --configuration production
38+
working-directory: src/fitspec-ui

.gitignore

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# .NET
2+
bin/
3+
obj/
4+
*.user
5+
*.suo
6+
*.vs/
7+
*.DotSettings.user
8+
packages/
9+
*.nupkg
10+
project.lock.json
11+
.vs/
12+
13+
# Angular
14+
src/fitspec-ui/node_modules/
15+
src/fitspec-ui/dist/
16+
src/fitspec-ui/.angular/
17+
src/fitspec-ui/.sass-cache/
18+
19+
# IDE
20+
.idea/
21+
*.swp
22+
*.swo
23+
*~
24+
.vscode/
25+
26+
# OS
27+
.DS_Store
28+
Thumbs.db
29+
30+
# Environment
31+
*.env
32+
appsettings.Development.json
33+
34+
# ML Models
35+
*.zip
36+
!src/FitSpec.ML/Models/.gitkeep
37+
38+
# Docker
39+
docker-compose.override.yml

FitSpec-SOP.md

Lines changed: 458 additions & 0 deletions
Large diffs are not rendered by default.

FitSpec.sln

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.0.31903.59
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FitSpec.API", "src\FitSpec.API\FitSpec.API.csproj", "{41CDBDB1-C46D-46C9-96EC-07776A2EE916}"
9+
EndProject
10+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FitSpec.Core", "src\FitSpec.Core\FitSpec.Core.csproj", "{677600D9-563C-41C7-9C00-810348F17F3F}"
11+
EndProject
12+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FitSpec.Data", "src\FitSpec.Data\FitSpec.Data.csproj", "{EA5BF996-7878-4F6C-9FA5-DDA76C47A932}"
13+
EndProject
14+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FitSpec.ML", "src\FitSpec.ML\FitSpec.ML.csproj", "{19567C56-F171-4D07-AF23-F2E4F56712CD}"
15+
EndProject
16+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FitSpec.Tests", "tests\FitSpec.Tests\FitSpec.Tests.csproj", "{FC233515-C127-4DB5-801F-E4B0BD26EE4E}"
17+
EndProject
18+
Global
19+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
20+
Debug|Any CPU = Debug|Any CPU
21+
Debug|x64 = Debug|x64
22+
Debug|x86 = Debug|x86
23+
Release|Any CPU = Release|Any CPU
24+
Release|x64 = Release|x64
25+
Release|x86 = Release|x86
26+
EndGlobalSection
27+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
28+
{41CDBDB1-C46D-46C9-96EC-07776A2EE916}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29+
{41CDBDB1-C46D-46C9-96EC-07776A2EE916}.Debug|Any CPU.Build.0 = Debug|Any CPU
30+
{41CDBDB1-C46D-46C9-96EC-07776A2EE916}.Debug|x64.ActiveCfg = Debug|Any CPU
31+
{41CDBDB1-C46D-46C9-96EC-07776A2EE916}.Debug|x64.Build.0 = Debug|Any CPU
32+
{41CDBDB1-C46D-46C9-96EC-07776A2EE916}.Debug|x86.ActiveCfg = Debug|Any CPU
33+
{41CDBDB1-C46D-46C9-96EC-07776A2EE916}.Debug|x86.Build.0 = Debug|Any CPU
34+
{41CDBDB1-C46D-46C9-96EC-07776A2EE916}.Release|Any CPU.ActiveCfg = Release|Any CPU
35+
{41CDBDB1-C46D-46C9-96EC-07776A2EE916}.Release|Any CPU.Build.0 = Release|Any CPU
36+
{41CDBDB1-C46D-46C9-96EC-07776A2EE916}.Release|x64.ActiveCfg = Release|Any CPU
37+
{41CDBDB1-C46D-46C9-96EC-07776A2EE916}.Release|x64.Build.0 = Release|Any CPU
38+
{41CDBDB1-C46D-46C9-96EC-07776A2EE916}.Release|x86.ActiveCfg = Release|Any CPU
39+
{41CDBDB1-C46D-46C9-96EC-07776A2EE916}.Release|x86.Build.0 = Release|Any CPU
40+
{677600D9-563C-41C7-9C00-810348F17F3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
41+
{677600D9-563C-41C7-9C00-810348F17F3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
42+
{677600D9-563C-41C7-9C00-810348F17F3F}.Debug|x64.ActiveCfg = Debug|Any CPU
43+
{677600D9-563C-41C7-9C00-810348F17F3F}.Debug|x64.Build.0 = Debug|Any CPU
44+
{677600D9-563C-41C7-9C00-810348F17F3F}.Debug|x86.ActiveCfg = Debug|Any CPU
45+
{677600D9-563C-41C7-9C00-810348F17F3F}.Debug|x86.Build.0 = Debug|Any CPU
46+
{677600D9-563C-41C7-9C00-810348F17F3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
47+
{677600D9-563C-41C7-9C00-810348F17F3F}.Release|Any CPU.Build.0 = Release|Any CPU
48+
{677600D9-563C-41C7-9C00-810348F17F3F}.Release|x64.ActiveCfg = Release|Any CPU
49+
{677600D9-563C-41C7-9C00-810348F17F3F}.Release|x64.Build.0 = Release|Any CPU
50+
{677600D9-563C-41C7-9C00-810348F17F3F}.Release|x86.ActiveCfg = Release|Any CPU
51+
{677600D9-563C-41C7-9C00-810348F17F3F}.Release|x86.Build.0 = Release|Any CPU
52+
{EA5BF996-7878-4F6C-9FA5-DDA76C47A932}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
53+
{EA5BF996-7878-4F6C-9FA5-DDA76C47A932}.Debug|Any CPU.Build.0 = Debug|Any CPU
54+
{EA5BF996-7878-4F6C-9FA5-DDA76C47A932}.Debug|x64.ActiveCfg = Debug|Any CPU
55+
{EA5BF996-7878-4F6C-9FA5-DDA76C47A932}.Debug|x64.Build.0 = Debug|Any CPU
56+
{EA5BF996-7878-4F6C-9FA5-DDA76C47A932}.Debug|x86.ActiveCfg = Debug|Any CPU
57+
{EA5BF996-7878-4F6C-9FA5-DDA76C47A932}.Debug|x86.Build.0 = Debug|Any CPU
58+
{EA5BF996-7878-4F6C-9FA5-DDA76C47A932}.Release|Any CPU.ActiveCfg = Release|Any CPU
59+
{EA5BF996-7878-4F6C-9FA5-DDA76C47A932}.Release|Any CPU.Build.0 = Release|Any CPU
60+
{EA5BF996-7878-4F6C-9FA5-DDA76C47A932}.Release|x64.ActiveCfg = Release|Any CPU
61+
{EA5BF996-7878-4F6C-9FA5-DDA76C47A932}.Release|x64.Build.0 = Release|Any CPU
62+
{EA5BF996-7878-4F6C-9FA5-DDA76C47A932}.Release|x86.ActiveCfg = Release|Any CPU
63+
{EA5BF996-7878-4F6C-9FA5-DDA76C47A932}.Release|x86.Build.0 = Release|Any CPU
64+
{19567C56-F171-4D07-AF23-F2E4F56712CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
65+
{19567C56-F171-4D07-AF23-F2E4F56712CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
66+
{19567C56-F171-4D07-AF23-F2E4F56712CD}.Debug|x64.ActiveCfg = Debug|Any CPU
67+
{19567C56-F171-4D07-AF23-F2E4F56712CD}.Debug|x64.Build.0 = Debug|Any CPU
68+
{19567C56-F171-4D07-AF23-F2E4F56712CD}.Debug|x86.ActiveCfg = Debug|Any CPU
69+
{19567C56-F171-4D07-AF23-F2E4F56712CD}.Debug|x86.Build.0 = Debug|Any CPU
70+
{19567C56-F171-4D07-AF23-F2E4F56712CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
71+
{19567C56-F171-4D07-AF23-F2E4F56712CD}.Release|Any CPU.Build.0 = Release|Any CPU
72+
{19567C56-F171-4D07-AF23-F2E4F56712CD}.Release|x64.ActiveCfg = Release|Any CPU
73+
{19567C56-F171-4D07-AF23-F2E4F56712CD}.Release|x64.Build.0 = Release|Any CPU
74+
{19567C56-F171-4D07-AF23-F2E4F56712CD}.Release|x86.ActiveCfg = Release|Any CPU
75+
{19567C56-F171-4D07-AF23-F2E4F56712CD}.Release|x86.Build.0 = Release|Any CPU
76+
{FC233515-C127-4DB5-801F-E4B0BD26EE4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
77+
{FC233515-C127-4DB5-801F-E4B0BD26EE4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
78+
{FC233515-C127-4DB5-801F-E4B0BD26EE4E}.Debug|x64.ActiveCfg = Debug|Any CPU
79+
{FC233515-C127-4DB5-801F-E4B0BD26EE4E}.Debug|x64.Build.0 = Debug|Any CPU
80+
{FC233515-C127-4DB5-801F-E4B0BD26EE4E}.Debug|x86.ActiveCfg = Debug|Any CPU
81+
{FC233515-C127-4DB5-801F-E4B0BD26EE4E}.Debug|x86.Build.0 = Debug|Any CPU
82+
{FC233515-C127-4DB5-801F-E4B0BD26EE4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
83+
{FC233515-C127-4DB5-801F-E4B0BD26EE4E}.Release|Any CPU.Build.0 = Release|Any CPU
84+
{FC233515-C127-4DB5-801F-E4B0BD26EE4E}.Release|x64.ActiveCfg = Release|Any CPU
85+
{FC233515-C127-4DB5-801F-E4B0BD26EE4E}.Release|x64.Build.0 = Release|Any CPU
86+
{FC233515-C127-4DB5-801F-E4B0BD26EE4E}.Release|x86.ActiveCfg = Release|Any CPU
87+
{FC233515-C127-4DB5-801F-E4B0BD26EE4E}.Release|x86.Build.0 = Release|Any CPU
88+
EndGlobalSection
89+
GlobalSection(SolutionProperties) = preSolution
90+
HideSolutionNode = FALSE
91+
EndGlobalSection
92+
GlobalSection(NestedProjects) = preSolution
93+
{41CDBDB1-C46D-46C9-96EC-07776A2EE916} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
94+
{677600D9-563C-41C7-9C00-810348F17F3F} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
95+
{EA5BF996-7878-4F6C-9FA5-DDA76C47A932} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
96+
{19567C56-F171-4D07-AF23-F2E4F56712CD} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
97+
{FC233515-C127-4DB5-801F-E4B0BD26EE4E} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
98+
EndGlobalSection
99+
EndGlobal

README.md

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
# FitSpec — Vehicle Parts Fitment Finder
2+
3+
Full-stack automotive parts fitment application built with **Angular 19**, **ASP.NET Core 9**, **SQL Server**, and **MongoDB**. Provides verified compatibility data for aftermarket parts, accessories, and modifications across 150+ products and 30 brands.
4+
5+
## Tech Stack
6+
7+
| Layer | Technology |
8+
|-------|-----------|
9+
| Frontend | Angular 19 (standalone components, signals, Material 3) |
10+
| Backend | ASP.NET Core 9, Dapper + EF Core, API versioning |
11+
| SQL Database | SQL Server 2022 (vehicles, products, fitment mappings, orders) |
12+
| Document Store | MongoDB 7 (reviews, product catalog, Q&A) |
13+
| ML | ML.NET (product recommendations) |
14+
| Real-time | SignalR (inventory updates) |
15+
| AI | Claude API (fitment assistant, install guides) |
16+
| Infrastructure | Docker Compose (4 containers), nginx reverse proxy |
17+
18+
## Architecture
19+
20+
```
21+
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
22+
│ Angular UI │────▶│ nginx :80 │────▶│ .NET API │
23+
│ (SPA) │ │ /api proxy │ │ :5062 │
24+
└─────────────┘ └──────────────┘ └──────┬──────┘
25+
26+
┌───────────┴───────────┐
27+
│ │
28+
┌─────▼─────┐ ┌─────▼─────┐
29+
│ SQL Server │ │ MongoDB │
30+
│ :1433 │ │ :27017 │
31+
└───────────┘ └───────────┘
32+
```
33+
34+
The Angular app is served by nginx, which also reverse-proxies `/api/` and `/hubs/` requests to the .NET API container. All API calls from the frontend use relative URLs (`/api/v1/...`).
35+
36+
## Features
37+
38+
1. **Vehicle Selector** — Year/Make/Model cascading dropdowns with URL-persisted state
39+
2. **Product Catalog** — Filterable grid with compatibility badges, category navigation
40+
3. **Product Detail** — Specs, compatibility check, install difficulty, pricing
41+
4. **Product Comparison** — Side-by-side compare with persistent tray
42+
5. **Garage Manager** — Save multiple vehicles to localStorage
43+
6. **AI Fitment Assistant** — Claude-powered Q&A about parts and compatibility
44+
7. **Community Builds** — Popular product combinations by vehicle
45+
8. **Product Q&A** — User questions stored in MongoDB
46+
9. **Reviews** — Star ratings with MongoDB storage
47+
10. **Real-time Inventory** — SignalR push updates for stock levels
48+
11. **Install Guides** — AI-generated or static HTML installation instructions
49+
12. **Required Accessories** — "Frequently Bought Together" cross-sell
50+
13. **Install Cost Estimator** — Difficulty-based labor cost ranges
51+
14. **Fitment Certificate** — SHA256-verified PDF certificate
52+
15. **Spec Sheets** — Vehicle-specific product specification documents
53+
16. **VIN Decoder** — NHTSA API integration with database matching
54+
17. **Price Drop Alerts** — Subscribe to price change notifications
55+
18. **Build Sheet PDF** — Export full build as printable document
56+
19. **Admin Dashboard** — Product CRUD, review moderation, analytics
57+
20. **Progressive Web App** — Installable with offline-capable service worker
58+
21. **Dark Mode** — System-aware theme toggle with CSS custom properties
59+
22. **Global Search** — Header autocomplete with typeahead
60+
61+
## Prerequisites
62+
63+
- [Docker Desktop](https://www.docker.com/products/docker-desktop/)
64+
- [Git](https://git-scm.com/)
65+
66+
## Quick Start
67+
68+
1. **Clone the repository**
69+
```bash
70+
git clone https://github.com/<your-username>/fitspec.git
71+
cd fitspec
72+
```
73+
74+
2. **Create a `.env` file** (optional — only needed for the AI Assistant feature)
75+
```bash
76+
# .env
77+
CLAUDE_API_KEY=your-api-key-here
78+
```
79+
Get a key at [console.anthropic.com](https://console.anthropic.com/settings/keys).
80+
81+
3. **Start all services**
82+
```bash
83+
docker compose up -d
84+
```
85+
This builds and starts 4 containers:
86+
- `fitspec-sql` — SQL Server 2022
87+
- `fitspec-mongo` — MongoDB 7
88+
- `fitspec-api` — ASP.NET Core API
89+
- `fitspec-ui` — Angular + nginx
90+
91+
4. **Seed the database**
92+
```bash
93+
bash scripts/setup-dev.sh
94+
```
95+
This applies EF Core migrations, runs stored procedures, and loads seed data into both SQL Server and MongoDB.
96+
97+
5. **Open the app**
98+
- UI: [http://localhost:4200](http://localhost:4200)
99+
- API (Swagger): [http://localhost:5062/swagger](http://localhost:5062/swagger) (development only)
100+
- Admin panel: [http://localhost:4200/admin](http://localhost:4200/admin)
101+
102+
## Project Structure
103+
104+
```
105+
fitspec/
106+
├── docker-compose.yml # 4-service orchestration
107+
├── .env # Secrets (gitignored)
108+
├── scripts/
109+
│ └── setup-dev.sh # Database setup & seeding
110+
├── infra/
111+
│ └── seed/ # SQL + MongoDB seed scripts
112+
├── src/
113+
│ ├── FitSpec.API/ # ASP.NET Core 9 API
114+
│ │ ├── Controllers/ # REST endpoints (versioned)
115+
│ │ ├── Hubs/ # SignalR hubs
116+
│ │ ├── Middleware/ # Exception handling
117+
│ │ └── Dockerfile
118+
│ ├── FitSpec.Core/ # Domain models, DTOs, interfaces
119+
│ ├── FitSpec.Data/ # Repositories (Dapper + EF Core)
120+
│ │ ├── Migrations/ # EF Core migrations
121+
│ │ └── Repositories/
122+
│ ├── FitSpec.ML/ # ML.NET recommendation engine
123+
│ └── fitspec-ui/ # Angular 19 SPA
124+
│ ├── src/app/
125+
│ │ ├── core/ # Services, state, interceptors, models
126+
│ │ └── features/ # Feature components
127+
│ ├── nginx.conf # Reverse proxy config
128+
│ └── Dockerfile
129+
└── tests/ # Test projects
130+
```
131+
132+
## Configuration
133+
134+
### Environment Variables
135+
136+
| Variable | Description | Required |
137+
|----------|-------------|----------|
138+
| `CLAUDE_API_KEY` | Anthropic API key for AI features | No (AI features disabled without it) |
139+
| `ConnectionStrings__DefaultConnection` | SQL Server connection string | Set in docker-compose.yml |
140+
| `ConnectionStrings__MongoDb` | MongoDB connection string | Set in docker-compose.yml |
141+
| `AllowedOrigins__0` | CORS allowed origin | Defaults to `http://localhost:4200` |
142+
143+
### Azure Deployment
144+
145+
When deploying to Azure, configure these as **App Settings** or environment variables:
146+
147+
- `ConnectionStrings__DefaultConnection` — Azure SQL connection string
148+
- `ConnectionStrings__MongoDb` — Azure Cosmos DB (MongoDB API) or MongoDB Atlas connection string
149+
- `CLAUDE_API_KEY` — Anthropic API key
150+
- `AllowedOrigins__0` — Your Azure app URL (e.g., `https://fitspec.azurewebsites.net`)
151+
152+
The `.env` file is gitignored and must be recreated in each environment.
153+
154+
## API Endpoints
155+
156+
All endpoints are versioned under `/api/v1/`.
157+
158+
| Endpoint | Description |
159+
|----------|-------------|
160+
| `GET /api/v1/vehicles/makes` | List vehicle makes |
161+
| `GET /api/v1/vehicles/makes/{id}/models` | Models for a make |
162+
| `GET /api/v1/vehicles/{makeId}/{modelId}` | Vehicles by make + model |
163+
| `GET /api/v1/categories` | Product categories |
164+
| `GET /api/v1/products` | Product listing (filterable) |
165+
| `GET /api/v1/products/{id}` | Product detail |
166+
| `GET /api/v1/products/{id}/compatibility/{vehicleId}` | Fitment check |
167+
| `GET /api/v1/products/{id}/recommendations` | ML recommendations |
168+
| `GET /api/v1/products/{id}/accessories` | Required accessories |
169+
| `GET /api/v1/products/{id}/reviews` | Product reviews |
170+
| `POST /api/v1/products/{id}/reviews` | Submit review |
171+
| `GET /api/v1/products/{id}/qa` | Product Q&A |
172+
| `POST /api/v1/products/{id}/qa` | Ask a question |
173+
| `GET /api/v1/search?q=...` | Global search |
174+
| `GET /api/v1/admin/dashboard` | Admin statistics |
175+
| `GET /api/v1/vin/{vin}/decode` | VIN decoder |
176+
| `POST /api/v1/assistant` | AI fitment assistant |
177+
| `WS /hubs/inventory` | SignalR inventory hub |
178+
179+
## Development
180+
181+
### Rebuild after code changes
182+
183+
```bash
184+
# Rebuild both containers
185+
docker compose up -d --build api ui
186+
187+
# Rebuild just the API
188+
docker compose up -d --build api
189+
190+
# Rebuild just the UI
191+
docker compose up -d --build ui
192+
```
193+
194+
### View logs
195+
196+
```bash
197+
docker compose logs -f api # API logs
198+
docker compose logs -f ui # nginx logs
199+
```
200+
201+
### Stop all services
202+
203+
```bash
204+
docker compose down # Stop containers (keep data)
205+
docker compose down -v # Stop and delete volumes (reset databases)
206+
```
207+
208+
## License
209+
210+
This is a portfolio project. All rights reserved.

0 commit comments

Comments
 (0)