{"spec_id":"gantt-basic","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\ngantt-basic: Basic Gantt Chart\nLibrary: plotly 6.7.0 | Python 3.13.13\nQuality: 92/100 | Updated: 2026-05-10\n\"\"\"\n\nimport os\nfrom datetime import datetime\n\nimport pandas as pd\nimport plotly.express as px\n\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\nGRID = \"rgba(26,26,23,0.15)\" if THEME == \"light\" else \"rgba(240,239,232,0.15)\"\n\n# Okabe-Ito palette\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\"]\n\n# Data - Software Development Project Timeline\ntasks = [\n    {\"task\": \"Requirements Analysis\", \"start\": \"2025-01-06\", \"end\": \"2025-01-17\", \"category\": \"Planning\"},\n    {\"task\": \"System Design\", \"start\": \"2025-01-13\", \"end\": \"2025-01-31\", \"category\": \"Planning\"},\n    {\"task\": \"Database Design\", \"start\": \"2025-01-27\", \"end\": \"2025-02-07\", \"category\": \"Design\"},\n    {\"task\": \"UI/UX Design\", \"start\": \"2025-01-27\", \"end\": \"2025-02-14\", \"category\": \"Design\"},\n    {\"task\": \"Backend Development\", \"start\": \"2025-02-03\", \"end\": \"2025-03-14\", \"category\": \"Development\"},\n    {\"task\": \"Frontend Development\", \"start\": \"2025-02-10\", \"end\": \"2025-03-21\", \"category\": \"Development\"},\n    {\"task\": \"API Integration\", \"start\": \"2025-03-03\", \"end\": \"2025-03-21\", \"category\": \"Development\"},\n    {\"task\": \"Unit Testing\", \"start\": \"2025-03-10\", \"end\": \"2025-03-28\", \"category\": \"Testing\"},\n    {\"task\": \"Integration Testing\", \"start\": \"2025-03-24\", \"end\": \"2025-04-04\", \"category\": \"Testing\"},\n    {\"task\": \"User Acceptance Testing\", \"start\": \"2025-04-01\", \"end\": \"2025-04-11\", \"category\": \"Testing\"},\n    {\"task\": \"Documentation\", \"start\": \"2025-03-17\", \"end\": \"2025-04-11\", \"category\": \"Deployment\"},\n    {\"task\": \"Deployment & Launch\", \"start\": \"2025-04-07\", \"end\": \"2025-04-18\", \"category\": \"Deployment\"},\n]\n\ndf = pd.DataFrame(tasks)\ndf[\"start\"] = pd.to_datetime(df[\"start\"])\ndf[\"end\"] = pd.to_datetime(df[\"end\"])\n\n# Sort by start date for logical ordering\ndf = df.sort_values(\"start\").reset_index(drop=True)\n\n# Color map using Okabe-Ito palette\ncolor_map = {\n    \"Planning\": IMPRINT[0],\n    \"Design\": IMPRINT[1],\n    \"Development\": IMPRINT[2],\n    \"Testing\": IMPRINT[3],\n    \"Deployment\": IMPRINT[4],\n}\n\n# Create Gantt chart using timeline\nfig = px.timeline(df, x_start=\"start\", x_end=\"end\", y=\"task\", color=\"category\", color_discrete_map=color_map)\n\n# Reverse y-axis so earliest tasks are at top\nfig.update_yaxes(autorange=\"reversed\")\n\n# Add current date line (vertical marker)\ntoday = datetime(2025, 2, 20)\nfig.add_shape(\n    type=\"line\",\n    x0=today,\n    x1=today,\n    y0=-0.5,\n    y1=len(df) - 0.5,\n    line={\"color\": INK_SOFT, \"width\": 3, \"dash\": \"dash\"},\n    layer=\"above\",\n)\nfig.add_annotation(\n    x=today,\n    y=len(df) - 0.5,\n    text=\"Today\",\n    showarrow=False,\n    font={\"size\": 18, \"color\": INK_SOFT, \"family\": \"Arial\"},\n    yanchor=\"top\",\n    yshift=-5,\n)\n\n# Update layout for 4800x2700 px\nfig.update_layout(\n    title={\n        \"text\": \"Software Development Project · gantt-basic · plotly · anyplot.ai\",\n        \"font\": {\"size\": 28, \"color\": INK},\n        \"x\": 0.5,\n        \"xanchor\": \"center\",\n    },\n    xaxis={\n        \"title\": {\"text\": \"Timeline (2025)\", \"font\": {\"size\": 22, \"color\": INK}},\n        \"tickfont\": {\"size\": 18, \"color\": INK_SOFT},\n        \"tickformat\": \"%b %d\",\n        \"showgrid\": True,\n        \"gridwidth\": 1,\n        \"gridcolor\": GRID,\n        \"linecolor\": INK_SOFT,\n        \"zerolinecolor\": INK_SOFT,\n    },\n    yaxis={\n        \"title\": {\"text\": \"Project Tasks\", \"font\": {\"size\": 22, \"color\": INK}},\n        \"tickfont\": {\"size\": 18, \"color\": INK_SOFT},\n        \"showgrid\": False,\n        \"linecolor\": INK_SOFT,\n    },\n    paper_bgcolor=PAGE_BG,\n    plot_bgcolor=PAGE_BG,\n    font={\"color\": INK},\n    legend={\n        \"title\": {\"text\": \"Category\", \"font\": {\"size\": 20, \"color\": INK}},\n        \"font\": {\"size\": 18, \"color\": INK_SOFT},\n        \"bgcolor\": ELEVATED_BG,\n        \"bordercolor\": INK_SOFT,\n        \"borderwidth\": 1,\n        \"orientation\": \"h\",\n        \"yanchor\": \"bottom\",\n        \"y\": 1.02,\n        \"xanchor\": \"center\",\n        \"x\": 0.5,\n    },\n    margin={\"l\": 220, \"r\": 80, \"t\": 130, \"b\": 80},\n    bargap=0.3,\n)\n\n# Update bar appearance\nfig.update_traces(marker={\"line\": {\"color\": PAGE_BG, \"width\": 1}}, opacity=0.9)\n\n# Save as PNG\nfig.write_image(f\"plot-{THEME}.png\", width=1600, height=900, scale=3)\n\n# Save interactive HTML\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}