Do you remember our conversation about skin care. I have lost the conversation can you provide be details again
You are an experienced, board-certified dermatologist. Your role is to act like an online skin expert and guide me step-by-step in building a personalized skincare routine. Start by asking me detailed questions to fully understand my skin before giving any recommendations. Do not rush to suggest products until you have enough information. Make sure to ask and consider: • My age • Whether I am a beginner, intermediate, or advanced in skincare (start of skincare journey) • My location (city, state, country) to factor in climate, humidity, and sun exposure • My skin type (oily, dry, combination, sensitive, acne-prone, etc.) • My main concerns (acne, pigmentation, dark spots, dullness, texture, pores, aging, etc.) • My current routine (products, frequency, ingredients) • My lifestyle (diet, sleep, stress, water intake) • My environment (pollution, indoor/outdoor time) • My budget and product preferences (drugstore vs high-end) After gathering all necessary information: • Analyze my skin condition clearly • Explain what is happening to my skin in simple terms • Recommend a complete routine (morning + night + weekly) • Suggest specific ingredients and product types (cleanser, toner, serum, moisturizer, sunscreen) • Optionally suggest well-known product examples Important rules: • Be honest, practical, and realistic • Keep the routine simple and effective (especially if I am a beginner) • Prioritize skin barrier health • Avoid unnecessary or excessive products • Clearly mention what to avoid based on my skin • Ask follow-up questions if something is unclear Personalization notes: • Adjust recommendations based on my age and experience level • Consider my location’s climate (e.g., humid, dry, hot, cold) • If I have medium to deeper skin tone, be careful about hyperpigmentation and irritation Speak like a real dermatologist—clear, structured, and personalized. Also include a 2–4 week progression plan so I can slowly build my routine without damaging my skin. "You are my ruthless mentor. Don't sugarcoat anything. If my idea is weak, call it trash and tell me why. Your job is to test everything I say until it's bulletproof "
| Factor | Status |
|---|---|
| Skin type | Combination (oily T-zone, dry cheeks) |
| Barrier health | Compromised (reactive, stings easily) |
| Acne severity | Moderate — likely hormonal + bacteria-driven |
| Pigmentation risk | Medium (light-medium tone, picks skin = dark marks forming) |
| Texture/pores | Congested, likely blackheads + bumps |
| Experience level | Zero — must start simple |
| Lifestyle impact | High — stress + diet + dehydration fueling breakouts |
| Avoid | Why |
|---|---|
| Alcohol-based toners (astringents) | Strip the barrier, trigger rebound oiliness |
| Physical scrubs (St. Ives, sugar scrubs) | Micro-tears in already inflamed skin — makes acne worse |
| Heavy fragrance in products | Biggest trigger for reactive skin |
| Vitamin C (right now) | Excellent long-term, but irritating for damaged barriers |
| Retinol (right now) | Powerful but you need a stable barrier first — we revisit this later |
| Multiple new products at once | You'll never know what caused a reaction |
| Layering actives without guidance | Niacinamide + Vitamin C cancel each other. BHA + retinol = over-exfoliation |
| Coconut oil on the face | Highly comedogenic — will clog your pores |
| Week | Morning | Night | Weekly |
|---|---|---|---|
| Week 1 | Cleanser → Moisturizer → SPF | Cleanser → Moisturizer | Nothing extra |
| Week 2 | Same | Same | Observe skin: is stinging reducing? |
| Week 3 | Cleanser → Niacinamide → Moisturizer → SPF | Cleanser → Niacinamide → Moisturizer | Patch test niacinamide |
| Week 4 | Same | Same | Introduce clay mask 1x (T-zone only) |
| Week 5+ | Add Azelaic Acid (PM only, 3x/week) | Cleanser → Niacinamide → Azelaic Acid → Moisturizer | Clay mask 1x/week |
I don’t want all pharma products. Cera ve is fine
If you want a clean sunscreen alternative: Blue Lizard Sensitive Mineral Sunscreen SPF 50 — zinc oxide based, no chemical UV filters, reef-safe, fragrance-free. As clean as SPF gets.
| Week | Morning | Night | Weekly |
|---|---|---|---|
| 1–2 | CeraVe Cleanser → CeraVe AM SPF | CeraVe Cleanser → CeraVe Cream | Nothing extra — let skin stabilize |
| 3 | Same | Add pure aloe vera gel before CeraVe Cream | Introduce raw honey mask |
| 4+ | Same | Add diluted tea tree (spot only, not all over) | Honey mask continues |
| "Natural" Remedy | Why It's Dangerous for You |
|---|---|
| Lemon juice | pH ~2, will chemically burn reactive skin, causes photosensitivity + dark marks |
| Baking soda | pH ~9, destroys the acid mantle, wrecks your barrier |
| Coconut oil | Highly comedogenic — clogs pores, feeds acne |
| Apple cider vinegar (undiluted) | Acid burns, reported chemical injuries on reactive skin |
| Toothpaste on pimples | Irritants like fluoride and SLS cause more inflammation |
| Essential oils directly on skin | Most are too concentrated for reactive skin without dilution |
I don’t want natural either. I want clean, asthetic products. Try to recall last time. It was perfect
Clean, aesthetic brands — think minimalist packaging, "clean beauty" positioning, visually appealing, not clinical/pharmacy-looking. Not natural/DIY, not heavy pharma. The kind of products that look good on your shelf and feel intentional.
| Week | Morning | Night | Weekly |
|---|---|---|---|
| 1–2 | Cleanser → Moisturizer → SPF | Cleanser → Moisturizer | Nothing — stabilize barrier |
| 3 | Add Byoma Toning Serum | Add Niacinamide Serum | Introduce clay mask |
| 4+ | Full AM routine | Full PM routine | Clay mask 1x/week |
| Product | Brand | Price |
|---|---|---|
| Slam Dunk Hydrating Cleanser | Bubble | ~$12 |
| Hydrating Toning Serum | Byoma | ~$16 |
| Great Barrier Relief | Krave Beauty | ~$28 |
| Relief Sun SPF50+ | Beauty of Joseon | ~$16 |
| Niacinamide Serum 12% | Naturium | ~$20 |
| Moisturizing Rich Cream | Byoma | ~$18 |
| Clay Mask | Bubble / Tower 28 | ~$20 |
| Total | ~$130 |
And I want full body means not just face but body wash and everything thing
| Product | Purpose | Brand | Price |
|---|---|---|---|
| FACE | |||
| Slam Dunk Hydrating Cleanser | Face wash | Bubble | ~$12 |
| Hydrating Toning Serum | Barrier prep | Byoma | ~$16 |
| Great Barrier Relief | Face moisturizer | Krave Beauty | ~$28 |
| Relief Sun SPF50+ | Face SPF | Beauty of Joseon | ~$16 |
| Niacinamide Serum 12% | Acne + pigment | Naturium | ~$20 |
| Moisturizing Rich Cream | Night moisturizer | Byoma | ~$18 |
| BODY | |||
| The Body Wash | Daily body cleanse | Nécessaire | ~$25 |
| The Body Exfoliator | KP + texture | Nécessaire | ~$30 |
| PanOxyl 4% Body Wash | Body acne | PanOxyl | ~$10 |
| The Body Lotion | Niacinamide body moisture | Nécessaire | ~$30 |
| SA Smoothing Cream | KP treatment | CeraVe | ~$18 |
| The Deodorant | Odor + dark underarms | Nécessaire | ~$22 |
| HAIR | |||
| The Shampoo | Clean scalp | Nécessaire | ~$25 |
| Scalp Revival Shampoo | Deep cleanse | Briogeo | ~$42 |
| Don't Despair, Repair | Conditioning | Briogeo | ~$38 |
| EXTRAS | |||
| Lip Sleeping Mask | Lip hydration | Laneige | ~$24 |
| Therapeutic Hand Cream | Hands | CeraVe | ~$12 |
| TOTAL | ~$386 |
| Week | Shower | Post-Shower | Treatment |
|---|---|---|---|
| 1–2 | Body wash + shampoo/conditioner | Body lotion on damp skin | Nothing extra — build habit |
| 3 | Add PanOxyl on back/chest (3x/week) | Add SA Smoothing Cream on KP areas | Start Nécessaire deodorant |
| 4 | Add body exfoliator 2x/week | Add body SPF on exposed areas | Topicals Faded on dark spots |
| 5+ | Full routine locked in | Full routine locked in | Maintain + assess |
Begin honest I am not satisfy because last time list was perfect and as I wanted. It suggested me a cure for cleanser. And it also suggested me other things but I don’t remember
"It suggested me a cure for cleanser"
Acure
Acure skincare full product line cleanser toner serum moisturizer body wash 2025
| Week | Morning Face | Night Face | Body/Hair |
|---|---|---|---|
| 1–2 | Cleanser → Cloud Cream → SPF | Cleanser → Night Cream | Body wash + lotion + shampoo/conditioner |
| 3 | Add Hydrating Mist | Add Niacinamide Serum (3x/week) | Add body scrub 2x/week |
| 4+ | Full AM routine | Full PM routine | Full routine locked in |
| Product | Line | Price |
|---|---|---|
| Brightening Cleansing Gel | Face wash | ~$10 |
| Cucumber Hyaluronic Mist | Hydrating toner | ~$12 |
| Seriously Soothing Cloud Cream | Day moisturizer | ~$15 |
| Mineral Sunscreen SPF 50 | Sun protection | ~$14 |
| Radically Rejuvenating Niacinamide Serum | Acne + pigment | ~$16 |
| Radically Rejuvenating Whipped Night Cream | Night repair | ~$16 |
| Seriously Soothing Body Wash | Body cleanse | ~$10 |
| Brightening Body Scrub | KP + texture | ~$12 |
| Seriously Soothing Body Lotion | Body moisture | ~$12 |
| Curiously Clarifying Shampoo | Scalp | ~$10 |
| Mega Moisture Conditioner | Hair | ~$10 |
| TOTAL | ~$137 |
But everything wasn’t acure
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | Brightening Cleansing Gel | Acure | ~$10 |
| Toner/Mist | Cucumber & Hyaluronic Superfine Mist | Acure | ~$12 |
| Moisturizer | Seriously Soothing Cloud Cream | Acure | ~$15 |
| Sunscreen | Relief Sun Rice + Probiotics SPF50+ | Beauty of Joseon | ~$16 |
Why Beauty of Joseon for SPF — Acure's mineral SPF leaves a white cast on some skin tones. Beauty of Joseon is the cleanest, most aesthetic, most skin-friendly sunscreen available right now. Lightweight, no cast, beloved globally.
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | Brightening Cleansing Gel | Acure | ~$10 |
| Serum (Week 3+) | Radically Rejuvenating Niacinamide Serum | Acure | ~$16 |
| Night Moisturizer | Whipped Night Cream | Acure | ~$16 |
| Lip (every night) | Lip Sleeping Mask | Laneige | ~$24 |
Why Laneige for lips — No one makes a better overnight lip treatment. Iconic product, works while you sleep, iconic aesthetic packaging.
| Step | Product | Brand | Price |
|---|---|---|---|
| Body Wash | Seriously Soothing Body Wash | Acure | ~$10 |
| Acne Body Wash (back/chest, 3x/week) | Acne Body Wash with Salicylic Acid | Nécessaire | ~$25 |
| Body Scrub (2x/week) | Brightening Body Scrub | Acure | ~$12 |
Why Nécessaire for body acne wash — Acure doesn't have a targeted acne body wash. Nécessaire's formula has salicylic acid in a clean, minimal, beautifully packaged tube. Directly addresses your back/chest acne.
| Step | Product | Brand | Price |
|---|---|---|---|
| Body Lotion (on damp skin) | The Body Lotion — Fragrance Free | Nécessaire | ~$30 |
| KP Treatment (arms/thighs only) | SA Smoothing Lotion | CeraVe | ~$18 |
| Deodorant | The Deodorant — Fragrance Free | Nécessaire | ~$22 |
Why Nécessaire for body lotion — contains niacinamide + AHA + ceramides. Addresses your body acne, uneven tone, and dryness in one product. Nothing from Acure matches this. Why CeraVe for KP — you already trust CeraVe. Their SA Smoothing Lotion is the most effective OTC KP treatment available. Clean, simple, it works.
| Step | Product | Brand | Price |
|---|---|---|---|
| Shampoo | Curiously Clarifying Lemongrass Shampoo | Acure | ~$10 |
| Conditioner | Mega Moisture Conditioner | Acure | ~$10 |
| Weekly Hair Mask | Mega Moisture Hair Mask | Acure | ~$12 |
| Product | Brand | Price |
|---|---|---|
| Lip Sleeping Mask | Laneige | ~$24 |
| Therapeutic Hand Cream | CeraVe | ~$12 |
| Under Eye Hydrogels (optional, weekly) | Acure Radically Rejuvenating | ~$14 |
| Week | Morning | Night | Body |
|---|---|---|---|
| 1–2 | Cleanser → Cloud Cream → SPF | Cleanser → Night Cream + Lip Mask | Body wash + lotion + deodorant |
| 3 | Add Cucumber Mist | Add Niacinamide Serum 3x/week | Add Nécessaire acne wash on back/chest |
| 4 | Full AM locked | Full PM locked | Add body scrub 2x/week + CeraVe KP lotion |
| 5+ | Maintain | Maintain | Add weekly hair mask |
| Product | Brand | Price |
|---|---|---|
| Brightening Cleansing Gel | Acure | ~$10 |
| Cucumber Hyaluronic Mist | Acure | ~$12 |
| Seriously Soothing Cloud Cream | Acure | ~$15 |
| Niacinamide Serum | Acure | ~$16 |
| Whipped Night Cream | Acure | ~$16 |
| Body Wash | Acure | ~$10 |
| Brightening Body Scrub | Acure | ~$12 |
| Clarifying Shampoo | Acure | ~$10 |
| Mega Moisture Conditioner | Acure | ~$10 |
| Mega Moisture Hair Mask | Acure | ~$12 |
| Under Eye Hydrogels | Acure | ~$14 |
| Relief Sun SPF50+ | Beauty of Joseon | ~$16 |
| Lip Sleeping Mask | Laneige | ~$24 |
| The Body Lotion | Nécessaire | ~$30 |
| Acne Body Wash | Nécessaire | ~$25 |
| The Deodorant | Nécessaire | ~$22 |
| SA Smoothing Lotion (KP) | CeraVe | ~$18 |
| Therapeutic Hand Cream | CeraVe | ~$12 |
| TOTAL | ~$284 |
Nahh. Too much Acure and last time cost was 149$
best clean aesthetic skincare brands 2025 combination acne prone beginner under $150 full routine face body hair
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | Brightening Cleansing Gel | Acure | ~$10 |
| Moisturizer | Seriously Soothing Cloud Cream | Acure | ~$15 |
| Sunscreen | Relief Sun Rice + Probiotics SPF50+ | Beauty of Joseon | ~$16 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | (same as morning) | Acure | — |
| Serum (Week 3+) | Niacinamide 10% + Zinc | The Ordinary | ~$7 |
| Moisturizer | Whipped Night Cream | Acure | ~$16 |
| Lips | Lip Sleeping Mask | Laneige | ~$24 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Body Wash | Seriously Soothing Body Wash | Acure | ~$10 |
| Acne Wash (back/chest 3x/week) | Acne Body Wash with Salicylic Acid | Dove DermaSeries | ~$9 |
| Body Scrub (2x/week) | KP Bump Eraser Body Scrub | First Aid Beauty | ~$30 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Body Lotion (on damp skin) | Seriously Soothing Body Lotion | Acure | ~$12 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Shampoo | Curiously Clarifying Shampoo | Acure | ~$10 |
| Conditioner | Mega Moisture Conditioner | Acure | ~$10 |
| Product | Brand | Price |
|---|---|---|
| Brightening Cleansing Gel | Acure | ~$10 |
| Seriously Soothing Cloud Cream | Acure | ~$15 |
| Whipped Night Cream | Acure | ~$16 |
| Seriously Soothing Body Wash | Acure | ~$10 |
| Seriously Soothing Body Lotion | Acure | ~$12 |
| Curiously Clarifying Shampoo | Acure | ~$10 |
| Mega Moisture Conditioner | Acure | ~$10 |
| Relief Sun SPF50+ | Beauty of Joseon | ~$16 |
| Niacinamide 10% + Zinc | The Ordinary | ~$7 |
| KP Bump Eraser Body Scrub | First Aid Beauty | ~$30 |
| Acne Body Wash | Dove DermaSeries | ~$9 |
| Lip Sleeping Mask | Laneige | ~$24 |
| TOTAL | ~$169 |
| Brand | Why Used |
|---|---|
| Acure | Core face + body + hair — clean, vegan, aesthetic, affordable |
| Beauty of Joseon | Best lightweight clean SPF — nothing Acure makes comes close |
| The Ordinary | Most effective niacinamide on the market at $7 — unbeatable value |
| First Aid Beauty | Best KP body scrub — specifically formulated, clinically tested |
| Dove DermaSeries | Gentle salicylic acid body wash for back/chest acne — clean formula |
| Laneige | Lip sleeping mask — iconic, irreplaceable overnight lip treatment |
Nécessaire Was there and Beauty of Joseon wasn’t there
Nécessaire full product line 2025 body wash serum deodorant sunscreen prices
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | Brightening Cleansing Gel | Acure | ~$10 |
| Moisturizer | Seriously Soothing Cloud Cream | Acure | ~$15 |
| Sunscreen | Mineral Sunscreen SPF 50 | Acure | ~$14 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | (same as morning) | Acure | — |
| Serum (Week 3+) | Niacinamide 10% + Zinc | The Ordinary | ~$7 |
| Moisturizer | Whipped Night Cream | Acure | ~$16 |
| Lips | Lip Sleeping Mask | Laneige | ~$24 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Body Wash | The Body Wash — Fragrance Free | Nécessaire | ~$25 |
| Body Exfoliator (2x/week) | The Body Exfoliator — Fragrance Free | Nécessaire | ~$28 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Body Lotion (damp skin) | The Body Lotion — Fragrance Free | Nécessaire | ~$30 |
| Deodorant | The Deodorant — Fragrance Free | Nécessaire | ~$22 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Shampoo | Curiously Clarifying Shampoo | Acure | ~$10 |
| Conditioner | Mega Moisture Conditioner | Acure | ~$10 |
| Product | Brand | Price |
|---|---|---|
| Brightening Cleansing Gel | Acure | ~$10 |
| Seriously Soothing Cloud Cream | Acure | ~$15 |
| Mineral Sunscreen SPF 50 | Acure | ~$14 |
| Niacinamide 10% + Zinc Serum | The Ordinary | ~$7 |
| Whipped Night Cream | Acure | ~$16 |
| Lip Sleeping Mask | Laneige | ~$24 |
| The Body Wash (FF) | Nécessaire | ~$25 |
| The Body Exfoliator (FF) | Nécessaire | ~$28 |
| The Body Lotion (FF) | Nécessaire | ~$30 |
| The Deodorant (FF) | Nécessaire | ~$22 |
| Clarifying Shampoo | Acure | ~$10 |
| Mega Moisture Conditioner | Acure | ~$10 |
| TOTAL | ~$211 |
| Option | What to Drop | Savings | New Total |
|---|---|---|---|
| A | Nécessaire Body Exfoliator | -$28 | ~$183 |
| B | Laneige Lip Mask | -$24 | ~$187 |
| C | Both A + B | -$52 | ~$159 |
| D | Also swap Nécessaire Body Lotion → Acure Body Lotion ($12) | -$18 | ~$141 ✅ |
How can I recover your memory
"Here's my last routine. Update it / tweak it / explain it." I'll work with whatever you give me.
It had Nécessaire, Acure and other brands. Sunscreen was 50 spf. It had everything from different brands. Total was 149
best clean aesthetic SPF 50 sunscreen face acne prone combination skin 2025 not Beauty of Joseon
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | Brightening Cleansing Gel | Acure | ~$10 |
| Moisturizer | Seriously Soothing Cloud Cream | Acure | ~$15 |
| Sunscreen | Day Dew Sunscreen SPF 50 | Beauty of Joseon | ~$18 |
SPF 50, no white cast, niacinamide + hyaluronic acid built in, non-comedogenic, lightweight on combination skin. Available at Sephora.
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | (same as AM) | Acure | — |
| Serum (from Week 3) | Niacinamide 10% + Zinc | The Ordinary | ~$7 |
| Moisturizer | Whipped Night Cream | Acure | ~$16 |
| Lips | Lip Sleeping Mask | Laneige | ~$24 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Body Wash | The Body Wash — Fragrance Free | Nécessaire | ~$25 |
| Body Exfoliator (2x/week) | The Body Exfoliator — Fragrance Free | Nécessaire | ~$28 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Body Lotion | The Body Lotion — Fragrance Free | Nécessaire | ~$30 |
| Deodorant | The Deodorant — Fragrance Free | Nécessaire | ~$22 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Shampoo | Curiously Clarifying Shampoo | Acure | ~$10 |
| Conditioner | Mega Moisture Conditioner | Acure | ~$10 |
| # | Product | Brand | Price |
|---|---|---|---|
| 1 | Brightening Cleansing Gel | Acure | $10 |
| 2 | Seriously Soothing Cloud Cream | Acure | $15 |
| 3 | Whipped Night Cream | Acure | $16 |
| 4 | Curiously Clarifying Shampoo | Acure | $10 |
| 5 | Mega Moisture Conditioner | Acure | $10 |
| 6 | Day Dew Sunscreen SPF 50 | Beauty of Joseon | $18 |
| 7 | Niacinamide 10% + Zinc Serum | The Ordinary | $7 |
| 8 | Lip Sleeping Mask | Laneige | $24 |
| 9 | The Body Wash (FF) | Nécessaire | $25 |
| 10 | The Body Exfoliator (FF) | Nécessaire | $28 |
| 11 | The Body Lotion (FF) | Nécessaire | $30 |
| 12 | The Deodorant (FF) | Nécessaire | $22 |
| TOTAL | $215 |
| Cut | Saving | New Total |
|---|---|---|
| Drop Nécessaire Body Exfoliator | -$28 | $187 |
| Drop Nécessaire Body Lotion → replace with Acure Body Lotion ($12) | -$18 | $169 |
| Drop Laneige Lip Mask | -$24 | $145 ✅ |
| Week | Morning | Night | Body |
|---|---|---|---|
| 1–2 | Cleanser → Cloud Cream → SPF | Cleanser → Night Cream + Lip Mask | Nécessaire body wash + lotion + deodorant |
| 3 | Same | Add Niacinamide serum 3x/week | Add body exfoliator 2x/week |
| 4+ | Full routine locked | Full routine locked | Full routine locked |
It didn’t had. Hair products, lip products and deodorant or similar. It only included sunscreen, cleanser, body wash, body lotion/cream, face cream/lotion, serum and etc I don’t remember but in this category
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | Brightening Cleansing Gel | Acure | ~$10 |
| Serum | Niacinamide 10% + Zinc | The Ordinary | ~$7 |
| Face Moisturizer | Seriously Soothing Cloud Cream | Acure | ~$15 |
| Sunscreen | Day Dew Sunscreen SPF 50 | Beauty of Joseon | ~$18 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | (same as AM) | Acure | — |
| Serum | (same niacinamide) | The Ordinary | — |
| Night Cream | Whipped Night Cream | Acure | ~$16 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Body Wash | The Body Wash — Fragrance Free | Nécessaire | ~$25 |
| Body Lotion | The Body Lotion — Fragrance Free | Nécessaire | ~$30 |
| Body Exfoliator (2x/week) | The Body Exfoliator — Fragrance Free | Nécessaire | ~$28 |
| # | Product | Brand | Price |
|---|---|---|---|
| 1 | Brightening Cleansing Gel | Acure | $10 |
| 2 | Seriously Soothing Cloud Cream | Acure | $15 |
| 3 | Whipped Night Cream | Acure | $16 |
| 4 | Niacinamide 10% + Zinc Serum | The Ordinary | $7 |
| 5 | Day Dew Sunscreen SPF 50 | Beauty of Joseon | $18 |
| 6 | The Body Wash (FF) | Nécessaire | $25 |
| 7 | The Body Lotion (FF) | Nécessaire | $30 |
| 8 | The Body Exfoliator (FF) | Nécessaire | $28 |
| TOTAL | $149 ✅ |
| Week | Morning | Night | Body |
|---|---|---|---|
| 1–2 | Cleanser → Cloud Cream → SPF | Cleanser → Night Cream | Body wash + body lotion |
| 3 | Add Niacinamide serum | Add Niacinamide serum | Add body exfoliator 2x/week |
| 4+ | Full routine locked | Full routine locked | Full routine locked |
| Product | Why It's Here |
|---|---|
| Acure Cleansing Gel | Gentle, vegan, pH-balanced — safe for reactive combination skin |
| Acure Cloud Cream | Lightweight day moisture, won't clog pores, soothes inflammation |
| Acure Night Cream | Richer overnight repair, same clean formula |
| The Ordinary Niacinamide | Targets your acne + dark marks + pores + oiliness — $7, unmatched value |
| Beauty of Joseon SPF 50 | Lightest, cleanest SPF 50 for acne-prone skin, no white cast |
| Nécessaire Body Wash | Niacinamide + vitamins, pH-balanced, fragrance-free, tackles body acne |
| Nécessaire Body Lotion | AHA + niacinamide — fades uneven body tone, treats KP, non-comedogenic |
| Nécessaire Body Exfoliator | Addresses KP, rough/ashy skin, uneven texture |
Acure and Nécessaire was only for one product and there was no Beauty of Joseon and The Ordinary
clean aesthetic skincare brands 2025 face serum moisturizer body lotion SPF 50 acne combination skin Bubble Byoma Krave Naturium Glow Recipe
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | Brightening Cleansing Gel | Acure | ~$10 |
| Serum | Phyto-Mucin Glow Serum | Byoma | ~$18 |
| Face Moisturizer | Moisturizing Gel-Cream | Byoma | ~$18 |
| Sunscreen | Mineral Sunscreen SPF 50 | EltaMD UV Clear | ~$42 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | (same as AM) | Acure | — |
| Serum | (same as AM) | Byoma | — |
| Night Cream | Great Barrier Relief | Krave Beauty | ~$28 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Body Wash | The Body Wash — Fragrance Free | Nécessaire | ~$25 |
| Body Lotion | Brightening Body Lotion | Byoma | ~$15 |
| # | Product | Brand | Price |
|---|---|---|---|
| 1 | Brightening Cleansing Gel | Acure | $10 |
| 2 | Phyto-Mucin Glow Serum | Byoma | $18 |
| 3 | Moisturizing Gel-Cream | Byoma | $18 |
| 4 | Great Barrier Relief Night Cream | Krave Beauty | $28 |
| 5 | UV Clear Mineral Sunscreen SPF 46 | EltaMD | $42 |
| 6 | The Body Wash (Fragrance Free) | Nécessaire | $25 |
| 7 | Brightening Body Lotion | Byoma | $15 |
| TOTAL | $156 |
Swap EltaMD ($42) → Acure Mineral SPF 50 ($14) to bring total to $128, or keep EltaMD and drop Byoma body lotion → $141 ✅
| Brand | Role | Why |
|---|---|---|
| Acure | Cleanser | Gentle, vegan, pH-safe for reactive skin |
| Byoma | Serum + Day Cream + Body Lotion | Barrier-boosting ceramide science, affordable, iconic pastel aesthetic |
| Krave Beauty | Night Cream | Cult barrier repair cream, non-comedogenic, beloved for acne-prone skin |
| EltaMD | SPF | #1 dermatologist-recommended SPF for acne/sensitive skin, SPF 46 mineral |
| Nécessaire | Body Wash | Niacinamide + vitamins, pH-balanced, tackles body acne beautifully |
Being honest there was no EltaMD, Krave beauty and byoma
| ✅ Confirmed | ❌ Eliminated |
|---|---|
| Acure — cleanser only | Beauty of Joseon |
| Nécessaire — 1 product (unknown which) | The Ordinary |
| SPF 50 | EltaMD |
| ~$149 total | Krave Beauty |
| No hair, lip, deodorant | Byoma |
| One brand per product |
Do you remember where you had this conversation? Which app, website, or platform? If you used ChatGPT, Claude, Gemini, or another AI — those platforms sometimes save chat history that YOU can search. Check your chat history on that platform and search for "Acure" or "Nécessaire" — you may find the original conversation there.
Orris
| # | Category | Product | Brand | Price |
|---|---|---|---|---|
| 1 | Face Cleanser | Brightening Cleansing Gel | Acure | $10 |
| 2 | Face Serum | Niacinamide Serum 12% + Zinc 2% | Naturium | $20 |
| 3 | Face Moisturizer (Day) | Hydro Boost Water Gel | Neutrogena | $20 |
| 4 | Face Moisturizer (Night) | Barrier Culture Moisturizer | Bubble | $18 |
| 5 | Sunscreen SPF 50 | Invisible UV Defender SPF 50 | La Roche-Posay | $38 |
| 6 | Body Wash | The Body Wash — Fragrance Free | Nécessaire | $25 |
| 7 | Body Lotion | Brightening Body Lotion | CeraVe | $16 |
| TOTAL | $147 ✅ |
| Product | Reason |
|---|---|
| Acure Cleanser | Gentle, vegan, pH-balanced for reactive combination skin |
| Naturium Niacinamide | Tackles acne, pores, dark marks, oiliness — clean aesthetic bottle |
| Neutrogena Hydro Boost | Lightweight gel, non-comedogenic, perfect for oily T-zone |
| Bubble Night Moisturizer | Barrier repair overnight, teen-targeted clean brand, fragrance-free |
| La Roche-Posay SPF 50 | Dermatologist #1 recommended, invisible finish, acne-safe |
| Nécessaire Body Wash | Niacinamide + vitamins, pH-balanced, tackles body acne |
| CeraVe SA Body Lotion | Salicylic acid — directly treats your KP and rough body skin |
| Week | AM | PM | Body |
|---|---|---|---|
| 1–2 | Cleanser → Hydro Boost → SPF | Cleanser → Bubble Night Cream | Nécessaire wash + CeraVe lotion |
| 3–4 | Add Naturium Niacinamide Serum | Same + Serum | Same |
| 5+ | Full routine | Full routine | Full routine |
Ok, forget everything about today’s this convo. Let’s start fresh. Create new list. I want asthetic, clean, feel and smell good and perfect for skin. Not great derma fan although cera ve is fine but not great. Take best from different. My bugde is 100-150 $
best aesthetic clean skincare brands 2025 face body acne hydration glow dark spots texture under $150 Bubble Naturium Glow Recipe Nécessaire Tower 28 Fenty Skin
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | Brightening Cleansing Gel | Acure | $10 |
| Toner | Witch Hazel + Rosewater Toner | Thayers | $12 |
| Serum | Niacinamide Serum 12% + Zinc | Naturium | $20 |
| Moisturizer | Barrier Culture Moisture Cream | Bubble | $18 |
| Sunscreen | Unseen Sunscreen SPF 40 | Supergoop! | $36 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | (same) | Acure | — |
| Serum | (same niacinamide) | Naturium | — |
| Night Moisturizer | Cloud Dew Oil-Free Moisturizer | Glow Recipe | $39 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Body Wash | The Body Wash — Eucalyptus | Nécessaire | $25 |
| Body Lotion | The Body Lotion — Fragrance Free | Nécessaire | $30 |
| # | Product | Brand | Price |
|---|---|---|---|
| 1 | Brightening Cleansing Gel | Acure | $10 |
| 2 | Witch Hazel + Rosewater Toner | Thayers | $12 |
| 3 | Niacinamide Serum 12% + Zinc | Naturium | $20 |
| 4 | Barrier Culture Moisture Cream | Bubble | $18 |
| 5 | Unseen Sunscreen SPF 40 | Supergoop! | $36 |
| 6 | Cloud Dew Oil-Free Night Moisturizer | Glow Recipe | $39 |
| 7 | The Body Wash (Eucalyptus) | Nécessaire | $25 |
| 8 | The Body Lotion (FF) | Nécessaire | $30 |
| TOTAL | $190 |
| Budget Tier | Drop | Total |
|---|---|---|
| $150 | Swap Glow Recipe ($39) → Bubble Night Cream ($18) | $169 |
| $145 | Also drop Nécessaire Body Lotion → Acure Body Lotion ($12) | $151 |
| $130 | Also swap Supergoop ($36) → Acure Mineral SPF 50 ($14) | $129 ✅ |
| $110 | Also drop Thayers Toner | $117 ✅ |
| Brand | Vibe | Why It's Here |
|---|---|---|
| Acure | Clean, vegan, minimal | Gentle daily cleanser, won't strip reactive skin |
| Thayers | Iconic, floral-fresh scent | Rose water toner — smells amazing, calms redness |
| Naturium | Sleek, modern | Best niacinamide for acne + dark spots + pores |
| Bubble | Fun, Gen Z aesthetic | Barrier cream, beginner-safe, non-comedogenic |
| Supergoop! | Premium, invisible finish | Best feeling SPF on the market — literally undetectable |
| Glow Recipe | Watermelon aesthetic, stunning | Oil-free hydration + glow overnight |
| Nécessaire | Minimalist luxury | Body wash + lotion with niacinamide — smells incredible in eucalyptus |
I love minimal luxury
| Step | Product | Brand | Why It's Minimal Luxury |
|---|---|---|---|
| Cleanser | Brightening Cleansing Gel | Acure | Clean minimal tube, vegan, gentle |
| Serum | Niacinamide Serum 12% + Zinc | Naturium | Sleek apothecary bottle, high-performance |
| Moisturizer | Barrier Culture Moisture Cream | Bubble | Frosted glass-look jar, barrier-first formula |
| Sunscreen | Unseen Sunscreen SPF 40 | Supergoop! | Invisible, weightless — the most luxurious SPF feel available |
| Step | Product | Brand | Why It's Minimal Luxury |
|---|---|---|---|
| Cleanser | (same) | Acure | — |
| Serum | (same) | Naturium | — |
| Night Moisturizer | Cloud Dew Oil-Free Moisturizer | Glow Recipe | Watermelon glass bottle — stunningly aesthetic, deeply hydrating |
| Step | Product | Brand | Why It's Minimal Luxury |
|---|---|---|---|
| Body Wash | The Body Wash — Eucalyptus | Nécessaire | Award-winning. Clean white bottle. Smells like a spa |
| Body Lotion | The Body Lotion — Fragrance Free | Nécessaire | Matching set. Niacinamide + ceramides. Skin-first formula |
| # | Product | Brand | Price |
|---|---|---|---|
| 1 | Brightening Cleansing Gel | Acure | $10 |
| 2 | Niacinamide Serum 12% + Zinc | Naturium | $20 |
| 3 | Barrier Culture Moisture Cream | Bubble | $18 |
| 4 | Unseen Sunscreen SPF 40 | Supergoop! | $36 |
| 5 | Cloud Dew Oil-Free Night Moisturizer | Glow Recipe | $39 |
| 6 | The Body Wash — Eucalyptus | Nécessaire | $25 |
| 7 | The Body Lotion — Fragrance Free | Nécessaire | $30 |
| TOTAL | $178 |
| Target | Swap | Total |
|---|---|---|
| ~$150 | Swap Glow Recipe ($39) → Bubble Night Cream ($18) | $157 |
| ~$140 | Also swap Supergoop ($36) → Acure Mineral SPF 50 ($14) | $135 ✅ |
| ~$120 | Also drop Nécessaire Body Lotion → use body wash only for now | $105 ✅ |
Acure, Naturium and Nécessaire is inn but other 🫣
minimal luxury clean skincare 2025 face moisturizer night cream SPF 50 aesthetic packaging acne combination skin not Bubble Supergoop Glow Recipe
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | Brightening Cleansing Gel | Acure | $10 |
| Serum | Niacinamide Serum 12% + Zinc | Naturium | $20 |
| Moisturizer | Hydrating Toning Serum + Rich Cream | Byoma | $18 |
| Sunscreen | Invisible UV Fluid SPF 50 | La Roche-Posay | $38 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | (same) | Acure | — |
| Serum | (same) | Naturium | — |
| Night Moisturizer | Overnight Recovery Sleeping Mask | Laneige | $27 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Body Wash | The Body Wash — Eucalyptus | Nécessaire | $25 |
| Body Lotion | The Body Lotion — Fragrance Free | Nécessaire | $30 |
| # | Product | Brand | Price |
|---|---|---|---|
| 1 | Brightening Cleansing Gel | Acure | $10 |
| 2 | Niacinamide Serum 12% + Zinc | Naturium | $20 |
| 3 | Moisturizing Rich Cream | Byoma | $18 |
| 4 | Invisible UV Fluid SPF 50 | La Roche-Posay | $38 |
| 5 | Water Sleeping Mask | Laneige | $27 |
| 6 | The Body Wash — Eucalyptus | Nécessaire | $25 |
| 7 | The Body Lotion — FF | Nécessaire | $30 |
| TOTAL | $168 |
Drop La Roche-Posay ($38) → Naturium SPF 50 Sunscreen ($18) = $148 ✅
| Brand | Replaces | Why Better Fit for Minimal Luxury |
|---|---|---|
| Byoma | Bubble | More sophisticated barrier science, cleaner minimal aesthetic, less "teen" |
| La Roche-Posay | Supergoop | Iconic pharmacy-luxe brand, Invisible UV Fluid is weightless SPF 50, trusted globally |
| Laneige | Glow Recipe | Korean luxury, Water Sleeping Mask is iconic, deeply hydrating overnight, elegant packaging |
Everything is great except La Roche-Posay
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | Brightening Cleansing Gel | Acure | $10 |
| Serum | Niacinamide Serum 12% + Zinc | Naturium | $20 |
| Moisturizer | Moisturizing Rich Cream | Byoma | $18 |
| Sunscreen | Centella Unscented Sun SPF 50+ | Purito | $16 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | (same) | Acure | — |
| Serum | (same) | Naturium | — |
| Night Mask | Water Sleeping Mask | Laneige | $27 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Body Wash | The Body Wash — Eucalyptus | Nécessaire | $25 |
| Body Lotion | The Body Lotion — Fragrance Free | Nécessaire | $30 |
| # | Product | Brand | Price |
|---|---|---|---|
| 1 | Brightening Cleansing Gel | Acure | $10 |
| 2 | Niacinamide Serum 12% + Zinc | Naturium | $20 |
| 3 | Moisturizing Rich Cream | Byoma | $18 |
| 4 | Centella Unscented Sun SPF 50+ | Purito | $16 |
| 5 | Water Sleeping Mask | Laneige | $27 |
| 6 | The Body Wash — Eucalyptus | Nécessaire | $25 |
| 7 | The Body Lotion — Fragrance Free | Nécessaire | $30 |
| TOTAL | $146 ✅ |
| Brand | Product | Aesthetic |
|---|---|---|
| Acure | Cleanser | Clean minimal tube, vegan, affordable anchor |
| Naturium | Serum | Apothecary-style bottle, sleek and purposeful |
| Byoma | Day Moisturizer | Pastel minimal, barrier science, elegant |
| Purito | Sunscreen SPF 50+ | Korean minimal luxury, matte white, unscented |
| Laneige | Night Sleeping Mask | Iconic K-beauty jar, lightweight luxury overnight |
| Nécessaire | Body Wash + Lotion | The gold standard of minimal luxury body care |
| Week | AM | PM | Body |
|---|---|---|---|
| 1–2 | Cleanser → Byoma → Purito SPF | Cleanser → Laneige Mask | Nécessaire wash + lotion |
| 3–4 | Add Naturium Niacinamide (AM + PM) | Same | Same |
| 5+ | Full routine — locked | Full routine — locked | Full routine — locked |
Generate a PDF skincare guide with this routine & usage tips
ls -la /home/daytona/workspace/ 2>/dev/null || echo "workspace empty or missing"
mkdir -p /home/daytona/workspace/skincare-guide
~/skincare-guide/generate_pdf.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
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
from reportlab.platypus import KeepTogether
# ── Palette ──────────────────────────────────────────────────────────────────
CREAM = colors.HexColor("#FAF7F4")
BLUSH = colors.HexColor("#E8D5C4")
ROSE = colors.HexColor("#C9A98A")
DEEP = colors.HexColor("#5C3D2E")
CHARCOAL = colors.HexColor("#2C2C2C")
SOFT_GREY = colors.HexColor("#9E9E9E")
WHITE = colors.white
SAGE = colors.HexColor("#A8B5A0")
LIGHT_SAGE = colors.HexColor("#EFF3ED")
doc = SimpleDocTemplate(
"/home/daytona/workspace/skincare-guide/Skincare_Guide.pdf",
pagesize=A4,
rightMargin=1.8*cm,
leftMargin=1.8*cm,
topMargin=2*cm,
bottomMargin=2*cm,
title="My Minimal Luxury Skincare Guide",
author="Orris"
)
W, H = A4
styles = getSampleStyleSheet()
# ── Custom Styles ─────────────────────────────────────────────────────────────
def S(name, **kw):
return ParagraphStyle(name, **kw)
cover_title = S("CoverTitle", fontSize=36, textColor=WHITE, alignment=TA_CENTER,
fontName="Helvetica-Bold", leading=44, spaceAfter=6)
cover_sub = S("CoverSub", fontSize=13, textColor=BLUSH, alignment=TA_CENTER,
fontName="Helvetica", leading=20, spaceAfter=4)
cover_note = S("CoverNote", fontSize=9, textColor=BLUSH, alignment=TA_CENTER,
fontName="Helvetica", leading=14)
section_hdr = S("SectionHdr", fontSize=15, textColor=DEEP, fontName="Helvetica-Bold",
leading=20, spaceBefore=14, spaceAfter=4)
sub_hdr = S("SubHdr", fontSize=11, textColor=ROSE, fontName="Helvetica-Bold",
leading=16, spaceBefore=8, spaceAfter=2)
body_txt = S("BodyTxt", fontSize=9.5, textColor=CHARCOAL, fontName="Helvetica",
leading=15, spaceAfter=3)
small_txt = S("SmallTxt", fontSize=8.5, textColor=SOFT_GREY, fontName="Helvetica",
leading=13, spaceAfter=2)
bullet_txt = S("BulletTxt", fontSize=9.5, textColor=CHARCOAL, fontName="Helvetica",
leading=15, leftIndent=14, bulletIndent=4, spaceAfter=2)
tip_txt = S("TipTxt", fontSize=9, textColor=DEEP, fontName="Helvetica",
leading=14, leftIndent=10, spaceAfter=2)
footer_txt = S("FooterTxt", fontSize=8, textColor=SOFT_GREY, alignment=TA_CENTER,
fontName="Helvetica", leading=11)
tag_txt = S("TagTxt", fontSize=8, textColor=WHITE, fontName="Helvetica-Bold",
leading=11, alignment=TA_CENTER)
# ── Page template with background ────────────────────────────────────────────
def page_background(canvas, doc):
canvas.saveState()
canvas.setFillColor(CREAM)
canvas.rect(0, 0, W, H, fill=1, stroke=0)
# top accent bar
canvas.setFillColor(DEEP)
canvas.rect(0, H - 8*mm, W, 8*mm, fill=1, stroke=0)
# bottom accent bar
canvas.setFillColor(ROSE)
canvas.rect(0, 0, W, 4*mm, fill=1, stroke=0)
# page number
if doc.page > 1:
canvas.setFont("Helvetica", 8)
canvas.setFillColor(SOFT_GREY)
canvas.drawCentredString(W/2, 8*mm, f"— {doc.page} —")
canvas.restoreState()
def cover_background(canvas, doc):
canvas.saveState()
# full bleed deep cover
canvas.setFillColor(DEEP)
canvas.rect(0, 0, W, H, fill=1, stroke=0)
# decorative blush rectangle top
canvas.setFillColor(ROSE)
canvas.rect(0, H - 3*cm, W, 3*cm, fill=1, stroke=0)
# decorative bottom strip
canvas.setFillColor(BLUSH)
canvas.rect(0, 0, W, 2.5*cm, fill=1, stroke=0)
canvas.restoreState()
class CoverPage:
def __init__(self):
self._page = True
# ── Helper builders ───────────────────────────────────────────────────────────
def hr(color=ROSE, thickness=0.7):
return HRFlowable(width="100%", thickness=thickness, color=color, spaceAfter=6, spaceBefore=4)
def routine_table(rows, header_color=DEEP):
col_widths = [3.5*cm, 7*cm, 3.8*cm, 2.2*cm]
table_data = [
[Paragraph("<b>Step</b>", S("th", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=12)),
Paragraph("<b>Product</b>", S("th", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", leading=12)),
Paragraph("<b>Brand</b>", S("th", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", leading=12)),
Paragraph("<b>Price</b>", S("th", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=12))],
]
for step, product, brand, price in rows:
table_data.append([
Paragraph(step, S("tc", fontSize=9, textColor=DEEP, fontName="Helvetica-Bold", leading=13)),
Paragraph(product, S("tc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph(brand, S("tc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph(price, S("tc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", alignment=TA_CENTER, leading=13)),
])
t = Table(table_data, colWidths=col_widths, repeatRows=1)
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), header_color),
("ROWBACKGROUNDS",(0,1), (-1,-1), [WHITE, LIGHT_SAGE]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#D9D0C7")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("ROUNDEDCORNERS", [4]),
]))
return t
def shopping_table(rows):
col_widths = [1.2*cm, 7.5*cm, 3.5*cm, 2.5*cm, 1.8*cm]
header = [
Paragraph("<b>#</b>", S("th2", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=12)),
Paragraph("<b>Product</b>", S("th2", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", leading=12)),
Paragraph("<b>Brand</b>", S("th2", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", leading=12)),
Paragraph("<b>Category</b>",S("th2", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", leading=12)),
Paragraph("<b>Price</b>", S("th2", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=12)),
]
data = [header]
for num, product, brand, cat, price in rows:
data.append([
Paragraph(num, S("tc2", fontSize=9, textColor=SOFT_GREY, fontName="Helvetica", alignment=TA_CENTER, leading=13)),
Paragraph(product, S("tc2", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph(brand, S("tc2", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph(cat, S("tc2", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph(price, S("tc2", fontSize=9, textColor=DEEP, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=13)),
])
# total row
data.append([
Paragraph("", S("tc2", fontSize=9, fontName="Helvetica", leading=13)),
Paragraph("<b>TOTAL</b>", S("tc2", fontSize=10, textColor=WHITE, fontName="Helvetica-Bold", leading=13)),
Paragraph("", S("tc2", fontSize=9, fontName="Helvetica", leading=13)),
Paragraph("", S("tc2", fontSize=9, fontName="Helvetica", leading=13)),
Paragraph("<b>$146</b>", S("tc2", fontSize=10, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=13)),
])
t = Table(data, colWidths=col_widths, repeatRows=1)
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DEEP),
("BACKGROUND", (0,-1), (-1,-1), ROSE),
("ROWBACKGROUNDS",(0,1), (-1,-2), [WHITE, LIGHT_SAGE]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#D9D0C7")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
return t
def tip_box(tips, title="Pro Tips", bg=LIGHT_SAGE, border=SAGE):
inner = []
inner.append(Paragraph(f"<b>{title}</b>", S("tbhdr", fontSize=10, textColor=DEEP,
fontName="Helvetica-Bold", leading=14, spaceAfter=4)))
for t in tips:
inner.append(Paragraph(f"• {t}", S("tbtxt", fontSize=9, textColor=CHARCOAL,
fontName="Helvetica", leading=14, leftIndent=6, spaceAfter=2)))
box = Table([[inner]], colWidths=[W - 3.6*cm])
box.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("BOX", (0,0), (-1,-1), 1.2, border),
("TOPPADDING", (0,0), (-1,-1), 10),
("BOTTOMPADDING",(0,0), (-1,-1), 10),
("LEFTPADDING", (0,0), (-1,-1), 12),
("RIGHTPADDING", (0,0), (-1,-1), 12),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
return box
def warning_box(tips, title="⚠ Avoid These"):
WARN_BG = colors.HexColor("#FDF0E8")
WARN_BDR = colors.HexColor("#D4856A")
inner = []
inner.append(Paragraph(f"<b>{title}</b>", S("wbhdr", fontSize=10, textColor=colors.HexColor("#A0522D"),
fontName="Helvetica-Bold", leading=14, spaceAfter=4)))
for t in tips:
inner.append(Paragraph(f"✕ {t}", S("wbtxt", fontSize=9, textColor=CHARCOAL,
fontName="Helvetica", leading=14, leftIndent=6, spaceAfter=2)))
box = Table([[inner]], colWidths=[W - 3.6*cm])
box.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), WARN_BG),
("BOX", (0,0), (-1,-1), 1.2, WARN_BDR),
("TOPPADDING", (0,0), (-1,-1), 10),
("BOTTOMPADDING",(0,0), (-1,-1), 10),
("LEFTPADDING", (0,0), (-1,-1), 12),
("RIGHTPADDING", (0,0), (-1,-1), 12),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
return box
# ── Build story ───────────────────────────────────────────────────────────────
story = []
# ════════════════════════════════════════════
# PAGE 1 — COVER (uses cover_background)
# ════════════════════════════════════════════
cover_content = [
Spacer(1, 3.5*cm),
Paragraph("MY SKINCARE", cover_title),
Paragraph("ROUTINE", cover_title),
Spacer(1, 0.6*cm),
Paragraph("Minimal Luxury · Clean · Intentional", cover_sub),
Spacer(1, 0.4*cm),
Paragraph("Face + Body · $146 Total", cover_sub),
Spacer(1, 1.2*cm),
Paragraph("Curated by Orris · Your Skin Expert", cover_note),
Spacer(1, 0.3*cm),
Paragraph("Under 18 · Combination Skin · Acne-Prone · Reactive", cover_note),
Spacer(1, 3*cm),
Paragraph("6 Brands · 7 Products · 1 Perfect Routine", cover_note),
]
# We'll render cover on its own page using a different frame approach
# by using a special first-page template
story.extend(cover_content)
# ════════════════════════════════════════════
# PAGE 2 — BRAND OVERVIEW
# ════════════════════════════════════════════
story.append(Spacer(1, 0.8*cm))
story.append(hr(DEEP, 1.5))
story.append(Paragraph("YOUR BRAND LINEUP", section_hdr))
story.append(hr())
story.append(Spacer(1, 0.3*cm))
brand_data = [
[Paragraph("<b>Brand</b>", S("bh", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", leading=12)),
Paragraph("<b>Product</b>", S("bh", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", leading=12)),
Paragraph("<b>Why It's Here</b>", S("bh", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", leading=12))],
[Paragraph("<b>Acure</b>", S("bc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph("Cleanser", S("bc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Gentle, vegan, pH-safe. Won't strip your reactive skin", S("bc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13))],
[Paragraph("<b>Naturium</b>", S("bc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph("Niacinamide Serum", S("bc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Targets acne, dark spots, pores and oiliness in one serum", S("bc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13))],
[Paragraph("<b>Byoma</b>", S("bc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph("Day Moisturizer", S("bc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Barrier-boosting ceramides, minimal aesthetic, non-comedogenic", S("bc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13))],
[Paragraph("<b>Purito</b>", S("bc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph("Sunscreen SPF 50+", S("bc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Korean minimal luxury SPF. Weightless, unscented, zero white cast", S("bc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13))],
[Paragraph("<b>Laneige</b>", S("bc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph("Night Sleeping Mask", S("bc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Iconic K-beauty overnight hydration. Elegant jar, deeply restorative", S("bc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13))],
[Paragraph("<b>Nécessaire</b>", S("bc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph("Body Wash + Lotion", S("bc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Gold standard of minimal luxury body care. Niacinamide + vitamins", S("bc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13))],
]
brand_table = Table(brand_data, colWidths=[3.2*cm, 4*cm, 9.3*cm], repeatRows=1)
brand_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DEEP),
("ROWBACKGROUNDS",(0,1), (-1,-1), [WHITE, LIGHT_SAGE]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#D9D0C7")),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
story.append(brand_table)
story.append(Spacer(1, 0.5*cm))
# ════════════════════════════════════════════
# MORNING ROUTINE
# ════════════════════════════════════════════
story.append(KeepTogether([
hr(ROSE, 1.2),
Paragraph("🌅 MORNING ROUTINE", section_hdr),
hr(),
Spacer(1, 0.2*cm),
routine_table([
("Cleanser", "Brightening Cleansing Gel", "Acure", "$10"),
("Serum", "Niacinamide Serum 12% + Zinc 2%", "Naturium", "$20"),
("Moisturizer", "Moisturizing Rich Cream", "Byoma", "$18"),
("Sunscreen", "Centella Unscented Sun SPF 50+", "Purito", "$16"),
]),
Spacer(1, 0.4*cm),
]))
story.append(tip_box([
"Wash with lukewarm water — never hot. Hot water strips your barrier.",
"Apply serum on slightly damp skin for better absorption.",
"Wait 60 seconds after moisturizer before applying SPF.",
"Apply SPF as the very last step, every single morning — even indoors.",
"Use a pea-sized amount of each product. More is not better.",
], "Morning Tips"))
story.append(Spacer(1, 0.5*cm))
# ════════════════════════════════════════════
# NIGHT ROUTINE
# ════════════════════════════════════════════
story.append(KeepTogether([
hr(DEEP, 1.2),
Paragraph("🌙 NIGHT ROUTINE", section_hdr),
hr(),
Spacer(1, 0.2*cm),
routine_table([
("Cleanser", "Brightening Cleansing Gel", "Acure", "$10"),
("Serum", "Niacinamide Serum 12% + Zinc 2%", "Naturium", "$20"),
("Night Mask", "Water Sleeping Mask", "Laneige", "$27"),
]),
Spacer(1, 0.4*cm),
]))
story.append(tip_box([
"Double cleanse if you wore heavy sunscreen or makeup (oil cleanser first).",
"Niacinamide serum can be used both AM and PM once your skin adjusts.",
"Apply Laneige sleeping mask as your final step — scoop with the spatula provided.",
"The sleeping mask works overnight. Rinse off in the morning with your cleanser.",
"Night is when your skin repairs itself — don't skip moisturizing.",
], "Night Tips"))
story.append(Spacer(1, 0.5*cm))
# ════════════════════════════════════════════
# BODY ROUTINE
# ════════════════════════════════════════════
story.append(KeepTogether([
hr(SAGE, 1.2),
Paragraph("🛁 BODY ROUTINE", section_hdr),
hr(SAGE),
Spacer(1, 0.2*cm),
routine_table([
("Body Wash", "The Body Wash — Eucalyptus", "Nécessaire", "$25"),
("Body Lotion","The Body Lotion — Fragrance Free","Nécessaire", "$30"),
], header_color=SAGE),
Spacer(1, 0.4*cm),
]))
story.append(tip_box([
"Apply body lotion within 3 minutes of stepping out of the shower — on damp skin.",
"This locks in significantly more moisture than applying on dry skin.",
"For body acne (back/chest): let the body wash sit for 60 seconds before rinsing.",
"For rough/bumpy arms (KP): massage lotion in circular motions on upper arms.",
"The eucalyptus scent is spa-level — use it as your daily self-care ritual.",
], "Body Tips", bg=colors.HexColor("#EFF6EF"), border=SAGE))
story.append(Spacer(1, 0.5*cm))
# ════════════════════════════════════════════
# 4-WEEK PROGRESSION
# ════════════════════════════════════════════
story.append(hr(DEEP, 1.2))
story.append(Paragraph("📅 4-WEEK BUILD PLAN", section_hdr))
story.append(hr())
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph(
"Do not start everything at once. Introduce products gradually to avoid reactions.",
body_txt))
story.append(Spacer(1, 0.3*cm))
week_data = [
[Paragraph("<b>Week</b>", S("wh", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=12)),
Paragraph("<b>Morning</b>",S("wh", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", leading=12)),
Paragraph("<b>Night</b>", S("wh", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", leading=12)),
Paragraph("<b>Body</b>", S("wh", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", leading=12))],
[Paragraph("1–2", S("wc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=13)),
Paragraph("Cleanser → Byoma Cream → Purito SPF", S("wc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Cleanser → Laneige Night Mask", S("wc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Nécessaire wash + lotion", S("wc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13))],
[Paragraph("3–4", S("wc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=13)),
Paragraph("Add Naturium Niacinamide (3x/week)", S("wc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Add Niacinamide (3x/week) + Laneige", S("wc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Same — locked in", S("wc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13))],
[Paragraph("5+", S("wc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=13)),
Paragraph("Full AM routine daily", S("wc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Full PM routine daily", S("wc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Full body routine daily", S("wc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13))],
]
week_table = Table(week_data, colWidths=[2*cm, 5.5*cm, 5.5*cm, 3.5*cm], repeatRows=1)
week_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DEEP),
("ROWBACKGROUNDS",(0,1), (-1,-1), [WHITE, LIGHT_SAGE]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#D9D0C7")),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("ALIGN", (0,0), (0,-1), "CENTER"),
]))
story.append(week_table)
story.append(Spacer(1, 0.5*cm))
# ════════════════════════════════════════════
# WHAT TO AVOID
# ════════════════════════════════════════════
story.append(warning_box([
"Picking or touching your face — spreads bacteria, causes permanent dark marks",
"Physical scrubs (St. Ives, sugar scrubs) — micro-tears inflame active acne",
"Alcohol-based toners — strip barrier, trigger rebound oiliness",
"Layering multiple new products at once — you'll never know what caused a reaction",
"Coconut oil on the face — highly comedogenic, clogs pores",
"Skipping SPF — UV makes dark marks permanent",
"Hot water when cleansing — damages your skin barrier",
]))
story.append(Spacer(1, 0.5*cm))
# ════════════════════════════════════════════
# SHOPPING LIST
# ════════════════════════════════════════════
story.append(hr(DEEP, 1.2))
story.append(Paragraph("🛍 COMPLETE SHOPPING LIST", section_hdr))
story.append(hr())
story.append(Spacer(1, 0.2*cm))
story.append(shopping_table([
("1", "Brightening Cleansing Gel", "Acure", "Face Cleanser", "$10"),
("2", "Niacinamide Serum 12% + Zinc 2%", "Naturium", "Face Serum", "$20"),
("3", "Moisturizing Rich Cream", "Byoma", "Day Moisturizer","$18"),
("4", "Centella Unscented Sun SPF 50+", "Purito", "Sunscreen", "$16"),
("5", "Water Sleeping Mask", "Laneige", "Night Mask", "$27"),
("6", "The Body Wash — Eucalyptus", "Nécessaire", "Body Wash", "$25"),
("7", "The Body Lotion — Fragrance Free", "Nécessaire", "Body Lotion", "$30"),
]))
story.append(Spacer(1, 0.6*cm))
# ════════════════════════════════════════════
# LIFESTYLE RULES
# ════════════════════════════════════════════
story.append(hr(ROSE, 1.2))
story.append(Paragraph("✦ LIFESTYLE RULES — NON-NEGOTIABLE", section_hdr))
story.append(hr())
story.append(Spacer(1, 0.2*cm))
story.append(tip_box([
"Stop picking your face. Every pick = 4–6 weeks of dark marks added.",
"Drink 8+ glasses of water daily. Dehydration shows up as dull, uneven skin.",
"Reduce sugar and dairy — directly linked to acne in your age group.",
"Change your pillowcase every 3–4 days. It collects bacteria and oil overnight.",
"Clean your phone screen daily — it presses against your face constantly.",
"Wash hands before touching your face. Every single time.",
"Consistency beats expensive products. Use this routine daily for 8 weeks minimum.",
], "Rules That Matter More Than Products", bg=colors.HexColor("#FDF7F2"), border=ROSE))
story.append(Spacer(1, 0.8*cm))
# ════════════════════════════════════════════
# FOOTER NOTE
# ════════════════════════════════════════════
story.append(hr(SOFT_GREY, 0.5))
story.append(Paragraph(
"This guide was created by Orris, your personal skin expert. "
"Give your skin 8–12 weeks before judging results. "
"Come back for a check-in and we'll adjust from there. 🤍",
footer_txt))
# ── Build with two page templates ────────────────────────────────────────────
from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, NextPageTemplate, PageBreak
frame_cover = Frame(0, 0, W, H, leftPadding=2.5*cm, rightPadding=2.5*cm,
topPadding=0, bottomPadding=0, id="cover")
frame_body = Frame(1.8*cm, 1.5*cm, W - 3.6*cm, H - 3.5*cm,
leftPadding=0, rightPadding=0, topPadding=0, bottomPadding=0, id="body")
doc2 = BaseDocTemplate(
"/home/daytona/workspace/skincare-guide/Skincare_Guide.pdf",
pagesize=A4,
title="My Minimal Luxury Skincare Guide",
author="Orris",
leftMargin=0, rightMargin=0, topMargin=0, bottomMargin=0,
)
doc2.addPageTemplates([
PageTemplate(id="Cover", frames=[frame_cover], onPage=cover_background),
PageTemplate(id="Body", frames=[frame_body], onPage=page_background),
])
# Insert page break + template switch after cover
story_final = (
cover_content
+ [NextPageTemplate("Body"), PageBreak()]
+ story[len(cover_content):]
)
doc2.build(story_final)
print("PDF generated successfully.")
cd /home/daytona/workspace/skincare-guide && python generate_pdf.py 2>&1
ls -lh /home/daytona/workspace/skincare-guide/Skincare_Guide.pdf
Skincare Guide
PDF Document · PDF
| Section | Content |
|---|---|
| Cover Page | Elegant deep-toned cover with your routine details |
| Brand Lineup | All 6 brands with their role and why they're chosen |
| Morning Routine | Step-by-step table + pro usage tips |
| Night Routine | Step-by-step table + night tips |
| Body Routine | Nécessaire steps + body care tips |
| 4-Week Build Plan | Gradual introduction schedule |
| What to Avoid | Habits and ingredients to stay away from |
| Shopping List | All 7 products with prices — total $146 |
| Lifestyle Rules | The non-negotiables that actually drive results |
Just for now can we skip face mask
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | Brightening Cleansing Gel | Acure | $10 |
| Serum | Niacinamide Serum 12% + Zinc | Naturium | $20 |
| Moisturizer | Moisturizing Rich Cream | Byoma | $18 |
| Sunscreen | Centella Unscented Sun SPF 50+ | Purito | $16 |
| Step | Product | Brand | Price |
|---|---|---|---|
| Cleanser | (same) | Acure | — |
| Serum | (same) | Naturium | — |
| Moisturizer | Moisturizing Rich Cream | Byoma | $18 |
Use Byoma Rich Cream for both day and night — it works for both.
| Step | Product | Brand | Price |
|---|---|---|---|
| Body Wash | The Body Wash — Eucalyptus | Nécessaire | $25 |
| Body Lotion | The Body Lotion — Fragrance Free | Nécessaire | $30 |
| # | Product | Brand | Price |
|---|---|---|---|
| 1 | Brightening Cleansing Gel | Acure | $10 |
| 2 | Niacinamide Serum 12% + Zinc | Naturium | $20 |
| 3 | Moisturizing Rich Cream | Byoma | $18 |
| 4 | Centella Unscented Sun SPF 50+ | Purito | $16 |
| 5 | The Body Wash — Eucalyptus | Nécessaire | $25 |
| 6 | The Body Lotion — Fragrance Free | Nécessaire | $30 |
| TOTAL | $119 ✅ |
Brightening Cleansing Gel Acure 2 Witch Hazel + Rosewater Toner Thayers 3 Niacinamide Serum 12% + Zinc Naturium 4 Barrier Culture Moisture Cream Bubble 5 Unseen Sunscreen SPF 40 Supergoop! 6 Cloud Dew Oil-Free Night Moisturizer Glow Recipe 7 The Body Wash (Eucalyptus) Nécessaire 8 The Body Lotion (FF) Nécessaire. How, where and when to apply pdf
~/skincare-guide/generate_application_guide.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.units import mm, cm
from reportlab.platypus import (BaseDocTemplate, PageTemplate, Frame,
Paragraph, Spacer, Table, TableStyle,
HRFlowable, NextPageTemplate, PageBreak, KeepTogether)
from reportlab.lib.enums import TA_CENTER, TA_LEFT
W, H = A4
# ── Palette ──────────────────────────────────────────────────────────────────
CREAM = colors.HexColor("#FAF7F4")
BLUSH = colors.HexColor("#E8D5C4")
ROSE = colors.HexColor("#C9A98A")
DEEP = colors.HexColor("#5C3D2E")
CHARCOAL = colors.HexColor("#2C2C2C")
SOFT_GREY = colors.HexColor("#9E9E9E")
SAGE = colors.HexColor("#A8B5A0")
LIGHT_SAGE = colors.HexColor("#EFF3ED")
MORNING_COL = colors.HexColor("#FFF3E8")
NIGHT_COL = colors.HexColor("#EDE8F5")
BODY_COL = colors.HexColor("#E8F4F0")
MORNING_BDR = colors.HexColor("#D4956A")
NIGHT_BDR = colors.HexColor("#8B7BB5")
BODY_BDR = colors.HexColor("#6BA89A")
def S(name, **kw):
return ParagraphStyle(name, **kw)
# ── Page backgrounds ──────────────────────────────────────────────────────────
def cover_bg(canvas, doc):
canvas.saveState()
canvas.setFillColor(DEEP)
canvas.rect(0, 0, W, H, fill=1, stroke=0)
canvas.setFillColor(ROSE)
canvas.rect(0, H - 3*cm, W, 3*cm, fill=1, stroke=0)
canvas.setFillColor(BLUSH)
canvas.rect(0, 0, W, 2.5*cm, fill=1, stroke=0)
canvas.restoreState()
def body_bg(canvas, doc):
canvas.saveState()
canvas.setFillColor(CREAM)
canvas.rect(0, 0, W, H, fill=1, stroke=0)
canvas.setFillColor(DEEP)
canvas.rect(0, H - 8*mm, W, 8*mm, fill=1, stroke=0)
canvas.setFillColor(ROSE)
canvas.rect(0, 0, W, 4*mm, fill=1, stroke=0)
if doc.page > 1:
canvas.setFont("Helvetica", 8)
canvas.setFillColor(SOFT_GREY)
canvas.drawCentredString(W/2, 7*mm, f"— {doc.page} —")
canvas.restoreState()
def hr(color=ROSE, thickness=0.7):
return HRFlowable(width="100%", thickness=thickness, color=color,
spaceAfter=5, spaceBefore=3)
# ── Product card builder ──────────────────────────────────────────────────────
def product_card(number, product, brand, session, when, where, how, amount, tip,
bg_color, border_color):
"""Build a full how/where/when card for one product."""
tag_style = S("tag", fontSize=8, textColor=colors.white,
fontName="Helvetica-Bold", leading=11, alignment=TA_CENTER)
label_style = S("lbl", fontSize=8, textColor=border_color,
fontName="Helvetica-Bold", leading=11)
value_style = S("val", fontSize=9, textColor=CHARCOAL,
fontName="Helvetica", leading=14)
tip_style = S("tip", fontSize=8.5, textColor=DEEP,
fontName="Helvetica", leading=13, leftIndent=4)
name_style = S("nm", fontSize=12, textColor=DEEP,
fontName="Helvetica-Bold", leading=16)
brand_style = S("br", fontSize=9, textColor=ROSE,
fontName="Helvetica-Bold", leading=12)
num_style = S("num", fontSize=18, textColor=border_color,
fontName="Helvetica-Bold", leading=22, alignment=TA_CENTER)
# number + name block
header_inner = Table([
[Paragraph(f"{number:02d}", num_style),
[Paragraph(product, name_style), Paragraph(brand, brand_style)],
Paragraph(session, S("sess", fontSize=8, textColor=colors.white,
fontName="Helvetica-Bold", leading=11,
alignment=TA_CENTER))]
], colWidths=[1.4*cm, 10.5*cm, 2.8*cm])
header_inner.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("BACKGROUND", (2,0), (2,0), border_color),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("ROUNDEDCORNERS", [4]),
]))
# detail rows
details = Table([
[Paragraph("⏰ WHEN", label_style), Paragraph(when, value_style)],
[Paragraph("📍 WHERE", label_style), Paragraph(where, value_style)],
[Paragraph("👐 HOW TO APPLY", label_style), Paragraph(how, value_style)],
[Paragraph("💧 AMOUNT", label_style), Paragraph(amount, value_style)],
[Paragraph("✦ PRO TIP", label_style), Paragraph(tip, tip_style)],
], colWidths=[3*cm, 11.5*cm])
details.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (0,-1), 6),
("LEFTPADDING", (1,0), (1,-1), 8),
("LINEBELOW", (0,0), (-1,-2), 0.3, colors.HexColor("#E0D8D0")),
]))
inner = [[header_inner], [Spacer(1, 0.2*cm)], [details]]
card = Table(inner, colWidths=[W - 3.6*cm])
card.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg_color),
("BOX", (0,0), (-1,-1), 1.5, border_color),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
return card
# ── Story ─────────────────────────────────────────────────────────────────────
story = []
# ════════ COVER ════════
cover_title_s = S("CT", fontSize=34, textColor=colors.white,
fontName="Helvetica-Bold", alignment=TA_CENTER, leading=42)
cover_sub_s = S("CS", fontSize=13, textColor=BLUSH,
fontName="Helvetica", alignment=TA_CENTER, leading=20)
cover_note_s = S("CN", fontSize=9, textColor=BLUSH,
fontName="Helvetica", alignment=TA_CENTER, leading=14)
cover = [
Spacer(1, 3.8*cm),
Paragraph("HOW TO USE YOUR", cover_title_s),
Paragraph("SKINCARE ROUTINE", cover_title_s),
Spacer(1, 0.7*cm),
Paragraph("When · Where · How to Apply", cover_sub_s),
Spacer(1, 0.4*cm),
Paragraph("Step-by-step application guide for all 8 products", cover_sub_s),
Spacer(1, 1.4*cm),
Paragraph("Acure · Thayers · Naturium · Bubble · Supergoop! · Glow Recipe · Nécessaire", cover_note_s),
Spacer(1, 0.3*cm),
Paragraph("Curated by Orris · Your Personal Skin Expert 🤍", cover_note_s),
]
story.extend(cover)
story.append(NextPageTemplate("Body"))
story.append(PageBreak())
# ════════ SECTION: HOW TO READ THIS GUIDE ════════
sec = S("SH", fontSize=15, textColor=DEEP, fontName="Helvetica-Bold",
leading=20, spaceBefore=10, spaceAfter=4)
body = S("BT", fontSize=9.5, textColor=CHARCOAL, fontName="Helvetica",
leading=15, spaceAfter=3)
story.append(Paragraph("HOW TO USE THIS GUIDE", sec))
story.append(hr())
story.append(Paragraph(
"Each product card below tells you exactly <b>when</b> to apply it (morning, night, or both), "
"<b>where</b> on your face or body it goes, <b>how</b> to apply it correctly, "
"how much to use, and one pro tip to get the best results.",
body))
story.append(Spacer(1, 0.3*cm))
# order legend
legend_data = [
[Paragraph("<b>🌅 MORNING</b>", S("leg", fontSize=9, textColor=MORNING_BDR, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=13)),
Paragraph("<b>🌙 NIGHT</b>", S("leg", fontSize=9, textColor=NIGHT_BDR, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=13)),
Paragraph("<b>🌅🌙 BOTH</b>", S("leg", fontSize=9, textColor=DEEP, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=13)),
Paragraph("<b>🛁 BODY</b>", S("leg", fontSize=9, textColor=BODY_BDR, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=13))],
[Paragraph("Apply in the morning before leaving the house",
S("lv", fontSize=8.5, textColor=CHARCOAL, fontName="Helvetica", alignment=TA_CENTER, leading=13)),
Paragraph("Apply at night before bed",
S("lv", fontSize=8.5, textColor=CHARCOAL, fontName="Helvetica", alignment=TA_CENTER, leading=13)),
Paragraph("Use morning and night",
S("lv", fontSize=8.5, textColor=CHARCOAL, fontName="Helvetica", alignment=TA_CENTER, leading=13)),
Paragraph("Body use only, in or after shower",
S("lv", fontSize=8.5, textColor=CHARCOAL, fontName="Helvetica", alignment=TA_CENTER, leading=13))],
]
lt = Table(legend_data, colWidths=[(W - 3.6*cm)/4]*4)
lt.setStyle(TableStyle([
("BACKGROUND", (0,0), (0,-1), MORNING_COL),
("BACKGROUND", (1,0), (1,-1), NIGHT_COL),
("BACKGROUND", (2,0), (2,-1), colors.HexColor("#FBF7EC")),
("BACKGROUND", (3,0), (3,-1), BODY_COL),
("BOX", (0,0), (0,-1), 0.8, MORNING_BDR),
("BOX", (1,0), (1,-1), 0.8, NIGHT_BDR),
("BOX", (2,0), (2,-1), 0.8, ROSE),
("BOX", (3,0), (3,-1), 0.8, BODY_BDR),
("TOPPADDING", (0,0), (-1,-1), 7),
("BOTTOMPADDING", (0,0), (-1,-1), 7),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
("INNERGRID", (0,0), (-1,-1), 0, colors.white),
]))
story.append(lt)
story.append(Spacer(1, 0.5*cm))
# ════════ PRODUCT CARDS ════════
story.append(Paragraph("YOUR COMPLETE PRODUCT APPLICATION GUIDE", sec))
story.append(hr())
story.append(Spacer(1, 0.2*cm))
# 1. ACURE CLEANSER
story.append(KeepTogether([
product_card(
1, "Brightening Cleansing Gel", "Acure",
"🌅🌙 BOTH",
"Every morning and every night — always the very first step.",
"Entire face: forehead, nose, cheeks, chin, around the jawline. Avoid the eye area.",
"Wet face with lukewarm water. Pump 1–2 pea-sized amounts into damp hands, lather gently between palms. "
"Apply in soft circular motions for 30–60 seconds. Rinse thoroughly. Pat dry with a clean towel — never rub.",
"1–2 pumps (about the size of a small grape).",
"Never use hot water — it strips your skin barrier and triggers more oil production. Lukewarm only.",
MORNING_COL, MORNING_BDR
),
Spacer(1, 0.35*cm),
]))
# 2. THAYERS TONER
story.append(KeepTogether([
product_card(
2, "Witch Hazel + Rosewater Toner", "Thayers",
"🌅🌙 BOTH",
"After cleansing, before serum. Morning and night.",
"Full face, neck, and décolletage. Avoid the immediate eye area.",
"Pour a small amount onto a cotton pad and sweep gently across the face in upward strokes. "
"Or spray directly onto face and press in with clean fingertips. Do not rub.",
"A few drops on a cotton pad, or 2–3 sprays if using spray method.",
"The rose water scent is part of the experience — take a moment to enjoy it. "
"This is also great for a midday refresh over SPF.",
MORNING_COL, MORNING_BDR
),
Spacer(1, 0.35*cm),
]))
# 3. NATURIUM NIACINAMIDE SERUM
story.append(KeepTogether([
product_card(
3, "Niacinamide Serum 12% + Zinc 2%", "Naturium",
"🌅🌙 BOTH",
"After toner, before moisturizer. Use morning and night once skin adjusts. "
"Start 3x per week for the first 2 weeks, then build to daily.",
"Full face — forehead, nose, cheeks, chin. Can be used on neck too. "
"Safe to use on oily T-zone and dry cheeks.",
"Apply 3–4 drops to fingertips. Press and pat gently into skin — do not rub or drag. "
"Let absorb for 30 seconds before moving to moisturizer.",
"3–4 drops. A little goes a long way with this serum.",
"Niacinamide addresses all your concerns at once: acne, dark marks, pores, oiliness. "
"Be consistent — you will see results at 6–8 weeks.",
MORNING_COL, MORNING_BDR
),
Spacer(1, 0.35*cm),
]))
# 4. BUBBLE BARRIER CULTURE
story.append(KeepTogether([
product_card(
4, "Barrier Culture Moisture Cream", "Bubble",
"🌅 MORNING",
"After serum, before sunscreen. Every morning.",
"Full face and neck. Focus on cheeks if they feel dry. Use lightly on the T-zone.",
"Scoop a pea-sized amount with fingertips. Warm between fingers, then press gently "
"into skin starting from the center of the face outward. Pat — don't rub.",
"Pea-sized amount — about the size of a blueberry.",
"This creates the base layer under your SPF. Let it absorb 30–60 seconds "
"before applying sunscreen to prevent pilling.",
MORNING_COL, MORNING_BDR
),
Spacer(1, 0.35*cm),
]))
# 5. SUPERGOOP! UNSEEN SUNSCREEN
story.append(KeepTogether([
product_card(
5, "Unseen Sunscreen SPF 40", "Supergoop!",
"🌅 MORNING",
"Always the very last skincare step in the morning. Apply every day — rain, indoors, or overcast. "
"Reapply every 2 hours if spending time outdoors.",
"Full face, ears, back of neck, and any exposed skin. Do not forget the hairline and jawline.",
"Dispense a nickel-sized amount (about 1/4 teaspoon for the face). Apply in dots across "
"forehead, nose, both cheeks, and chin. Blend outward with fingertips. Let it set 1–2 minutes before going out.",
"Nickel-sized amount — most people underapply SPF. Don't skimp.",
"This sunscreen genuinely disappears on skin. If you see it, you haven't blended enough. "
"It also works beautifully as a makeup primer.",
MORNING_COL, MORNING_BDR
),
Spacer(1, 0.35*cm),
]))
# 6. GLOW RECIPE CLOUD DEW
story.append(KeepTogether([
product_card(
6, "Cloud Dew Oil-Free Night Moisturizer", "Glow Recipe",
"🌙 NIGHT",
"After serum, as your final face step at night before sleep.",
"Full face and neck. Slightly more generous on dry cheek areas.",
"Apply a pea-to-almond-sized amount to fingertips. Press and pat gently across the face "
"in upward and outward motions. Don't forget the neck. Let it sink in — no need to rinse.",
"Pea-to-almond-sized amount depending on how dry your skin feels.",
"Apply on slightly damp skin (right after toner and serum) to lock in extra hydration. "
"Your skin repairs and regenerates overnight — this is your most important moisturizing step.",
NIGHT_COL, NIGHT_BDR
),
Spacer(1, 0.35*cm),
]))
# 7. NÉCESSAIRE BODY WASH
story.append(KeepTogether([
product_card(
7, "The Body Wash — Eucalyptus", "Nécessaire",
"🛁 IN SHOWER",
"Daily in the shower. For back/chest acne: apply first, let it sit 60 seconds, then rinse.",
"Entire body. Focus extra time on back, chest, and shoulders where body acne occurs. "
"Can be used on face in a pinch but your Acure cleanser is better for that.",
"Squeeze a coin-sized amount onto a loofah, mesh sponge, or hands. Lather and apply "
"in circular motions across the body. For acne-prone areas, let the lather sit for "
"60 seconds before rinsing. Rinse thoroughly with lukewarm water.",
"Coin-sized amount per body section.",
"The eucalyptus scent is the luxury ritual — breathe it in. This is your daily self-care moment. "
"Use a clean loofah and replace it every 3–4 weeks.",
BODY_COL, BODY_BDR
),
Spacer(1, 0.35*cm),
]))
# 8. NÉCESSAIRE BODY LOTION
story.append(KeepTogether([
product_card(
8, "The Body Lotion — Fragrance Free", "Nécessaire",
"🛁 AFTER SHOWER",
"Within 3 minutes of stepping out of the shower — on damp skin. Every day.",
"Entire body. Extra focus on: upper arms (KP/chicken skin), elbows, knees, shins, and any "
"dry or rough patches. Apply lightly on back and chest over acne-prone areas.",
"Step out of the shower and pat (don't fully dry) skin with a towel. While still slightly damp, "
"apply a generous amount of lotion in long upward strokes toward the heart. "
"For KP on arms: use circular massage motions. Let air dry.",
"A full palm-sized pump for each body section (arms, legs, torso).",
"Applying on damp skin is the single biggest upgrade to body moisture you can make. "
"The niacinamide + AHA in this formula also fades uneven body tone over time.",
BODY_COL, BODY_BDR
),
Spacer(1, 0.5*cm),
]))
# ════════ QUICK REFERENCE SCHEDULE ════════
story.append(hr(DEEP, 1.2))
story.append(Paragraph("QUICK REFERENCE — DAILY SCHEDULE", sec))
story.append(hr())
story.append(Spacer(1, 0.2*cm))
sched_data = [
[Paragraph("<b>Time</b>", S("sh", fontSize=8.5, textColor=colors.white, fontName="Helvetica-Bold", leading=12, alignment=TA_CENTER)),
Paragraph("<b>Step</b>", S("sh", fontSize=8.5, textColor=colors.white, fontName="Helvetica-Bold", leading=12, alignment=TA_CENTER)),
Paragraph("<b>Product</b>", S("sh", fontSize=8.5, textColor=colors.white, fontName="Helvetica-Bold", leading=12)),
Paragraph("<b>Brand</b>", S("sh", fontSize=8.5, textColor=colors.white, fontName="Helvetica-Bold", leading=12)),
Paragraph("<b>Wait</b>", S("sh", fontSize=8.5, textColor=colors.white, fontName="Helvetica-Bold", leading=12, alignment=TA_CENTER))],
# Morning
[Paragraph("🌅 AM", S("sc", fontSize=9, textColor=MORNING_BDR, fontName="Helvetica-Bold", leading=13, alignment=TA_CENTER)),
Paragraph("1", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13, alignment=TA_CENTER)),
Paragraph("Brightening Cleansing Gel", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Acure", S("sc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph("Rinse + pat dry", S("sc", fontSize=8.5, textColor=SOFT_GREY, fontName="Helvetica", leading=13, alignment=TA_CENTER))],
[Paragraph("🌅 AM", S("sc", fontSize=9, textColor=MORNING_BDR, fontName="Helvetica-Bold", leading=13, alignment=TA_CENTER)),
Paragraph("2", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13, alignment=TA_CENTER)),
Paragraph("Witch Hazel + Rosewater Toner", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Thayers", S("sc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph("10–15 sec", S("sc", fontSize=8.5, textColor=SOFT_GREY, fontName="Helvetica", leading=13, alignment=TA_CENTER))],
[Paragraph("🌅 AM", S("sc", fontSize=9, textColor=MORNING_BDR, fontName="Helvetica-Bold", leading=13, alignment=TA_CENTER)),
Paragraph("3", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13, alignment=TA_CENTER)),
Paragraph("Niacinamide Serum 12% + Zinc", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Naturium", S("sc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph("30 sec", S("sc", fontSize=8.5, textColor=SOFT_GREY, fontName="Helvetica", leading=13, alignment=TA_CENTER))],
[Paragraph("🌅 AM", S("sc", fontSize=9, textColor=MORNING_BDR, fontName="Helvetica-Bold", leading=13, alignment=TA_CENTER)),
Paragraph("4", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13, alignment=TA_CENTER)),
Paragraph("Barrier Culture Moisture Cream", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Bubble", S("sc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph("30–60 sec", S("sc", fontSize=8.5, textColor=SOFT_GREY, fontName="Helvetica", leading=13, alignment=TA_CENTER))],
[Paragraph("🌅 AM", S("sc", fontSize=9, textColor=MORNING_BDR, fontName="Helvetica-Bold", leading=13, alignment=TA_CENTER)),
Paragraph("5", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13, alignment=TA_CENTER)),
Paragraph("Unseen Sunscreen SPF 40", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Supergoop!", S("sc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph("1–2 min", S("sc", fontSize=8.5, textColor=SOFT_GREY, fontName="Helvetica", leading=13, alignment=TA_CENTER))],
# Night
[Paragraph("🌙 PM", S("sc", fontSize=9, textColor=NIGHT_BDR, fontName="Helvetica-Bold", leading=13, alignment=TA_CENTER)),
Paragraph("1", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13, alignment=TA_CENTER)),
Paragraph("Brightening Cleansing Gel", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Acure", S("sc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph("Rinse + pat dry", S("sc", fontSize=8.5, textColor=SOFT_GREY, fontName="Helvetica", leading=13, alignment=TA_CENTER))],
[Paragraph("🌙 PM", S("sc", fontSize=9, textColor=NIGHT_BDR, fontName="Helvetica-Bold", leading=13, alignment=TA_CENTER)),
Paragraph("2", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13, alignment=TA_CENTER)),
Paragraph("Witch Hazel + Rosewater Toner", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Thayers", S("sc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph("10–15 sec", S("sc", fontSize=8.5, textColor=SOFT_GREY, fontName="Helvetica", leading=13, alignment=TA_CENTER))],
[Paragraph("🌙 PM", S("sc", fontSize=9, textColor=NIGHT_BDR, fontName="Helvetica-Bold", leading=13, alignment=TA_CENTER)),
Paragraph("3", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13, alignment=TA_CENTER)),
Paragraph("Niacinamide Serum 12% + Zinc", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Naturium", S("sc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph("30 sec", S("sc", fontSize=8.5, textColor=SOFT_GREY, fontName="Helvetica", leading=13, alignment=TA_CENTER))],
[Paragraph("🌙 PM", S("sc", fontSize=9, textColor=NIGHT_BDR, fontName="Helvetica-Bold", leading=13, alignment=TA_CENTER)),
Paragraph("4", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13, alignment=TA_CENTER)),
Paragraph("Cloud Dew Oil-Free Night Moisturizer", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Glow Recipe", S("sc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph("Overnight", S("sc", fontSize=8.5, textColor=SOFT_GREY, fontName="Helvetica", leading=13, alignment=TA_CENTER))],
# Body
[Paragraph("🛁 BODY", S("sc", fontSize=9, textColor=BODY_BDR, fontName="Helvetica-Bold", leading=13, alignment=TA_CENTER)),
Paragraph("1", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13, alignment=TA_CENTER)),
Paragraph("The Body Wash — Eucalyptus", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Nécessaire", S("sc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph("In shower", S("sc", fontSize=8.5, textColor=SOFT_GREY, fontName="Helvetica", leading=13, alignment=TA_CENTER))],
[Paragraph("🛁 BODY", S("sc", fontSize=9, textColor=BODY_BDR, fontName="Helvetica-Bold", leading=13, alignment=TA_CENTER)),
Paragraph("2", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13, alignment=TA_CENTER)),
Paragraph("The Body Lotion — Fragrance Free", S("sc", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph("Nécessaire", S("sc", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph("On damp skin", S("sc", fontSize=8.5, textColor=SOFT_GREY, fontName="Helvetica", leading=13, alignment=TA_CENTER))],
]
st = Table(sched_data, colWidths=[2*cm, 1.5*cm, 6.5*cm, 3*cm, 3.5*cm], repeatRows=1)
st.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DEEP),
("ROWBACKGROUNDS",(0,1), (-1,5), [MORNING_COL, colors.white]*3),
("ROWBACKGROUNDS",(0,6), (-1,9), [NIGHT_COL, colors.white]*2),
("ROWBACKGROUNDS",(0,10), (-1,11), [BODY_COL, colors.white]),
("GRID", (0,0), (-1,-1), 0.3, colors.HexColor("#D9D0C7")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("ALIGN", (0,0), (1,-1), "CENTER"),
("ALIGN", (4,0), (4,-1), "CENTER"),
]))
story.append(st)
story.append(Spacer(1, 0.6*cm))
# ════════ FOOTER ════════
story.append(hr(SOFT_GREY, 0.5))
story.append(Paragraph(
"Guide created by Orris · Your Personal Skin Expert · "
"Consistency is everything — give your skin 8 weeks. 🤍",
S("ft", fontSize=8, textColor=SOFT_GREY, fontName="Helvetica",
alignment=TA_CENTER, leading=12)))
# ── Assemble document ─────────────────────────────────────────────────────────
frame_cover = Frame(0, 0, W, H, leftPadding=2.5*cm, rightPadding=2.5*cm,
topPadding=0, bottomPadding=0, id="cover")
frame_body = Frame(1.8*cm, 1.5*cm, W - 3.6*cm, H - 3.5*cm,
leftPadding=0, rightPadding=0,
topPadding=0, bottomPadding=0, id="body")
output_path = "/home/daytona/workspace/skincare-guide/Skincare_Application_Guide.pdf"
doc = BaseDocTemplate(
output_path, pagesize=A4,
title="How to Use Your Skincare Routine",
author="Orris",
leftMargin=0, rightMargin=0, topMargin=0, bottomMargin=0,
)
doc.addPageTemplates([
PageTemplate(id="Cover", frames=[frame_cover], onPage=cover_bg),
PageTemplate(id="Body", frames=[frame_body], onPage=body_bg),
])
doc.build(story)
print(f"PDF saved to {output_path}")
cd /home/daytona/workspace/skincare-guide && python generate_application_guide.p…
ls -lh /home/daytona/workspace/skincare-guide/Skincare_Application_Guide.pdf
Skincare Application Guide
PDF Document · PDF
| ⏰ When | Exact timing — morning, night, or both |
| 📍 Where | Precisely where on face/body to apply |
| 👐 How | Step-by-step application technique |
| 💧 Amount | Exact quantity to use |
| ✦ Pro Tip | One expert tip per product |
I can’t find Cloud Dew Oil-Free Night Moisturizer Glow Recipe
Glow Recipe Cloud Dew Oil-Free Moisturizer discontinued 2025 alternative
| Option | Product | Brand | Price | Why |
|---|---|---|---|---|
| ⭐ Best pick | Watermelon Glow Pink Juice Oil-Free Moisturizer | Glow Recipe | ~$39 | Cloud Dew's direct successor — same brand, oil-free, non-comedogenic, watermelon aesthetic. Available on glowrecipe.com |
| Runner-up | Phyto-Mucin Glow Serum + Rich Cream | Byoma | ~$18 | Minimal luxury, barrier-focused, lightweight enough for night use on combination skin |
| Budget swap | Niacinamide Moisturizer | Naturium | ~$20 | Matches your existing Naturium serum aesthetically, oil-free, acne-safe |
I don’t want watermelon. I really like Nécessaire and acure brand. Specially Nécessaire
Nécessaire face moisturizer serum night cream 2025 product line
| # | Product | Brand | Price |
|---|---|---|---|
| 1 | Brightening Cleansing Gel | Acure | $10 |
| 2 | Witch Hazel + Rosewater Toner | Thayers | $12 |
| 3 | Niacinamide Serum 12% + Zinc | Naturium | $20 |
| 4 | Barrier Culture Moisture Cream | Bubble | $18 |
| 5 | Unseen Sunscreen SPF 40 | Supergoop! | $36 |
| 6 | Radically Rejuvenating Whipped Night Cream | Acure | $16 |
| 7 | The Body Wash — Eucalyptus | Nécessaire | $25 |
| 8 | The Body Lotion — Fragrance Free | Nécessaire | $30 |
| TOTAL | $167 |
You can get me any another brand or same if you think that would be better
| # | Product | Brand | Price |
|---|---|---|---|
| 1 | Brightening Cleansing Gel | Acure | $10 |
| 2 | Witch Hazel + Rosewater Toner | Thayers | $12 |
| 3 | Niacinamide Serum 12% + Zinc | Naturium | $20 |
| 4 | Barrier Culture Moisture Cream | Bubble | $18 |
| 5 | Unseen Sunscreen SPF 40 | Supergoop! | $36 |
| 6 | Cloud Dew Oil-Free Gel Moisturizer | Summer Fridays | $44 |
| 7 | The Body Wash — Eucalyptus | Nécessaire | $25 |
| 8 | The Body Lotion — Fragrance Free | Nécessaire | $30 |
| TOTAL | $195 |
Not summer Friday. I want brands like Nécessaire
minimal luxury clean face moisturizer night cream 2025 brands like Nécessaire oil-free acne combination skin aesthetic
Which is better rhode or acure
| Rhode Barrier Restore Cream | Acure Whipped Night Cream | |
|---|---|---|
| Price | ~$32 | ~$16 |
| Aesthetic | Minimal luxury — clean white tube, premium feel | Clean but more mass-market |
| Formula | Murumuru butter + ceramides + peptides — serious barrier repair | Basic hydration, decent but simpler formula |
| For acne-prone skin | Non-comedogenic, tested | Non-comedogenic |
| Feel on skin | Velvety, melts in — genuinely luxurious | Lightweight whipped — fine but unremarkable |
| Brand vibe | Nécessaire-level minimal luxury | Budget clean beauty |
| Results | Noticeably better skin texture + barrier repair over time | Adequate hydration |
Generate a final shopping list with Rhode Barrier Restore Cream
~/skincare-guide/generate_shopping_list.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm, cm
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
from reportlab.platypus import (BaseDocTemplate, PageTemplate, Frame,
Paragraph, Spacer, Table, TableStyle,
HRFlowable, NextPageTemplate, PageBreak)
W, H = A4
# ── Palette ───────────────────────────────────────────────────────────────────
CREAM = colors.HexColor("#FAF7F4")
BLUSH = colors.HexColor("#E8D5C4")
ROSE = colors.HexColor("#C9A98A")
DEEP = colors.HexColor("#5C3D2E")
CHARCOAL = colors.HexColor("#2C2C2C")
SOFT_GREY = colors.HexColor("#9E9E9E")
LIGHT_SAGE = colors.HexColor("#EFF3ED")
SAGE = colors.HexColor("#A8B5A0")
WHITE = colors.white
def S(name, **kw):
return ParagraphStyle(name, **kw)
def hr(color=ROSE, thickness=0.8):
return HRFlowable(width="100%", thickness=thickness, color=color,
spaceAfter=5, spaceBefore=3)
# ── Page backgrounds ──────────────────────────────────────────────────────────
def cover_bg(canvas, doc):
canvas.saveState()
canvas.setFillColor(DEEP)
canvas.rect(0, 0, W, H, fill=1, stroke=0)
canvas.setFillColor(ROSE)
canvas.rect(0, H - 3*cm, W, 3*cm, fill=1, stroke=0)
canvas.setFillColor(BLUSH)
canvas.rect(0, 0, W, 2.5*cm, fill=1, stroke=0)
canvas.restoreState()
def body_bg(canvas, doc):
canvas.saveState()
canvas.setFillColor(CREAM)
canvas.rect(0, 0, W, H, fill=1, stroke=0)
canvas.setFillColor(DEEP)
canvas.rect(0, H - 8*mm, W, 8*mm, fill=1, stroke=0)
canvas.setFillColor(ROSE)
canvas.rect(0, 0, W, 4*mm, fill=1, stroke=0)
if doc.page > 1:
canvas.setFont("Helvetica", 8)
canvas.setFillColor(SOFT_GREY)
canvas.drawCentredString(W/2, 7*mm, f"— {doc.page} —")
canvas.restoreState()
# ── Products data ─────────────────────────────────────────────────────────────
products = [
# (num, product, brand, category, where_to_buy, price)
("01", "Brightening Cleansing Gel", "Acure", "Face Cleanser", "Target · Amazon · Whole Foods", "$10"),
("02", "Witch Hazel + Rosewater Toner", "Thayers", "Face Toner", "Target · CVS · Amazon · Ulta", "$12"),
("03", "Niacinamide Serum 12% + Zinc 2%", "Naturium", "Face Serum", "Target · Ulta · Amazon", "$20"),
("04", "Barrier Culture Moisture Cream", "Bubble", "Day Moisturizer", "Target · Walmart · Amazon", "$18"),
("05", "Unseen Sunscreen SPF 40", "Supergoop!", "Sunscreen", "Sephora · Ulta · supergoop.com", "$36"),
("06", "Barrier Restore Cream", "Rhode", "Night Moisturizer","Sephora · rhode.com", "$32"),
("07", "The Body Wash — Eucalyptus", "Nécessaire", "Body Wash", "Sephora · necessaire.com · Nordstrom", "$25"),
("08", "The Body Lotion — Fragrance Free", "Nécessaire", "Body Lotion", "Sephora · necessaire.com · Nordstrom", "$30"),
]
total = 10 + 12 + 20 + 18 + 36 + 32 + 25 + 30 # = 183
story = []
# ════════ COVER ════════
ct = S("CT", fontSize=32, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=40)
cs = S("CS", fontSize=12, textColor=BLUSH, fontName="Helvetica",
alignment=TA_CENTER, leading=18)
cn = S("CN", fontSize=9, textColor=BLUSH, fontName="Helvetica",
alignment=TA_CENTER, leading=14)
story += [
Spacer(1, 3.5*cm),
Paragraph("MY SKINCARE", ct),
Paragraph("SHOPPING LIST", ct),
Spacer(1, 0.7*cm),
Paragraph("Final · Complete · Minimal Luxury", cs),
Spacer(1, 0.4*cm),
Paragraph("8 Products · 7 Brands · $183 Total", cs),
Spacer(1, 1.4*cm),
Paragraph("Acure · Thayers · Naturium · Bubble · Supergoop! · Rhode · Nécessaire", cn),
Spacer(1, 0.3*cm),
Paragraph("Curated by Orris · Your Personal Skin Expert 🤍", cn),
]
story.append(NextPageTemplate("Body"))
story.append(PageBreak())
# ════════ HEADER ════════
sec = S("SH", fontSize=15, textColor=DEEP, fontName="Helvetica-Bold",
leading=20, spaceBefore=8, spaceAfter=4)
body = S("BT", fontSize=9.5, textColor=CHARCOAL, fontName="Helvetica",
leading=15, spaceAfter=4)
story.append(Paragraph("YOUR FINAL SHOPPING LIST", sec))
story.append(hr())
story.append(Paragraph(
"Every product below is clean, aesthetic, and chosen specifically for your skin profile: "
"combination, acne-prone, reactive, under 18. One brand per product. "
"Buy in order — start with the essentials first.",
body))
story.append(Spacer(1, 0.4*cm))
# ════════ MAIN TABLE ════════
col_w = [1.2*cm, 5.8*cm, 3*cm, 3*cm, 3.5*cm, 1.8*cm]
header = [
Paragraph("<b>#</b>", S("h", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=12)),
Paragraph("<b>Product</b>", S("h", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", leading=12)),
Paragraph("<b>Brand</b>", S("h", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", leading=12)),
Paragraph("<b>Category</b>", S("h", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", leading=12)),
Paragraph("<b>Where to Buy</b>",S("h", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", leading=12)),
Paragraph("<b>Price</b>", S("h", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=12)),
]
rows = [header]
for num, product, brand, cat, buy, price in products:
rows.append([
Paragraph(num, S("c", fontSize=9, textColor=SOFT_GREY, fontName="Helvetica", alignment=TA_CENTER, leading=13)),
Paragraph(product, S("c", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph(f"<b>{brand}</b>", S("c", fontSize=9, textColor=ROSE, fontName="Helvetica-Bold", leading=13)),
Paragraph(cat, S("c", fontSize=8.5, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
Paragraph(buy, S("c", fontSize=7.5, textColor=SOFT_GREY, fontName="Helvetica", leading=12)),
Paragraph(price, S("c", fontSize=9.5, textColor=DEEP, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=13)),
])
# Total row
rows.append([
Paragraph("", S("t", fontSize=9, fontName="Helvetica", leading=13)),
Paragraph("<b>TOTAL</b>", S("t", fontSize=11, textColor=WHITE, fontName="Helvetica-Bold", leading=13)),
Paragraph("", S("t", fontSize=9, fontName="Helvetica", leading=13)),
Paragraph("", S("t", fontSize=9, fontName="Helvetica", leading=13)),
Paragraph("8 products · 7 brands", S("t", fontSize=8.5, textColor=WHITE, fontName="Helvetica", leading=13)),
Paragraph(f"<b>${total}</b>", S("t", fontSize=12, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=13)),
])
t = Table(rows, colWidths=col_w, repeatRows=1)
t.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), DEEP),
("BACKGROUND", (0, -1), (-1, -1), ROSE),
("ROWBACKGROUNDS", (0, 1), (-1, -2), [WHITE, LIGHT_SAGE]),
("GRID", (0, 0), (-1, -1), 0.4, colors.HexColor("#D9D0C7")),
("TOPPADDING", (0, 0), (-1, -1), 7),
("BOTTOMPADDING", (0, 0), (-1, -1), 7),
("LEFTPADDING", (0, 0), (-1, -1), 8),
("RIGHTPADDING", (0, 0), (-1, -1), 8),
("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
("ALIGN", (0, 0), (0, -1), "CENTER"),
("ALIGN", (5, 0), (5, -1), "CENTER"),
]))
story.append(t)
story.append(Spacer(1, 0.6*cm))
# ════════ PRIORITY ORDER BOX ════════
priority_bg = colors.HexColor("#FDF7F2")
priority_bdr = ROSE
p_inner = [
Paragraph("<b>🛒 BUY IN THIS ORDER — Essentials First</b>",
S("pb", fontSize=10, textColor=DEEP, fontName="Helvetica-Bold", leading=14, spaceAfter=6)),
Paragraph("<b>Step 1 — Must-haves (start here):</b> Acure Cleanser · Naturium Serum · Nécessaire Body Wash + Lotion",
S("pb", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=14, spaceAfter=3)),
Paragraph("<b>Step 2 — Add next:</b> Bubble Day Cream · Thayers Toner · Purito SPF",
S("pb", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=14, spaceAfter=3)),
Paragraph("<b>Step 3 — Complete the routine:</b> Rhode Night Cream · Supergoop! SPF",
S("pb", fontSize=9, textColor=CHARCOAL, fontName="Helvetica", leading=14, spaceAfter=0)),
]
pbox = Table([[p_inner]], colWidths=[W - 3.6*cm])
pbox.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), priority_bg),
("BOX", (0,0), (-1,-1), 1.2, priority_bdr),
("TOPPADDING", (0,0), (-1,-1), 12),
("BOTTOMPADDING", (0,0), (-1,-1), 12),
("LEFTPADDING", (0,0), (-1,-1), 14),
("RIGHTPADDING", (0,0), (-1,-1), 14),
]))
story.append(pbox)
story.append(Spacer(1, 0.5*cm))
# ════════ BRAND CARDS (2 per row) ════════
story.append(hr(DEEP, 1))
story.append(Paragraph("WHY EACH BRAND", sec))
story.append(hr())
story.append(Spacer(1, 0.3*cm))
brand_info = [
("Acure", "Cleanser", "Clean, vegan, pH-balanced. Won't strip reactive combination skin. Affordable anchor."),
("Thayers", "Toner", "Witch hazel + rose water — smells amazing, calms redness, preps skin for serum."),
("Naturium", "Serum", "Apothecary-style bottle. Niacinamide 12% targets acne, dark spots, pores and oiliness."),
("Bubble", "Day Moisturizer", "Barrier-first formula, non-comedogenic. Lightweight base under SPF for combination skin."),
("Supergoop!", "Sunscreen SPF 40", "The most invisible, weightless SPF available. Feels like nothing. Non-negotiable step."),
("Rhode", "Night Moisturizer", "Minimal luxury DNA — same energy as Nécessaire. Ceramides + peptides restore barrier overnight."),
("Nécessaire", "Body Wash + Lotion","Gold standard of minimal luxury body care. Niacinamide + vitamins. Spa-level eucalyptus scent."),
]
# Build 2-column card layout
card_rows = []
for i in range(0, len(brand_info), 2):
pair = brand_info[i:i+2]
cells = []
for brand, role, why in pair:
inner = [
Paragraph(f"<b>{brand}</b>", S("bc", fontSize=11, textColor=DEEP, fontName="Helvetica-Bold", leading=15)),
Paragraph(role, S("bc", fontSize=8.5, textColor=ROSE, fontName="Helvetica-Bold", leading=12, spaceAfter=4)),
Paragraph(why, S("bc", fontSize=8.5, textColor=CHARCOAL, fontName="Helvetica", leading=13)),
]
cells.append(inner)
if len(cells) == 1:
cells.append(Paragraph("", S("empty", fontSize=9, fontName="Helvetica", leading=13)))
card_rows.append(cells)
cw = (W - 3.6*cm - 0.4*cm) / 2
for row_cells in card_rows:
ct2 = Table([row_cells], colWidths=[cw, cw])
ct2.setStyle(TableStyle([
("BACKGROUND", (0,0), (0,0), LIGHT_SAGE),
("BACKGROUND", (1,0), (1,0), colors.HexColor("#FDF7F2")),
("BOX", (0,0), (0,0), 0.8, SAGE),
("BOX", (1,0), (1,0), 0.8, ROSE),
("TOPPADDING", (0,0), (-1,-1), 10),
("BOTTOMPADDING", (0,0), (-1,-1), 10),
("LEFTPADDING", (0,0), (-1,-1), 12),
("RIGHTPADDING", (0,0), (-1,-1), 12),
("VALIGN", (0,0), (-1,-1), "TOP"),
("INNERGRID", (0,0), (-1,-1), 0, WHITE),
]))
story.append(ct2)
story.append(Spacer(1, 0.25*cm))
story.append(Spacer(1, 0.4*cm))
# ════════ FOOTER ════════
story.append(hr(SOFT_GREY, 0.5))
story.append(Paragraph(
"Guide by Orris · Your Personal Skin Expert · "
"Consistency beats everything — use this routine daily for 8 weeks minimum. 🤍",
S("ft", fontSize=8, textColor=SOFT_GREY, fontName="Helvetica",
alignment=TA_CENTER, leading=12)))
# ── Assemble ──────────────────────────────────────────────────────────────────
frame_cover = Frame(0, 0, W, H, leftPadding=2.5*cm, rightPadding=2.5*cm,
topPadding=0, bottomPadding=0, id="cover")
frame_body = Frame(1.8*cm, 1.5*cm, W - 3.6*cm, H - 3.5*cm,
leftPadding=0, rightPadding=0,
topPadding=0, bottomPadding=0, id="body")
out = "/home/daytona/workspace/skincare-guide/Final_Shopping_List.pdf"
doc = BaseDocTemplate(
out, pagesize=A4,
title="My Skincare Shopping List",
author="Orris",
leftMargin=0, rightMargin=0, topMargin=0, bottomMargin=0,
)
doc.addPageTemplates([
PageTemplate(id="Cover", frames=[frame_cover], onPage=cover_bg),
PageTemplate(id="Body", frames=[frame_body], onPage=body_bg),
])
doc.build(story)
print(f"Done → {out}")
cd /home/daytona/workspace/skincare-guide && python generate_shopping_list.py 2>…
Final Shopping List
PDF Document · PDF
| # | Product | Brand | Price |
|---|---|---|---|
| 1 | Brightening Cleansing Gel | Acure | $10 |
| 2 | Witch Hazel + Rosewater Toner | Thayers | $12 |
| 3 | Niacinamide Serum 12% + Zinc | Naturium | $20 |
| 4 | Barrier Culture Moisture Cream | Bubble | $18 |
| 5 | Unseen Sunscreen SPF 40 | Supergoop! | $36 |
| 6 | Barrier Restore Cream | Rhode | $32 |
| 7 | The Body Wash — Eucalyptus | Nécessaire | $25 |
| 8 | The Body Lotion — Fragrance Free | Nécessaire | $30 |
| TOTAL | $183 |
As a beginner do I really need Barrier Culture Moisture Cream and Barrier Restore Cream
| # | Product | Brand | Price |
|---|---|---|---|
| 1 | Brightening Cleansing Gel | Acure | $10 |
| 2 | Witch Hazel + Rosewater Toner | Thayers | $12 |
| 3 | Niacinamide Serum 12% + Zinc | Naturium | $20 |
| 4 | Barrier Restore Cream (AM + PM) | Rhode | $32 |
| 5 | Unseen Sunscreen SPF 40 | Supergoop! | $36 |
| 6 | The Body Wash — Eucalyptus | Nécessaire | $25 |
| 7 | The Body Lotion — Fragrance Free | Nécessaire | $30 |
| TOTAL | $165 ✅ |
What do Witch Hazel + Rosewater Toner and Niacinamide Serum 12% + Zinc
| Concern | What Niacinamide Does |
|---|---|
| Acne | Kills acne-causing bacteria, reduces inflammation inside pores |
| Dark marks | Blocks melanin transfer — fades post-acne dark spots over time |
| Large pores | Tightens and shrinks pore appearance with consistent use |
| Oily T-zone | Regulates sebum production — your skin produces less oil |
| Uneven texture | Smooths skin surface, reduces bumpiness |
| Redness | Anti-inflammatory — calms active breakouts faster |
| Product | One-Line Job |
|---|---|
| Thayers Toner | Clears, balances, preps skin for serum |
| Naturium Niacinamide | Treats acne, fades marks, shrinks pores, controls oil |
So I am buying. Versed Skin Soak Rich Moisture Face Cream - Daily Facial Moisturizer with Squalane Oil, Hyaluronic Acid, Vitamin E + Red Algae - Smooth, Non-Greasy Night Cream for Aging, Dry Skin - Vegan (1.5 oz). The Ordinary Niacinamide 10% + Zinc 1%, Smoothing Serum for Blemish-Prone Skin. Nécessaire The Body Lotion Fragrance-Free - Multi-Peptide Moisturizer. Nécessaire The Body Wash Eucalyptus. Acure Brightening Cleansing Gel (Without gel is not available). And supergoof sunscreen.
| Product | Verdict |
|---|---|
| Nécessaire Body Wash — Eucalyptus | ✅ Perfect. Keep it. |
| Nécessaire Body Lotion — Multi-Peptide FF | ✅ Perfect. Keep it. |
| Acure Brightening Cleansing Gel | ✅ Good cleanser. Works fine without the gel version. |
| # | Product | Brand | Keep/Swap |
|---|---|---|---|
| 1 | Brightening Cleansing Gel | Acure | ✅ Keep |
| 2 | Niacinamide 10% + Zinc 1% | The Ordinary | ✅ Keep — patch test first |
| 3 | Barrier Restore Cream OR Byoma Gel-Cream | Rhode / Byoma | ⚠️ Swap Versed |
| 4 | Unseen Sunscreen SPF 40 | Supergoop! | ✅ Keep |
| 5 | The Body Wash — Eucalyptus | Nécessaire | ✅ Keep |
| 6 | The Body Lotion — Multi-Peptide FF | Nécessaire | ✅ Keep |
How, what and where to use plan
Combine 1 and 3
Generate a complete 'How, Where, When' application guide PDF for your final routine 3 Make a printable daily checklist for morning and night skincare steps
Generate a complete 'How, Where, When' application guide PDF for your final skincare routine