Overview
This skill generates Hebrew presentations with correct right-to-left (RTL) layout. It covers two practical output paths: Marp markdown for developers who want version-controlled, text-based slides, and python-pptx for anyone who needs a .pptx file compatible with PowerPoint and Google Slides.
Hebrew presentations have unique technical requirements that generic presentation tools ignore. Bullet alignment defaults to LTR. Punctuation jumps to the wrong end of a line. Number formatting in Israeli business contexts follows conventions that differ from what US-centric templates assume. This skill addresses all of those problems with working code and explicit configuration rather than workarounds.
Instructions
Follow these steps to produce a correct RTL Hebrew deck:
- Choose the output path: Marp markdown for version-controlled, text-based slides, or python-pptx for a
.pptxfile that opens cleanly in PowerPoint and Google Slides. For Israeli business recipients, prefer python-pptx (XML-level RTL is reliable); use Marp PDF for read-only sharing. - Pick the font: Heebo for business and tech decks, David Libre for formal reports, Assistant for education, Rubik for bold startup decks. Load via
@importin Marp CSS, or ensure the font is installed on the machine running python-pptx. - Generate the content: write the slide text in Hebrew. Structure pitch decks per the Israeli VC ordering below; use NIS formatting and the Israeli fiscal calendar.
- Apply the RTL patches: for Marp, set
direction: rtl; text-align: rightin the theme CSS. For python-pptx, callset_paragraph_rtl()on every paragraph that holds Hebrew text, plus the table-cell and inline-English helpers inreferences/pptx-rtl-patches.md. For charts, speaker notes, and the slide master, see the dedicated sections below. - Export: run
marp presentation.md --pptx(or--pdf/--html), orprs.save(output_path)in python-pptx. - Verify: open the file and confirm bullets align right, punctuation sits at the correct end of each line, the currency symbol is placed correctly, and tables read right-to-left. Inspect the XML if a paragraph still renders LTR (each
<a:pPr>must carry thertl="1"attribute).
When to Use
- Startup pitch deck: Building a deck for Israeli VCs or accelerators (Pitango, Grove Ventures, OurCrowd) where the primary language is Hebrew. Confirm the fund is still active and still investing at your stage before tailoring a deck to it; the Israeli VC roster turns over, and an earlier edition of this skill named a fund that does not exist.
- Quarterly business report: Presenting KPIs, P&L, or operational metrics in Hebrew with NIS figures and Israeli fiscal calendar.
- Marketing campaign deck: Internal or client-facing decks for campaigns, product launches, or brand presentations in Hebrew.
- Educational slides: University lectures, school materials, training sessions, or workshops delivered in Hebrew.
- Bilingual investor materials: Decks that mix Hebrew narrative with English technical details or financial tables.
Do not use this skill for fully English presentations (use standard Marp or PowerPoint templates), video export, or interactive web-based slideshows (use Reveal.js separately).
Quick Start
Ask your AI agent:
Create a 10-slide startup pitch deck in Hebrew for a B2B SaaS company in the legal-tech space.
Include: problem, solution, product demo, market size, business model, traction, team, and ask.
Use Marp format with RTL Hebrew layout.
Or for a PPTX file:
Create a quarterly business report presentation in Hebrew (12 slides) as a .pptx file.
Include NIS financial figures, charts placeholders, and Hebrew section headers.
Slide Generation Approaches
Marp (Markdown Presentations)
Marp converts Markdown into slides. It is developer-friendly, version-controllable, and outputs PDF, HTML, or PPTX. RTL support is implemented via CSS directives embedded in the Marp theme.
Marp does not have native RTL support at the engine level. RTL is achieved by setting direction: rtl and text-align: right in the theme CSS, and using a Hebrew-capable font. This is a CSS-level workaround, but it is robust and widely used.
Install Marp CLI:
npm install -g @marp-team/marp-cli
Basic Marp file structure with RTL:
---
marp: true
theme: rtl-hebrew
lang: he
---
<!-- _class: title -->
# כותרת המצגת
## כותרת משנה
---
# שקף ראשון
- נקודה ראשונה
- נקודה שנייה
- נקודה שלישית
Export commands:
marp presentation.md --pdf # Export to PDF
marp presentation.md --html # Export to HTML
marp presentation.md --pptx # Export to PPTX (requires an installed browser)
python-pptx (Native PPTX)
python-pptx creates .pptx files directly. RTL support requires XML-level patches because python-pptx's Python API does not expose the RTL paragraph attribute. You set the rtl="1" attribute on each paragraph's <a:pPr> element after adding text (this is what PowerPoint itself writes). DrawingML has no run-level direction toggle, so inline English runs render LTR via the Unicode bidi algorithm with no per-run XML patch.
Install:
pip install python-pptx
See scripts/create-presentation.py for a complete working example with all RTL patches applied.
Google Slides API
For Google Slides output, the Slides REST API sets paragraph direction through ParagraphStyle.direction, applied with an UpdateParagraphStyleRequest inside batchUpdate. The enum values are LEFT_TO_RIGHT and RIGHT_TO_LEFT, and the API documents that direction is not inherited: if unset it defaults to LEFT_TO_RIGHT, so every Hebrew paragraph must be set explicitly. The RTL surface is still narrower than PowerPoint's. This path is more involved and requires OAuth; in most cases it is simpler to generate the deck with python-pptx and import the .pptx into Google Slides.
Hebrew RTL Configuration
Marp CSS Theme
Save as themes/rtl-hebrew.css and reference it in your Marp config:
/* themes/rtl-hebrew.css */
@import url('https://fonts.googleapis.com/css2?family=Heebo:wght@300;400;700&display=swap');
section {
direction: rtl;
text-align: right;
font-family: 'Heebo', 'David Libre', Arial, sans-serif;
font-size: 28px;
background: #ffffff;
color: #1a1a2e;
padding: 60px 80px;
}
h1, h2, h3 {
text-align: right;
direction: rtl;
font-weight: 700;
}
ul, ol {
direction: rtl;
text-align: right;
padding-right: 1.5em;
padding-left: 0;
}
/* Reverse list marker position for RTL */
ul li::marker,
ol li::marker {
unicode-bidi: plaintext;
}
/* Override for LTR content blocks (English code, URLs) */
.ltr {
direction: ltr;
text-align: left;
font-family: 'Courier New', monospace;
}
Reference in .marprc.yml:
theme: ./themes/rtl-hebrew.css
html: true
python-pptx XML Patches
python-pptx exposes the paragraph.alignment property but not the rtl XML attribute on <a:pPr>. The patch sets that attribute directly:
from pptx.oxml.ns import qn
from lxml import etree
def set_paragraph_rtl(paragraph):
"""Set the rtl="1" attribute on a paragraph's pPr element."""
pPr = paragraph._p.get_or_add_pPr()
pPr.set('rtl', '1') # paragraph-level RTL is an attribute, not a child element
stale = pPr.find(qn('a:rtl')) # drop any invalid child <a:rtl> from old versions
if stale is not None:
pPr.remove(stale)
Call this on every paragraph that contains Hebrew text. See references/pptx-rtl-patches.md for the full patch set including table cells and text frames.
Font Recommendations
| Font | Style | Notes |
|---|---|---|
| Heebo | Clean, modern sans-serif | Best for business/tech decks. Available on Google Fonts. |
| David Libre | Classic serif | Formal reports, legal documents. Available on Google Fonts. |
| Assistant | Rounded, approachable | Education, consumer-facing decks. Available on Google Fonts. |
| Rubik | Geometric, strong | Startup decks, bold headers. Available on Google Fonts. |
For Marp, load fonts via @import url(...) in the theme CSS. For python-pptx, fonts must be installed on the system running the script, or embedded in the PPTX by specifying the font name in text run properties.
Native Charts in python-pptx
Quarterly reports and pitch decks need real charts, not image placeholders. python-pptx creates native, editable PowerPoint charts via slide.shapes.add_chart. The chart object stays editable in PowerPoint, which Israeli recipients expect.
from pptx.chart.data import CategoryChartData
from pptx.enum.chart import XL_CHART_TYPE, XL_LEGEND_POSITION
from pptx.util import Inches, Pt
def add_revenue_chart(slide):
chart_data = CategoryChartData()
# Category labels are Hebrew. Reverse the order so the axis reads
# right-to-left visually (Q1 on the right, Q4 on the left).
chart_data.categories = ['רבעון 4', 'רבעון 3', 'רבעון 2', 'רבעון 1']
chart_data.add_series('הכנסות (מיליוני ש"ח)', (4.8, 3.9, 3.1, 2.4))
graphic_frame = slide.shapes.add_chart(
XL_CHART_TYPE.COLUMN_CLUSTERED,
Inches(0.6), Inches(1.6), Inches(8.8), Inches(4.0),
chart_data,
)
chart = graphic_frame.chart
chart.has_legend = True
chart.legend.position = XL_LEGEND_POSITION.BOTTOM
chart.legend.include_in_layout = False
# Set the category axis font to a Hebrew font so the labels render.
category_axis = chart.category_axis
category_axis.tick_labels.font.name = 'Heebo'
category_axis.tick_labels.font.size = Pt(12)
chart.value_axis.tick_labels.font.name = 'Heebo'
return chart
Hebrew Chart Quirks
- Category-axis labels: python-pptx does not expose an RTL toggle for the chart plot area. Reverse the
categorieslist so the visual left-to-right order matches the reader's right-to-left expectation (the first item appears on the right of the axis). This mirrors the table column-order rule. - Hebrew labels need a Hebrew font: set
chart.category_axis.tick_labels.font.nameandchart.value_axis.tick_labels.font.nameexplicitly. The chart does not inherit the slide theme font, and the default falls back to a non-Hebrew face that renders boxes. - Series names: a Hebrew series name in the legend renders correctly with a Hebrew font set, but mixed Hebrew/Latin series names (for example
הכנסות ARR) can show the Latin token displaced. Keep series names in one script where possible. - Useful
XL_CHART_TYPEvalues:COLUMN_CLUSTEREDandBAR_CLUSTEREDfor comparisons (bar charts read naturally in RTL since the bars grow from the right baseline if you reverse categories),LINEfor trends,PIEandDOUGHNUTfor share-of-total. For a KPI grid, several smallCOLUMN_CLUSTEREDcharts read better than one dense chart. - Number formatting: set
chart.value_axis.tick_labels.number_formatto a NIS-aware format string (for example'₪#,##0') andnumber_format_is_linked = Falseso the comma thousands separator shows.
Israeli Presentation Conventions
Startup Pitch Deck Structure (Israeli VC Format)
Israeli VCs expect a specific ordering that differs from Silicon Valley conventions. The emphasis is on technical proof early, team credibility through military/academic context, and dual-market sizing.
Recommended 10-slide structure:
- כותרת וסלוגן (Title + tagline): One sentence, no fluff.
- הבעיה (Problem): Specific, quantified. Name Israeli companies or regulations affected if relevant.
- הפתרון (Solution): Product screenshot or diagram on first presentation, not slide 5.
- הדגמה / פרודקט (Demo/Product): Actual UI or architecture diagram. Investors expect proof early.
- גודל שוק (Market Size): TAM/SAM/SOM. Show Israel TAM separately from global. Use NIS for local figures, USD for global.
- מודל עסקי (Business Model): Pricing in NIS (Israeli market) and USD (export). ARR, not MRR, for B2B.
- מנוע צמיחה (Growth): GTM for Israel first, then EMEA. Israeli reference customers carry disproportionate weight.
- טרקשן (Traction): Numbers. Revenue, pilot customers, LOIs. Israeli VCs weight signed agreements heavily.
- צוות (Team): Military unit context (8200, Mamram, Shaldag) and academic credentials (Technion, TAU, Hebrew University) are standard and expected.
- הבקשה (The Ask): Amount in USD. Round in NIS equivalent at current rate is a nice touch for local VCs.
NIS Currency Formatting
Use the shekel sign with no space before the number: ₪1,234,567
For thousands: Israeli convention in formal documents uses comma as the thousands separator (matching international financial standards), not period. ₪1,234,567.89 is correct. ₪1.234.567,89 is German-style and incorrect for Israeli business documents.
In mixed Hebrew/English documents, place the ₪ symbol before the number even in RTL text (the symbol itself is LTR). Use Unicode bidirectional control characters if the rendering engine displaces it: \u200e (LRM) before the currency symbol forces correct placement.
Israeli Fiscal Year
Israel's tax year runs January to December, the same as the calendar year, unlike the UK or US government fiscal years. The Income Tax Ordinance defines it as twelve consecutive months beginning 1 January, with one exception: a taxpayer may be assigned a special assessment period (tkufat shuma meyuchedet), so confirm with the client before labelling a quarterly deck if they are unusual in that way. Quarterly reports use Q1-Q4 with the following Hebrew labels:
- Q1: רבעון ראשון (ינואר-מרץ)
- Q2: רבעון שני (אפריל-יוני)
- Q3: רבעון שלישי (יולי-ספטמבר)
- Q4: רבעון רביעי (אוקטובר-דצמבר)
Hebrew Date Format
Standard Israeli date format: DD/MM/YYYY or DD ב<שם החודש> YYYY, where the placeholder is the Hebrew month name prefixed with ב, for example 27 באוגוסט 2026. Do not emit the literal word בחודש. For slide footers, מרץ 2026 is cleaner than 03/2026.
Education Slides
For educational content, bullet formatting differs from business:
- Use
•(U+2022) rather than-for bullet markers. They render more reliably in RTL. - Numbered lists in Hebrew run right to left but numbers are still Arabic numerals (1, 2, 3), not Hebrew letters, in most modern contexts.
- Avoid putting English terms in parentheses after Hebrew terms in body text. Put them in footnotes or a separate glossary slide.
Bilingual Slides
Mixing Hebrew and English
When a single slide needs both Hebrew and English (common in tech decks where code, API names, or English product names appear):
In Marp, wrap LTR blocks in a <div> with inline style:
# כותרת בעברית
- נקודה עברית ראשונה
- שימוש ב-<span style="direction:ltr;display:inline-block">API endpoint: /v1/users</span>
<div style="direction:ltr; text-align:left; font-family: monospace">
```python
response = client.get("/v1/users")
In python-pptx, set separate runs within the same paragraph, applying RTL to Hebrew runs and LTR to English runs:
from pptx.util import Pt
from pptx.oxml.ns import qn
from lxml import etree
def add_mixed_paragraph(text_frame, hebrew_text, english_term):
para = text_frame.add_paragraph()
set_paragraph_rtl(para) # RTL for the whole paragraph
# Hebrew run
run_he = para.add_run()
run_he.text = hebrew_text
run_he.font.name = 'Heebo'
# English term run within an RTL paragraph: no run-level RTL XML exists
# in DrawingML, so the bidi algorithm renders the Latin run LTR on its
# own. Set lang only as a proofing hint. If the Latin fragment is glued
# to Hebrew with no space, wrap it in bidi isolates (LRI U+2066 ...
# PDI U+2069) in the text instead.
run_en = para.add_run()
run_en.text = f' {english_term}'
run_en.font.name = 'Calibri'
run_en._r.get_or_add_rPr().set('lang', 'en-US')
Title Slides with Both Languages
A common Israeli business pattern: Hebrew title on line one, English subtitle on line two. Both are handled correctly if you set the text frame to RTL and override alignment for the English line.
Mixed Hebrew and Latin Inside a Single Word or Tight Token
The paragraph-level RTL attribute plus the bidi algorithm above handle Hebrew sentences with separate English words. The harder, and far more common, real-world bug is a single token that mixes scripts with no whitespace boundary: B2B-חברות, חברת-SaaS, a version string like גרסה-2.0, or a hashtag like #עברית2026. The bidi algorithm reorders the run at every script boundary inside the token, so B2B-חברות can display as חברות-B2B even though it is one visual word.
This happens inside the Unicode Bidirectional Algorithm, which runs over the paragraph's character stream. A DrawingML <a:r> run boundary is a formatting artifact and is not an input to it, so B2B-חברות reorders identically whether you write it as one run or three. What actually reorders it is that the hyphen is a neutral character sitting between a strong LTR run (B2B) and a strong RTL run (חברות), so the algorithm resolves it toward the surrounding text rather than leaving it where you typed it. Splitting or merging runs will not change the outcome; only inserting directional characters will.
Fixes, in order of reliability:
- Anchor neutrals with bidi marks. Wrap the Latin fragment in directional isolates so it cannot leak into the surrounding Hebrew:
(LRI, Left-to-Right Isolate) before and(PDI, Pop Directional Isolate) after. For a single Latin run inside an RTL paragraph,(LRM) immediately after the Latin fragment pins the trailing neutral. Example:f'B2B-חברות'. - Do not try to fix this by restructuring runs. Run boundaries are invisible to the bidi algorithm, so splitting or merging them changes nothing. Keeping a token in one run is good hygiene for font and colour, not a bidi fix.
- For version strings and identifiers, isolate them the same way:
Ver 2.0with LRI before and PDI after. Do not reach for LRM or RLM here. Those are strong characters, not isolation: they pin an adjacent neutral to a direction but cannot make a span behave as a self-contained island, which is exactly what a mixed-script token needs. LRI/PDI is the mechanism that does.
def add_intratoken_run(paragraph, hebrew_part, latin_part, sep='-'):
"""Add a token like 'B2B-חברות' with the Latin fragment bidi-isolated.
Embeds LRI/PDI around the Latin fragment so the script boundary
does not let the bidi algorithm reorder the token.
"""
run = paragraph.add_run()
# = LRI, = PDI. The separator stays on the Hebrew side.
run.text = f'{latin_part}{sep}{hebrew_part}'
run.font.name = 'Heebo'
return run
In Marp, wrap the Latin fragment in <span dir="ltr"> (requires html: true), or use the same / characters directly in the Markdown. CSS unicode-bidi: isolate on an inline span achieves the same effect without literal control characters.
Speaker Notes, Slide Master, and Image Placement
- Speaker notes RTL: notes have their own text frame, reached via
slide.notes_slide.notes_text_frame. They are not patched by slide-body RTL helpers. Callset_text_frame_rtl(slide.notes_slide.notes_text_frame)after writing notes, or Hebrew notes render LTR in the presenter view. - Slide master and layout defaults: setting RTL on each paragraph is reliable but repetitive. To make RTL the default for a layout, patch the
<a:lstStyle>(list style) inside the placeholder's<p:txBody>on the slide layout (prs.slide_layouts[i]) or slide master (prs.slide_masters[0]): set thertl="1"attribute on each level's paragraph-properties element (<a:lvl1pPr>...<a:lvl9pPr>). New placeholders that inherit from that layout then start RTL. This does not retroactively fix existing slides; it only changes the default for placeholders created afterward. - Image and logo placement in RTL:
add_picturepositions images by absolute EMU coordinates, so RTL does not move them automatically. By Israeli convention, the company logo sits in the top-right corner (the start of the reading flow). Compute the right-edge position asprs.slide_width - Inches(logo_width) - Inches(margin)rather than hardcoding a left offset, so the logo stays anchored to the visual start of the slide regardless of slide width.
Gotchas
1. Hebrew punctuation displacement in PPTX exports
When exporting to PPTX from tools that do not set RTL at the XML level, periods and commas jump to the opposite end of the line. A sentence like הפתרון שלנו. renders as .הפתרון שלנו visually. The fix is the rtl="1" attribute on every paragraph's <a:pPr> in the XML, not just at the text-frame level. The text-frame-level txBody attribute is insufficient; each <a:pPr> needs it.
2. Default bullet alignment is LTR
Both Marp (without custom CSS) and python-pptx (without XML patches) default all bullet lists to LTR. You will see bullets flush to the left margin with text flowing left-to-right. This is the single most common Hebrew presentation bug. It must be overridden explicitly: CSS direction: rtl; text-align: right for Marp, and the rtl attribute on <a:pPr> for PPTX. There is no global toggle in either tool.
3. Number formatting ambiguity
Israeli convention uses comma as the thousands separator for financial figures (matching the English-language standard). However, some Israeli government and academic documents use a period for thousands. Before generating slides with large numbers, confirm which convention the audience expects. For business and VC presentations, always use comma: ₪1,234,567. For government reports, ask explicitly.
4. Font fallback silently degrades quality
If Heebo or David Libre are not installed on the rendering machine, Marp and PPTX viewers fall back to Arial or Times New Roman. Both support Hebrew but are visually inferior and may have different line-height metrics that break slide layouts. Always verify font availability before presenting. For Marp PDF export, fonts are embedded via Chromium, so the export is safe. For PPTX shared to other machines, embed fonts via File > Options > Save > Embed fonts in the file (PowerPoint). python-pptx 1.0.x does not expose a high-level EmbedTrueTypeFonts property; embedding via the library still requires direct XML edits to the .pptx package.
5. Table column order needs its own attribute, and cell patches do not provide it
Column order and cell-text direction are two different OOXML settings, and the one everybody reaches for is the wrong one. Patching each cell's <a:pPr> sets the direction of the text inside that cell and leaves the columns running left-to-right. Column order is governed by the rtl attribute on <a:tblPr>, which python-pptx does not expose, so it has to be set through the XML:
tblPr = table._tbl.find(qn('a:tblPr'))
if tblPr is None:
tblPr = etree.SubElement(table._tbl, qn('a:tblPr'))
tblPr.set('rtl', '1')
Once it is set, column index 0 is the rightmost column, so populate your data in natural Hebrew reading order and do not pre-reverse it. Reversing the data as well is the classic double-reversal: through an earlier version of this skill the attribute was never set while the docs told you to reverse, so every generated table came out mirrored. Verify a table-heavy deck in PowerPoint; LibreOffice Impress ignores this attribute, so a LibreOffice render can show you a bug but cannot confirm the fix.
Output Formats
| Tool | Input | Output formats | RTL quality |
|---|---|---|---|
| Marp CLI | .md |
PDF, HTML, PPTX | Good (CSS-level) |
| python-pptx | Python script | .pptx |
Excellent (XML-level) |
| Google Slides API | API calls | Google Slides, PDF | Partial: ParagraphStyle.direction is documented, but the RTL surface is narrower than PPTX and direction is not inherited |
| LibreOffice Impress | .odp / .pptx |
PDF, PPTX | Partial (varies by version) |
For maximum compatibility with Israeli business recipients (who almost universally use Windows + PowerPoint or Google Slides), prefer python-pptx output. Marp PDF export is best for read-only sharing (email attachments, pitch email).
Examples
Example 1: Startup Pitch Deck with python-pptx
Input: "Create a 5-slide Hebrew pitch deck for a B2B SaaS legal-tech company. Include title, problem, solution, technical integration, and a Q1 metrics table. Output a .pptx file."
Process:
- Choose python-pptx (recipient is an Israeli VC who will open it in PowerPoint).
- Pick Heebo (business/tech deck).
- Write Hebrew content per the Israeli VC 10-slide ordering, trimmed to 5 slides.
- Build each slide with
scripts/create-presentation.pypatterns:set_paragraph_rtl()on every title and bullet,add_english_run()for inline Latin product names, an RTL table with reversed column order for the metrics slide. - Export via
prs.save('pitch-deck.pptx'). - Open in PowerPoint, confirm bullets align right,
₪3.4Mshows the symbol on the correct side, and the table reads right-to-left.
Output: a .pptx where slide 2 ("הבעיה") shows four right-aligned Hebrew bullets, slide 4 mixes הפלטפורמה שלנו מתחברת ישירות ל-Salesforce CRM with the Latin product name as an LTR island, and slide 5 renders a metrics table with מדד as the rightmost column. Running python scripts/create-presentation.py --output pitch-deck.pptx --title "שם החברה" produces exactly this deck.
Example 2: Quarterly Report with a Native Chart in Marp
Input: "Build a Hebrew quarterly business report. Slide 1 is a title, slide 2 shows Q1-Q4 revenue as a chart, slide 3 is a financial table. Marp format, export to PDF."
Process:
- Choose Marp (text-based, version-controlled, PDF export for email distribution).
- Pick Heebo, loaded via
@importinthemes/rtl-hebrew.css. - Write the deck markdown with
marp: true,theme: rtl-hebrew,lang: he. There is nodirdirective in Marpit, so do not add one; RTL comes from the theme CSS. - Apply RTL via the theme CSS (
direction: rtl; text-align: right). For the revenue chart, Marp has no native chart engine, so either embed a pre-rendered chart image or generate the chart slide with python-pptx and theadd_revenue_chartpattern, then merge. Write the financial table with columns in right-to-left visual order in the Markdown source. - Export via
marp report.md --pdf --allow-local-files -o report.pdf. - Open the PDF, confirm Hebrew renders with Heebo (fonts embed via the browser Marp drives), bullets and table columns flow right-to-left, and no slides are blank.
Output: a 3-slide PDF where the title slide is right-aligned, the revenue slide shows רבעון 1 through רבעון 4 with the first quarter on the right, and the financial table reads מדד | ממוצע ענף | החברה שלנו | שינוי from right to left.
Bundled Resources
scripts/create-presentation.py- Working python-pptx script that builds a complete 5-slide RTL Hebrew pitch deck (title, problem, solution, mixed-language technical slide, financial table). All RTL XML patches are applied. Runpython scripts/create-presentation.py --output deck.pptx --title "שם החברה". Use it as the canonical reference for the patch functions.references/marp-rtl-guide.md- Marp RTL configuration quick reference: minimum viable theme, project config, slide templates (title, content, two-column, code block, financial table), export commands, font loading options, a full business-grade theme, and known limitations.references/pptx-rtl-patches.md- The complete python-pptx RTL patch set: paragraph, text-frame, inline-English, table-cell, and table patches, the full slide-building pattern, reversed-column table helper, font embedding, and XML debugging snippets.
Reference Links
| Source | URL | What to Check |
|---|---|---|
| python-pptx | https://python-pptx.readthedocs.io/en/latest/ | Python library for PowerPoint generation, shape, text, and chart API |
| Marp | https://marp.app | Markdown-to-slides CLI, themes, PDF/HTML/PPTX export |
| pptxgenjs (JavaScript PPTX generator) | https://gitbrent.github.io/PptxGenJS/ | Node.js library for creating PowerPoint files, RTL support |
| Reveal.js | https://revealjs.com | HTML-based presentations, keyboard shortcuts, RTL layouts |
| Google Slides API | https://developers.google.com/slides/api | Slides REST API, batchUpdate, placeholders, text direction |
| Unicode Bidirectional Algorithm (UAX #9) | https://unicode.org/reports/tr9/ | Bidi reordering rules, isolates (LRI/PDI), directional marks |
| Google Fonts: Heebo | https://fonts.google.com/specimen/Heebo | Hebrew sans-serif, weights, download for local embedding |
| DrawingML text schema (ECMA-376) | https://www.datypic.com/sc/ooxml/e-a_pPr-1.html | CT_TextParagraphProperties: the rtl attribute lives on <a:pPr>, not on runs |
Troubleshooting
Text appears mirrored or reversed: The font is rendering but direction is not set. Add dir="rtl" to the HTML element (Marp HTML export) or verify the rtl="1" attribute is present on each <a:pPr> in the PPTX XML.
Bullet markers appear on the wrong side: CSS list-style-position: inside combined with direction: rtl fixes Marp. For PPTX, the bullet marker follows paragraph direction, so setting paragraph RTL is sufficient.
Mixed Hebrew/English line breaks poorly: Long English words in RTL paragraphs can cause unusual line breaks. Use word-break: break-word in Marp CSS, or break long English strings manually in PPTX.
Exported PDF has blank slides: Marp drives a real browser for PDF, PPTX and image export, and does not bundle one. Install Google Chrome, Microsoft Edge or Firefox, or point Marp at an existing binary with --browser-path. Run marp --allow-local-files presentation.md --pdf if fonts are local. marp --version reports Marp's own version only and tells you nothing about the browser, so do not use it to check this; if export fails, confirm a supported browser is installed.
PPTX opens with font substitution warning: The Hebrew font named in the PPTX is not installed on the recipient's machine. Either embed fonts or instruct recipients to install Heebo from Google Fonts before opening.
Currency symbol renders on wrong side: Insert \u200e (Left-to-Right Mark) immediately before ₪ in Hebrew text to anchor it correctly in the bidi algorithm.