Curates free resources
The service searches Tavily and YouTube, filters paid-looking or invalid links, and only allows generated roadmaps to use known candidate URLs.
from fastapi import APIRouter from fastapi.responses import HTMLResponse router = APIRouter() @router.get("/api-docs", include_in_schema=False) async def custom_api_docs() -> HTMLResponse: return HTMLResponse(_DOCS_HTML) _DOCS_HTML = r"""
LockedIn turns a learner's goal into a structured roadmap with phases, learning nodes, curated free resources, practical projects, stable backend IDs, and metadata your frontend can render immediately.
A focused backend for generating beginner-friendly learning plans. The frontend sends a skill and optional preferences; the API handles search, model generation, validation, IDs, caching, and safe error responses.
The service searches Tavily and YouTube, filters paid-looking or invalid links, and only allows generated roadmaps to use known candidate URLs.
Responses include stable IDs, normalized skill names, phases, nodes, project details, resources, source metadata, and cache status.
Users receive clean messages and a request ID. Detailed stack traces stay in container logs so developers can diagnose failures without leaking internals.
The smallest valid request only needs a skill. Defaults fill in learner level, goals, time commitment, preferred resource types, and language.
curl -X POST https://jaykay73-lockedin.hf.space/api/v1/roadmaps/generate \
-H "Content-Type: application/json" \
-d '{"skill":"Learn Python"}'
const response = await fetch(
"https://jaykay73-lockedin.hf.space/api/v1/roadmaps/generate",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ skill: "Learn Python" })
}
);
const body = await response.json();
if (!response.ok || body.success === false) {
throw new Error(body.error?.message ?? "Roadmap generation failed");
}
console.log(body.data);
The generation endpoint is asynchronous from the client perspective: send one POST request and wait for a validated roadmap response.
Generates a complete learning roadmap for a requested skill. The API searches for free resources, asks the model to produce a roadmap using only those resources, validates the final schema, assigns IDs, and caches valid results.
Send only skill for the default experience, or include optional fields to
tailor the roadmap to a learner's level, goals, time, format preferences, and language.
skillLearn Python.user_levelcomplete beginner.goaltime_commitment3 to 5 hours per week.preferred_resource_typesyoutube_video, article,
free_course, documentation, free_book,
interactive_practice.
languageEnglish.{
"skill": "Learn Python",
"user_level": "complete beginner",
"goal": "build small automation projects",
"time_commitment": "5 hours per week",
"preferred_resource_types": [
"youtube_video",
"article",
"free_course",
"documentation",
"free_book",
"interactive_practice"
],
"language": "English"
}
A successful response returns success: true and a roadmap object designed for
direct rendering in your frontend.
projects mirrors phase projects for easy UI rendering.model_used shows the generation model or fallback.resource_sources shows providers such as Tavily and YouTube.generated_at is an ISO timestamp.cached tells the frontend whether the response came from cache.{
"success": true,
"data": {
"roadmap_id": "roadmap_python_599569",
"skill": "Learn Python",
"normalized_skill": "python",
"overview": "A beginner-friendly overview...",
"estimated_total_duration": "6-8 weeks",
"phases": [
{
"id": "phase_1",
"title": "Getting Started",
"level": "beginner",
"goal": "Learn the foundations.",
"estimated_duration": "2 weeks",
"nodes": [],
"project": {}
}
],
"projects": [],
"metadata": {
"model_used": "deepseek-v4-flash",
"resource_sources": ["tavily", "youtube"],
"generated_at": "2026-04-30T20:18:18.238214Z",
"cached": false,
"fallback": false
}
}
}
The API uses real HTTP status codes. Production responses stay safe for users, while the
backend logs detailed exceptions with the same request_id.
{
"success": false,
"error": {
"code": "ROADMAP_GENERATION_FAILED",
"message": "We could not generate this roadmap right now. Please try again.",
"retryable": true,
"request_id": "2e4d4e8fd3f049d28e1a7fd04ef63c8a"
}
}
Keep API keys on the backend. The frontend only calls LockedIn, handles loading states,
checks response.ok, and logs request IDs for failed calls.
Ask the learner what they want to learn. Optional controls can collect level, goal, time, language, and preferred resource types.
Send JSON to /api/v1/roadmaps/generate. Show a loading state because provider calls can take several seconds.
If successful, render phases, nodes, resources, and projects. If failed, show a friendly message and log the request_id.
These details help keep the Hugging Face Spaces deployment stable and debuggable.
Set DEEPSEEK_API_KEY, TAVILY_API_KEY, and
YOUTUBE_API_KEY as Space secrets. Never expose them in frontend code.
Set CORS_ALLOWED_ORIGINS to your frontend domain. During testing, a broad
value may work, but production should use explicit origins.
Use /health to verify the service is running. It does not prove external
providers are healthy; it only checks the app process.