Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/content/blog/how-to-do-meeting-minutes.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ source_knowcap_ids: []
read_minutes: 13
lang: en
dir: ltr
template_download_href: "/downloads/meeting-minutes-template.docx"
template_download_label: "Free meeting minutes template (.docx)"
---

# How to Do Meeting Minutes in 2026: Steps + Free Template
Expand Down
31 changes: 3 additions & 28 deletions app/content/blog/namuthaj-mahdar-ijtimaa-ar.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,40 +22,15 @@ source_knowcap_ids: []
read_minutes: 8
lang: ar
dir: rtl
template_download_href: "/downloads/namuthaj-mahdar-ijtimaa-template.docx"
template_download_label: "نموذج محضر اجتماع جاهز (.docx)"
---

محضر الاجتماع هو الوثيقة الرسمية التي تُدوَّن فيها أحداث الاجتماع: مكانه وزمانه، وأسماء الحاضرين والغائبين، والبنود التي نوقشت، والقرارات التي اتُّخذت، والمهام المُسندة لكل شخص. الغرض منه ليس تلخيص ما قيل، بل إثبات ما تم الاتفاق عليه حتى لا تختلف الذاكرة حوله بعد فترة. محضرٌ مكتوب جيداً يجيب عن ثلاثة أسئلة بوضوح: ماذا قرّرنا؟ ومن المسؤول عن كل قرار؟ وما الموعد النهائي؟ أما المحاضر الضعيفة فتسجّل النقاش وتغفل القرار، فتصبح بلا قيمة عند أول خلاف. في هذا الدليل نموذج محضر اجتماع جاهز يمكنك نسخه واستخدامه فوراً، ثم شرح عملي لكيفية كتابة محضر اجتماع خطوة بخطوة، ومن يكتبه ومتى، والعناصر التي يجب أن يتضمنها كل محضر رسمي.

## نموذج محضر اجتماع جاهز للنسخ

انسخ النموذج التالي واملأ الفراغات. صالح للاجتماعات الإدارية ومجالس الإدارة ولجان التدقيق:

```
محضر اجتماع: [اسم الجهة / اللجنة]
رقم الاجتماع: [ ] التاريخ: [ / / ] الوقت: من [ ] إلى [ ]
مكان الانعقاد: [حضوري / عن بُعد عبر … ]

الحاضرون: [الاسم — الصفة]
الغائبون (بعذر / بدون): [الاسم — الصفة]
رئيس الجلسة: [ ] مُحرِّر المحضر: [ ]

جدول الأعمال:
١. [البند الأول]
٢. [البند الثاني]
٣. [البند الثالث]

المناقشات والقرارات:
البند ١: [ملخّص النقاش] — القرار: [نص القرار] — التصويت: [بالإجماع / الأغلبية]
البند ٢: [ملخّص النقاش] — القرار: [نص القرار]

المهام والمسؤوليات:
| المهمة | المسؤول | الموعد النهائي |
| [ ] | [ ] | [ / / ] |

موعد الاجتماع القادم: [ / / ]
تم إقفال الجلسة الساعة: [ ]
التوقيعات: رئيس الجلسة [ ] — مُحرِّر المحضر [ ]
```
حمّل النموذج الجاهز أدناه (.docx — يفتح في Word أو Google Docs) واملأ الفراغات، أو انسخ عناصره من هنا: ترويسة، الحاضرون، جدول الأعمال، المناقشات والقرارات، المهام والمسؤوليات، موعد الاجتماع القادم والتوقيعات.

هذا نموذج أولي صالح لأغلب الاجتماعات؛ أما مجالس الإدارة واللجان النظامية فقد تحتاج حقولاً إضافية بحسب لائحتها — مثل النصاب، وصفة الحضور (أصالةً أو إنابةً)، والتحفّظات على القرارات. احفظ نسخة موحّدة واستخدمها في كل اجتماع؛ فالتنسيق الثابت يجعل المحاضر قابلة للمقارنة والمراجعة، وهو ما يسهّل التدقيق والحوكمة.

Expand Down
Binary file not shown.
47 changes: 41 additions & 6 deletions scripts/gen-template-docx.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,42 @@
from docx import Document
from docx.shared import Pt, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.oxml.ns import qn

ACCENT = RGBColor(0x1F, 0x6B, 0x3A)
INK = RGBColor(0x18, 0x18, 0x1B)
INK_2 = RGBColor(0x4A, 0x4F, 0x5A)


def is_section_heading(line: str) -> bool:
letters = [c for c in line if c.isalpha()]
return bool(letters) and line == line.upper() and len(line.strip()) > 1
def apply_rtl(paragraph):
"""Right-align + set bidi paragraph direction (python-docx has no high-level API for this)."""
paragraph.alignment = WD_ALIGN_PARAGRAPH.RIGHT
pPr = paragraph._p.get_or_add_pPr()
bidi = pPr.makeelement(qn('w:bidi'), {})
pPr.append(bidi)
for run in paragraph.runs:
rPr = run._r.get_or_add_rPr()
rtl = rPr.makeelement(qn('w:rtl'), {})
rPr.append(rtl)


def build(title: str, subtitle: str, text: str, out_path: str, source_url: str):
def is_section_heading(line: str) -> bool:
s = line.strip()
if len(s) <= 1:
return False
# Bare label ending in a colon (e.g. Arabic "جدول الأعمال:") — no cased
# script needed, works for any language.
if s.endswith(':') or s.endswith(':'):
return True
# ALL-CAPS heading in a cased script (e.g. "MEETING MINUTES"). str.isupper()
# is False for scripts with no case distinction (Arabic, CJK, digits-only),
# so this never false-positives on non-Latin text the way `s == s.upper()`
# would (that comparison is a no-op — and therefore always true — on
# uncased text).
return s.isupper()


def build(title: str, subtitle: str, text: str, out_path: str, source_url: str, rtl: bool = False):
doc = Document()

style = doc.styles["Normal"]
Expand All @@ -48,13 +72,17 @@ def build(title: str, subtitle: str, text: str, out_path: str, source_url: str):
run.bold = True
run.font.size = Pt(22)
run.font.color.rgb = INK
if rtl:
apply_rtl(h)

if subtitle:
sub = doc.add_paragraph()
srun = sub.add_run(subtitle)
srun.italic = True
srun.font.size = Pt(10.5)
srun.font.color.rgb = INK_2
if rtl:
apply_rtl(sub)

doc.add_paragraph()

Expand All @@ -70,13 +98,19 @@ def build(title: str, subtitle: str, text: str, out_path: str, source_url: str):
r.font.size = Pt(13)
r.font.color.rgb = ACCENT
p.space_before = Pt(10)
if rtl:
apply_rtl(p)
continue
if line.strip().startswith("- "):
doc.add_paragraph(line.strip()[2:], style="List Bullet")
p = doc.add_paragraph(line.strip()[2:], style="List Bullet")
if rtl:
apply_rtl(p)
continue
p = doc.add_paragraph()
r = p.add_run(line)
r.font.color.rgb = INK_2
if rtl:
apply_rtl(p)

doc.add_paragraph()
foot = doc.add_paragraph()
Expand All @@ -97,12 +131,13 @@ def main():
ap.add_argument("--text-file", required=True)
ap.add_argument("--out", required=True)
ap.add_argument("--source-url", default="knowcap.ai/blog")
ap.add_argument("--rtl", action="store_true", help="right-align + bidi paragraph direction (Arabic/Hebrew)")
args = ap.parse_args()

with open(args.text_file, "r", encoding="utf-8") as f:
text = f.read()

build(args.title, args.subtitle, text, args.out, args.source_url)
build(args.title, args.subtitle, text, args.out, args.source_url, rtl=args.rtl)


if __name__ == "__main__":
Expand Down
6 changes: 6 additions & 0 deletions scripts/publish-draft.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ function buildPublishedFrontmatter(meta, body) {
pub.lang = meta.lang || 'en'
pub.dir = meta.dir || 'ltr'

// Free downloadable template (tracked TemplateDownload component) — passthrough
if (meta.template_download_href) {
pub.template_download_href = meta.template_download_href
pub.template_download_label = meta.template_download_label || 'Download the template'
}

return pub
}

Expand Down