Best shampoo
What about bare anatomy shampoo
Bare Anatomy shampoo review 2025
| Factor | Rating |
|---|---|
| Ingredients | ✅ Good |
| Effectiveness | ⚠️ Mixed |
| Value for money | ✅ Decent |
| Customer service | ❌ Weak |
| Sulfate/paraben free | ✅ Yes |
Create a guide for choosing the right shampoo by hair type
mkdir -p /tmp/workspace/shampoo-guide && ls /tmp/workspace/shampoo-guide/
~/shampoo-guide/create_guide.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import mm, cm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import PageBreak
OUTPUT = "/tmp/workspace/shampoo-guide/Shampoo_Guide_By_Hair_Type.pdf"
# ── Colour palette ──────────────────────────────────────────────────────────
TEAL = colors.HexColor("#2E7D7B")
TEAL_LIGHT = colors.HexColor("#E0F2F1")
CORAL = colors.HexColor("#E8704A")
CORAL_LIGHT = colors.HexColor("#FBE9E7")
GOLD = colors.HexColor("#F5A623")
GOLD_LIGHT = colors.HexColor("#FFF8E1")
PURPLE = colors.HexColor("#6A4C9C")
PURPLE_LIGHT= colors.HexColor("#EDE7F6")
GREEN = colors.HexColor("#388E3C")
GREEN_LIGHT = colors.HexColor("#E8F5E9")
BLUE = colors.HexColor("#1565C0")
BLUE_LIGHT = colors.HexColor("#E3F2FD")
PINK = colors.HexColor("#AD1457")
PINK_LIGHT = colors.HexColor("#FCE4EC")
DARK = colors.HexColor("#212121")
GREY = colors.HexColor("#757575")
LIGHT_GREY = colors.HexColor("#F5F5F5")
WHITE = colors.white
# ── Styles ───────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
def S(name, **kw):
return ParagraphStyle(name, **kw)
cover_title = S("CoverTitle",
fontName="Helvetica-Bold", fontSize=34, textColor=WHITE,
alignment=TA_CENTER, leading=42, spaceAfter=6)
cover_sub = S("CoverSub",
fontName="Helvetica", fontSize=14, textColor=colors.HexColor("#E0F2F1"),
alignment=TA_CENTER, leading=20)
section_header = S("SectionHeader",
fontName="Helvetica-Bold", fontSize=16, textColor=WHITE,
alignment=TA_LEFT, leading=22, spaceBefore=2, spaceAfter=4)
hair_type_title = S("HairTypeTitle",
fontName="Helvetica-Bold", fontSize=13, textColor=DARK,
leading=18, spaceBefore=4, spaceAfter=2)
body = S("Body",
fontName="Helvetica", fontSize=10, textColor=DARK,
leading=15, spaceAfter=3, alignment=TA_JUSTIFY)
bullet_style = S("Bullet",
fontName="Helvetica", fontSize=10, textColor=DARK,
leading=14, leftIndent=14, spaceAfter=2)
tip_style = S("Tip",
fontName="Helvetica-Oblique", fontSize=9.5, textColor=GREY,
leading=14, leftIndent=10, spaceAfter=2)
label_style = S("Label",
fontName="Helvetica-Bold", fontSize=9, textColor=GREY,
leading=12)
table_header = S("TableHeader",
fontName="Helvetica-Bold", fontSize=9.5, textColor=WHITE,
alignment=TA_CENTER, leading=13)
table_cell = S("TableCell",
fontName="Helvetica", fontSize=9, textColor=DARK,
alignment=TA_CENTER, leading=13)
table_cell_left = S("TableCellLeft",
fontName="Helvetica", fontSize=9, textColor=DARK,
alignment=TA_LEFT, leading=13)
toc_style = S("TOC",
fontName="Helvetica", fontSize=11, textColor=DARK,
leading=20, leftIndent=10)
toc_bold = S("TOCBold",
fontName="Helvetica-Bold", fontSize=12, textColor=TEAL,
leading=20, leftIndent=0)
footer_style = S("Footer",
fontName="Helvetica", fontSize=8, textColor=GREY,
alignment=TA_CENTER)
# ── Helper: coloured header band ────────────────────────────────────────────
def section_band(text, colour, icon=""):
full = f"{icon} {text}" if icon else text
cell = Paragraph(full, section_header)
t = Table([[cell]], colWidths=[170*mm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), colour),
("ROUNDEDCORNERS", [6,6,6,6]),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 12),
]))
return t
# ── Helper: ingredient / product pill table ─────────────────────────────────
def two_col_table(col1_header, col1_items, col2_header, col2_items, accent):
rows = [[Paragraph(col1_header, table_header),
Paragraph(col2_header, table_header)]]
max_len = max(len(col1_items), len(col2_items))
for i in range(max_len):
c1 = col1_items[i] if i < len(col1_items) else ""
c2 = col2_items[i] if i < len(col2_items) else ""
rows.append([Paragraph(f"• {c1}", table_cell_left),
Paragraph(f"• {c2}", table_cell_left)])
t = Table(rows, colWidths=[83*mm, 83*mm])
ts = TableStyle([
("BACKGROUND", (0,0), (-1,0), accent),
("BACKGROUND", (0,1), (-1,-1), LIGHT_GREY),
("ROWBACKGROUNDS",(0,1), (-1,-1), [WHITE, LIGHT_GREY]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#DDDDDD")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
("ROUNDEDCORNERS",[4,4,4,4]),
])
t.setStyle(ts)
return t
# ── Helper: avoid box ───────────────────────────────────────────────────────
def avoid_box(items, accent):
rows = [[Paragraph("Ingredients to AVOID", table_header)]]
for item in items:
rows.append([Paragraph(f"✗ {item}", table_cell_left)])
t = Table(rows, colWidths=[170*mm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), CORAL),
("BACKGROUND", (0,1), (-1,-1), CORAL_LIGHT),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#FFCCBC")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 10),
]))
return t
# ── Cover page drawing ───────────────────────────────────────────────────────
def draw_cover(canvas, doc):
w, h = A4
# background gradient simulation using stacked rectangles
for i in range(100):
frac = i / 100
r = 0.18 + frac * (0.08 - 0.18)
g = 0.49 + frac * (0.40 - 0.49)
b = 0.49 + frac * (0.35 - 0.49)
canvas.setFillColorRGB(r, g, b)
canvas.rect(0, h * (1 - (i+1)/100), w, h/100, fill=1, stroke=0)
# decorative circles
canvas.setFillColorRGB(1, 1, 1, 0.07)
canvas.circle(w * 0.85, h * 0.85, 90, fill=1, stroke=0)
canvas.circle(w * 0.1, h * 0.2, 60, fill=1, stroke=0)
canvas.circle(w * 0.5, h * 0.05, 40, fill=1, stroke=0)
# footer bar
canvas.setFillColor(colors.HexColor("#1A4F4E"))
canvas.rect(0, 0, w, 28, fill=1, stroke=0)
canvas.setFont("Helvetica", 8)
canvas.setFillColor(colors.HexColor("#B2DFDB"))
canvas.drawCentredString(w/2, 10, "Your complete reference for healthier, happier hair")
def draw_page(canvas, doc):
w, h = A4
# top accent bar
canvas.setFillColor(TEAL)
canvas.rect(0, h - 14, w, 14, fill=1, stroke=0)
# bottom bar
canvas.setFillColor(LIGHT_GREY)
canvas.rect(0, 0, w, 22, fill=1, stroke=0)
canvas.setFont("Helvetica", 8)
canvas.setFillColor(GREY)
canvas.drawCentredString(w/2, 7, f"Shampoo Selection Guide | Page {doc.page}")
# ── Build document ───────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=20*mm, rightMargin=20*mm,
topMargin=22*mm, bottomMargin=28*mm,
title="Choosing the Right Shampoo by Hair Type",
author="Hair Care Guide"
)
story = []
# ============================================================
# COVER PAGE
# ============================================================
story.append(Spacer(1, 60*mm))
story.append(Paragraph("Choosing the Right", cover_title))
story.append(Paragraph("Shampoo", S("CoverBig",
fontName="Helvetica-Bold", fontSize=52, textColor=WHITE,
alignment=TA_CENTER, leading=58)))
story.append(Paragraph("by Hair Type", cover_title))
story.append(Spacer(1, 10*mm))
story.append(Paragraph("A complete guide to ingredients, products & routines\nfor every hair type and scalp condition", cover_sub))
story.append(PageBreak())
# ============================================================
# HOW TO USE THIS GUIDE
# ============================================================
story.append(section_band("How to Use This Guide", TEAL))
story.append(Spacer(1, 4*mm))
story.append(Paragraph(
"Finding the right shampoo starts with understanding your hair type and scalp condition. "
"This guide is organised into 7 hair-type sections. Each section covers:",
body))
steps = [
("1", "How to identify your hair type"),
("2", "Key ingredients to look for"),
("3", "Ingredients to avoid"),
("4", "Top product recommendations (drugstore + premium)"),
("5", "Pro tips for best results"),
]
for num, text in steps:
story.append(Paragraph(f"<b>{num}.</b> {text}", bullet_style))
story.append(Spacer(1, 3*mm))
story.append(Paragraph(
"<b>Tip:</b> Many people have a combination of types (e.g., oily scalp + dry ends). "
"Read both relevant sections and combine the advice.",
tip_style))
story.append(HRFlowable(width="100%", thickness=0.5, color=LIGHT_GREY, spaceAfter=6))
# ============================================================
# QUICK REFERENCE TABLE
# ============================================================
story.append(section_band("Quick Reference Table", TEAL))
story.append(Spacer(1, 3*mm))
qr_data = [
[Paragraph("Hair Type", table_header),
Paragraph("Formula to Look For", table_header),
Paragraph("Avoid", table_header),
Paragraph("Wash Frequency", table_header)],
[Paragraph("Oily", table_cell), Paragraph("Clarifying, balancing", table_cell),
Paragraph("Heavy oils, silicones", table_cell), Paragraph("Daily or every other day", table_cell)],
[Paragraph("Dry", table_cell), Paragraph("Moisturising, creamy", table_cell),
Paragraph("Sulfates, alcohol", table_cell), Paragraph("2-3x per week", table_cell)],
[Paragraph("Curly / Coily", table_cell), Paragraph("Hydrating, co-wash", table_cell),
Paragraph("SLS, parabens", table_cell), Paragraph("1-2x per week", table_cell)],
[Paragraph("Fine / Limp", table_cell), Paragraph("Volumising, lightweight", table_cell),
Paragraph("Heavy conditioners", table_cell), Paragraph("Every other day", table_cell)],
[Paragraph("Color-Treated", table_cell), Paragraph("Sulfate-free, colour-safe", table_cell),
Paragraph("Sulfates, hot water", table_cell), Paragraph("2-3x per week", table_cell)],
[Paragraph("Dandruff / Flaky", table_cell), Paragraph("Anti-fungal, medicated", table_cell),
Paragraph("Harsh surfactants", table_cell), Paragraph("3x per week", table_cell)],
[Paragraph("Hair Loss", table_cell), Paragraph("Stimulating, strengthening", table_cell),
Paragraph("Harsh chemicals", table_cell), Paragraph("2-3x per week", table_cell)],
]
qr_table = Table(qr_data, colWidths=[32*mm, 48*mm, 48*mm, 38*mm])
qr_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("ROWBACKGROUNDS",(0,1), (-1,-1), [WHITE, TEAL_LIGHT]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#B2DFDB")),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
story.append(qr_table)
story.append(PageBreak())
# ============================================================
# HAIR TYPE SECTIONS - data
# ============================================================
sections = [
{
"title": "1. Oily Hair & Scalp",
"icon": "",
"colour": TEAL,
"light": TEAL_LIGHT,
"identify": (
"Your hair looks greasy within 24 hours of washing. "
"Roots appear flat and limp, scalp may feel itchy, and hair lacks volume. "
"You may notice residue on your pillow."
),
"why": (
"The scalp produces excess sebum (natural oil) due to overactive sebaceous glands. "
"This can be triggered by hormones, diet, stress, or over-washing. "
"Using heavy products makes it worse."
),
"look_for": [
"Salicylic acid (exfoliates scalp)",
"Tea tree oil (antibacterial)",
"Zinc pyrithione (controls oil)",
"Charcoal (deep cleanse)",
"Balancing / clarifying formula",
"Lightweight surfactants",
],
"avoid": [
"Dimethicone & heavy silicones",
"Coconut oil in formula",
"Thick conditioning bases",
"Over-washing (strips oil, rebounds)",
],
"drugstore": ["Neutrogena T/Sal", "Head & Shoulders Classic Clean", "Dove DermaCare Scalp"],
"premium": ["Briogeo Scalp Revival", "Moroccanoil Clarifying", "dpHUE Apple Cider Vinegar"],
"tips": [
"Wash every day or every other day - not less.",
"Apply shampoo directly to the scalp, not the lengths.",
"Use cool or lukewarm water - hot water stimulates more oil production.",
"Avoid touching your scalp throughout the day.",
],
},
{
"title": "2. Dry Hair",
"icon": "",
"colour": CORAL,
"light": CORAL_LIGHT,
"identify": (
"Hair feels rough, brittle, or straw-like. Ends may be split or frayed. "
"Hair is prone to frizz, breaks easily, and looks dull even after washing. "
"Scalp may feel tight or flaky."
),
"why": (
"Dry hair lacks moisture and natural oils, often from heat styling, environmental "
"damage, chemical treatments, or using harsh shampoos. The hair cuticle is raised, "
"allowing moisture to escape."
),
"look_for": [
"Glycerin (humectant)",
"Argan oil / Jojoba oil",
"Shea butter",
"Hyaluronic acid",
"Ceramides (repair cuticle)",
"Aloe vera",
],
"avoid": [
"Sodium Lauryl Sulfate (SLS)",
"Drying alcohols (alcohol denat.)",
"Fragrance-heavy formulas",
"Clarifying shampoos daily",
],
"drugstore": ["Dove Intense Repair", "Garnier Fructis Sleek & Shine", "Pantene Repair & Protect"],
"premium": ["Olaplex No. 4", "Moroccanoil Moisture Repair", "Kerastase Nutritive Bain Satin"],
"tips": [
"Wash only 2-3 times per week to preserve natural oils.",
"Always follow with a deep conditioner or hair mask weekly.",
"Pat hair dry gently - never rub with a towel.",
"Use a heat protectant spray before any heat styling.",
],
},
{
"title": "3. Curly & Coily Hair",
"icon": "",
"colour": PURPLE,
"light": PURPLE_LIGHT,
"identify": (
"Hair forms defined curls, coils, or tight spirals (Type 2C to 4C). "
"Naturally drier than straight hair as scalp oil cannot travel down the curl shaft. "
"Prone to frizz, shrinkage, and tangles."
),
"why": (
"The helical shape of curly hair makes it structurally weaker and harder to moisturise. "
"Curly hair needs more hydration and gentler cleansing to maintain curl definition "
"and prevent breakage."
),
"look_for": [
"Shea butter",
"Castor oil / Avocado oil",
"Aloe vera",
"Protein (hydrolysed keratin)",
"Sulfate-free surfactants",
"Co-wash (conditioner wash) formula",
],
"avoid": [
"Sodium Lauryl Sulfate (SLS)",
"Sodium Laureth Sulfate (SLES)",
"Parabens",
"Heavy mineral oil",
],
"drugstore": ["SheaMoisture Jamaican Black Castor Oil", "As I Am Coconut Co-Wash", "Cantu Shea Butter"],
"premium": ["Briogeo Don't Despair Repair", "Ouidad Curl Quencher", "Davines Love Curl"],
"tips": [
"Try the 'Curly Girl Method' - co-washing replaces or supplements shampooing.",
"Detangle gently with a wide-tooth comb while hair is wet with conditioner.",
"Apply products to soaking-wet hair to lock in moisture.",
"Diffuse or air-dry to maintain curl pattern.",
],
},
{
"title": "4. Fine & Limp Hair",
"icon": "",
"colour": GOLD,
"light": GOLD_LIGHT,
"identify": (
"Individual strands are thin in diameter. Hair falls flat quickly after styling, "
"lacks body and bounce, and gets weighed down easily by products. "
"May look greasy faster than other types."
),
"why": (
"Fine hair has fewer cuticle layers, making it more delicate and susceptible to "
"product build-up. It needs lightweight volumising formulas that lift the root "
"without adding weight."
),
"look_for": [
"Biotin (strengthens strand)",
"Hydrolysed silk / wheat protein",
"Panthenol (Pro-Vitamin B5)",
"Rice water / rice protein",
"Volumising polymers",
"Lightweight, clear formulas",
],
"avoid": [
"Heavy silicones (dimethicone)",
"Thick oils in formula",
"2-in-1 shampoo + conditioner",
"Heavy moisturising formulas",
],
"drugstore": ["Pantene Volume & Body", "Dove Volume & Fullness", "OGX Thick & Full Biotin"],
"premium": ["Nioxin System 1", "Aveda Pure Abundance", "Kerastase Densifique"],
"tips": [
"Apply conditioner to ends only - never the roots.",
"Use a volumising mousse at the roots before blow drying.",
"Flip hair upside down while blow-drying for instant lift.",
"Wash every other day to avoid product build-up.",
],
},
{
"title": "5. Color-Treated Hair",
"icon": "",
"colour": PINK,
"light": PINK_LIGHT,
"identify": (
"Hair has been dyed, highlighted, bleached, or chemically treated. "
"Color tends to fade within weeks of dyeing. Hair may feel more porous, "
"brittle, or prone to breakage post-treatment."
),
"why": (
"Chemical color processing opens the hair cuticle and strips its natural protective "
"layer. Sulfate shampoos further strip color molecules, causing rapid fade. "
"Color-safe shampoos use gentler surfactants and lock in pigment."
),
"look_for": [
"Sulfate-free surfactants",
"UV filters (protect color from sun)",
"Keratin / protein complex",
"Antioxidants (Vitamin E)",
"Color-depositing pigments (toning)",
"pH-balanced formula",
],
"avoid": [
"Sodium Lauryl Sulfate (SLS)",
"Sodium Chloride (salt)",
"Hot water when rinsing",
"Clarifying shampoos frequently",
],
"drugstore": ["Pureology Hydrate (diluted)", "Pantene Color Protect", "L'Oreal EverPure"],
"premium": ["Olaplex No. 4C Bond Maintenance", "Kerastase Chroma Absolu", "Redken Color Extend"],
"tips": [
"Wait 48-72 hours after coloring before first wash.",
"Always rinse with cool water to seal the cuticle and lock in color.",
"Use a color-depositing shampoo once a week to refresh tone.",
"Deep condition weekly to combat chemical dryness.",
],
},
{
"title": "6. Dandruff & Flaky Scalp",
"icon": "",
"colour": GREEN,
"light": GREEN_LIGHT,
"identify": (
"White or yellowish flakes visible on scalp and clothing. Scalp is itchy, "
"sometimes red or irritated. Flaking may worsen in cold/dry weather or with stress. "
"Seborrheic dermatitis is a more severe form."
),
"why": (
"Most dandruff is caused by Malassezia - a yeast that naturally lives on the scalp. "
"When overgrown, it irritates the scalp and accelerates skin cell turnover, "
"producing visible flakes. Medicated shampoos target this fungus directly."
),
"look_for": [
"Ketoconazole 1-2% (antifungal)",
"Zinc pyrithione (ZPT)",
"Selenium sulfide",
"Salicylic acid (exfoliant)",
"Coal tar (slows cell turnover)",
"Piroctone olamine",
],
"avoid": [
"Heavy butters/oils on scalp",
"Excessive product build-up",
"Skipping washes (feeds fungus)",
"Scratching the scalp",
],
"drugstore": ["Nizoral A-D (Ketoconazole 1%)", "Head & Shoulders CLINICAL", "Selsun Blue Medicated"],
"premium": ["Briogeo Scalp Revival Charcoal", "Ducray Squanorm", "Vichy Dercos Anti-Dandruff"],
"tips": [
"Use medicated shampoo 3x per week for 4 weeks, then reduce to maintenance.",
"Leave shampoo on scalp for 3-5 minutes before rinsing for best results.",
"Alternate with a gentle shampoo on non-medicated wash days.",
"See a dermatologist if dandruff is severe, persistent, or accompanied by redness.",
],
},
{
"title": "7. Hair Loss & Thinning",
"icon": "",
"colour": BLUE,
"light": BLUE_LIGHT,
"identify": (
"Noticeable increase in hair fall in the shower or on your pillow. "
"Scalp becomes more visible, hair part widens, or ponytail becomes thinner. "
"Normal hair loss is 50-100 strands per day - more than this is a concern."
),
"why": (
"Hair thinning can result from genetics (androgenetic alopecia), stress (telogen "
"effluvium), nutritional deficiency, hormonal changes, or scalp conditions. "
"Strengthening shampoos improve scalp environment but cannot reverse genetic hair loss."
),
"look_for": [
"Adenosine (stimulates follicles)",
"Caffeine (extends growth phase)",
"Biotin (strengthens strand)",
"Saw palmetto (DHT blocker)",
"Niacinamide (improves circulation)",
"Redensyl / Anagain (plant actives)",
],
"avoid": [
"Harsh sulfates",
"Tight hairstyles during fragile phase",
"Hot water on scalp",
"Products with alcohol denat.",
],
"drugstore": ["Nioxin System 2", "OGX Thick & Full Biotin", "Klorane Quinine & B Vitamins"],
"premium": ["Viviscal Gorgeous Growth", "Kerastase Genesis", "Philip Kingsley Tricho Pro"],
"tips": [
"Massage the scalp for 4-5 minutes while shampooing to boost circulation.",
"Be gentle when detangling - always work from ends to roots.",
"Combine with a balanced diet rich in iron, zinc, and protein.",
"Consult a trichologist or dermatologist if shedding is sudden or severe.",
],
},
]
for section in sections:
story.append(KeepTogether([
section_band(section["title"], section["colour"]),
Spacer(1, 3*mm),
]))
story.append(Paragraph("How to Identify", label_style))
story.append(Paragraph(section["identify"], body))
story.append(Spacer(1, 2*mm))
story.append(Paragraph("Why It Happens", label_style))
story.append(Paragraph(section["why"], body))
story.append(Spacer(1, 3*mm))
# Ingredients table
story.append(two_col_table(
"Ingredients to LOOK FOR", section["look_for"],
"Recommended Products", section["drugstore"] + section["premium"],
section["colour"]
))
story.append(Spacer(1, 2*mm))
# Avoid box
story.append(avoid_box(section["avoid"], section["colour"]))
story.append(Spacer(1, 3*mm))
story.append(Paragraph("Pro Tips", label_style))
for tip in section["tips"]:
story.append(Paragraph(f"✓ {tip}", bullet_style))
story.append(Spacer(1, 4*mm))
story.append(HRFlowable(width="100%", thickness=0.5, color=LIGHT_GREY, spaceAfter=4))
story.append(PageBreak())
# ============================================================
# INGREDIENT GLOSSARY
# ============================================================
story.append(section_band("Ingredient Glossary", TEAL))
story.append(Spacer(1, 3*mm))
story.append(Paragraph(
"Understanding labels helps you make smarter choices. Here are key ingredients explained:",
body))
story.append(Spacer(1, 2*mm))
glossary = [
("Sodium Lauryl Sulfate (SLS)", "A strong foaming surfactant that strips natural oils. Harsh for dry, damaged, or curly hair."),
("Sodium Laureth Sulfate (SLES)", "Milder version of SLS, still a sulfate. Avoid for color-treated and very dry hair."),
("Dimethicone", "A silicone that coats the hair shaft for smoothness. Can cause build-up on fine or oily hair."),
("Ketoconazole", "Prescription-strength antifungal that treats dandruff and seborrheic dermatitis."),
("Salicylic Acid", "A beta-hydroxy acid that exfoliates the scalp and removes dead skin cells and build-up."),
("Panthenol (Pro-Vitamin B5)", "Penetrates the hair shaft to add moisture, shine, and elasticity."),
("Glycerin", "A humectant that draws moisture from the air into the hair. Great for dry and curly hair."),
("Biotin (Vitamin B7)", "Supports keratin infrastructure. Deficiency is linked to hair thinning."),
("Adenosine", "Promotes hair growth by extending the anagen (growth) phase of the hair cycle."),
("Ceramides", "Lipids that fill gaps in the hair cuticle, reducing breakage and moisture loss."),
("Keratin", "The main structural protein of hair. Hydrolysed keratin penetrates to repair damage."),
("Zinc Pyrithione (ZPT)", "Antifungal and antibacterial. Controls dandruff-causing Malassezia yeast."),
]
glos_data = [[Paragraph("Ingredient", table_header), Paragraph("What It Does", table_header)]]
for name, desc in glossary:
glos_data.append([Paragraph(name, S("GN", fontName="Helvetica-Bold", fontSize=9, textColor=TEAL, leading=13)),
Paragraph(desc, table_cell_left)])
glos_table = Table(glos_data, colWidths=[55*mm, 111*mm])
glos_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("ROWBACKGROUNDS",(0,1), (-1,-1), [WHITE, TEAL_LIGHT]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#B2DFDB")),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(glos_table)
story.append(PageBreak())
# ============================================================
# GENERAL BEST PRACTICES
# ============================================================
story.append(section_band("General Best Practices for All Hair Types", TEAL))
story.append(Spacer(1, 4*mm))
best = [
("Read the label", "The first 5 ingredients make up ~80% of the formula. Check those first before the marketing claims on the front."),
("pH matters", "Healthy scalp pH is 4.5-5.5. Look for pH-balanced shampoos, especially for color-treated or damaged hair."),
("Rotate shampoos", "Alternate between two shampoos (e.g., clarifying + moisturising) to prevent build-up and over-stripping."),
("Temperature", "Hot water opens the cuticle (good for cleansing), but always finish with a cool rinse to seal it shut."),
("Amount", "You only need a coin-sized amount for medium-length hair. More shampoo does not mean cleaner hair."),
("Scalp focus", "Shampoo is for the scalp. Work it in with your fingertips (not nails) in gentle circular motions."),
("Conditioner focus", "Conditioner is for the mid-lengths to ends - not the scalp. Leave on for 2-3 minutes before rinsing."),
("Patch test", "New scalp products can cause reactions. Apply a small amount behind the ear and wait 24 hours first."),
("Give it time", "Most shampoos need 4-6 weeks of consistent use before results are noticeable. Do not switch too quickly."),
("See a professional", "Persistent dandruff, significant hair loss, or scalp pain warrants a visit to a dermatologist or trichologist."),
]
for title, text in best:
story.append(Paragraph(f"<b>{title}</b>", hair_type_title))
story.append(Paragraph(text, body))
story.append(Spacer(1, 1*mm))
story.append(HRFlowable(width="100%", thickness=1, color=TEAL_LIGHT, spaceAfter=8))
story.append(Spacer(1, 3*mm))
story.append(Paragraph(
"This guide is for general information only and does not constitute medical advice. "
"For persistent scalp conditions, consult a qualified dermatologist or trichologist.",
S("Disclaimer", fontName="Helvetica-Oblique", fontSize=8.5, textColor=GREY,
alignment=TA_CENTER, leading=13)))
# ── Build ────────────────────────────────────────────────────────────────────
doc.build(story,
onFirstPage=draw_cover,
onLaterPages=draw_page)
print(f"PDF created: {OUTPUT}")
cd /tmp/workspace/shampoo-guide && python create_guide.py 2>&1
ls -lh /tmp/workspace/shampoo-guide/
Shampoo Guide By Hair Type
PDF Document · PDF
| Section | What's Covered |
|---|---|
| Cover + How to Use | Navigation tips, combination hair types |
| Quick Reference Table | All 7 hair types at a glance - formula, avoid list, wash frequency |
| 1. Oily Hair | Salicylic acid, tea tree, zinc pyrithione picks |
| 2. Dry Hair | Glycerin, argan oil, ceramide-rich formulas |
| 3. Curly & Coily | Co-washing, sulfate-free, shea butter options |
| 4. Fine & Limp | Volumising polymers, biotin, lightweight formulas |
| 5. Color-Treated | Sulfate-free, UV filters, color-depositing tips |
| 6. Dandruff & Flaky | Ketoconazole, ZPT, selenium sulfide medicated picks |
| 7. Hair Loss & Thinning | Adenosine, caffeine, Redensyl-based formulas |
| Ingredient Glossary | 12 key ingredients explained in plain language |
| General Best Practices | pH, water temperature, rotation strategy, when to see a doctor |