Skip to content

Commit b970088

Browse files
committed
feat: open consumer-electronics specs API + curated dataset + static dump
FastAPI + SQLModel service for smartphones, SoCs, GPUs, CPUs and brands (/v1, paginated lists, detail responses, scoring). Curated dataset of 445 records (brand/soc/smartphone/gpu/cpu, organised by manufacturer; CPUs also by year). seed/validate/dump scripts, ~98% test coverage, Docker, CI.
1 parent 559c007 commit b970088

511 files changed

Lines changed: 19910 additions & 1 deletion

File tree

Some content is hidden

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

.dockerignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
.git
2+
.github
3+
.venv
4+
venv
5+
__pycache__
6+
*.pyc
7+
.pytest_cache
8+
.mypy_cache
9+
.ruff_cache
10+
.coverage
11+
htmlcov
12+
tests
13+
docs
14+
*.db
15+
*.sqlite3
16+
.env
17+
.env.*
18+
!.env.example

.env.example

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# === Database ===
2+
# Local dev defaults to SQLite (no external service needed).
3+
# For Postgres (docker-compose / production), use a postgresql+psycopg URL, e.g.:
4+
# postgresql+psycopg://techapi:techapi@db:5432/techapi
5+
DATABASE_URL=sqlite:///./techapi.db
6+
DATABASE_POOL_SIZE=10
7+
8+
# === Supabase (production Postgres host) ===
9+
SUPABASE_URL=https://xxx.supabase.co
10+
SUPABASE_ANON_KEY=eyJ...
11+
SUPABASE_SERVICE_KEY=eyJ... # secret, never expose to clients
12+
13+
# === API ===
14+
API_HOST=0.0.0.0
15+
API_PORT=8000
16+
API_ENV=development # development | staging | production
17+
API_BASE_URL=http://localhost:8000
18+
19+
# === Security ===
20+
SECRET_KEY=change-me # JWT/session (Phase 4+)
21+
CORS_ORIGINS=http://localhost:3000,https://techpicks.app
22+
23+
# === Logging ===
24+
LOG_LEVEL=INFO
25+
SENTRY_DSN=https://... # optional
26+
27+
# === External Services ===
28+
REDIS_URL=redis://localhost:6379 # optional (Phase 2+)
29+
30+
# === Scoring ===
31+
SCORING_CONFIG_PATH=./config/scoring.yaml

.github/CODEOWNERS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Default owners for everything in the repo.
2+
# TODO: replace with the maintainer's GitHub handle or org team before Phase 1.
3+
* @GetTechAPI/maintainers
4+
5+
/data/ @GetTechAPI/maintainers
6+
/app/ @GetTechAPI/maintainers
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: "🐛 Bug report"
2+
description: Report a bug in the API or tooling
3+
labels: ["type:bug"]
4+
body:
5+
- type: textarea
6+
id: what-happened
7+
attributes:
8+
label: What happened?
9+
description: A clear description of the bug.
10+
validations:
11+
required: true
12+
- type: textarea
13+
id: reproduce
14+
attributes:
15+
label: Steps to reproduce
16+
description: Include the exact request (curl) where possible.
17+
placeholder: |
18+
curl https://api.techapi.dev/v1/smartphones/galaxy-s25
19+
validations:
20+
required: true
21+
- type: textarea
22+
id: expected
23+
attributes:
24+
label: Expected behavior
25+
validations:
26+
required: true
27+
- type: input
28+
id: request-id
29+
attributes:
30+
label: request_id (if any)
31+
description: The `request_id` from the error response helps us trace it.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: "📥 Data addition"
2+
description: Request a new device, SoC, or GPU
3+
labels: ["type:data", "data:missing"]
4+
body:
5+
- type: dropdown
6+
id: category
7+
attributes:
8+
label: Category
9+
options:
10+
- smartphone
11+
- soc
12+
- gpu
13+
- brand
14+
validations:
15+
required: true
16+
- type: input
17+
id: name
18+
attributes:
19+
label: Name
20+
placeholder: "Galaxy S25 FE"
21+
validations:
22+
required: true
23+
- type: textarea
24+
id: sources
25+
attributes:
26+
label: Source URLs (at least one)
27+
description: Manufacturer spec sheet preferred (§9.2).
28+
validations:
29+
required: true
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: "✏️ Data correction"
2+
description: Correct an existing spec value
3+
labels: ["type:data", "data:incorrect"]
4+
body:
5+
- type: input
6+
id: slug
7+
attributes:
8+
label: Resource slug
9+
placeholder: "galaxy-s25"
10+
validations:
11+
required: true
12+
- type: input
13+
id: field
14+
attributes:
15+
label: Field to correct
16+
placeholder: "battery_mah"
17+
validations:
18+
required: true
19+
- type: textarea
20+
id: correction
21+
attributes:
22+
label: Current value → correct value (with source)
23+
placeholder: |
24+
current: 4500
25+
correct: 4000
26+
source: https://www.samsung.com/...
27+
validations:
28+
required: true
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: "✨ Feature request"
2+
description: Propose a new feature or endpoint
3+
labels: ["type:feature"]
4+
body:
5+
- type: textarea
6+
id: problem
7+
attributes:
8+
label: Problem / motivation
9+
description: What are you trying to do? Who benefits?
10+
validations:
11+
required: true
12+
- type: textarea
13+
id: proposal
14+
attributes:
15+
label: Proposed solution
16+
validations:
17+
required: true
18+
- type: checkboxes
19+
id: scope
20+
attributes:
21+
label: Scope check
22+
options:
23+
- label: This is generalizable to all consumers (not TechPicks-specific, see ADR-008).
24+
required: true

.github/pull_request_template.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!-- PR title must follow Conventional Commits (§14.5), e.g. feat(api): add /compare endpoint -->
2+
3+
## What & why
4+
5+
<!-- What does this change and why? Link issues with "Closes #123". -->
6+
7+
## How
8+
9+
<!-- Key implementation notes. -->
10+
11+
## Testing
12+
13+
<!-- How was this verified? Paste test output or screenshots. -->
14+
15+
## Checklist
16+
17+
- [ ] Type hints on all new functions (§0.5.4)
18+
- [ ] Tests added/updated (§15)
19+
- [ ] `ruff check` and `pytest` pass locally
20+
- [ ] Data changes pass `python -m scripts.validate`
21+
- [ ] SPEC/README updated if behavior changed (§0.5.4)

.github/workflows/refresh-data.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: refresh-data
2+
3+
# Static-dump refresh (PokeAPI api-data style + git-scraping pattern).
4+
# Regenerates dump/ from the curated seed data and commits it back when it changes.
5+
# - weekly schedule keeps the static dump fresh
6+
# - runs on any change to data/ (e.g. a curated-data PR)
7+
# - manual trigger for on-demand rebuilds
8+
on:
9+
schedule:
10+
- cron: "17 6 * * 1" # Mondays 06:17 UTC (offset minute is polite, per git-scraping)
11+
push:
12+
branches: [main]
13+
paths:
14+
- "data/**"
15+
- "app/**"
16+
- "scripts/dump.py"
17+
workflow_dispatch:
18+
19+
permissions:
20+
contents: read
21+
22+
jobs:
23+
dump:
24+
runs-on: ubuntu-latest
25+
steps:
26+
- uses: actions/checkout@v4
27+
28+
- uses: actions/setup-python@v5
29+
with:
30+
python-version: "3.12"
31+
cache: pip
32+
33+
- name: Install
34+
run: pip install -e .
35+
36+
- name: Validate seed data
37+
run: python -m scripts.validate
38+
39+
# Data collection happens via a separate internal pipeline that publishes
40+
# curated data into data/ (PR). This workflow only re-dumps it.
41+
- name: Generate static dump
42+
run: python -m scripts.dump
43+
44+
# Publish target depends on the public/private decision (docs/DATA_PIPELINE.md §5).
45+
# Default: keep the dump as a downloadable build artifact (works for public OR private repos).
46+
- name: Upload static dump artifact
47+
uses: actions/upload-artifact@v4
48+
with:
49+
name: techapi-static-dump
50+
path: dump/
51+
52+
# To serve a public static API, enable Pages and swap the step above for:
53+
# - uses: actions/upload-pages-artifact@v3
54+
# with: { path: dump/ }
55+
# - uses: actions/deploy-pages@v4
56+
# (requires `permissions: pages: write, id-token: write` and Settings → Pages → GitHub Actions)

.github/workflows/test.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: test
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
8+
jobs:
9+
test:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
14+
- uses: actions/setup-python@v5
15+
with:
16+
python-version: "3.12"
17+
cache: pip
18+
19+
- name: Install dependencies
20+
run: pip install -e ".[dev]"
21+
22+
- name: Lint (ruff)
23+
run: ruff check app scripts tests
24+
25+
- name: Type check (mypy)
26+
run: mypy app
27+
28+
- name: Validate seed data
29+
run: python -m scripts.validate
30+
31+
- name: Tests + coverage (fail under 60%)
32+
run: pytest --cov=app --cov-report=term-missing --cov-fail-under=60

0 commit comments

Comments
 (0)