What it builds
- ✓A web form at / with a drop zone for CSV files
- ✓Type coercion: numbers, booleans, nulls detected on parse
- ✓POST /upload returns a live grid URL
- ✓Mounts cleanly inside any existing FastAPI app
The key step
@app.post("/upload")
async def upload(
name: Annotated[str, Form()],
file: Annotated[UploadFile, File()],
):
rows = [_coerce(r) for r in csv.DictReader(io.StringIO(
(await file.read()).decode("utf-8")
))]
req = Request("https://instadash.io/ingest",
data=json.dumps(rows).encode(), method="POST")
req.add_header("Authorization", f"Bearer {INSTADASH_KEY}")
req.add_header("X-Grid-Name", name)
# ... return grid_urlnote ▸
This is the core of the recipe. The full file (including setup, error handling, and the surrounding scaffolding) lives in the GitHub folder linked below — clone or copy it directly.
Run it
Stack
fastapipythonuvicorn
Full source on GitHub
README, runnable code, .env.example, dependencies — all in one folder.