Syméon del Marmol
10/23/2025, 11:30 AMMarvin
10/23/2025, 11:30 AMMarvin
10/23/2025, 11:34 AM<table border="1"> aren’t reliable.
Workarounds and better options:
- Use a TableArtifact for tabular data. It renders with the UI’s table component (not customizable, but typically clearer than raw HTML-in-Markdown).
- If you need precise styling (borders, padding, fonts), render your report externally and:
- Publish an ImageArtifact (screenshot or generated image of your table/report).
- Publish a LinkArtifact to a hosted HTML report (e.g., S3/GCS/BI tool).
- For minor spacing in Markdown, add blank lines or use a horizontal rule (---) between sections. HTML tags for spacing aren’t guaranteed to render.
Examples:
from prefect.artifacts import (
create_markdown_artifact,
create_table_artifact,
create_image_artifact,
create_link_artifact,
)
# Markdown (plain styling)
create_markdown_artifact(
markdown="""
# Report
---
Some summary text.
## Section A
- Item 1
- Item 2
"""
)
# Table artifact (structured tabular display)
rows = [
{"Name": "Alice", "Score": 92},
{"Name": "Bob", "Score": 87},
]
create_table_artifact(rows)
# Image artifact (for fully custom-styled visuals you render elsewhere)
create_image_artifact(image_url="<https://your-bucket.s3.amazonaws.com/reports/run-123/table.png>")
# Link artifact (to a hosted HTML report with your own CSS)
create_link_artifact(
link_url="<https://your-bucket.s3.amazonaws.com/reports/run-123/index.html>",
link_text="Open detailed styled report"
)
Docs for reference:
- Artifacts guide: How to use artifacts
- SDK API reference: Artifacts API
If richer Markdown styling (margins, table borders/padding) would help your workflow, I’m happy to file a feature request or you can open one here: Discussions or Issues.
What specific styling do you need (e.g., border thickness, cell padding)? If you share an example, I can recommend the most practical approach (TableArtifact vs. image vs. hosted HTML).Syméon del Marmol
10/23/2025, 11:42 AMMarvin
10/23/2025, 11:42 AMMarvin
10/23/2025, 11:43 AMfrom prefect.artifacts import create_link_artifact
from prefect_aws.s3 import upload_to_bucket
from prefect_aws.credentials import AwsCredentials
bucket = "my-reports-bucket"
key = "runs/1234/index.html"
html = """<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Run 1234 Report</title></head>
<body><h1>Run 1234</h1><p>Styled HTML report...</p></body>
</html>
"""
# Upload HTML to S3
aws_creds = AwsCredentials(aws_access_key_id="...", aws_secret_access_key="...", region_name="us-east-1")
upload_to_bucket(
data=html.encode("utf-8"),
bucket=bucket,
aws_credentials=aws_creds,
key=key,
)
# Ensure the object is publicly readable (via bucket policy or your infra setup)
# Then choose one of these URLs depending on how you serve S3:
public_url = f"https://{bucket}.<http://s3.amazonaws.com/{key}|s3.amazonaws.com/{key}>"
# or, if using S3 static website hosting:
# public_url = f"http://{bucket}.<http://s3-website-us-east-1.amazonaws.com/{key}|s3-website-us-east-1.amazonaws.com/{key}>"
# Create a link artifact to the hosted HTML
create_link_artifact(
link=public_url,
link_text="Open styled HTML report",
key="run-1234-report"
)
Notes:
- Make sure the object is served with Content-Type text/html so browsers render it. If your upload path doesn’t set it, configure it via your S3 tooling/bucket policy/static website settings.
- If you prefer to keep the object private, you can generate a presigned URL (e.g., via boto3) and pass that to create_link_artifact, but it will expire.
Refs:
- Artifacts guide: How to use artifacts
- Artifacts API: Artifacts API
If you share whether you need a public or private link, I can tailor the snippet (e.g., presigned URL generation or CloudFront URL).