Download Examples and Best Practices¶
This notebook demonstrates various download link scenarios and TOC integration patterns.
Quick Start¶
When you view this page in the built documentation, you'll see:
- A download link at the top of the page
- This TOC structure in the sidebar
- Clickable section navigation
In [ ]:
Copied!
# Example mkdocs.yml configuration
config = """
plugins:
- mkdocs-jupyter:
include_source: true # This enables download links
"""
print("Download links are now enabled!")
# Example mkdocs.yml configuration
config = """
plugins:
- mkdocs-jupyter:
include_source: true # This enables download links
"""
print("Download links are now enabled!")
TOC Configuration Options¶
Control how the table of contents is generated:
In [ ]:
Copied!
# Advanced TOC configuration
advanced_config = """
plugins:
- mkdocs-jupyter:
include_source: true
toc_depth: 3 # Include h1, h2, h3 in TOC
enable_default_notebooks_toc: true # Extract from markdown headings
enable_default_jupyter_toc: true # Jupyter-style TOC
"""
print("Advanced TOC features configured!")
# Advanced TOC configuration
advanced_config = """
plugins:
- mkdocs-jupyter:
include_source: true
toc_depth: 3 # Include h1, h2, h3 in TOC
enable_default_notebooks_toc: true # Extract from markdown headings
enable_default_jupyter_toc: true # Jupyter-style TOC
"""
print("Advanced TOC features configured!")
In [ ]:
Copied!
# Example: Custom download link handler
def create_secure_download_link(notebook_path, user_role):
"""
Generate a secure download link based on user permissions.
Args:
notebook_path: Path to the notebook file
user_role: User's role (member, guest, admin)
Returns:
Secure download URL or None if unauthorized
"""
allowed_roles = ["member", "admin"]
if user_role in allowed_roles:
# Generate time-limited signed URL
import hashlib
import time
timestamp = int(time.time())
secret = "your-secret-key"
# Create signature
data = f"{notebook_path}{timestamp}{secret}"
signature = hashlib.sha256(data.encode()).hexdigest()[:16]
return f"/secure-download/{notebook_path}?t={timestamp}&s={signature}"
return None
# Test the function
link = create_secure_download_link("analysis.ipynb", "member")
print(f"Secure download link: {link}")
# Example: Custom download link handler
def create_secure_download_link(notebook_path, user_role):
"""
Generate a secure download link based on user permissions.
Args:
notebook_path: Path to the notebook file
user_role: User's role (member, guest, admin)
Returns:
Secure download URL or None if unauthorized
"""
allowed_roles = ["member", "admin"]
if user_role in allowed_roles:
# Generate time-limited signed URL
import hashlib
import time
timestamp = int(time.time())
secret = "your-secret-key"
# Create signature
data = f"{notebook_path}{timestamp}{secret}"
signature = hashlib.sha256(data.encode()).hexdigest()[:16]
return f"/secure-download/{notebook_path}?t={timestamp}&s={signature}"
return None
# Test the function
link = create_secure_download_link("analysis.ipynb", "member")
print(f"Secure download link: {link}")
Time-Limited Access¶
Implement expiring download links:
In [ ]:
Copied!
from datetime import datetime, timedelta
import jwt # Note: requires PyJWT
def create_expiring_link(notebook_path, expiry_hours=24):
"""
Create a download link that expires after specified hours.
"""
# Token payload
payload = {
"notebook": notebook_path,
"exp": datetime.utcnow() + timedelta(hours=expiry_hours),
"iat": datetime.utcnow(),
}
# Generate token (in production, use proper secret management)
secret = "your-secret-key"
token = jwt.encode(payload, secret, algorithm="HS256")
return f"/download/{notebook_path}?token={token}"
# Example usage
temp_link = create_expiring_link("workshop-materials.ipynb", expiry_hours=48)
print(f"This link expires in 48 hours: {temp_link[:50]}...")
from datetime import datetime, timedelta
import jwt # Note: requires PyJWT
def create_expiring_link(notebook_path, expiry_hours=24):
"""
Create a download link that expires after specified hours.
"""
# Token payload
payload = {
"notebook": notebook_path,
"exp": datetime.utcnow() + timedelta(hours=expiry_hours),
"iat": datetime.utcnow(),
}
# Generate token (in production, use proper secret management)
secret = "your-secret-key"
token = jwt.encode(payload, secret, algorithm="HS256")
return f"/download/{notebook_path}?token={token}"
# Example usage
temp_link = create_expiring_link("workshop-materials.ipynb", expiry_hours=48)
print(f"This link expires in 48 hours: {temp_link[:50]}...")
Dynamic TOC Generation¶
You can programmatically generate TOC entries:
In [ ]:
Copied!
# Generate TOC from data
sections = [
"Data Collection",
"Data Cleaning",
"Exploratory Analysis",
"Model Training",
"Results",
]
# Create markdown headings
from IPython.display import Markdown, display
toc_md = "### Analysis Sections\n\n"
for i, section in enumerate(sections, 1):
toc_md += f"#### {i}. {section}\n"
toc_md += f"Content for {section} goes here...\n\n"
display(Markdown(toc_md))
# Generate TOC from data
sections = [
"Data Collection",
"Data Cleaning",
"Exploratory Analysis",
"Model Training",
"Results",
]
# Create markdown headings
from IPython.display import Markdown, display
toc_md = "### Analysis Sections\n\n"
for i, section in enumerate(sections, 1):
toc_md += f"#### {i}. {section}\n"
toc_md += f"Content for {section} goes here...\n\n"
display(Markdown(toc_md))
In [ ]:
Copied!
from IPython.display import HTML
# Custom download button HTML
download_button = """
<div style="margin: 20px 0; padding: 15px; background-color: #f0f0f0; border-radius: 5px;">
<h4 style="margin-top: 0;">Download This Notebook</h4>
<p>Get the source code and run it locally:</p>
<a href="./download-examples.ipynb"
download="download-examples.ipynb"
style="display: inline-block; padding: 10px 20px; background-color: #2196F3;
color: white; text-decoration: none; border-radius: 3px;">
⬇ Download Notebook
</a>
</div>
"""
display(HTML(download_button))
from IPython.display import HTML
# Custom download button HTML
download_button = """
"""
display(HTML(download_button))
Download Tracking¶
Monitor download activity:
In [ ]:
Copied!
import json
from datetime import datetime
class DownloadTracker:
"""Track notebook downloads for analytics."""
def __init__(self, log_file="download_log.json"):
self.log_file = log_file
def log_download(self, notebook_path, user_id=None, metadata=None):
"""Log a download event."""
event = {
"timestamp": datetime.utcnow().isoformat(),
"notebook": notebook_path,
"user_id": user_id or "anonymous",
"metadata": metadata or {},
}
# In production, write to database or analytics service
print(f"Download logged: {json.dumps(event, indent=2)}")
return event
def get_download_stats(self, notebook_path):
"""Get download statistics for a notebook."""
# Simulated stats
return {
"total_downloads": 42,
"unique_users": 28,
"last_download": datetime.utcnow().isoformat(),
"popular_times": ["09:00-10:00", "14:00-15:00"],
}
# Example usage
tracker = DownloadTracker()
tracker.log_download("analysis.ipynb", user_id="user123")
stats = tracker.get_download_stats("analysis.ipynb")
print(f"\nDownload stats: {json.dumps(stats, indent=2)}")
import json
from datetime import datetime
class DownloadTracker:
"""Track notebook downloads for analytics."""
def __init__(self, log_file="download_log.json"):
self.log_file = log_file
def log_download(self, notebook_path, user_id=None, metadata=None):
"""Log a download event."""
event = {
"timestamp": datetime.utcnow().isoformat(),
"notebook": notebook_path,
"user_id": user_id or "anonymous",
"metadata": metadata or {},
}
# In production, write to database or analytics service
print(f"Download logged: {json.dumps(event, indent=2)}")
return event
def get_download_stats(self, notebook_path):
"""Get download statistics for a notebook."""
# Simulated stats
return {
"total_downloads": 42,
"unique_users": 28,
"last_download": datetime.utcnow().isoformat(),
"popular_times": ["09:00-10:00", "14:00-15:00"],
}
# Example usage
tracker = DownloadTracker()
tracker.log_download("analysis.ipynb", user_id="user123")
stats = tracker.get_download_stats("analysis.ipynb")
print(f"\nDownload stats: {json.dumps(stats, indent=2)}")
In [ ]:
Copied!
# Test checklist
checklist = [
"✓ Download link appears at top of page",
"✓ Link downloads the correct notebook",
"✓ TOC shows all markdown headings",
"✓ TOC links navigate to sections",
"✓ Nested headings create nested TOC",
"✓ Download works on mobile devices",
"✓ Custom styling is applied",
"✓ Access control works (if implemented)",
]
for item in checklist:
print(item)
# Test checklist
checklist = [
"✓ Download link appears at top of page",
"✓ Link downloads the correct notebook",
"✓ TOC shows all markdown headings",
"✓ TOC links navigate to sections",
"✓ Nested headings create nested TOC",
"✓ Download works on mobile devices",
"✓ Custom styling is applied",
"✓ Access control works (if implemented)",
]
for item in checklist:
print(item)
Common Issues¶
Troubleshooting guide:
In [ ]:
Copied!
# Common issues and solutions
issues = {
"No download link": [
"Check include_source: true in mkdocs.yml",
"Verify mkdocs-jupyter plugin is installed",
"Rebuild the site with mkdocs build",
],
"TOC missing entries": [
"Ensure headings use proper markdown syntax",
"Check toc_depth setting",
"Verify enable_default_notebooks_toc: true",
],
"Download fails": [
"Check file permissions",
"Verify notebook path is correct",
"Test with a simple notebook first",
],
}
for issue, solutions in issues.items():
print(f"\n{issue}:")
for solution in solutions:
print(f" - {solution}")
# Common issues and solutions
issues = {
"No download link": [
"Check include_source: true in mkdocs.yml",
"Verify mkdocs-jupyter plugin is installed",
"Rebuild the site with mkdocs build",
],
"TOC missing entries": [
"Ensure headings use proper markdown syntax",
"Check toc_depth setting",
"Verify enable_default_notebooks_toc: true",
],
"Download fails": [
"Check file permissions",
"Verify notebook path is correct",
"Test with a simple notebook first",
],
}
for issue, solutions in issues.items():
print(f"\n{issue}:")
for solution in solutions:
print(f" - {solution}")
Summary¶
Download links and TOC integration provide:
- Easy access to source notebooks
- Better navigation within long notebooks
- Flexibility for custom implementations
- Security options for restricted content
This notebook itself demonstrates all these features - check the download link at the top and the TOC in the sidebar!