Developmental milestones paediatrics

Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
I now have comprehensive content from Harriet Lane and Kaplan & Sadock. I have enough to write a thorough, well-organized answer. Let me compile the full response.

Developmental Milestones in Paediatrics

Developmental assessment is based on the premise that milestone acquisition occurs at a specific rate, in an orderly and sequential manner. Milestones span four core domains: Motor (gross and fine), Language/Communication, Cognitive (problem-solving, learning), and Social/Emotional.

Primitive Reflexes (Birth)

Present at birth and must disappear on schedule - persistence is a red flag.
ReflexDisappears
Moro (startle) - arms abduct/extend when head drops~4 months
Grasp reflex~4 months
Tonic neck reflex ("fencing")~4 months
Babinski (plantar)~12 months
Rooting, suckingIntegrated ~4 months

Milestone Table by Age

2 Months

DomainMilestones
Social/EmotionalCalms when picked up or spoken to; smiles in response to face
LanguageMakes sounds other than crying; reacts to loud sounds
CognitiveWatches you move; looks at a toy for several seconds
MotorHolds head up while on tummy; opens hands briefly; moves all four limbs

4 Months

DomainMilestones
Social/EmotionalSmiles spontaneously to get attention; chuckles (not full laugh)
LanguageCooing sounds ("ooo", "aahh"); turns head toward voice; responds to speech
CognitiveOpens mouth when sees breast/bottle; looks at hands with interest
MotorHolds head steady when held; holds toy when placed in hand; pushes onto elbows when prone; brings hands to mouth

6 Months

DomainMilestones
Social/EmotionalRecognises familiar people; laughs; looks at self in mirror
LanguageTakes turns making sounds with caregiver; blows raspberries
CognitivePuts things in mouth; reaches for objects; closes lips to indicate "no more"
MotorRolls from tummy to back; sits with support; pushes up on straight arms when prone; leans on hands for support

9 Months

DomainMilestones
Social/EmotionalStranger/separation anxiety begins; shy with strangers
LanguageMakes different sounds ("mamama", "bababa"); lifts arms to be picked up
CognitiveLooks for objects when dropped; bangs two objects together
MotorSits without support; crawls; pulls to stand (some); picks up small objects with a raking grasp

12 Months

DomainMilestones
Social/EmotionalPlays pat-a-cake; waves bye-bye
LanguageSays "mama/dada" with intent; understands "no"; 1-2 words other than mama/dada (some)
CognitivePuts objects into containers; object permanence - looks for hidden toy
MotorPulls to stand; cruises along furniture; some take first steps; pincer grasp (thumb + index finger)

15 Months

DomainMilestones
Social/EmotionalCopies other children; shows affection; hugs stuffed toys; shows you objects they like
Language1-2 words beyond mama/dada; points to ask for things or get help; follows directions with gesture
CognitiveUses objects correctly (phone, cup, book); stacks 2 blocks
MotorTakes a few steps independently; feeds self finger food

18 Months

DomainMilestones
Social/EmotionalMoves away from parent but checks back; points to show interesting things; helps with dressing
Language3+ words beyond mama/dada; follows 1-step directions without gesture
CognitiveCopies simple chores (sweeping); simple pretend play
MotorWalks independently; scribbles; climbs onto couch/chair; tries to use spoon

24 Months (2 Years)

DomainMilestones
Social/EmotionalNotices others hurt/upset; looks to parent for cues in new situations
LanguagePoints to pictures in book when asked; 2-word phrases ("more milk"); names 2 body parts
CognitiveHolds something in one hand while using the other; plays with 2 toys at once
MotorRuns; kicks a ball; climbs; 50 recognisable words in vocabulary
Toilet training: Daytime urinary control usually complete by 2.5 years; night-time continence by 4 years.

30 Months (2.5 Years)

DomainMilestones
Social/EmotionalPlays alongside others; "parallel play"
Language2-3 word sentences; uses pronouns (I, me)
CognitiveNames some colours; completes simple puzzles
MotorJumps with both feet; turns book pages one at a time

3 Years

DomainMilestones
Social/EmotionalTakes turns; plays with other children (cooperative play begins); expresses love/jealousy/envy
Language3-word sentences; strangers can understand speech ~75%; asks "why?" frequently
CognitiveCounts to 3; draws a circle; undresses self; knows own name/age/sex
MotorPedals tricycle; runs well; hops on preferred foot

4 Years

DomainMilestones
Social/EmotionalPretend/dramatic play; concern for others; sharing improves; "Band-Aid phase" (preoccupied with bodily injury)
LanguageStrangers understand most speech; tells stories; uses sentences of 4-5 words
CognitiveNames some colours/letters; draws a person with 3 parts; understands "same/different"
MotorCatches a bounced ball; hops on one foot; can dress/undress with minimal help

5 Years

DomainMilestones
Social/EmotionalFollows rules in games; performs for others (sings/dances); does simple chores
LanguageTells a story with at least 2 events; maintains conversation (3+ exchanges); uses simple rhymes
CognitiveCounts to 10; names numbers 1-5; writes some letters; uses words about time ("yesterday/tomorrow"); pays attention for 5-10 minutes
MotorHops on one foot; buttons clothes

School-Age (6-12 Years)

  • Logical thinking dominates over fantasy; ability to concentrate well established by age 9-10
  • Abstract thinking begins to emerge by end of period
  • Best friend relationships form (Harry Stack Sullivan: necessary for healthy psychological development)
  • Moral development: until ~7 years, rules seen as absolute ("immanent justice")
  • Complex motor tasks (sports, gymnastics, writing fluently) achieved
  • Same-sex peer groups predominate
  • Gender identity is usually fixed by 24-30 months and is largely innate

Key "Red Flags" - When to Worry

(Harriet Lane Handbook, 23rd ed.)
At any age: Loss of previously acquired skills is always a red flag - refer immediately.
AgeRed Flag
2 monthsNot responding to loud sounds; not watching things that move; not smiling at people
4 monthsDoes not bring objects to mouth; does not push down with legs when feet placed on hard surface
6 monthsNo babbling; cannot sit with support
9 monthsNo back-and-forth gestures (pointing, waving)
12 monthsNo babbling; no gestures (pointing/waving); no single words by 16 months
18 monthsNo single words; no pointing
24 monthsNo 2-word meaningful phrases (without imitating); no pointing to pictures
Any ageRegression - losing language or social skills previously gained

Developmental Screening Tools

ToolAge RangeCompleted by
Ages and Stages Questionnaire (ASQ)4-60 monthsParent
Parents' Evaluation of Developmental Status (PEDS)0-8 yearsParent
Capute Scales (CLAMS + CAT)3-36 monthsClinician
M-CHAT-R/F (autism screen)16-30 monthsParent
CSBS DP Infant-Toddler Checklist (autism)6-24 monthsParent
AAP guidelines: Formal developmental screening at 9, 18, and 30 months (or 24 months if 30-month visit not possible). Autism-specific screening at 18 and 24 months.

Mnemonic Aids

  • No social smile by 6 weeks - refer
  • "2 words by 2 years" - a common bedside rule (2-word phrases by age 2)
  • "Words by 12 months" - at least mama/dada with intent
  • Pincer grasp by 9-10 months
  • Walking independently by 18 months (if not, evaluate for motor delay)
  • Speech intelligibility: 50% at 2 years → 75% at 3 years → 100% at 4 years

Sources: The Harriet Lane Handbook (Johns Hopkins Hospital, 23rd ed.); Kaplan and Sadock's Synopsis of Psychiatry; CDC Developmental Milestones (reviewed Dec. 2022)

Create a quick reference PDF for developmental milestones by age

Reading File
Running Command

ls -la /home/daytona/workspace/ 2>/dev/null || echo "workspace does not exist"

Running Command

mkdir -p /home/daytona/workspace/dev-milestones && python3 -c "import reportlab; print('reportlab ok')" && python3 -c "from reportlab.lib import colors; print('colors ok')"

Writing File

~/dev-milestones/generate_pdf.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether, PageBreak
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT
from reportlab.pdfgen import canvas

OUTPUT = "/home/daytona/workspace/dev-milestones/Developmental_Milestones_Quick_Reference.pdf"

# ── Colour palette ──────────────────────────────────────────────
C_HEADER   = colors.HexColor("#1B4F72")   # deep navy – page header
C_AGE_BG   = colors.HexColor("#2E86C1")   # blue – age band header
C_AGE_FG   = colors.white
C_MOTOR    = colors.HexColor("#1A5276")   # dark blue
C_LANG     = colors.HexColor("#1E8449")   # green
C_COG      = colors.HexColor("#7D3C98")   # purple
C_SOC      = colors.HexColor("#CA6F1E")   # amber
C_RED      = colors.HexColor("#C0392B")   # red flags
C_LIGHT1   = colors.HexColor("#D6EAF8")   # motor row bg
C_LIGHT2   = colors.HexColor("#D5F5E3")   # lang row bg
C_LIGHT3   = colors.HexColor("#E8DAEF")   # cog row bg
C_LIGHT4   = colors.HexColor("#FDEBD0")   # soc row bg
C_RED_LIGHT= colors.HexColor("#FADBD8")   # red flag bg
C_RULE     = colors.HexColor("#AED6F1")
C_FOOTER   = colors.HexColor("#566573")

PAGE_W, PAGE_H = A4
MARGIN = 14 * mm

# ── Styles ───────────────────────────────────────────────────────
styles = getSampleStyleSheet()

def S(name, **kw):
    return ParagraphStyle(name, **kw)

title_style = S("Title2",
    fontSize=20, textColor=C_HEADER, alignment=TA_CENTER,
    fontName="Helvetica-Bold", spaceAfter=2)

subtitle_style = S("Sub",
    fontSize=10, textColor=C_FOOTER, alignment=TA_CENTER,
    fontName="Helvetica", spaceAfter=8)

section_style = S("Section",
    fontSize=11, textColor=colors.white, fontName="Helvetica-Bold",
    alignment=TA_CENTER, leading=14)

age_label_style = S("AgeLabel",
    fontSize=12, textColor=colors.white, fontName="Helvetica-Bold",
    alignment=TA_CENTER, leading=14)

domain_style = S("Domain",
    fontSize=8.5, textColor=colors.white, fontName="Helvetica-Bold",
    alignment=TA_CENTER, leading=11)

cell_style = S("Cell",
    fontSize=8, textColor=colors.HexColor("#1C2833"),
    fontName="Helvetica", leading=11, leftIndent=3, rightIndent=3)

red_head_style = S("RedHead",
    fontSize=10, textColor=C_RED, fontName="Helvetica-Bold",
    spaceAfter=4, spaceBefore=6)

red_cell_style = S("RedCell",
    fontSize=8, textColor=colors.HexColor("#1C2833"),
    fontName="Helvetica", leading=11, leftIndent=3, rightIndent=3)

tip_style = S("Tip",
    fontSize=8.5, textColor=colors.HexColor("#1C2833"),
    fontName="Helvetica-Oblique", leading=12, leftIndent=6)

footer_style = S("Footer",
    fontSize=7.5, textColor=C_FOOTER, fontName="Helvetica",
    alignment=TA_CENTER)

# ── Milestone data ───────────────────────────────────────────────
# Each entry: (age_label, motor, language, cognitive, social)
MILESTONES = [
    ("2 Months",
     "Holds head up prone\nMoves all 4 limbs\nOpens hands briefly",
     "Sounds beyond crying\nReacts to loud sounds",
     "Watches faces move\nLooks at toy for seconds",
     "Calms when picked up/spoken to\nSmiles in response to face"),

    ("4 Months",
     "Head steady when held\nHolds toy placed in hand\nPushes onto elbows prone\nHands to mouth",
     "Cooing ('ooo','aahh')\nTurns head toward voice\nVocalises back when talked to",
     "Opens mouth seeing breast/bottle\nLooks at hands with interest",
     "Spontaneous social smile\nChuckles when made to laugh\nMakes sounds to hold attention"),

    ("6 Months",
     "Rolls tummy→back\nSits with support\nPushes up on straight arms\nReaches/grabs objects",
     "Babbles; takes turns vocalising\nBlows 'raspberries'\nResponds to own name",
     "Brings objects to mouth\nReaches for nearby toys\nLooks for dropped object",
     "Recognises familiar people\nLaughs out loud\nLooks at self in mirror"),

    ("9 Months",
     "Sits independently\nBegins crawling\nPulls to stand (some)\nRaking grasp→early pincer",
     "Mama/dada (non-specific)\nBacks-and-forth sounds\nLifts arms to be picked up",
     "Looks for dropped objects\nBangs two objects together\nPermanence: finds partly hidden toy",
     "Stranger anxiety begins\nSeparation anxiety\nWaves bye-bye (some)"),

    ("12 Months",
     "Pulls to stand; cruises furniture\nFirst independent steps (some)\nPincer grasp (thumb+index)\nDrinks from held cup",
     "Mama/dada with intent\nUnderstands 'no'\n1–2 words (some)\nPoints to request",
     "Object permanence – finds hidden toy\nPuts objects in containers",
     "Plays pat-a-cake\nWaves bye-bye\nShows affection"),

    ("15 Months",
     "Takes several steps alone\nFeeds self finger food",
     "1–2 words beyond mama/dada\nPoints to ask/get help\nFollows directions + gesture",
     "Uses objects correctly (cup, phone)\nStacks 2 blocks",
     "Copies other children\nShows favourite objects\nClaps when excited; hugs toys"),

    ("18 Months",
     "Walks independently\nClimbs on/off furniture\nScribbles\nTries to use spoon",
     "3+ words beyond mama/dada\nFollows 1-step direction (no gesture)",
     "Simple pretend play\nCopies simple chores (sweeping)",
     "Moves from parent but checks back\nPoints to share interest\nHelps with dressing"),

    ("24 Months",
     "Runs\nKicks a ball\n≥50 recognisable words in vocab",
     "2-word phrases ('more milk')\nPoints to pictures when asked\nNames 2 body parts",
     "Uses one hand while other holds\nSimple 2-piece puzzles\nUses switches/knobs on toys",
     "Notices when others are upset\nLooks to parent for cues\nParallel play begins"),

    ("3 Years",
     "Pedals tricycle\nRuns well; hops on preferred foot\nUndresses self",
     "3-word sentences\n~75% intelligible to strangers\nAsks 'why?' frequently",
     "Counts to 3\nDraws a circle\nKnows name, age, sex",
     "Takes turns\nCooperative play begins\nExpresses complex emotions"),

    ("4 Years",
     "Hops on one foot\nCatches bounced ball\nDresses/undresses with minimal help",
     "Most speech understood by strangers\n4–5 word sentences\nTells simple stories",
     "Names some colours/letters\nDraws person with 3 parts\nUnderstands same/different",
     "Dramatic/pretend play\nConcern for others\nImproved sharing\n'Band-Aid phase'"),

    ("5 Years",
     "Hops on one foot (sustained)\nButtons clothes\nComplex sports/motor tasks",
     "Tells story with ≥2 events\nMaintains 3+ exchange conversation\nUses simple rhymes",
     "Counts to 10; names numbers 1–5\nWrites some letters\nAttends 5–10 min task",
     "Follows rules in games\nDoes simple chores\nPerforms for others (sings/dances)"),

    ("6–12 Years\n(School Age)",
     "Writes fluently\nComplex sports (tennis, gymnastics)\nFine motor well-developed",
     "Complex ideas; multiple elements\nAbstract thinking emerges (~10 yr)\nExpletives/sex words (typical)",
     "Logical > fantasy thinking\nCan concentrate well (by age 9–10)\nMoral: rules = absolute until ~7 yr",
     "Same-sex peer groups dominate\nBest friend relationship (~10 yr)\nEmpathy & compassion by 9–10 yr"),
]

# ── Red flags ────────────────────────────────────────────────────
RED_FLAGS = [
    ("Any age",       "Loss of ANY previously acquired skill — refer immediately"),
    ("2 months",      "Not responding to loud sounds; not watching moving things; not smiling"),
    ("4 months",      "Not bringing objects to mouth; not pushing down with legs on hard surface"),
    ("6 months",      "No babbling; cannot sit with support"),
    ("9 months",      "No back-and-forth gestures; no pointing/waving"),
    ("12 months",     "No babbling; no intentional words; no pointing/waving"),
    ("16 months",     "No single words"),
    ("18 months",     "No pointing; no single words"),
    ("24 months",     "No 2-word meaningful phrases (not just imitating)"),
    ("Any age",       "Regression: losing language or social skills previously gained"),
]

# ── Mnemonics / pearls ───────────────────────────────────────────
PEARLS = [
    "Social smile by 6 weeks  |  Object permanence ~8–9 months  |  Pincer grasp ~9–10 months",
    "Words by 12 months  |  2-word phrases by 2 years  |  Sentences by 3 years",
    "Walk independently by 18 months (if not, evaluate for motor delay)",
    "Speech intelligibility: ~50% at 2 yr → ~75% at 3 yr → ~100% at 4 yr",
    "Daytime continence ~2.5 yr  |  Night-time continence ~4 yr",
    "Gender identity fixed: ~24–30 months (largely innate)",
    "Stranger anxiety onset: ~9 months  |  Separation anxiety peak: ~12–18 months",
    "AAP formal screening: 9, 18, and 30 months  |  Autism screen: 18 and 24 months",
]

# ── Screening tools ───────────────────────────────────────────────
SCREENS = [
    ["Tool", "Age Range", "By Whom", "Purpose"],
    ["Ages & Stages Q (ASQ)", "4–60 months", "Parent", "Cognitive & motor"],
    ["PEDS", "0–8 years", "Parent", "Developmental & behavioural"],
    ["Capute Scales (CLAMS+CAT)", "3–36 months", "Clinician", "Language & problem-solving DQ"],
    ["M-CHAT-R/F", "16–30 months", "Parent", "Autism spectrum"],
    ["CSBS DP Infant-Toddler Checklist", "6–24 months", "Parent", "Autism spectrum"],
]

# ── Domain colour map ─────────────────────────────────────────────
DOMAIN_COLORS = {
    "Motor":        (C_MOTOR,  C_LIGHT1),
    "Language":     (C_LANG,   C_LIGHT2),
    "Cognitive":    (C_COG,    C_LIGHT3),
    "Social/Emot.": (C_SOC,    C_LIGHT4),
}
DOMAINS = list(DOMAIN_COLORS.keys())

# ── Helper: build one age block ───────────────────────────────────
def build_age_block(age, motor, lang, cog, soc):
    """Returns a KeepTogether containing the coloured age table."""
    usable_w = PAGE_W - 2 * MARGIN
    col_w = usable_w / 5  # age col + 4 domain cols

    header_row = [
        Paragraph(age, age_label_style),
        Paragraph("Motor", domain_style),
        Paragraph("Language", domain_style),
        Paragraph("Cognitive", domain_style),
        Paragraph("Social/Emot.", domain_style),
    ]
    data_row = [
        "",
        Paragraph(motor, cell_style),
        Paragraph(lang,  cell_style),
        Paragraph(cog,   cell_style),
        Paragraph(soc,   cell_style),
    ]

    t = Table(
        [header_row, data_row],
        colWidths=[col_w] * 5,
        repeatRows=0,
    )

    # Flatten colour pairs for columns 1-4
    col_fg = [fg for (fg, _) in DOMAIN_COLORS.values()]
    col_bg = [bg for (_, bg) in DOMAIN_COLORS.values()]

    ts = TableStyle([
        # Age band – full width merge for header row col 0
        ("BACKGROUND", (0, 0), (0, 1), C_AGE_BG),
        ("TEXTCOLOR",  (0, 0), (0, 1), C_AGE_FG),
        ("SPAN",       (0, 0), (0, 1)),
        ("VALIGN",     (0, 0), (-1, -1), "MIDDLE"),
        ("ALIGN",      (0, 0), (-1, -1), "CENTER"),
        ("ALIGN",      (1, 1), (-1, 1), "LEFT"),
        ("VALIGN",     (1, 1), (-1, 1), "TOP"),
        # Domain header colours
        ("BACKGROUND", (1, 0), (1, 0), col_fg[0]),
        ("BACKGROUND", (2, 0), (2, 0), col_fg[1]),
        ("BACKGROUND", (3, 0), (3, 0), col_fg[2]),
        ("BACKGROUND", (4, 0), (4, 0), col_fg[3]),
        # Data row bg colours
        ("BACKGROUND", (1, 1), (1, 1), col_bg[0]),
        ("BACKGROUND", (2, 1), (2, 1), col_bg[1]),
        ("BACKGROUND", (3, 1), (3, 1), col_bg[2]),
        ("BACKGROUND", (4, 1), (4, 1), col_bg[3]),
        ("TEXTCOLOR",  (1, 0), (-1, 0), colors.white),
        ("GRID",       (0, 0), (-1, -1), 0.5, colors.white),
        ("TOPPADDING",    (0, 0), (-1, -1), 4),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 4),
        ("LEFTPADDING",   (0, 0), (-1, -1), 4),
        ("RIGHTPADDING",  (0, 0), (-1, -1), 4),
        ("ROUNDEDCORNERS", [3]),
    ])
    t.setStyle(ts)
    return KeepTogether([t, Spacer(1, 3)])

# ── Helper: red flags table ───────────────────────────────────────
def build_red_flags():
    usable_w = PAGE_W - 2 * MARGIN
    rows = [[Paragraph("<b>Age</b>", cell_style),
             Paragraph("<b>Red Flag</b>", cell_style)]]
    for age, flag in RED_FLAGS:
        rows.append([
            Paragraph(f"<b>{age}</b>", red_cell_style),
            Paragraph(flag, red_cell_style),
        ])
    t = Table(rows, colWidths=[30 * mm, usable_w - 30 * mm])
    ts = TableStyle([
        ("BACKGROUND", (0, 0), (-1, 0), C_RED),
        ("TEXTCOLOR",  (0, 0), (-1, 0), colors.white),
        ("BACKGROUND", (0, 1), (-1, -1), C_RED_LIGHT),
        ("ROWBACKGROUNDS", (0, 1), (-1, -1), [C_RED_LIGHT, colors.HexColor("#FDFEFE")]),
        ("GRID",       (0, 0), (-1, -1), 0.4, colors.HexColor("#E74C3C")),
        ("VALIGN",     (0, 0), (-1, -1), "TOP"),
        ("TOPPADDING",    (0, 0), (-1, -1), 3),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 3),
        ("LEFTPADDING",   (0, 0), (-1, -1), 5),
        ("RIGHTPADDING",  (0, 0), (-1, -1), 5),
    ])
    t.setStyle(ts)
    return t

# ── Helper: screening table ───────────────────────────────────────
def build_screening():
    usable_w = PAGE_W - 2 * MARGIN
    col_ws = [55*mm, 30*mm, 25*mm, usable_w - 55*mm - 30*mm - 25*mm]
    rows = []
    for i, row in enumerate(SCREENS):
        rows.append([Paragraph(cell, cell_style) for cell in row])
    t = Table(rows, colWidths=col_ws)
    ts = TableStyle([
        ("BACKGROUND", (0, 0), (-1, 0), C_HEADER),
        ("TEXTCOLOR",  (0, 0), (-1, 0), colors.white),
        ("FONTNAME",   (0, 0), (-1, 0), "Helvetica-Bold"),
        ("ROWBACKGROUNDS", (0, 1), (-1, -1),
         [colors.HexColor("#EBF5FB"), colors.HexColor("#FDFEFE")]),
        ("GRID",       (0, 0), (-1, -1), 0.4, C_RULE),
        ("VALIGN",     (0, 0), (-1, -1), "TOP"),
        ("TOPPADDING",    (0, 0), (-1, -1), 3),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 3),
        ("LEFTPADDING",   (0, 0), (-1, -1), 5),
        ("RIGHTPADDING",  (0, 0), (-1, -1), 5),
    ])
    t.setStyle(ts)
    return t

# ── Page template with header/footer ─────────────────────────────
class HeaderFooterCanvas(canvas.Canvas):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._saved_page_states = []

    def showPage(self):
        self._saved_page_states.append(dict(self.__dict__))
        self._startPage()

    def save(self):
        num_pages = len(self._saved_page_states)
        for state in self._saved_page_states:
            self.__dict__.update(state)
            self.draw_header_footer(num_pages)
            canvas.Canvas.showPage(self)
        canvas.Canvas.save(self)

    def draw_header_footer(self, total):
        self.saveState()
        w, h = A4
        # Header bar
        self.setFillColor(C_HEADER)
        self.rect(0, h - 12 * mm, w, 12 * mm, fill=1, stroke=0)
        self.setFillColor(colors.white)
        self.setFont("Helvetica-Bold", 11)
        self.drawCentredString(w / 2, h - 8 * mm,
            "PAEDIATRIC DEVELOPMENTAL MILESTONES – QUICK REFERENCE")
        # Footer
        self.setFillColor(C_FOOTER)
        self.setFont("Helvetica", 7)
        page_num = self._saved_page_states.index(
            {k: self.__dict__[k] for k in self.__dict__ if k in self._saved_page_states[0]}
        ) if False else self._pageNumber
        self.drawCentredString(
            w / 2, 7 * mm,
            f"Source: Harriet Lane Handbook 23rd ed. | Kaplan & Sadock's Synopsis of Psychiatry | CDC Milestones 2022     Page {self._pageNumber} / {total}"
        )
        self.restoreState()

# ── Build document ────────────────────────────────────────────────
doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    leftMargin=MARGIN, rightMargin=MARGIN,
    topMargin=16 * mm, bottomMargin=14 * mm,
    title="Paediatric Developmental Milestones",
    author="Orris Medical Reference",
)

story = []

# Title block
story.append(Spacer(1, 2 * mm))
story.append(Paragraph("Paediatric Developmental Milestones", title_style))
story.append(Paragraph(
    "Motor · Language · Cognitive · Social/Emotional  |  Birth to School Age",
    subtitle_style))
story.append(HRFlowable(width="100%", thickness=1.5, color=C_RULE, spaceAfter=5))

# Legend row
legend_data = [[
    Paragraph("<b><font color='#1A5276'>■ Motor</font></b>", cell_style),
    Paragraph("<b><font color='#1E8449'>■ Language</font></b>", cell_style),
    Paragraph("<b><font color='#7D3C98'>■ Cognitive</font></b>", cell_style),
    Paragraph("<b><font color='#CA6F1E'>■ Social/Emotional</font></b>", cell_style),
    Paragraph("<b><font color='#C0392B'>■ Red Flags</font></b>", cell_style),
]]
legend_t = Table(legend_data, colWidths=[(PAGE_W - 2*MARGIN)/5]*5)
legend_t.setStyle(TableStyle([
    ("ALIGN",  (0,0), (-1,-1), "CENTER"),
    ("VALIGN", (0,0), (-1,-1), "MIDDLE"),
    ("TOPPADDING",    (0,0), (-1,-1), 2),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
]))
story.append(legend_t)
story.append(HRFlowable(width="100%", thickness=0.5, color=C_RULE, spaceAfter=5))

# Milestone blocks
for entry in MILESTONES:
    story.append(build_age_block(*entry))

story.append(Spacer(1, 4 * mm))
story.append(HRFlowable(width="100%", thickness=1.5, color=C_RED, spaceAfter=3))

# Red flags
story.append(Paragraph("⚠  Developmental Red Flags", red_head_style))
story.append(build_red_flags())
story.append(Spacer(1, 5 * mm))

# Mnemonics / pearls
story.append(HRFlowable(width="100%", thickness=1, color=C_RULE, spaceAfter=3))
story.append(Paragraph("Clinical Pearls & Mnemonics", ParagraphStyle(
    "PearlHead", fontSize=10, textColor=C_HEADER,
    fontName="Helvetica-Bold", spaceAfter=3)))
for pearl in PEARLS:
    story.append(Paragraph(f"• {pearl}", tip_style))
story.append(Spacer(1, 5 * mm))

# Screening tools
story.append(HRFlowable(width="100%", thickness=1, color=C_RULE, spaceAfter=3))
story.append(Paragraph("Developmental Screening Tools (AAP-Recommended)", ParagraphStyle(
    "ScreenHead", fontSize=10, textColor=C_HEADER,
    fontName="Helvetica-Bold", spaceAfter=3)))
story.append(build_screening())

story.append(Spacer(1, 4*mm))
story.append(Paragraph(
    "AAP guideline: formal developmental screening at 9, 18, and 30 months (or 24 months if 30-month visit not possible). "
    "Autism-specific screening at 18 and 24 months.",
    tip_style))

# Build
doc.build(story, canvasmaker=HeaderFooterCanvas)
print("PDF generated:", OUTPUT)
Running Command

cd /home/daytona/workspace/dev-milestones && python3 generate_pdf.py 2>&1

Running Command

ls -lh /home/daytona/workspace/dev-milestones/Developmental_Milestones_Quick_Reference.pdf

The PDF is ready. Here it is:

Developmental Milestones Quick Reference

PDF Document · PDF


What's inside the PDF:
  • Colour-coded milestone table for every age checkpoint from 2 months through school age (12 ages total), with 4 columns per age:
    • 🔵 Motor (gross + fine)
    • 🟢 Language/Communication
    • 🟣 Cognitive (problem-solving)
    • 🟠 Social/Emotional
  • Red Flags table - age-specific warning signs requiring immediate referral, highlighted in red
  • Clinical Pearls & Mnemonics - quick bedside rules (speech intelligibility progression, continence ages, gender identity, screening schedule)
  • Developmental Screening Tools table - ASQ, PEDS, Capute Scales, M-CHAT-R/F, CSBS DP with age ranges
  • Running header + footer on every page citing Harriet Lane Handbook 23rd ed., Kaplan & Sadock, and CDC Milestones 2022
This is a shared conversation. Sign in to Orris to start your own chat.