Implement blog snippet system and new landing page - #1
Conversation
Added: - Blog images in public/images/ - Global styles in public/styles/mylanding.css - BlogCard component for displaying blog previews - blogsnippets.ts with blog metadata - blogLayout.astro to render individual blog posts - blogSnippets page to show all previews - newLnding page for updated landing layout
WalkthroughAdded React integration and TypeScript JSX settings, installed React deps, introduced a dark-themed landing and blog UI, added a BlogPost type, added /newLanding, /blogSnippets, and dynamic /[slug] pages (with getStaticPaths fetching WP posts), and updated CSP to allow Google Fonts and an external script. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant AstroServer as Astro Page
participant WP as WordPress API
User->>AstroServer: GET /blogSnippets
AstroServer->>WP: GET /wp-json/wp/v2/posts
WP-->>AstroServer: posts[]
AstroServer-->>User: Rendered blog list (titles, excerpts, read-more links)
sequenceDiagram
participant Builder as Astro Build
participant WP as WordPress API
participant Page as [slug].astro
Builder->>WP: GET /wp-json/wp/v2/posts?_embed
WP-->>Builder: posts[]
loop for each post
Builder->>Page: provide post props for /{slug}
Page-->>Builder: render static HTML (title, content, media, meta)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (8)
landing-panda/src/data/blogsnippets.ts (1)
8-33: Consider improving maintainability of blog data structure.While the current static array works, consider these improvements for better maintainability:
- Add metadata like tags, author, or publication status
- Consider moving to a more scalable data source (JSON file, CMS, or database)
- Add validation for required fields
Here's an enhanced version with additional metadata:
export type BlogSnippet = { date: string; title: string; snippet: string; link: string; + author?: string; + tags?: string[]; + published?: boolean; };landing-panda/src/pages/index.astro (1)
17-18: Clean up commented code and consider baseUrl consistency.Consider removing the commented line rather than leaving it in the codebase. Also, for consistency with other links, you might want to use the same baseUrl pattern:
- <!-- <p><a href="/landing">Go to Landing Page</a></p> --> - <p><a href="/newLanding">Go to Landing Page</a></p> + <p><a href={`${baseUrl}/newLanding`}>Go to Landing Page</a></p>landing-panda/src/pages/blogSnippets.astro (1)
15-19: Consider adding semantic structure.The navigation links would benefit from being wrapped in a
<nav>element for better accessibility and semantic HTML.Apply this diff to improve semantics:
<div class="blogs_container"> - <div class="first_links"> + <nav class="first_links"> <a href="/newLanding">Akong'a Labs</a> <a href="/blogSnippets">Blogs</a> - </div> + </nav>landing-panda/src/components/BlogCard.tsx (1)
12-14: Consider consolidating duplicate links for better UX.Both the title and "Read more" link point to the same destination, which could be confusing for users and screen readers. Consider making the entire card clickable or removing one of the links.
Option 1 - Make the entire card clickable:
const BlogCard = ({ title, date, snippet, link }: BlogCardProps) => { return ( - <div> + <div className="blog-card" onClick={() => window.location.href = link} style={{ cursor: 'pointer' }}> <p className="bluecolor" >{date}</p> - <h1><a href={link}>{title}</a></h1> + <h1>{title}</h1> <p className="para_space">{snippet}</p> - <a className="bluecolor readmore" href={link}>Read more→</a> </div> ); };Option 2 - Keep only the "Read more" link:
<p className="bluecolor" >{date}</p> - <h1><a href={link}>{title}</a></h1> + <h1>{title}</h1> <p className="para_space">{snippet}</p> <a className="bluecolor readmore" href={link}>Read more→</a>landing-panda/src/pages/newLanding.astro (1)
18-21: Enhance navigation with semantic HTML.Similar to the blog snippets page, the navigation would benefit from proper semantic structure.
Apply this diff to improve accessibility:
- <div class="first_links"> + <nav class="first_links" aria-label="Main navigation"> <a href="/newLanding">Akong'a Labs</a> <a href="/blogSnippets">Blogs</a> - </div> + </nav>landing-panda/src/pages/blogs/blog1.md (1)
15-15: Missing space after period breaks the sentenceThere is no space between “nothing”. and “The”, which renders as a single word in most markdown engines.
-...I **owned nothing**.The outsized returns of my work... +...I **owned nothing**. The outsized returns of my work...landing-panda/src/pages/blogs/blog2.md (1)
3-3: Consistent image pathingSame concern as in
blog1.md– prefer the root-based path so directory moves don’t break links.-cover: ../../../images/blog2.webp +cover: /images/blog2.webplanding-panda/src/pages/blogs/blog3.md (1)
3-3: Aligncoverpath with public asset conventionFor consistency and to avoid broken URLs on future refactors:
-cover: ../../../images/blog3.webp +cover: /images/blog3.webp
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (14)
landing-panda/astro.config.mjs(1 hunks)landing-panda/package.json(1 hunks)landing-panda/public/styles/mylanding.css(1 hunks)landing-panda/src/components/BlogCard.tsx(1 hunks)landing-panda/src/data/blogsnippets.ts(1 hunks)landing-panda/src/pages/blogLayout.astro(1 hunks)landing-panda/src/pages/blogSnippets.astro(1 hunks)landing-panda/src/pages/blogs/blog1.md(1 hunks)landing-panda/src/pages/blogs/blog2.md(1 hunks)landing-panda/src/pages/blogs/blog3.md(1 hunks)landing-panda/src/pages/blogs/blog4.md(1 hunks)landing-panda/src/pages/index.astro(1 hunks)landing-panda/src/pages/newLanding.astro(1 hunks)landing-panda/tsconfig.json(1 hunks)
🧰 Additional context used
🪛 LanguageTool
landing-panda/src/pages/blogs/blog4.md
[uncategorized] ~112-~112: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ... Previous: Solve, Build, Get Paid: Open Source Bounties at Akong’a 🖤 GitHub...
(EN_COMPOUND_ADJECTIVE_INTERNAL)
landing-panda/src/pages/blogs/blog2.md
[uncategorized] ~119-~119: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...](#) Next: Solve, Build, Get Paid: Open Source Bounties at Akong’a
(EN_COMPOUND_ADJECTIVE_INTERNAL)
landing-panda/src/pages/blogs/blog1.md
[style] ~45-~45: ‘by all means’ might be wordy. Consider a shorter alternative.
Context: ...nless you’re in a regulated field. Then by all means, go study, my dear Lawyers and Doctors....
(EN_WORDINESS_PREMIUM_BY_ALL_MEANS)
[style] ~47-~47: ‘in this day and age’ might be wordy. Consider a shorter alternative.
Context: ...us. Learning is very very close to free in this day and age. If you’re reading this, you already pa...
(EN_WORDINESS_PREMIUM_IN_THIS_DAY_AND_AGE)
landing-panda/src/pages/blogs/blog3.md
[uncategorized] ~6-~6: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...og3.webp --- # Solve, Build, Get Paid: Open Source Bounties at Akong’a 
[uncategorized] ~17-~17: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...arn by solving real problems.** How? Open source bounties. To be clear—this isn’t the...
(EN_COMPOUND_ADJECTIVE_INTERNAL)
[style] ~73-~73: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...e not for people looking for shortcuts. They’re for: - Developers who want a seriou...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
🪛 markdownlint-cli2 (0.17.2)
landing-panda/src/pages/blogs/blog4.md
112-112: No empty links
(MD042, no-empty-links)
114-114: No empty links
(MD042, no-empty-links)
landing-panda/src/pages/blogs/blog3.md
142-142: No empty links
(MD042, no-empty-links)
158-158: No empty links
(MD042, no-empty-links)
168-168: No empty links
(MD042, no-empty-links)
169-169: No empty links
(MD042, no-empty-links)
🔇 Additional comments (15)
landing-panda/src/data/blogsnippets.ts (2)
1-6: LGTM! Clean type definition.The
BlogSnippettype is well-structured with appropriate string properties for blog metadata.
10-13: Verify future dates and incomplete snippet content.The date "June 28, 2025" appears to be in the future, and the snippet text contains incomplete sentences ("Her interpretation of brutal honesty was focused on the word "brutal". This led to a very very spirited discussion on whether one needs to be brutal to be honest. She questioned whether brutal…").
Please confirm these are intentional for demo purposes.
landing-panda/astro.config.mjs (1)
4-9: LGTM! Proper React integration setup.The React integration is correctly configured following Astro's standard approach. This enables React components to be used within Astro pages.
landing-panda/tsconfig.json (2)
3-9: LGTM! Improved formatting and structure.The multiline formatting of include/exclude arrays improves readability and maintainability.
10-13: LGTM! Correct React JSX configuration.The compiler options are properly configured for React integration using the modern JSX transform. This aligns perfectly with the React integration added to the Astro config.
landing-panda/package.json (2)
11-18: LGTM! Complete React integration dependency setup.All necessary dependencies for React integration are included with appropriate type definitions. The dependency structure supports the React components and configuration changes made throughout the project.
12-17: React 19.1.0 compatibility with @astrojs/react@4.3.0 confirmedVerified that
@astrojs/react@4.3.0lists a peer dependency ofreact: ^19.0.0(andreact-dom: ^19.0.0), so using React 19.1.0 (and its matching type definitions) is fully supported. No further action needed.landing-panda/src/pages/blogLayout.astro (1)
20-23: LGTM! Navigation structure is well-organized.The navigation links provide clear pathways between the main site and blog sections, enhancing user experience.
landing-panda/src/pages/blogSnippets.astro (1)
20-29: LGTM! Clean React integration and data mapping.The mapping over
blogPostsand passing props to theBlogCardcomponent is well-structured. The destructuring and prop passing follows React best practices within the Astro context.landing-panda/src/components/BlogCard.tsx (1)
1-6: LGTM! Well-defined TypeScript interface.The
BlogCardPropstype definition is clean and provides clear typing for all required props.landing-panda/src/pages/blogs/blog4.md (1)
1-4: LGTM! Proper frontmatter configuration.The layout reference and cover image configuration correctly integrate with the blog system architecture.
landing-panda/src/pages/newLanding.astro (2)
34-34: LGTM! Good image accessibility.The image includes proper alt text, which is essential for accessibility and SEO.
22-26: LGTM! Clear and engaging content structure.The company description effectively communicates the mission and values with good use of strikethrough text for emphasis.
landing-panda/src/pages/blogs/blog1.md (1)
3-3: Prefer absolute/images/...path for thecoverfield
coveris consumed byblogLayout.astro. All other image references in the post use the public-rooted version (/images/blog1.webp). Keeping the same convention prevents accidental 404s if the page is ever moved or the directory depth changes.-cover: ../../../images/blog1.webp +cover: /images/blog1.webplanding-panda/src/pages/blogs/blog2.md (1)
118-119: Placeholder links render as empty anchors
(#)is flagged by markdown-lint (MD042) and will produce dead links in production.
Either point to the real URL or remove the link markup until it exists.-**Previous:** [Why I’m Starting This Company](#) -**Next:** [Solve, Build, Get Paid: Open Source Bounties at Akong’a](#) +<!-- TODO: replace “#” with the actual permalinks once available --> +**Previous:** Why I’m Starting This Company +**Next:** Solve, Build, Get Paid: Open Source Bounties at Akong’a
| .blog-post title{ | ||
| align-content: center; | ||
| align-self: center; | ||
| } |
There was a problem hiding this comment.
Selector does nothing – title is not a valid HTML element
If you intended to target a .title class inside .blog-post, the selector needs a dot; otherwise the rule is ignored.
-.blog-post title{
+.blog-post .title{🤖 Prompt for AI Agents
In landing-panda/public/styles/mylanding.css around lines 136 to 139, the
selector ".blog-post title" is invalid because "title" is not an HTML element.
To fix this, change the selector to ".blog-post .title" to target elements with
the class "title" inside elements with the class "blog-post". This will ensure
the CSS rules are applied correctly.
| .blog-post h1, h2, h3 { | ||
| margin-top: 1.5rem; | ||
| margin-bottom: 0.75rem; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Unintentionally un-scoped h2 & h3 selectors
h2, h3 are no longer under .blog-post, so these rules will apply globally.
Scope each selector explicitly:
-.blog-post h1, h2, h3 {
+.blog-post h1,
+.blog-post h2,
+.blog-post h3 {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .blog-post h1, h2, h3 { | |
| margin-top: 1.5rem; | |
| margin-bottom: 0.75rem; | |
| } | |
| .blog-post h1, | |
| .blog-post h2, | |
| .blog-post h3 { | |
| margin-top: 1.5rem; | |
| margin-bottom: 0.75rem; | |
| } |
🤖 Prompt for AI Agents
In landing-panda/public/styles/mylanding.css at lines 141 to 144, the selectors
h2 and h3 are not scoped under .blog-post, causing the styles to apply globally.
To fix this, explicitly scope h2 and h3 by prefixing them with .blog-post so the
CSS rules only apply to headings within .blog-post elements.
| import "../../public/images/blog1.webp" | ||
| import "../../public/images/blog2.webp" | ||
| import "../../public/images/blog3.webp" | ||
| import "../../public/images/blog4.webp" |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Remove unnecessary image imports.
The image imports in the frontmatter appear unused in this layout component. These should only be imported where they're actually referenced.
Apply this diff to remove unused imports:
---
import "../../public/styles/mylanding.css"
-import "../../public/images/blog1.webp"
-import "../../public/images/blog2.webp"
-import "../../public/images/blog3.webp"
-import "../../public/images/blog4.webp"
---📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import "../../public/images/blog1.webp" | |
| import "../../public/images/blog2.webp" | |
| import "../../public/images/blog3.webp" | |
| import "../../public/images/blog4.webp" | |
| import "../../public/styles/mylanding.css" |
🤖 Prompt for AI Agents
In landing-panda/src/pages/blogLayout.astro around lines 3 to 6, the image
imports are unused in this layout component. Remove all four import statements
for the blog images to clean up the code and avoid unnecessary imports.
| <head> | ||
| <head> | ||
| <meta charset="utf-8" /> | ||
| <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> | ||
| <meta name="viewport" content="width=device-width" /> | ||
| <title>Blog layout</title> | ||
| </head> |
There was a problem hiding this comment.
Fix duplicate head tags.
There are nested <head> tags which creates invalid HTML structure that can cause rendering issues and prevent proper meta tag processing.
Apply this diff to fix the structure:
<head>
- <head>
- <meta charset="utf-8" />
- <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
- <meta name="viewport" content="width=device-width" />
- <title>Blog layout</title>
+ <meta charset="utf-8" />
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
+ <meta name="viewport" content="width=device-width" />
+ <title>Blog layout</title>
</head>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <head> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> | |
| <meta name="viewport" content="width=device-width" /> | |
| <title>Blog layout</title> | |
| </head> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> | |
| <meta name="viewport" content="width=device-width" /> | |
| <title>Blog layout</title> | |
| </head> |
🤖 Prompt for AI Agents
In landing-panda/src/pages/blogLayout.astro around lines 10 to 16, there are
nested <head> tags causing invalid HTML structure. Remove the inner <head> tag
so that only one <head> tag wraps all the meta and link elements, ensuring
proper HTML structure and correct meta tag processing.
| 🔗 **Check out the bounties here**: | ||
| 👉 [Akong’a Labs OSS Bounties GitHub Repo](#) | ||
|
|
||
| - Pick a challenge | ||
| - Read the instructions | ||
| - Follow them to the letter | ||
| - Ask questions in public if you’re stuck | ||
| - **And most importantly—build something that works.** | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion
Multiple empty links – fails MD042 and hurts UX
Replace (#) with real URLs or leave plain text until the targets exist.
-🔗 **Check out the bounties here**:
-👉 [Akong’a Labs OSS Bounties GitHub Repo](#)
+🔗 **Check out the bounties here**: 👉 Akong’a Labs OSS Bounties GitHub Repo
...
-Check it out: [Antiwork/bounties](#)
+Check it out: Antiwork/bounties
...
-**Previous:** [Understanding Remote Onboarding: Lessons from Akong'a Labs](#)
-**Next:** [The Power of Honest Communication in Teams](#)
+<!-- TODO: Add real permalinks when available -->
+**Previous:** Understanding Remote Onboarding: Lessons from Akong'a Labs
+**Next:** The Power of Honest Communication in Teams📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 🔗 **Check out the bounties here**: | |
| 👉 [Akong’a Labs OSS Bounties GitHub Repo](#) | |
| - Pick a challenge | |
| - Read the instructions | |
| - Follow them to the letter | |
| - Ask questions in public if you’re stuck | |
| - **And most importantly—build something that works.** | |
| 🔗 **Check out the bounties here**: 👉 Akong’a Labs OSS Bounties GitHub Repo | |
| - Pick a challenge | |
| - Read the instructions | |
| - Follow them to the letter | |
| - Ask questions in public if you’re stuck | |
| - **And most importantly—build something that works.** | |
| Check it out: Antiwork/bounties | |
| <!-- TODO: Add real permalinks when available --> | |
| **Previous:** Understanding Remote Onboarding: Lessons from Akong'a Labs | |
| **Next:** The Power of Honest Communication in Teams |
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
142-142: No empty links
(MD042, no-empty-links)
🤖 Prompt for AI Agents
In landing-panda/src/pages/blogs/blog3.md around lines 141 to 149, the markdown
contains empty links using (#) which triggers MD042 lint errors and degrades
user experience. Replace these placeholder links with actual URLs pointing to
the correct resources. If the URLs are not yet available, remove the link
formatting and leave the text as plain text until valid targets exist.
| **Previous:** [Solve, Build, Get Paid: Open Source Bounties at Akong’a](#) | ||
|
|
||
| 🖤 [GitHub](#) |
There was a problem hiding this comment.
Fix empty placeholder links.
The markdown contains empty links that will not function properly and create a poor user experience.
Apply this diff to either remove the placeholders or add proper URLs:
-**Previous:** [Solve, Build, Get Paid: Open Source Bounties at Akong'a](#)
+**Previous:** [Solve, Build, Get Paid: Open Source Bounties at Akong'a](/blogs/blog3)
-🖤 [GitHub](#)
+🖤 [GitHub](https://github.com/AkongaLabs)Or remove the placeholders entirely if the links aren't ready:
-**Previous:** [Solve, Build, Get Paid: Open Source Bounties at Akong'a](#)
-
-🖤 [GitHub](#)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| **Previous:** [Solve, Build, Get Paid: Open Source Bounties at Akong’a](#) | |
| 🖤 [GitHub](#) | |
| **Previous:** [Solve, Build, Get Paid: Open Source Bounties at Akong'a](/blogs/blog3) | |
| 🖤 [GitHub](https://github.com/AkongaLabs) |
🧰 Tools
🪛 LanguageTool
[uncategorized] ~112-~112: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ... Previous: Solve, Build, Get Paid: Open Source Bounties at Akong’a 🖤 GitHub...
(EN_COMPOUND_ADJECTIVE_INTERNAL)
🪛 markdownlint-cli2 (0.17.2)
112-112: No empty links
(MD042, no-empty-links)
114-114: No empty links
(MD042, no-empty-links)
🤖 Prompt for AI Agents
In landing-panda/src/pages/blogs/blog4.md around lines 112 to 114, there are
empty placeholder links that do not function properly. To fix this, either
replace the "#" in the markdown links with the correct URLs or remove the links
entirely if the URLs are not yet available, ensuring no empty or broken links
remain.
| const isDev = import.meta.env.DEV; | ||
| const baseUrl = isDev ? "http://localhost:3001" : ""; |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Remove unused baseUrl variable.
The baseUrl variable is declared but never used in the component, creating unnecessary code.
Apply this diff to remove the unused variable:
---
import '../../public/styles/mylanding.css'
-const isDev = import.meta.env.DEV;
-const baseUrl = isDev ? "http://localhost:3001" : "";
---📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const isDev = import.meta.env.DEV; | |
| const baseUrl = isDev ? "http://localhost:3001" : ""; | |
| --- | |
| import '../../public/styles/mylanding.css' | |
| --- |
🤖 Prompt for AI Agents
In landing-panda/src/pages/newLanding.astro at lines 3 to 4, the variable
baseUrl is declared but never used. Remove the declaration of baseUrl entirely
to clean up the code and avoid unused variables.
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (3)
landing-panda/src/pages/blogs/blog3.md (1)
95-96: Empty placeholder links trigger MD042 againBoth “Previous” and “Next” still point to
(#)/ empty parentheses, re-introducing the lint error already raised in the earlier review. Replace with real permalinks or fall back to plain text until the URLs exist.-**Previous:** [Understanding Remote Onboarding: Lessons from Akong'a Labs](#) -**Next:** [The Power of Honest Communication in Teams]() +<!-- TODO: add real permalinks when available --> +**Previous:** Understanding Remote Onboarding: Lessons from Akong'a Labs +**Next:** The Power of Honest Communication in Teamslanding-panda/src/pages/blogs/blog4.md (2)
66-66: Replace placeholder “[EMAIL BOX]” with a real signup form or remove it.
70-70: Update or remove the empty placeholder link (#).
🧹 Nitpick comments (5)
landing-panda/src/pages/blogs/blog3.md (2)
84-86: Extraneous trailing colon after the Antiwork linkThe sentence already ends with a colon before the link. The second colon after the closing parenthesis is redundant and will render oddly.
-Check it out over at: [Antiwork/bounties](https://antiwork.com/bounties): +Check it out over at: [Antiwork/bounties](https://antiwork.com/bounties)
92-94:[EMAIL BOX]is a visible placeholderLeaving the placeholder in published markdown breaks immersion and looks unfinished. Either embed a real email signup form/component or replace the section with a TODO comment so it is excluded from the rendered HTML.
landing-panda/src/pages/blogs/blog4.md (2)
16-16: Correct typos “wheathe” → “whether” and “concerened” → “concerned”.-... She questioned wheathe brutal honesty equated to being rude? She was concerened and rightfully so... +... She questioned whether brutal honesty equated to being rude? She was concerned and rightfully so...
57-57: Refine the wording of the sentence for clarity.-Good communication breeds by comprehension. +Good communication is cultivated through comprehension.landing-panda/src/pages/blogs/blog2.md (1)
24-26: Fix missing initial character in paragraph “First Contact”.The paragraph currently starts with “fter I got the job…”, dropping the leading “A”.
This typo is visible to end-users and undermines credibility.-fter I got the job, my manager told me I would be contacted by his assistant, Ivy, through their main communication channel, Telegram. +After I got the job, my manager told me I would be contacted by his assistant, Ivy, through their main communication channel, Telegram.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
landing-panda/public/styles/mylanding.css(1 hunks)landing-panda/src/components/BlogCard.tsx(1 hunks)landing-panda/src/pages/blogs/blog1.md(1 hunks)landing-panda/src/pages/blogs/blog2.md(1 hunks)landing-panda/src/pages/blogs/blog3.md(1 hunks)landing-panda/src/pages/blogs/blog4.md(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- landing-panda/public/styles/mylanding.css
🚧 Files skipped from review as they are similar to previous changes (1)
- landing-panda/src/components/BlogCard.tsx
🧰 Additional context used
🪛 LanguageTool
landing-panda/src/pages/blogs/blog1.md
[style] ~31-~31: ‘by all means’ might be wordy. Consider a shorter alternative.
Context: ...nless you’re in a regulated field. Then by all means go study my dear Lawyers and Doctors. (...
(EN_WORDINESS_PREMIUM_BY_ALL_MEANS)
[style] ~33-~33: ‘in this day and age’ might be wordy. Consider a shorter alternative.
Context: ...us. Learning is very very close to free in this day and age. If you’re reading this, you already pa...
(EN_WORDINESS_PREMIUM_IN_THIS_DAY_AND_AGE)
landing-panda/src/pages/blogs/blog2.md
[grammar] ~24-~24: Ensure spelling is correct
Context: ...ng from day one. --- ## First Contact fter I got the job, my manager told me I wou...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[uncategorized] ~94-~94: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...](#) Next: Solve, Build, Get Paid: Open Source Bounties at Akong’a
(EN_COMPOUND_ADJECTIVE_INTERNAL)
landing-panda/src/pages/blogs/blog3.md
[uncategorized] ~6-~6: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...og3.webp --- # Solve, Build, Get Paid: Open Source Bounties at Akong’a 
[uncategorized] ~13-~13: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ... to earn by solving real problems. How? Open source bounties. To be clear, this isn’t the v...
(EN_COMPOUND_ADJECTIVE_INTERNAL)
[style] ~40-~40: As a shorter alternative for ‘able to’, consider using “can”.
Context: ...ssions are of the quality we expect. We are able to look at them knowing they meet our stan...
(BE_ABLE_TO)
[style] ~43-~43: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...e not for people looking for shortcuts. They’re for developers who want a serious ch...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
landing-panda/src/pages/blogs/blog4.md
[grammar] ~16-~16: Ensure spelling is correct
Context: ... be brutal to be honest. She questioned wheathe brutal honesty equated to being rude? S...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~16-~16: Ensure spelling is correct
Context: ... honesty equated to being rude? She was concerened and rightfully so... --- ## The Akong...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~26-~26: As an alternative to the over-used intensifier ‘very’, consider replacing this phrase.
Context: ...ng disgruntled. This is something very very important to me and that’s at the core of the Ako...
(EN_WEAK_ADJECTIVE)
[style] ~26-~26: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...DNA. I am human. I am not always right. I will not tolerate a team of “yes” men. ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~26-~26: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... will not tolerate a team of “yes” men. I need to trust that my team will questio...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[uncategorized] ~70-~70: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ... Previous: Solve, Build, Get Paid: Open Source Bounties at Akong’a
(EN_COMPOUND_ADJECTIVE_INTERNAL)
🪛 markdownlint-cli2 (0.17.2)
landing-panda/src/pages/blogs/blog2.md
93-93: No empty links
(MD042, no-empty-links)
94-94: No empty links
(MD042, no-empty-links)
landing-panda/src/pages/blogs/blog3.md
95-95: No empty links
(MD042, no-empty-links)
96-96: No empty links
(MD042, no-empty-links)
landing-panda/src/pages/blogs/blog4.md
70-70: No empty links
(MD042, no-empty-links)
🔇 Additional comments (2)
landing-panda/src/pages/blogs/blog1.md (1)
46-46:Nextlink is a dead placeholder
href="#"hurts navigation and SEO. Point it to the real next post (e.g./blogs/blog2) or omit the link until the destination exists.-**Next:** [Understanding Remote Onboarding: Lessons from Akong'a Labs](#) +**Next:** [Understanding Remote Onboarding: Lessons from Akong'a Labs](/blogs/blog2)landing-panda/src/pages/blogs/blog2.md (1)
2-4: Verify “cover” image path – may break at build time.
cover: ../../../images/blog2.webpclimbs three directories fromsrc/pages/blogs/to resolveimages/blog2.webp, but the image resides underpublic/images/.
Astro generally expects either an absolute path (/images/...) or a path undersrc/assets. Please confirm the asset is picked up correctly; otherwise the cover thumbnail will 404.
| --- | ||
| layout: ../blogLayout.astro | ||
| cover: ../../../images/blog1.webp | ||
| --- |
There was a problem hiding this comment.
Cover image path likely breaks at runtime
cover: "../../../images/blog1.webp" walks three levels up to project root, but the asset actually lives under public/images/. Astro serves everything inside public from the site-root (/images/...). Use an absolute site path (preferred) or walk into ../public/images.
-cover: ../../../images/blog1.webp
+cover: /images/blog1.webp # or "../public/images/blog1.webp"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| --- | |
| layout: ../blogLayout.astro | |
| cover: ../../../images/blog1.webp | |
| --- | |
| --- | |
| layout: ../blogLayout.astro | |
| cover: /images/blog1.webp # or "../public/images/blog1.webp" | |
| --- |
🤖 Prompt for AI Agents
In landing-panda/src/pages/blogs/blog1.md lines 1 to 4, the cover image path is
incorrect because it uses a relative path that goes three levels up, but the
image is actually in the public/images directory served from the site root. Fix
this by changing the cover path to an absolute site path like
"/images/blog1.webp" instead of "../../../images/blog1.webp".
- Embedded external form script on blog snippet and individual blog pages - Implemented responsive design using media queries for different screens sizes - Adjusted layout and image positioning for better mobile view
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (1)
landing-panda/src/pages/blogs/blog1.md (1)
3-3: Cover image path still incorrect – will 404 at runtime
The image lives underpublic/images/, which Astro serves from site-root.
Keep the inline image on Line 6, but update the front-matter to the same absolute path to avoid a brokencoverURL.-cover: ../../../images/blog1.webp +cover: /images/blog1.webp
🧹 Nitpick comments (7)
landing-panda/src/pages/blogs/blog3.md (2)
84-86: Superfluous colon after the Antiwork linkThe text already ends with a colon before the link. The extra colon immediately after
)renders as plain text and looks like a typo.-Check it out over at: [Antiwork/bounties](https://antiwork.com/bounties): +Check it out over at: [Antiwork/bounties](https://antiwork.com/bounties)
48-52: Minor wording tweak for readabilityMissing punctuation after “help you” makes the list of tools read oddly.
-Yup. Use AI tools if they help you Cursor, Zed, ChatGPT, whatever works for you. +Yup. Use AI tools if they help you—Cursor, Zed, ChatGPT, whatever works for you.landing-panda/src/pages/blogs/blog4.md (2)
20-30: Style nitpick – repeated intensifiers dilute impactSentences such as “very very positive” and “very very important” appear twice in this paragraph. Consider dropping one “very” or using a stronger adjective for tighter prose.
53-54: Grammar tweak for clarity“Good communication breeds by comprehension.” reads awkwardly.
Suggested: “Good communication is bred by comprehension.” or “Good communication stems from comprehension.”landing-panda/src/pages/blogs/blog2.md (3)
24-26: Typo: leading “A” droppedSmall but visible copy error.
-fter I got the job, my manager told me … +After I got the job, my manager told me …
77-77: Extraneous space before commaMinor punctuation issue—remove the space before the comma to avoid rendering a stray “ , ”.
-article by our founder , it’s the heartbeat behind the company. +article by our founder, it’s the heartbeat behind the company.
96-97: Use “Open-Source” as a compound adjectiveHyphenating avoids the markdown-lint MD040 complaint and reads better.
-**Next:** [Solve, Build, Get Paid: Open Source Bounties at Akong’a](/blogs/blog3) +**Next:** [Solve, Build, Get Paid: Open-Source Bounties at Akong’a](/blogs/blog3)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
landing-panda/public/styles/mylanding.css(1 hunks)landing-panda/src/pages/blogLayout.astro(1 hunks)landing-panda/src/pages/blogSnippets.astro(1 hunks)landing-panda/src/pages/blogs/blog1.md(1 hunks)landing-panda/src/pages/blogs/blog2.md(1 hunks)landing-panda/src/pages/blogs/blog3.md(1 hunks)landing-panda/src/pages/blogs/blog4.md(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- landing-panda/src/pages/blogLayout.astro
- landing-panda/public/styles/mylanding.css
- landing-panda/src/pages/blogSnippets.astro
🧰 Additional context used
🪛 LanguageTool
landing-panda/src/pages/blogs/blog1.md
[style] ~31-~31: ‘by all means’ might be wordy. Consider a shorter alternative.
Context: ...nless you’re in a regulated field. Then by all means go study my dear Lawyers and Doctors. (...
(EN_WORDINESS_PREMIUM_BY_ALL_MEANS)
[style] ~33-~33: ‘in this day and age’ might be wordy. Consider a shorter alternative.
Context: ...us. Learning is very very close to free in this day and age. If you’re reading this, you already pa...
(EN_WORDINESS_PREMIUM_IN_THIS_DAY_AND_AGE)
landing-panda/src/pages/blogs/blog2.md
[grammar] ~24-~24: Ensure spelling is correct
Context: ...ng from day one. --- ## First Contact fter I got the job, my manager told me I wou...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[uncategorized] ~97-~97: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...og1) Next: Solve, Build, Get Paid: Open Source Bounties at Akong’a
(EN_COMPOUND_ADJECTIVE_INTERNAL)
landing-panda/src/pages/blogs/blog3.md
[uncategorized] ~6-~6: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...og3.webp --- # Solve, Build, Get Paid: Open Source Bounties at Akong’a 
[style] ~40-~40: As a shorter alternative for ‘able to’, consider using “can”.
Context: ...ssions are of the quality we expect. We are able to look at them knowing they meet our stan...
(BE_ABLE_TO)
[style] ~43-~43: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...e not for people looking for shortcuts. They’re for developers who want a serious ch...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
landing-panda/src/pages/blogs/blog4.md
[style] ~24-~24: As an alternative to the over-used intensifier ‘very’, consider replacing this phrase.
Context: ...g disgruntled.* This is something very very important to me and that’s at the core of the Ako...
(EN_WEAK_ADJECTIVE)
[style] ~24-~24: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...DNA. I am human. I am not always right. I will not tolerate a team of “yes” men. ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~24-~24: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... will not tolerate a team of “yes” men. I need to trust that my team will questio...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[uncategorized] ~35-~35: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...Honesty"? We think of our company as a high performance sports team. When we’re on the field we...
(EN_COMPOUND_ADJECTIVE_INTERNAL)
[uncategorized] ~67-~67: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ... Previous: Solve, Build, Get Paid: Open Source Bounties at Akong’a
(EN_COMPOUND_ADJECTIVE_INTERNAL)
🪛 markdownlint-cli2 (0.17.2)
landing-panda/src/pages/blogs/blog1.md
12-12: Blank line inside blockquote
(MD028, no-blanks-blockquote)
🔇 Additional comments (4)
landing-panda/src/pages/blogs/blog3.md (2)
98-99: Placeholders successfully removed – nice cleanup
Previous/Nextnavigation now points to concrete routes instead of empty(#)links. This resolves MD042 lint violations from earlier iterations and improves UX.
93-95: Unvetted third-party script inclusion – validate necessity & CSPEmbedding
https://akongalabs.kit.com/4e5ba9cc5c/index.jsinjects remote JS into every reader’s browser. This:
- Adds a network hit that can hurt performance.
- Introduces a security/CSP maintenance burden.
- Can break static-site guarantees if the script ever goes down.
Verify the script is required (e.g. for forms/analytics) and whitelist the domain in your Astro deployment’s CSP. If it is only used here, consider lazy-loading or replacing with a static embed instead.
landing-panda/src/pages/blogs/blog4.md (1)
60-63: Verify external embed script reliability & privacyThe embedded script at
https://akongalabs.kit.com/4e5ba9cc5c/index.jsis loaded from a third-party domain. Make sure:
- The domain actually hosts the script (avoid runtime 404).
- Loading it complies with your privacy / cookie policy.
- A
<noscript>fallback or graceful degradation path exists.If unsure, test the script URL in staging before merging.
landing-panda/src/pages/blogs/blog1.md (1)
41-44: Inline<script>embeds third-party code – verify CSP & privacy requirements
Loading external scripts inside Markdown bypasses Astro’s component sandboxing and may clash with a future Content-Security-Policy. Confirm this script is approved, adddeferif synchronous execution isn’t required, and document the data it captures.
| > *“You’re going to be somewhere in your career in ten years, why not in your absolute ideal role, doing the kind of work you’d find most rewarding and having the kind of impact that you’re capable of? If you don’t believe that this is possible, you will surely fail. If you do believe it’s possible, look honestly — you might still fail! But you’ll at least see better outcomes by believing consistency will work than by believing it won’t.”* | ||
|
|
||
| > **Oz Nova, April 2023** |
There was a problem hiding this comment.
Remove blank line inside blockquote to satisfy MD028 and render correctly
The empty Line 12 terminates the blockquote prematurely; the attribution on Line 13 is rendered outside the quote.
> *“You’re going to be somewhere in your career in ten years, why not in your absolute ideal role, doing the kind of work you’d find most rewarding and having the kind of impact that you’re capable of? If you don’t believe that this is possible, you will surely fail. If you do believe it’s possible, look honestly — you might still fail! But you’ll at least see better outcomes by believing consistency will work than by believing it won’t.”*
-
-> **Oz Nova, April 2023**
+> **Oz Nova, April 2023**Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
12-12: Blank line inside blockquote
(MD028, no-blanks-blockquote)
🤖 Prompt for AI Agents
In landing-panda/src/pages/blogs/blog1.md around lines 11 to 13, remove the
blank line between the quoted text and the attribution inside the blockquote.
This will prevent the blockquote from terminating early and ensure the
attribution is rendered as part of the quote, satisfying MD028.
| layout: ../blogLayout.astro | ||
| cover: ../../../images/blog2.webp | ||
| --- |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Invalid cover path will break image resolution at build-time
cover should point to a URL that the Astro asset pipeline can resolve.
../../../images/blog2.webp walks outside src/ and misses the public/ prefix, so the image will 404 on the generated page.
-cover: ../../../images/blog2.webp
+cover: /images/blog2.webpVerify that /public/images/blog2.webp exists (it does per this PR) and let Astro serve it from the root.
🏁 Script executed:
#!/bin/bash
# Locate blog2.webp in the repository
echo "Searching for blog2.webp..."
find . -type f -name blog2.webp
# Verify existence of public/images directory
echo "Checking for public/images directory..."
find . -type d -path "./public/images"Length of output: 267
🏁 Script executed:
#!/bin/bash
# Locate blogLayout.astro in the repository
echo "Searching for blogLayout.astro..."
find . -type f -name "blogLayout.astro"Length of output: 159
Fix invalid cover path in blog2.md
The frontmatter in landing-panda/src/pages/blogs/blog2.md currently points outside of src/ and misses the public/ prefix, so the image won’t be found at build time.
• File: landing-panda/src/pages/blogs/blog2.md
- cover: ../../../images/blog2.webp
+ cover: /images/blog2.webpThis change lets Astro serve the image from landing-panda/public/images/blog2.webp at /images/blog2.webp.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| layout: ../blogLayout.astro | |
| cover: ../../../images/blog2.webp | |
| --- | |
| layout: ../blogLayout.astro | |
| cover: /images/blog2.webp | |
| --- |
🤖 Prompt for AI Agents
In landing-panda/src/pages/blogs/blog2.md around lines 2 to 4, the cover image
path in the frontmatter is incorrect because it points outside the src/
directory and lacks the public/ prefix, causing the image not to be found at
build time. Fix this by updating the cover path to start with /images/blog2.webp
so Astro can correctly serve the image from the public/images directory.
| @@ -0,0 +1,67 @@ | |||
| --- | |||
| layout: ../blogLayout.astro | |||
| cover: ../../../images/blog4.webp | |||
There was a problem hiding this comment.
Fix incorrect cover path – image will not be found at build time
../../../images/blog4.webp points outside Astro’s public/ directory, so the build pipeline won’t copy it and the image will 404 in production.
Replace with an absolute path under public/ (consistent with the in-post image):
-cover: ../../../images/blog4.webp
+cover: /images/blog4.webp📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| cover: ../../../images/blog4.webp | |
| cover: /images/blog4.webp |
🤖 Prompt for AI Agents
In landing-panda/src/pages/blogs/blog4.md at line 3, the cover image path is
relative and points outside the public directory, causing a 404 error in
production. Change the cover path to an absolute path starting from the public
directory, matching the format used for in-post images, to ensure the image is
correctly found and included during the build.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (2)
landing-panda/public/styles/mylanding.css (2)
140-143: Selector does nothing – duplicate of prior feedback
titleis not an HTML element, so.blog-post titlenever matches. Use.blog-post .title(note the dot).
145-151:h2&h3unintentionally global – duplicate of prior feedback
Onlyh1is scoped under.blog-post;h2andh3will style every heading on the site. Add the class prefix for each selector.
🧹 Nitpick comments (1)
landing-panda/public/styles/mylanding.css (1)
91-99: Fixedwidth: 700pxlimits responsivenessThe hard-coded width defeats the responsive fluid grid on screens narrower than 700 px and wider than your media-query breakpoints. Consider using
max-width: 700pxwith a percentage width or removing the fixed width entirely and relying on padding/margins.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
landing-panda/public/styles/mylanding.css(1 hunks)landing-panda/src/components/BlogCard.tsx(1 hunks)landing-panda/src/pages/blogSnippets.astro(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- landing-panda/src/pages/blogSnippets.astro
- landing-panda/src/components/BlogCard.tsx
| justify-content: center; | ||
| padding-left: 60px; | ||
| align-content: left; |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Invalid value left for align-content – rule is ignored
align-content only accepts values such as flex-start, flex-end, center, space-between, etc. Because left is not valid, the declaration is dropped and the layout may not behave as intended.
- align-content: left;
+ /* Align items to the start of the cross-axis */
+ align-content: flex-start;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| justify-content: center; | |
| padding-left: 60px; | |
| align-content: left; | |
| justify-content: center; | |
| padding-left: 60px; | |
| /* Align items to the start of the cross-axis */ | |
| align-content: flex-start; |
🤖 Prompt for AI Agents
In landing-panda/public/styles/mylanding.css around lines 36 to 38, the CSS
property align-content is set to an invalid value 'left', which is ignored by
browsers. Replace 'left' with a valid value such as 'flex-start' to align
content to the start of the cross axis, ensuring the layout behaves as intended.
| .insider{ | ||
| font-style: var(--font-family); | ||
| font-size: 35px; | ||
| } | ||
|
|
There was a problem hiding this comment.
Mis-used CSS property – should be font-family, not font-style
font-style expects keywords like italic, normal, oblique. Passing a font family token makes the declaration invalid and silently ignored.
-.insider{
- font-style: var(--font-family);
- font-size: 35px;
-}
+.insider{
+ font-family: var(--font-family);
+ font-size: 35px;
+}(The same defect appears again at Lines 218-220 – apply the same fix there.)
🤖 Prompt for AI Agents
In landing-panda/public/styles/mylanding.css at lines 177 to 181, the property
`font-style` is incorrectly used with a font family variable; replace
`font-style: var(--font-family);` with `font-family: var(--font-family);` to
correctly apply the font family. Also, apply this same correction to lines 218
to 220 where the same mistake occurs.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
landing-panda/src/pages/blogs/blog4.md (1)
3-3: Fix cover image path to avoid 404 in production.Use an absolute path under /public like the in-post image.
Apply this diff:
-cover: ../../../images/blog4.webp +cover: /images/blog4.webp
🧹 Nitpick comments (5)
landing-panda/src/pages/blogs/blog4.md (5)
7-7: Alt text + brand consistency.Align brand spelling in alt text with body usage.
- +
15-24: Tighten phrasing; remove repeated “very”; improve clarity.Minor readability/grammar tweaks.
-Her interpretation of brutal honesty was focused on the word “brutal”. This led to a very very spirited discussion on whether one needs to be brutal to be honest. She questioned whether brutal honesty equated to being rude. She was concerned and rightfully so… +Her interpretation of brutal honesty was focused on the word “brutal.” This led to a very spirited discussion on whether one needs to be brutal to be honest. She questioned whether brutal honesty equated to being rude. She was concerned—and rightfully so… ->*Charity chose using questioning to gain clarity as opposed to bowing down to her leader while being disgruntled.* +>*Charity chose to ask questions to gain clarity rather than defer to her leader while feeling disgruntled.* -This is something very very important to me and that’s at the core of the Akong’a DNA. I am human. I am not always right. I will not tolerate a team of “yes” men. I need to trust that my team will question my questionable moves. That my team will keep me accountable. That my team will have my back. +This is extremely important to me and is at the core of the Akong’a DNA. I am human. I am not always right. I will not tolerate a team of “yes” men. I need to trust that my team will question my questionable moves, keep me accountable, and have my back. -This to me, was a very teachable moment on the core of our culture here at Akong’a. Charity had done something very very positive by questioning me: +This, to me, was a very teachable moment on the core of our culture here at Akong’a. Charity had done something very positive by questioning me:
35-41: Compound adjectives and word choices: high‑performance, sugarcoat, teammate; sentence polish.-We think of our company as a high performance sports team. When we’re on the field we need to make critical decisions in split seconds and be able to trust each other’s judgement. +We think of our company as a high-performance sports team. When we’re on the field, we need to make critical decisions in split seconds and be able to trust each other’s judgment. -No time to sugar coat. +No time to sugarcoat. -You say it as it is and your team mate knows the critique is of their work and not of them. Which means that we are all able to pivot quickly and avoid disastrous situations. +You say it as it is, and your teammate knows the critique is of their work and not of them. That means we can pivot quickly and avoid disastrous situations. -While we are in training, it’s a chill environment where we don’t have to be as “brutal”. We spend most of our time in training mode. But when the situation calls for it, we switch quickly, execute. Then get back to rest state. +While we are in training, it’s a chill environment where we don’t have to be as “brutal.” We spend most of our time in training mode, but when the situation calls for it, we switch quickly, execute, then return to a resting state.
48-51: Make bullet list grammar consistent (use gerunds).- Adjusting expectations -- Make realistic adjustments -- Highlight critical issues -- Upholding working systems +- Making realistic adjustments +- Highlighting critical issues +- Maintaining working systems
53-57: Polish phrasing for clarity.-Good communication breeds by comprehension. +Good communication thrives on comprehension. -Comprehension breeds understanding. +Comprehension breeds understanding. -Understanding opens up space for healthy arguing and dialogue that moves us forward. I believe in curiosity which opens up spaces for dialogues. +Understanding opens up space for healthy debate and dialogue that moves us forward. I believe in curiosity, which opens up space for dialogue.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
landing-panda/public/styles/mylanding.css(1 hunks)landing-panda/src/pages/blogLayout.astro(1 hunks)landing-panda/src/pages/blogs/blog4.md(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- landing-panda/public/styles/mylanding.css
- landing-panda/src/pages/blogLayout.astro
🧰 Additional context used
🪛 LanguageTool
landing-panda/src/pages/blogs/blog4.md
[style] ~24-~24: As an alternative to the over-used intensifier ‘very’, consider replacing this phrase.
Context: ...g disgruntled.* This is something very very important to me and that’s at the core of the Ako...
(EN_WEAK_ADJECTIVE)
[style] ~24-~24: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...DNA. I am human. I am not always right. I will not tolerate a team of “yes” men. ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~24-~24: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... will not tolerate a team of “yes” men. I need to trust that my team will questio...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[uncategorized] ~66-~66: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ... Previous: Solve, Build, Get Paid: Open Source Bounties at Akong’a
(EN_COMPOUND_ADJECTIVE_INTERNAL)
🔇 Additional comments (2)
landing-panda/src/pages/blogs/blog4.md (2)
62-63: Verify newsletter embed domain and CSP allowances.Ensure the script domain is correct and permitted by your Content Security Policy, otherwise the form won’t load in production.
Please verify in a staging build that:
- The script successfully loads (no 404/CORS errors).
- If you enforce a CSP, script-src includes the domain in this tag.
- The embed renders with JS disabled (provide a noscript fallback if needed).
66-66: Prev link fix LGTM.Placeholder “#” link replaced with a valid route. Thanks.
| --- | ||
| layout: ../blogLayout.astro | ||
| cover: ../../../images/blog4.webp | ||
| --- |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Add essential frontmatter metadata (title, author, pubDate, description) for layout/SEO.
Many blog layouts and cards consume these. Keeps metadata out of body and improves previews.
Apply this diff:
---
layout: ../blogLayout.astro
+title: The Power of Honest Communication in Teams
+author: adrianmurage
+pubDate: 2025-06-28
+description: "Why direct, respectful feedback accelerates teams and how we practice it at Akong’a."
-cover: ../../../images/blog4.webp
+cover: /images/blog4.webp
---Verify blogLayout.astro uses these keys (or adjust names to match).
🏁 Script executed:
#!/bin/bash
# Locate and inspect the blog layout component to confirm frontmatter keys
files=$(fd blogLayout.astro)
if [ -z "$files" ]; then
echo "No blogLayout.astro file found"
exit 1
fi
for f in $files; do
echo "===== Inspecting $f ====="
# Print the first 200 lines to see frontmatter destructuring
sed -n '1,200p' "$f"
doneLength of output: 1488
Ensure frontmatter is consumed by your layout and update metadata
The blog4.md frontmatter should include title, author, pubDate, description, and a normalized cover path—however, blogLayout.astro currently only imports assets and does not reference any frontmatter fields. You’ll need to:
- In
landing-panda/src/pages/blogs/blog4.md, apply the diff below. - In
landing-panda/src/pages/blogLayout.astro, add frontmatter props (e.g.export interface Props { title: string; author: string; pubDate: string; description: string; cover: string; }) and insert them into your<head>(set<title>,<meta name="description">, etc.) and rendercoverwhere appropriate.
Diff for blog4.md:
@@ landing-panda/src/pages/blogs/blog4.md
---
layout: ../blogLayout.astro
+title: The Power of Honest Communication in Teams
+author: adrianmurage
+pubDate: 2025-06-28
+description: "Why direct, respectful feedback accelerates teams and how we practice it at Akong’a."
-cover: ../../../images/blog4.webp
+cover: /images/blog4.webp
---Once you’ve updated the layout to destructure and render these props, the new metadata will populate your page’s <head> and previews as intended.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| --- | |
| layout: ../blogLayout.astro | |
| cover: ../../../images/blog4.webp | |
| --- | |
| --- | |
| layout: ../blogLayout.astro | |
| title: The Power of Honest Communication in Teams | |
| author: adrianmurage | |
| pubDate: 2025-06-28 | |
| description: "Why direct, respectful feedback accelerates teams and how we practice it at Akong’a." | |
| cover: /images/blog4.webp | |
| --- |
🤖 Prompt for AI Agents
In landing-panda/src/pages/blogs/blog4.md lines 1 to 4, the frontmatter lacks
essential metadata fields like title, author, pubDate, and description, and the
cover path needs normalization. Add these fields to the frontmatter with
appropriate values and ensure the cover path is relative and correct. Then, in
landing-panda/src/pages/blogLayout.astro, define a Props interface including
these fields, destructure them from frontmatter, and use them to set the page's
<title>, <meta name="description">, and render the cover image properly in the
layout.
There was a problem hiding this comment.
Actionable comments posted: 11
♻️ Duplicate comments (5)
landing-panda/public/styles/mylanding.css (5)
38-38: Invalid CSS value:align-content: leftis ignoredUse a valid value (or use
align-itemsif the intent is to align items on the cross-axis).- align-content: left; + /* align items to the start of the cross-axis */ + align-content: flex-start; + /* or, if you meant flex items themselves: */ + /* align-items: flex-start; */
145-148: Selector does nothing –titleis not an HTML elementTarget the
.titleclass (and center via text-align rather than flex alignment on non-flex parents).-.blog-post title{ - align-content: center; - align-self: center; -} +.blog-post .title{ + text-align: center; +}
150-156: Unscoped h2 & h3 – currently apply globallyScope each heading explicitly to
.blog-post.-.blog-post h1,h2,h3 { +.blog-post h1, +.blog-post h2, +.blog-post h3 {
182-185: Misused property – should befont-family, notfont-styleThis declaration is ignored by browsers; use
font-family.-.insider{ - font-style: var(--font-family); - font-size: 35px; -} +.insider{ + font-family: var(--font-family); + font-size: 35px; +}
216-222: Repeat of misused property inside media querySame fix as above: use
font-familyinstead offont-style.- .insider{ - /*border: 1px solid purple;*/ - font-style: var(--font-family); - font-size: 40px; - line-height: 1.2; - margin: 0; - padding: 0; - } + .insider{ + /*border: 1px solid purple;*/ + font-family: var(--font-family); + font-size: 40px; + line-height: 1.2; + margin: 0; + padding: 0; + }
🧹 Nitpick comments (4)
landing-panda/public/styles/mylanding.css (4)
87-93: Global “all anchors white” may conflict with page themingYou later use
.blog-post a { color: inherit; }. Consider scoping the global white rule to a site/container wrapper (e.g.,.container aor.blog-body a) to avoid accidental overrides in future pages/components.
16-18: Globaloverflow-x: hiddencan mask layout bugsThis hides horizontal overflow instead of fixing it. With the width fixes proposed, you should be able to remove this.
-body { - font-family: var(--font-family); - overflow-x: hidden; -} +body { + font-family: var(--font-family); + /* overflow-x: hidden; Avoid masking layout issues */ +}
43-52: Debug borders left in stylesheetThese borders appear to be dev-only. Consider removing or guarding under a debug class.
- border: 1px solid deeppink; + /* border: 1px solid deeppink; */Also applies to: 189-191, 199-207, 379-384
150-156: Heading hierarchy looks inverted (h2 larger than h1 on small screens)On small phones,
.blog-body h1is 45px while.blog-body h2is 65px. Verify intended hierarchy for readability and SEO.Also applies to: 387-399
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
landing-panda/public/styles/mylanding.css(1 hunks)landing-panda/src/pages/blogSnippets.astro(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- landing-panda/src/pages/blogSnippets.astro
🔇 Additional comments (1)
landing-panda/public/styles/mylanding.css (1)
1-9: Overall theme and structure look solidGood use of CSS variables, consistent dark theme, and scoped blog styles. Once the issues above are addressed, this sheet will be in good shape for the new landing and blog pages.
Also applies to: 11-18, 20-31, 33-41, 54-63, 64-73, 74-85, 86-94, 95-105, 106-122, 123-138, 157-170, 171-181, 187-224, 225-267, 268-294, 295-322, 323-350, 351-378, 379-385, 386-408, 410-424
| /* Blogs snippets page */ | ||
| .blogs_container{ | ||
| /*border: 1px solid red;*/ | ||
| display: flex; | ||
| flex-direction: column; | ||
| margin: auto; | ||
| width: 700px; | ||
| gap: 60px; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Fixed width harms responsiveness – prefer fluid width with a max
Use a fluid container with max-width to avoid overflow on small screens.
.blogs_container{
/*border: 1px solid red;*/
display: flex;
flex-direction: column;
margin: auto;
- width: 700px;
+ width: 100%;
+ max-width: 700px;
gap: 60px;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /* Blogs snippets page */ | |
| .blogs_container{ | |
| /*border: 1px solid red;*/ | |
| display: flex; | |
| flex-direction: column; | |
| margin: auto; | |
| width: 700px; | |
| gap: 60px; | |
| } | |
| /* Blogs snippets page */ | |
| .blogs_container{ | |
| /*border: 1px solid red;*/ | |
| display: flex; | |
| flex-direction: column; | |
| margin: auto; | |
| width: 100%; | |
| max-width: 700px; | |
| gap: 60px; | |
| } |
🤖 Prompt for AI Agents
In landing-panda/public/styles/mylanding.css around lines 96 to 104, the
.blogs_container uses a fixed width: 700px which breaks responsiveness; change
it to a fluid layout using width: 100% with a max-width: 700px (and keep margin:
auto) so the container scales down on small screens while capping its maximum
width on large screens.
| width: 710px; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Blog body width should be fluid with a max
Prevents clipping and reliance on overflow-x: hidden.
- width: 710px;
+ width: 100%;
+ max-width: 710px;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| width: 710px; | |
| } | |
| width: 100%; | |
| max-width: 710px; | |
| } |
🤖 Prompt for AI Agents
In landing-panda/public/styles/mylanding.css around lines 137 to 138, the blog
body uses a fixed width (width: 710px) which can cause clipping and relies on
overflow-x: hidden; change this to a fluid layout by replacing the fixed width
with width: 100% and adding max-width: 710px so the content scales on small
viewports while capping at 710px on large screens; ensure any unnecessary
overflow-x: hidden is removed or reevaluated if present.
| .blog-post img { | ||
| max-width: 700px; /* or whatever width you prefer */ | ||
| height: auto; | ||
| display: block; | ||
| /* margin-top: 1px; */ | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Images should scale with container
Use responsive image sizing to avoid overflow.
-.blog-post img {
- max-width: 700px; /* or whatever width you prefer */
- height: auto;
- display: block;
- /* margin-top: 1px; */
-}
+.blog-post img {
+ display: block;
+ max-width: 100%;
+ width: 100%;
+ height: auto;
+}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .blog-post img { | |
| max-width: 700px; /* or whatever width you prefer */ | |
| height: auto; | |
| display: block; | |
| /* margin-top: 1px; */ | |
| } | |
| .blog-post img { | |
| display: block; | |
| max-width: 100%; | |
| width: 100%; | |
| height: auto; | |
| } |
🤖 Prompt for AI Agents
In landing-panda/public/styles/mylanding.css around lines 139 to 144, the
.blog-post img rule uses a fixed max-width which can still overflow on smaller
containers; change it to be responsive by setting width: 100% and max-width:
700px with height: auto (keep display: block) so images scale down with their
container while capping their maximum size.
| @media (max-width: 479px) { | ||
| .blogs_container{ | ||
| border: 1px solid green; | ||
| padding: 2px 30px; | ||
| text-align: left; | ||
| /*font-size: 120%;*/ | ||
| width: 430px; | ||
| line-height: 1.6; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Overflow risk on small phones (fixed 430px width)
Make it fluid; padding is fine.
- .blogs_container{
- border: 1px solid green;
- padding: 2px 30px;
- text-align: left;
- /*font-size: 120%;*/
- width: 430px;
- line-height: 1.6;
- }
+ .blogs_container{
+ /* border: 1px solid green; (debug) */
+ padding: 2px 30px;
+ text-align: left;
+ /* font-size: 120%; */
+ width: 100%;
+ max-width: 700px;
+ line-height: 1.6;
+ }🤖 Prompt for AI Agents
In landing-panda/public/styles/mylanding.css around lines 189 to 197 the
.blogs_container rule for max-width:479px uses a fixed width: 430px which can
overflow on smaller phones; remove the fixed width and make it fluid by
replacing width: 430px with width: 100% (or max-width: 430px if you want an
upper cap) and add box-sizing: border-box so the existing padding is included in
the element width; keep the padding and text-align as-is.
| a{ | ||
| text-decoration:none ; | ||
| } |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Avoid removing link underlines globally in breakpoints
Removing underlines degrades accessibility and discoverability. If you must, ensure alternative cues (color contrast, focus styles) are present. Safer: keep underlines or scope the change narrowly.
- a{
- text-decoration:none ;
- }
+ /* Consider preserving underlines for accessibility */
+ /* a { text-decoration: underline; } */Please verify across these breakpoints that links remain clearly identifiable by sight and focus outline.
Also applies to: 247-249, 291-292, 317-319, 345-347, 373-375
To verify that alternative link cues (hover, focus, color) are defined elsewhere and aren’t being globally stripped, let’s search the stylesheet for all link-related rules:
🏁 Script executed:
#!/bin/bash
# List all `a { … }` rules
rg -n "a\s*\{" landing-panda/public/styles
# Find every use of text-decoration
rg -n "text-decoration" landing-panda/public/styles
# Check for focus styles on links
rg -n ":focus" landing-panda/public/styles
# Check for hover styles on links
rg -n ":hover" landing-panda/public/stylesLength of output: 2290
To confirm that your non-underlined links still have sufficient visual cues, let’s inspect the hover and focus rules:
🏁 Script executed:
#!/bin/bash
# Show the `a:hover` rules for context
rg -n -A5 "a:hover" landing-panda/public/styles/mylanding.css
# Show the `a:focus` rules for context
rg -n -A5 "a:focus" landing-panda/public/styles/mylanding.cssLength of output: 263
Ensure link accessibility by scoping or augmenting underline removal
Across multiple breakpoints you’re stripping link underlines (text-decoration: none;) but only changing hover/focus color to white—no additional visual cues are provided. This impairs discoverability and keyboard focus visibility. Either preserve underlines or add compensating styles (e.g. clear focus outlines, border-bottom, or distinct hover backgrounds).
Affected locations in landing-panda/public/styles/mylanding.css:
- Lines 212–214, 247–249, 290–292, 317–319, 345–347, 373–375
Suggested diff example for each block:
- a {
- text-decoration: none;
- }
+ /* Keep underline or add visual cue for focus/hover */
+ a {
+ /* text-decoration: none; */
+ text-decoration: underline;
+ }
+
+ /* Or, if you must remove underlines: */
+ a:focus {
+ outline: 2px dotted #fff;
+ outline-offset: 2px;
+ }
+ a:hover {
+ background-color: rgba(255,255,255,0.1);
+ }Please update each breakpoint block accordingly so links remain clearly identifiable by sight and keyboard navigation.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| a{ | |
| text-decoration:none ; | |
| } | |
| /* Keep underline or add visual cue for focus/hover */ | |
| a { | |
| /* text-decoration: none; */ | |
| text-decoration: underline; | |
| } | |
| /* Or, if you must remove underlines: */ | |
| a:focus { | |
| outline: 2px dotted #fff; | |
| outline-offset: 2px; | |
| } | |
| a:hover { | |
| background-color: rgba(255,255,255,0.1); | |
| } |
| .insider{ | ||
| font-style: var(--font-family); | ||
| font-size: 35px; | ||
| line-height: 1.2; | ||
| margin: 0; | ||
| padding: 0; | ||
| } |
There was a problem hiding this comment.
Third occurrence – font-style still used instead of font-family
This one wasn’t covered by earlier comments; fix it as well.
- .insider{
- font-style: var(--font-family);
- font-size: 35px;
- line-height: 1.2;
- margin: 0;
- padding: 0;
- }
+ .insider{
+ font-family: var(--font-family);
+ font-size: 35px;
+ line-height: 1.2;
+ margin: 0;
+ padding: 0;
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .insider{ | |
| font-style: var(--font-family); | |
| font-size: 35px; | |
| line-height: 1.2; | |
| margin: 0; | |
| padding: 0; | |
| } | |
| .insider{ | |
| font-family: var(--font-family); | |
| font-size: 35px; | |
| line-height: 1.2; | |
| margin: 0; | |
| padding: 0; | |
| } |
🤖 Prompt for AI Agents
In landing-panda/public/styles/mylanding.css around lines 259 to 265, the
.insider rule mistakenly uses the font-style property with var(--font-family);
replace font-style with font-family so the rule reads font-family:
var(--font-family); and remove the incorrect font-style line to ensure the
custom property is applied correctly.
| @media (min-width: 770px) and (max-width: 1024px) { | ||
| .blogs_container{ | ||
| /*border: 1px solid deeppink;*/ | ||
| padding: 2px 70px; | ||
| text-align: left; | ||
| font-size: 100%; | ||
| width: 750px; | ||
| line-height: 1; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Fixed 750px width – make fluid
Same rationale as above.
- .blogs_container{
- /*border: 1px solid deeppink;*/
- padding: 2px 70px;
- text-align: left;
- font-size: 100%;
- width: 750px;
- line-height: 1;
- }
+ .blogs_container{
+ /*border: 1px solid deeppink;*/
+ padding: 2px 70px;
+ text-align: left;
+ font-size: 100%;
+ width: 100%;
+ max-width: 750px;
+ line-height: 1;
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @media (min-width: 770px) and (max-width: 1024px) { | |
| .blogs_container{ | |
| /*border: 1px solid deeppink;*/ | |
| padding: 2px 70px; | |
| text-align: left; | |
| font-size: 100%; | |
| width: 750px; | |
| line-height: 1; | |
| } | |
| @media (min-width: 770px) and (max-width: 1024px) { | |
| .blogs_container{ | |
| /*border: 1px solid deeppink;*/ | |
| padding: 2px 70px; | |
| text-align: left; | |
| font-size: 100%; | |
| width: 100%; | |
| max-width: 750px; | |
| line-height: 1; | |
| } | |
| } |
🤖 Prompt for AI Agents
In landing-panda/public/styles/mylanding.css around lines 269 to 277, the
.blogs_container rule uses a fixed width: 750px which prevents fluid layouts;
replace the fixed width with a responsive rule such as width: 100% and
max-width: 750px (or remove width and use max-width only), keep the padding and
text alignment, and ensure box-sizing/layout behaves as expected so the
container becomes fluid across viewport sizes within this media query.
| @media (min-width: 1025px) and (max-width: 1439px) { | ||
| .blogs_container{ | ||
| /*border: 1px solid deeppink;*/ | ||
| padding: 2px 70px; | ||
| text-align: left; | ||
| font-size: 100%; | ||
| width: 750px; | ||
| line-height: 1; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Fixed 750px width – make fluid
Avoid fixed widths for better responsiveness.
- .blogs_container{
- /*border: 1px solid deeppink;*/
- padding: 2px 70px;
- text-align: left;
- font-size: 100%;
- width: 750px;
- line-height: 1;
- }
+ .blogs_container{
+ /*border: 1px solid deeppink;*/
+ padding: 2px 70px;
+ text-align: left;
+ font-size: 100%;
+ width: 100%;
+ max-width: 750px;
+ line-height: 1;
+ }🤖 Prompt for AI Agents
In landing-panda/public/styles/mylanding.css around lines 296 to 304, the
.blogs_container uses a fixed width: 750px which breaks responsiveness; change
to a fluid layout by replacing width: 750px with width: 100% and max-width:
750px, and ensure box-sizing: border-box so the 2px 70px padding is included in
the container size; this keeps the container fluid on smaller screens while
capping its maximum width on larger viewports.
| @media (min-width: 1440px) and (max-width: 1920px) { | ||
| .blogs_container{ | ||
| /*border: 1px solid deeppink;*/ | ||
| padding: 2px 70px; | ||
| text-align: left; | ||
| font-size: 100%; | ||
| width: 750px; | ||
| line-height: 1; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Fixed 750px width – make fluid
Same change for desktop breakpoint.
- .blogs_container{
- /*border: 1px solid deeppink;*/
- padding: 2px 70px;
- text-align: left;
- font-size: 100%;
- width: 750px;
- line-height: 1;
- }
+ .blogs_container{
+ /*border: 1px solid deeppink;*/
+ padding: 2px 70px;
+ text-align: left;
+ font-size: 100%;
+ width: 100%;
+ max-width: 750px;
+ line-height: 1;
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @media (min-width: 1440px) and (max-width: 1920px) { | |
| .blogs_container{ | |
| /*border: 1px solid deeppink;*/ | |
| padding: 2px 70px; | |
| text-align: left; | |
| font-size: 100%; | |
| width: 750px; | |
| line-height: 1; | |
| } | |
| @media (min-width: 1440px) and (max-width: 1920px) { | |
| .blogs_container{ | |
| /*border: 1px solid deeppink;*/ | |
| padding: 2px 70px; | |
| text-align: left; | |
| font-size: 100%; | |
| width: 100%; | |
| max-width: 750px; | |
| line-height: 1; | |
| } | |
| } |
🤖 Prompt for AI Agents
In landing-panda/public/styles/mylanding.css around lines 324 to 332, the
.blogs_container uses a fixed width: 750px which prevents fluid resizing on
large desktop screens; change it to be responsive by removing the fixed width
and using a fluid rule such as width: 100% with a max-width (e.g., max-width:
750px) or an appropriate percentage so the container scales with viewport, and
keep padding/text-align/line-height as-is.
| @media (min-width: 1921px) { | ||
| .blogs_container{ | ||
| /*border: 1px solid deeppink;*/ | ||
| padding: 2px 70px; | ||
| text-align: left; | ||
| font-size: 100%; | ||
| width: 750px; | ||
| line-height: 1; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Fixed 750px width – make fluid
Same change for very large screens.
- .blogs_container{
- /*border: 1px solid deeppink;*/
- padding: 2px 70px;
- text-align: left;
- font-size: 100%;
- width: 750px;
- line-height: 1;
- }
+ .blogs_container{
+ /*border: 1px solid deeppink;*/
+ padding: 2px 70px;
+ text-align: left;
+ font-size: 100%;
+ width: 100%;
+ max-width: 750px;
+ line-height: 1;
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @media (min-width: 1921px) { | |
| .blogs_container{ | |
| /*border: 1px solid deeppink;*/ | |
| padding: 2px 70px; | |
| text-align: left; | |
| font-size: 100%; | |
| width: 750px; | |
| line-height: 1; | |
| } | |
| @media (min-width: 1921px) { | |
| .blogs_container{ | |
| /*border: 1px solid deeppink;*/ | |
| padding: 2px 70px; | |
| text-align: left; | |
| font-size: 100%; | |
| width: 100%; | |
| max-width: 750px; | |
| line-height: 1; | |
| } | |
| } |
🤖 Prompt for AI Agents
In landing-panda/public/styles/mylanding.css around lines 352 to 360, the
.blogs_container rule sets a fixed width: 750px which prevents a fluid layout on
very large screens; replace the fixed width with a fluid pattern such as width:
100% plus max-width: 750px (or remove the fixed width and add a sensible
max-width) so the container scales with viewport while capping its maximum size,
and keep existing padding, text-align and line-height unchanged.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
landing-panda/src/pages/newLanding.astro (1)
3-4: Remove unused baseUrl variable.The
baseUrlvariable is declared but never used in the component, creating unnecessary code.Apply this diff to remove the unused variable:
--- import "../../public/styles/landing_page.css"; -const isDev = import.meta.env.DEV; -const baseUrl = isDev ? "http://localhost:3001" : ""; ---
🧹 Nitpick comments (1)
landing-panda/public/styles/landing_page.css (1)
37-51: Consider simplifying padding declaration.The container and content classes implement a good flex-based layout structure. However, there's redundant padding specification.
.container { display: flex; flex-direction: column; height: auto; - padding: 0 0px; + padding: 0; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
landing-panda/public/styles/landing_page.css(1 hunks)landing-panda/src/pages/newLanding.astro(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
landing-panda/src/pages/**/*.astro
📄 CodeRabbit Inference Engine (.cursorrules)
Create landing pages as Astro files under landing-panda/src/pages/
Files:
landing-panda/src/pages/newLanding.astro
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
PR: AkongaLabs/akongalabs-beta#0
File: .cursorrules:0-0
Timestamp: 2025-08-15T14:47:01.737Z
Learning: Applies to landing-panda/src/pages/**/*.astro : Create landing pages as Astro files under landing-panda/src/pages/
📚 Learning: 2025-08-15T14:47:01.737Z
Learnt from: CR
PR: AkongaLabs/akongalabs-beta#0
File: .cursorrules:0-0
Timestamp: 2025-08-15T14:47:01.737Z
Learning: Applies to landing-panda/src/pages/**/*.astro : Create landing pages as Astro files under landing-panda/src/pages/
Applied to files:
landing-panda/src/pages/newLanding.astro
🔇 Additional comments (11)
landing-panda/public/styles/landing_page.css (5)
1-9: Well-structured CSS foundation with clear design system.The font imports, CSS custom properties, and color scheme establish a good foundation for a consistent dark-themed design. The variable naming is descriptive and follows conventions.
11-35: Solid CSS reset and typography foundation.The box-sizing reset and base styles for html, body, and links are properly implemented. The link color inheritance ensures consistent theming across all states.
53-95: Well-structured navigation and content sections.The typography hierarchy and spacing for the first_links, title, about, and last_links sections is well thought out. The use of different font families (Bricolage Grotesque for headings, Inter for body text) creates good visual hierarchy.
97-119: Effective hero image implementation with overlay text.The image container and overlay text positioning create an engaging hero section. The full viewport coverage and object-fit properties ensure proper image display across different screen sizes.
121-224: Comprehensive responsive design with smooth scaling.The media queries provide excellent responsive behavior across multiple breakpoints (480px, 780px, 1440px, 1920px). The typography scales appropriately, and the layout transition to two-column at 780px is well-implemented. The font sizes and spacing adjustments maintain visual hierarchy at all screen sizes.
landing-panda/src/pages/newLanding.astro (6)
7-17: Well-structured HTML document head.The meta tags are properly configured for a modern web application, including proper charset, favicon, responsive viewport settings, and Astro generator meta tag.
19-24: Navigation links properly implemented.The navigation structure uses semantic class names and provides clear paths to the main landing page and blog sections. The links are properly structured for the site's navigation flow.
25-35: Engaging content with good typography hierarchy.The about section effectively communicates the company's mission with good use of semantic HTML (h2 for title) and visual emphasis through strikethrough and bold text. The messaging clearly differentiates the "stayup" concept from traditional startups.
37-41: External links properly configured.The social media links use proper external URLs and are well-structured within the navigation footer.
42-50: Hero image implementation with effective branding.The image container with overlay text creates a strong visual impact. The image path follows proper public asset conventions, and the alt text provides appropriate accessibility support.
1-52: Header image present — file verifiedFound: landing-panda/public/images/header-background.webp (WebP, 289,728 bytes ≈ 283 KB). The page landing-panda/src/pages/newLanding.astro (lines 1–52) references /images/header-background.webp.
Optional: consider further compression, responsive srcset, or lazy-loading for better performance.
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (5)
landing-panda/src/data/types.ts (2)
4-15: DRY the repeated{ rendered: string }shape and clarify intent.
title,guid,content, andexcerptall share the same nested shape. Extracting a named type improves readability and reusability.Apply this diff within the interface:
- title: { - rendered: string; - }; - guid: { - rendered: string; - }; - content: { - rendered: string; - }; - excerpt: { - rendered: string; - }; + title: RenderedHTML; + guid: RenderedHTML; + content: RenderedHTML; + excerpt: RenderedHTML;And add this type alias above the interface:
type RenderedHTML = { rendered: string };
10-15: Verify sanitization of content.rendered / excerpt.rendered before rendering (potential XSS)Quick findings from repo scan:
- landing-panda/src/data/types.ts — defines content.rendered and excerpt.rendered as strings (likely HTML from a WP-style API).
content: { rendered: string; }; excerpt: { rendered: string; };- I found NO occurrences of common raw-HTML sinks in source files (set:html, dangerouslySetInnerHTML, {@html}, v-html, unsafeHTML, innerHTML).
- I found NO sanitizer libraries in source files (dompurify, isomorphic-dompurify, sanitize-html, rehype-sanitize). Only references appear in lockfiles.
- server-panda/src/middleware/security.ts contains a Content Security Policy (useful but not a replacement for sanitizing input).
Recommendation (verify & act):
- If any component injects content.rendered or excerpt.rendered as HTML, sanitize it first (e.g., DOMPurify or rehype-sanitize) or avoid injecting raw HTML.
- If you want, I can add a small DOMPurify wrapper for both Astro and React to standardize sanitization.
landing-panda/src/styles/mylanding.css (3)
41-48: Use dynamic viewport units to avoid mobile 100vh issues.
height: 100vhcan cause content to be clipped behind mobile browser UI. Prefer100svh(ordvh) for more predictable behavior on mobile.Apply this diff:
.content { - height: 100vh; + min-height: 100svh; display: flex; flex-direction: column; justify-content: space-between; align-items: start; padding: 24px 24px 16px 24px; } .image_container { position: relative; width: 100vw; - height: 100vh; + min-height: 100svh; overflow: hidden; }Also applies to: 94-99
126-136: Remove debug borders and avoid!important.Borders on production layout (.blogs_container, .blog-title, .asnip, .para_space) and a forced
line-height: 1.5 !importantlook like debugging artifacts and may degrade UX.Apply this diff:
.blogs_container{ - border: 1px solid red; display: flex; flex-direction: column; margin: auto; - width: 700px; + width: min(700px, 100%); gap: 10px; /*line-height: 1.5;*/ } .blog-title{ - border: 1px solid yellow; } .asnip{ - border: 1px solid green; display: flex; flex-direction: column; } .para_space{ - border: 1px solid peru; - line-height: 1.5 !important; + line-height: 1.5; }And for the small-phone media query:
@media (max-width: 479px) { .blogs_container{ - border: 1px solid green; padding: 2px 30px; text-align: left; /*font-size: 120%;*/ - width: 430px; + width: 100%; line-height: 1.6; }Also applies to: 149-161, 337-345
1-9: “Inter” is used but not imported; unify font usage.
.aboutreferences"Inter", sans-serifbut only Bricolage Grotesque is imported. Either import Inter or use the same CSS variable for consistency.Two options:
- Import Inter:
@import url('https://fonts.googleapis.com/css2?family=Bricolage+Grotesque&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap');
- Or standardize on
var(--font-family)in.about:.about { flex: 1; display: flex; line-height: 1.25rem; flex-direction: column; justify-content: center; - font-family: "Inter", sans-serif; + font-family: var(--font-family); }Also applies to: 75-76
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
landing-panda/src/data/types.ts(1 hunks)landing-panda/src/pages/newLanding.astro(1 hunks)landing-panda/src/styles/mylanding.css(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- landing-panda/src/pages/newLanding.astro
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (.cursorrules)
Use TypeScript across the codebase
Files:
landing-panda/src/data/types.ts
| @import url('https://fonts.googleapis.com/css2?family=Bricolage+Grotesque&display=swap'); | ||
|
|
||
| :root { | ||
| --bg-color: #1a1f2e; | ||
| --text-color: #e2e8f0; | ||
| --font-family:'Bricolage Grotesque', sans-serif; | ||
| --blue-color:#7091ff; | ||
| --lblue-color:#538cd3; | ||
| } |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Avoid duplicating styles between src/styles and public/styles.
The PR adds a parallel stylesheet under public/styles/mylanding.css. Duplication invites drift and maintenance bugs.
Consider centralizing the stylesheet in src/styles and removing the public copy. If both are needed, ensure a single source of truth with a build step copying assets to public.
To locate duplicates and their references:
🏁 Script executed:
#!/bin/bash
fd -a 'mylanding.css' -S
rg -n --fixed-strings 'mylanding.css'Length of output: 606
Centralize mylanding.css — duplicates found; update imports or remove the public copy
rg shows both copies are referenced, which will cause drift and maintenance bugs.
Files to fix:
- Imports referencing public/styles/mylanding.css
- landing-panda/src/components/BlogCard.tsx:1
- landing-panda/src/pages/blogSnippets.astro:2
- landing-panda/src/pages/blogLayout.astro:2
- Imports referencing src/styles/mylanding.css
- landing-panda/src/pages/newLanding.astro:3 (line 2 contains a commented import for the public copy)
Recommended actions (pick one):
- Preferred: Use src/styles/mylanding.css as the single source of truth — delete public/styles/mylanding.css and update the three files above to import "../../src/styles/mylanding.css".
- Or: If you must serve a static file from public, keep only public/styles/mylanding.css and add a build step that copies the canonical src file into public, then make all imports consistently point to public.
Quick verification command:
- rg -n --hidden --glob '!node_modules' 'mylanding.css'
🤖 Prompt for AI Agents
In landing-panda/src/styles/mylanding.css (lines 1-9): there are duplicate
copies of mylanding.css causing drift; pick a canonical source and make imports
consistent. Preferred: delete public/styles/mylanding.css, update imports in
landing-panda/src/components/BlogCard.tsx,
landing-panda/src/pages/blogSnippets.astro, and
landing-panda/src/pages/blogLayout.astro to point to the src file (e.g. correct
relative path like ../../src/styles/mylanding.css), and remove the commented
public import in landing-panda/src/pages/newLanding.astro; Alternative: if
public must be served, keep only public/styles/mylanding.css, add a build step
to copy src/styles/mylanding.css -> public/styles/mylanding.css, and change all
imports to point to public/styles/mylanding.css so a single file is referenced
by every consumer.
| .blog-body { | ||
| /*border: 1px solid pink;*/ | ||
| display: flex; | ||
| flex-direction: column; | ||
| margin: 10px auto; | ||
| font-size: 120%; | ||
| /* align-items: center; */ | ||
| justify-content: center; | ||
| background-color:var(--bg-color); | ||
| font-family: var(--font-family); | ||
| line-height: 1.6; | ||
| padding: 9px; | ||
| color:var(--text-color); | ||
| width: 710px; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Make blog layout responsive: avoid fixed widths.
Fixed pixel widths will overflow on small screens (e.g., width: 710px and image max-width: 700px). Prefer fluid widths that cap at a max width.
Apply this diff:
.blog-body {
- margin: 10px auto;
- font-size: 120%;
+ margin: 10px auto;
+ font-size: 120%;
/* align-items: center; */
justify-content: center;
background-color:var(--bg-color);
font-family: var(--font-family);
line-height: 1.6;
padding: 9px;
color:var(--text-color);
- width: 710px;
+ width: min(710px, 100%);
}
.blog-post img {
- max-width: 700px; /* or whatever width you prefer */
+ max-width: 100%;
height: auto;
display: block;
/* margin-top: 1px; */
}Also applies to: 179-184
🤖 Prompt for AI Agents
In landing-panda/src/styles/mylanding.css around lines 164-178 (also apply same
change to 179-184), the .blog-body uses a fixed width (width: 710px) which
causes overflow on small screens; change this to use a fluid layout by replacing
the fixed width with width: 100% and constrain it using max-width: 710px (keep
margin: 10px auto to center), ensure box-sizing is set so padding is included in
the width, and add responsive image rules (e.g., img inside .blog-body should
have max-width: 100% and height: auto) so images scale on small viewports.
| .blog-post title{ | ||
| align-content: center; | ||
| align-self: center; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Likely typo: .blog-post title should be .blog-post .title.
title is not a valid descendant element you'd expect here (and the HTML <title> tag is not rendered in body). This selector currently does nothing.
Apply this diff:
-.blog-post title{
+.blog-post .title{📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .blog-post title{ | |
| align-content: center; | |
| align-self: center; | |
| } | |
| .blog-post .title{ | |
| align-content: center; | |
| align-self: center; | |
| } |
🤖 Prompt for AI Agents
In landing-panda/src/styles/mylanding.css around lines 185 to 188 the selector
`.blog-post title` is a typo and matches nothing; change it to the descendant
class selector `.blog-post .title` so the rules apply to elements with class
"title" inside `.blog-post`. Update the selector and keep the existing
properties (or if centering text is intended, consider using `text-align:
center` on `.blog-post .title`) to ensure the styles take effect.
| .blog-post h1,h2,h3 { | ||
| margin-top: 1.5rem; | ||
| margin-bottom: 0.75rem; | ||
| font-size: 40px; | ||
| font-weight: 200; | ||
| /* margin-left: 3rem; */ | ||
| } |
There was a problem hiding this comment.
Selector scoping bug: this styles all h2/h3 globally.
.blog-post h1,h2,h3 only scopes h1 to .blog-post; h2 and h3 are global. This will unintentionally restyle headings site-wide.
Apply this diff:
-.blog-post h1,h2,h3 {
+.blog-post h1,
+.blog-post h2,
+.blog-post h3 {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .blog-post h1,h2,h3 { | |
| margin-top: 1.5rem; | |
| margin-bottom: 0.75rem; | |
| font-size: 40px; | |
| font-weight: 200; | |
| /* margin-left: 3rem; */ | |
| } | |
| .blog-post h1, | |
| .blog-post h2, | |
| .blog-post h3 { | |
| margin-top: 1.5rem; | |
| margin-bottom: 0.75rem; | |
| font-size: 40px; | |
| font-weight: 200; | |
| /* margin-left: 3rem; */ | |
| } |
🤖 Prompt for AI Agents
In landing-panda/src/styles/mylanding.css around lines 190 to 196, the selector
".blog-post h1,h2,h3" only scopes h1 to .blog-post and leaves h2 and h3 global;
update the selector so each heading is properly scoped (for example replace with
".blog-post h1, .blog-post h2, .blog-post h3") so the styles apply only to
headings inside .blog-post while leaving global h2/h3 untouched.
| font-style: var(--font-family); | ||
| font-size: 35px; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Invalid property: font-style used with a font family.
font-style accepts values like normal|italic|oblique. Here you likely intended font-family. The current rule is ignored by the browser, so the intended font isn’t applied.
Apply this diff in all three places:
-.insider{
- font-style: var(--font-family);
+.insider{
+ font-family: var(--font-family);Also applies to: 362-369, 406-412
🤖 Prompt for AI Agents
In landing-panda/src/styles/mylanding.css around lines 223-225 (and also at
362-369 and 406-412), the rule mistakenly uses "font-style: var(--font-family);"
which is invalid for font-family values; replace font-style with font-family so
the variable is applied correctly (e.g., change to "font-family:
var(--font-family);") in each of the three locations and ensure no other
font-style values rely on the font-family variable.
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (7)
landing-panda/src/pages/[slug].astro (4)
30-31: Add alt text and lazy-loading to the featured imageImproves a11y and performance (CLS/LCP).
- <img src={post.jetpack_featured_media_url}/> + <img + src={post.jetpack_featured_media_url} + alt={titleText} + loading="lazy" + decoding="async" + />If available, consider using the embedded media alt text:
// Replace the fallback: const featuredAlt = post._embedded?.["wp:featuredmedia"]?.[0]?.alt_text || titleText;…and then use alt={featuredAlt}.
17-20: Add lang attribute and use the sanitized title in <title>Minor SEO/a11y improvement and consistency.
-<html> +<html lang="en"> <head> - <title>{post.title.rendered}</title> + <title>{titleText}</title> </head>
for primary links
24-27: Use semanticImproves accessibility without changing visuals.
- <div class="first_links_snips"> - <a href="/newLanding">Akong'a Labs</a> - <a href="/blogSnippets">Blogs</a> - </div> + <nav class="first_links_snips" aria-label="Primary"> + <a href="/newLanding">Akong'a Labs</a> + <a href="/blogSnippets">Blogs</a> + </nav>
31-34: Provide a fallback for missing author and format the date safelyThe author field might be absent depending on WP configuration.
- <span class="author">{post._embedded?.author?.[0]?.name}</span> + <span class="author">{post._embedded?.author?.[0]?.name ?? "Akong'a Labs"}</span>landing-panda/src/pages/blogSnippets.astro (3)
5-6: Add failure handling for the posts fetchPrevents a hard crash at build/runtime on transient API issues; you can also show an empty state when posts.length === 0.
The diff in the previous comment already shows a minimal res.ok guard. Optionally, wrap in try/catch and log a warning:
-const res = await fetch("https://akongalabs.com/wp-json/wp/v2/posts?per_page=10"); -let posts: BlogPost[] = []; -if (res.ok) { - posts = (await res.json()) as BlogPost[]; -} else { - console.warn("Failed to fetch posts:", res.status, res.statusText); -} +let posts: BlogPost[] = []; +try { + const res = await fetch("https://akongalabs.com/wp-json/wp/v2/posts?per_page=10"); + if (res.ok) posts = (await res.json()) as BlogPost[]; + else console.warn("Failed to fetch posts:", res.status, res.statusText); +} catch (err) { + console.warn("Error fetching posts:", err); +}Then render an empty-state message if posts.length === 0.
18-21: Wrap header links in a semanticMinor a11y improvement.
- <div class="first_links"> - <a href="/newLanding">Akong'a Labs</a> - <a href="/blogSnippets">Blogs</a> - </div> + <nav class="first_links" aria-label="Primary"> + <a href="/newLanding">Akong'a Labs</a> + <a href="/blogSnippets">Blogs</a> + </nav>
47-48: Make the “X” link accessibleThe single-letter link text is ambiguous for screen readers.
- <p><a href="https://x.com/adrianmurage">X</a></p> + <p><a href="https://x.com/adrianmurage" aria-label="Akong'a Labs on X (Twitter)">X</a></p>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
landing-panda/src/data/types.ts(1 hunks)landing-panda/src/pages/[slug].astro(1 hunks)landing-panda/src/pages/blogSnippets.astro(1 hunks)landing-panda/src/styles/mylanding.css(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- landing-panda/src/data/types.ts
- landing-panda/src/styles/mylanding.css
🧰 Additional context used
📓 Path-based instructions (1)
landing-panda/src/pages/**/*.astro
📄 CodeRabbit Inference Engine (.cursorrules)
Create landing pages as Astro files under landing-panda/src/pages/
Files:
landing-panda/src/pages/[slug].astrolanding-panda/src/pages/blogSnippets.astro
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
PR: AkongaLabs/akongalabs-beta#0
File: .cursorrules:0-0
Timestamp: 2025-08-15T14:47:01.737Z
Learning: Applies to landing-panda/src/pages/**/*.astro : Create landing pages as Astro files under landing-panda/src/pages/
📚 Learning: 2025-08-15T14:47:01.737Z
Learnt from: CR
PR: AkongaLabs/akongalabs-beta#0
File: .cursorrules:0-0
Timestamp: 2025-08-15T14:47:01.737Z
Learning: Applies to landing-panda/src/pages/**/*.astro : Create landing pages as Astro files under landing-panda/src/pages/
Applied to files:
landing-panda/src/pages/[slug].astrolanding-panda/src/pages/blogSnippets.astro
🔇 Additional comments (2)
landing-panda/src/pages/[slug].astro (1)
1-1: File placement LGTM and aligns with our pages conventionThis page is correctly placed under landing-panda/src/pages and follows the guideline for Astro pages.
landing-panda/src/pages/blogSnippets.astro (1)
1-1: File placement LGTM and aligns with our pages conventionThis page is correctly placed under landing-panda/src/pages and follows the guideline for Astro landing/blog pages.
| --- | ||
| import type { BlogPost } from "../data/types"; | ||
| import "../../src/styles/mylanding.css"; |
There was a problem hiding this comment.
Sanitize injected HTML and avoid set:html where plain text will do (XSS hardening)
Title, content and other WP-rendered fields can contain HTML. Injecting them directly with set:html is a high-impact XSS risk if upstream sanitization ever regresses or plugins add unsafe markup.
- Use sanitize-html on the post body.
- For titles, prefer plain text rendering instead of set:html.
Apply these diffs:
---
-import type { BlogPost } from "../data/types";
-import "../../src/styles/mylanding.css";
+import type { BlogPost } from "../data/types";
+import sanitizeHtml from "sanitize-html";
+import "../styles/mylanding.css";
export async function getStaticPaths() {-const { post } = Astro.props as { post: BlogPost };
+const { post } = Astro.props as { post: BlogPost };
+// Avoid injecting raw HTML where not necessary; sanitize rich content.
+const titleText = (post.title?.rendered ?? "").replace(/<[^>]*>/g, "");
+const contentHTML = sanitizeHtml(post.content?.rendered ?? "", {
+ allowedTags: sanitizeHtml.defaults.allowedTags.concat([
+ "img",
+ "figure",
+ "figcaption",
+ "h1",
+ "h2",
+ "h3",
+ "span",
+ "iframe",
+ ]),
+ allowedAttributes: {
+ a: ["href", "name", "target", "rel"],
+ img: ["src", "alt", "loading", "decoding", "width", "height", "srcset", "sizes"],
+ iframe: ["src", "width", "height", "allow", "allowfullscreen", "frameborder"],
+ "*": ["class", "id", "style"],
+ },
+ allowedSchemes: ["http", "https", "mailto"],
+});- <h1 set:html={post.title.rendered}></h1>
+ <h1>{titleText}</h1>- <div set:html={post.content.rendered}></div>
+ <div set:html={contentHTML}></div>Also applies to: 14-15, 29-29, 42-42
| export async function getStaticPaths() { | ||
| // _embed query param expands related objects like authors | ||
| const res = await fetch("https://akongalabs.com/wp-json/wp/v2/posts?_embed"); | ||
| const posts: BlogPost[] = await res.json(); | ||
|
|
||
| return posts.map((post) => ({ | ||
| params: { slug: post.slug }, | ||
| props: { post }, | ||
| })); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Handle pagination and failures in getStaticPaths() to avoid silently missing posts or build breaks
WordPress REST defaults to 10 posts per page. As written, older posts won’t get static paths, and any transient network/API error will throw at build time without context.
Apply this diff to fetch all pages and add basic error handling:
export async function getStaticPaths() {
- // _embed query param expands related objects like authors
- const res = await fetch("https://akongalabs.com/wp-json/wp/v2/posts?_embed");
- const posts: BlogPost[] = await res.json();
-
- return posts.map((post) => ({
- params: { slug: post.slug },
- props: { post },
- }));
+ // Fetch all posts (WP caps per_page at 100)
+ const posts: BlogPost[] = [];
+ let page = 1;
+ const perPage = 100;
+ while (true) {
+ const res = await fetch(
+ `https://akongalabs.com/wp-json/wp/v2/posts?_embed&per_page=${perPage}&page=${page}`
+ );
+ if (!res.ok) {
+ throw new Error(`Failed to fetch posts (page ${page}): ${res.status} ${res.statusText}`);
+ }
+ const batch: BlogPost[] = await res.json();
+ posts.push(...batch);
+ if (batch.length < perPage) break;
+ page++;
+ }
+ return posts.map((post) => ({
+ params: { slug: post.slug },
+ props: { post },
+ }));
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export async function getStaticPaths() { | |
| // _embed query param expands related objects like authors | |
| const res = await fetch("https://akongalabs.com/wp-json/wp/v2/posts?_embed"); | |
| const posts: BlogPost[] = await res.json(); | |
| return posts.map((post) => ({ | |
| params: { slug: post.slug }, | |
| props: { post }, | |
| })); | |
| } | |
| export async function getStaticPaths() { | |
| // Fetch all posts (WP caps per_page at 100) | |
| const posts: BlogPost[] = []; | |
| let page = 1; | |
| const perPage = 100; | |
| while (true) { | |
| const res = await fetch( | |
| `https://akongalabs.com/wp-json/wp/v2/posts?_embed&per_page=${perPage}&page=${page}` | |
| ); | |
| if (!res.ok) { | |
| throw new Error(`Failed to fetch posts (page ${page}): ${res.status} ${res.statusText}`); | |
| } | |
| const batch: BlogPost[] = await res.json(); | |
| posts.push(...batch); | |
| if (batch.length < perPage) break; | |
| page++; | |
| } | |
| return posts.map((post) => ({ | |
| params: { slug: post.slug }, | |
| props: { post }, | |
| })); | |
| } |
🤖 Prompt for AI Agents
In landing-panda/src/pages/[slug].astro around lines 4–13, getStaticPaths
currently fetches only the first 10 posts and has no error handling; update it
to paginate through the WP REST API (e.g., loop pages with a per_page param
until an empty page or by reading X-WP-TotalPages header) and accumulate all
posts, and wrap fetches in try/catch to surface contextual errors (log or
rethrow a descriptive error including URL, page number and response status).
Ensure you return an empty paths array or fail early with a clear message if
requests repeatedly fail, and preserve the existing return shape params: { slug:
post.slug }, props: { post }.
| --- | ||
| import "../../src/styles/mylanding.css"; | ||
| import type { BlogPost } from "../data/types"; | ||
|
|
||
| const res = await fetch("https://akongalabs.com/wp-json/wp/v2/posts"); | ||
| const posts: BlogPost[] = await res.json(); | ||
| --- |
There was a problem hiding this comment.
Sanitize HTML, avoid unnecessary set:html, and improve heading semantics
- Excerpt is injected as HTML; sanitize it.
- Date doesn’t need set:html; render as text.
- Prefer H2 for each post card to keep a single H1 per page.
Apply these diffs:
---
-import "../../src/styles/mylanding.css";
+import "../styles/mylanding.css";
import type { BlogPost } from "../data/types";
+import sanitizeHtml from "sanitize-html";
-const res = await fetch("https://akongalabs.com/wp-json/wp/v2/posts");
-const posts: BlogPost[] = await res.json();
+const res = await fetch("https://akongalabs.com/wp-json/wp/v2/posts?per_page=10");
+let posts: BlogPost[] = [];
+if (res.ok) {
+ posts = (await res.json()) as BlogPost[];
+} else {
+ console.warn("Failed to fetch posts:", res.status, res.statusText);
+}
---- <p class="bluecolor" set:html={formattedDate}></p>
- <h1 class="blog-title" set:html={post.title.rendered}></h1>
- <div class="para_space" set:html={cleanedExcerpt}></div>
+ <p class="bluecolor">{formattedDate}</p>
+ <h2 class="blog-title">
+ {post.title.rendered.replace(/<[^>]*>/g, "")}
+ </h2>
+ <div
+ class="para_space"
+ set:html={sanitizeHtml(cleanedExcerpt, {
+ allowedTags: ["p", "em", "strong", "a", "code", "pre", "ul", "ol", "li", "span", "br"],
+ allowedAttributes: { a: ["href", "rel", "target"] },
+ allowedSchemes: ["http", "https", "mailto"],
+ })}
+ ></div>Also applies to: 34-38
🤖 Prompt for AI Agents
In landing-panda/src/pages/blogSnippets.astro lines 1-7 (and also apply same
fixes to lines 34-38), the excerpt is being injected unsanitized with set:html,
the post date is rendered using set:html unnecessarily, and headings use H1 per
post; fix by sanitizing the excerpt HTML before rendering (use a sanitizer
library or a safe-html utility and pass the sanitized HTML to set:html), stop
using set:html for the date and render it as plain text (e.g., interpolate the
formatted date string), and change per-post headings from H1 to H2 to preserve a
single page H1; ensure imports include the sanitizer and update markup
accordingly.
- Fixed the Kit.com form import issue (scripts not loading properly). - Resolved porting issue where visiting the general port(3001) wouldn’t display the react page. - Fixed stylesheet import issue by adjusting CSP rules to allow external styles.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
server-panda/src/middleware/security.ts (1)
40-41: AddformActiondirective to allow ConvertKit form submissionsNo static
<iframe>or<form>targets were found in the frontend code, and yourscriptSrcalready permits the ConvertKit embed script (https://akongalabs.kit.com/4e5ba9cc5c/index.js) . However, the ConvertKit JavaScript embed (loaded from that script) dynamically injects a<form>whoseactionposts tohttps://app.convertkit.com/forms/{Form ID}/subscriptions(help.convertkit.com). Without aformActiondirective, these submissions will be blocked in production.Please update your CSP configuration in
server-panda/src/middleware/security.ts:• File: server-panda/src/middleware/security.ts
Add under your existing directives:frameSrc: ["'none'"], workerSrc: ["'self'"], + formAction: ["'self'", "https://app.convertkit.com"],This ensures inline forms post successfully to ConvertKit without broadening your CSP beyond the specific host.
♻️ Duplicate comments (5)
landing-panda/src/styles/mylanding.css (5)
157-172: Make blog layout fluid; avoid fixed widths that overflow on small screensFixed widths (710px for .blog-body and 700px for images) cause horizontal overflow on narrow devices. Use a fluid width with a max cap; let images scale to container.
Apply this diff:
.blog-body { display: flex; flex-direction: column; margin: 10px auto; font-size: 110%; justify-content: center; background-color:var(--bg-color); font-family: var(--font-family); line-height: 1.6; padding: 9px; color:var(--text-color); - width: 710px; + width: min(710px, 100%); } .blog-post img { - max-width: 700px; + max-width: 100%; height: auto; display: block; }
1-9: Centralize mylanding.css to a single source of truth; remove duplicate in public/There are duplicate copies under src/styles and public/styles, and multiple import sites reference each. This will drift and cause hard-to-debug inconsistencies.
Preferred:
- Keep landing-panda/src/styles/mylanding.css as canonical.
- Delete public/styles/mylanding.css and update all imports to reference the src file.
Alternative:
- If a static public file is required, keep only public/styles/mylanding.css and add a build step to copy from src (so one file is edited).
I can generate a quick PR patch to update imports once you confirm the preferred direction.
175-178: Fix selector typo:.blog-post titlematches nothingThis selector doesn’t select elements inside .blog-post. It should likely target an element with class "title".
Apply this diff:
-.blog-post title{ +.blog-post .title{ align-content: center; align-self: center; }
180-185: Scope heading selectors correctly to avoid global H2/H3 restyling“.blog-post h1,h2,h3” only scopes h1; h2 and h3 are global. This will unintentionally restyle site-wide headings.
Apply this diff:
-.blog-post h1,h2,h3 { +.blog-post h1, +.blog-post h2, +.blog-post h3 { margin-top: 1rem; margin-bottom: 0.75rem; font-size: 40px; font-weight: 200; }
217-220: Invalid CSS:font-styleused with a font-family variable; replace withfont-familyThis rule is ignored by browsers; intended font won’t apply.
Apply this diff in all three locations:
.insider{ - font-style: var(--font-family); + font-family: var(--font-family); font-size: 35px; } @@ .insider{ - font-style: var(--font-family); + font-family: var(--font-family); font-size: 40px; line-height: 1.2; margin: 0; padding: 0; } @@ .insider{ - font-style: var(--font-family); + font-family: var(--font-family); font-size: 35px; line-height: 1.2; margin: 0; padding: 0; }Also applies to: 360-366, 394-399
🧹 Nitpick comments (4)
server-panda/src/middleware/security.ts (2)
35-35: Tighten fontSrc to the exact Google Fonts hostCurrently fontSrc allows any HTTPS origin, which is broader than needed. Google Fonts files are served from fonts.gstatic.com; restricting to that host reduces exposure.
Apply this diff:
- fontSrc: ["'self'", "https:", "data:"], + fontSrc: ["'self'", "https://fonts.gstatic.com", "data:"],
30-34: Clean up comments and make allowlist stableMinor clarity:
- The comment on Line 30 mixes “inline styles” and the Google Fonts CSS endpoint; clarify intent.
- Path-level allowlisting (…/4e5ba9cc5c/index.js) is brittle; vendor rotations will break CSP. Prefer the origin host and pair with SRI or a nonce.
Proposed tidy-up:
- // styleSrc: ["'self'", "'unsafe-inline'"], // Allow inline styles for React/Astro https://fonts.googleapis.com - styleSrc: ["'self'", "'unsafe-inline'","https://fonts.googleapis.com"], // Allow inline styles for React/Astro + // Allow Google Fonts stylesheet; inline styles are controlled via nonce + styleSrc: ["'self'", "https://fonts.googleapis.com"], - // scriptSrc: ["'self'", "'unsafe-inline'"], // Allow inline scripts for React - scriptSrc: ["'self'", "'unsafe-inline'", "https://akongalabs.kit.com/4e5ba9cc5c/index.js"], // Allow inline scripts for React + // Allow external kit script host; inline scripts are controlled via nonce + scriptSrc: ["'self'", "https://akongalabs.kit.com"],landing-panda/src/styles/mylanding.css (2)
124-130: Unify .blogs_container sizing; remove repeated fixed widths across breakpointsMultiple media queries set .blogs_container widths (430px, 720px, 750px), which are brittle and can overflow. Centralize to a single fluid rule and drop per-breakpoint widths.
Apply this diff to set a single fluid width and remove per-breakpoint width overrides:
.blogs_container{ display: flex; flex-direction: column; margin: auto; - width: 700px; + width: min(750px, 100%); gap: 10px; } @@ @media (max-width: 479px) { .blogs_container{ padding: 2px 30px; text-align: left; - width: 430px; line-height: 1.6; } @@ @media (min-width: 480px) and (max-width: 769px) { .blogs_container{ padding: 2px 30px; text-align: left; font-size: 100%; - width: 720px; line-height: 1; } @@ @media (min-width: 770px) and (max-width: 1024px) { .blogs_container{ padding: 2px 70px; text-align: left; font-size: 100%; - width: 750px; line-height: 1; } @@ @media (min-width: 1025px) and (max-width: 1439px) { .blogs_container{ padding: 2px 70px; text-align: left; font-size: 100%; - width: 750px; line-height: 1; } @@ @media (min-width: 1440px) and (max-width: 1920px) { .blogs_container{ padding: 2px 70px; text-align: left; font-size: 100%; - width: 750px; line-height: 1; } @@ @media (min-width: 1921px) { .blogs_container{ padding: 2px 70px; text-align: left; font-size: 100%; - width: 750px; line-height: 1; }Also applies to: 336-343, 371-377, 404-410, 430-436, 456-463, 484-490
344-351: Remove debug border on .first_links_snips (mobile)The 1px white border looks like a leftover debug aid and clashes with the dark theme.
Apply this diff:
- .first_links_snips{ - border: 1px solid white; + .first_links_snips{ display: flex; flex-direction: column; font-size: 25px; margin-top: 15px; text-decoration: underline; line-height: 1;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
landing-panda/src/pages/blogSnippets.astro(1 hunks)landing-panda/src/styles/mylanding.css(1 hunks)server-panda/src/middleware/security.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- landing-panda/src/pages/blogSnippets.astro
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
Use TypeScript across the codebase
Files:
server-panda/src/middleware/security.ts
| // styleSrc: ["'self'", "'unsafe-inline'"], // Allow inline styles for React/Astro https://fonts.googleapis.com | ||
| styleSrc: ["'self'", "'unsafe-inline'","https://fonts.googleapis.com"], // Allow inline styles for React/Astro | ||
| // scriptSrc: ["'self'", "'unsafe-inline'"], // Allow inline scripts for React | ||
| scriptSrc: ["'self'", "'unsafe-inline'", "https://akongalabs.kit.com/4e5ba9cc5c/index.js"], // Allow inline scripts for React | ||
| imgSrc: ["'self'", "data:", "https:"], // Allow images from self, data URLs, and HTTPS |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Harden CSP: replace 'unsafe-inline' with nonces/hashes; keep external origins minimal
Allowing 'unsafe-inline' for scripts/styles negates most CSP XSS protection. Prefer nonces (or SHA-256 hashes) and restrict external origins to host-level (not paths) only if necessary.
- Move CSP to a per-request middleware and inject a nonce.
- Remove 'unsafe-inline' from script/style sources.
- Keep the external script origin as tight as possible, and consider SRI if the vendor supports it.
Apply this focused diff to drop 'unsafe-inline' (pair with the snippet below to add a nonce):
- // styleSrc: ["'self'", "'unsafe-inline'"], // Allow inline styles for React/Astro https://fonts.googleapis.com
- styleSrc: ["'self'", "'unsafe-inline'","https://fonts.googleapis.com"], // Allow inline styles for React/Astro
- // scriptSrc: ["'self'", "'unsafe-inline'"], // Allow inline scripts for React
- scriptSrc: ["'self'", "'unsafe-inline'", "https://akongalabs.kit.com/4e5ba9cc5c/index.js"], // Allow inline scripts for React
+ // styleSrc: ["'self'","'nonce-<INJECTED>'","https://fonts.googleapis.com"],
+ styleSrc: ["'self'", "https://fonts.googleapis.com"],
+ // scriptSrc: ["'self'","'nonce-<INJECTED>'","https://akongalabs.kit.com"],
+ scriptSrc: ["'self'", "https://akongalabs.kit.com"],Then inject a CSP nonce per request and apply CSP dynamically:
// Place above the Helmet call(s)
import crypto from "crypto";
// Generate nonce per request
app.use((req, res, next) => {
res.locals.cspNonce = crypto.randomBytes(16).toString("base64");
next();
});
// Split Helmet so CSP can use the per-request nonce
app.use(helmet({
// ...keep other helmet options...
// IMPORTANT: temporarily remove contentSecurityPolicy here
}));
app.use((req, res, next) =>
helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", `'nonce-${res.locals.cspNonce}'`, "https://fonts.googleapis.com"],
scriptSrc: ["'self'", `'nonce-${res.locals.cspNonce}'`, "https://akongalabs.kit.com"],
imgSrc: ["'self'", "data:", "https:"],
fontSrc: ["'self'", "https://fonts.gstatic.com", "data:"],
connectSrc: ["'self'"],
objectSrc: ["'none'"],
// ...keep remaining directives...
upgradeInsecureRequests: [],
},
})(req, res, next)
);Note: If inline scripts/styles are truly required, add the matching nonce to the tags, e.g. <script nonce={res.locals.cspNonce}>…</script>. If the vendor rotates script paths, stay on the host allowlist and use SRI where possible.
🤖 Prompt for AI Agents
In server-panda/src/middleware/security.ts around lines 30-34 the CSP currently
uses 'unsafe-inline' for script/style and includes full script URL paths; remove
"'unsafe-inline'" from styleSrc and scriptSrc, replace the external script
origin with just the host (e.g., "https://akongalabs.kit.com"), and implement a
per-request nonce: generate a base64 nonce (e.g., crypto.randomBytes(16)) and
store it on res.locals, split Helmet so contentSecurityPolicy is applied
per-request using that nonce in scriptSrc/styleSrc (e.g.,
'nonce-${res.locals.cspNonce}'), update any inline <script>/<style> tags to
include the nonce, and consider adding fontSrc/connectSrc directives and SRI for
vendor scripts if supported.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (4)
landing-panda/src/pages/[slug].astro (4)
2-3: Add sanitize-html import and fix CSS import path
- Bring in sanitize-html to harden against XSS when rendering WP HTML.
- The CSS import path is incorrect; from pages/[slug].astro to styles is ../styles/mylanding.css (not ../../src/styles/...).
Apply:
import type { BlogPost } from "../data/types"; -import "../../src/styles/mylanding.css"; +import sanitizeHtml from "sanitize-html"; +import "../styles/mylanding.css";
5-18: Paginate and add error handling in getStaticPaths (fetches only first page today)Current code fetches a single page (WP default 10 posts) and lacks failure context. Paginating avoids silently missing older posts; basic checks prevent opaque build errors.
Apply:
export async function getStaticPaths() { - // _embed query param expands related objects like authors - const res = await fetch("https://akongalabs.com/wp-json/wp/v2/posts?_embed"); - const posts: BlogPost[] = await res.json(); - - return posts.map((post, index) => ({ - params: { slug: post.slug }, - props: { - post, - prevPost: posts[index + 1] || null, - nextPost: posts[index - 1] || null, - }, - })); + const posts: BlogPost[] = []; + let page = 1; + const perPage = 100; // WP caps at 100 + while (true) { + const url = `https://akongalabs.com/wp-json/wp/v2/posts?_embed&orderby=date&order=desc&per_page=${perPage}&page=${page}`; + const res = await fetch(url); + if (!res.ok) { + throw new Error(`Failed to fetch posts (page ${page}): ${res.status} ${res.statusText}`); + } + const batch: BlogPost[] = await res.json(); + posts.push(...batch); + if (batch.length < perPage) break; + page++; + } + if (posts.length === 0) { + return []; + } + return posts.map((post, index) => ({ + params: { slug: post.slug }, + props: { + post, + // With order=desc, "previous" is the next older post in the list. + prevPost: posts[index + 1] || null, + nextPost: posts[index - 1] || null, + }, + })); }
20-25: Precompute safe title text and sanitized HTML before renderingAvoid injecting raw HTML. Strip tags for the title; sanitize the content with a conservative allowlist.
Apply:
const { post, prevPost, nextPost } = Astro.props as { post: BlogPost; prevPost: BlogPost | null; nextPost: BlogPost | null; }; --- +// Avoid injecting raw HTML where not necessary; sanitize rich content. +const titleText = (post.title?.rendered ?? "").replace(/<[^>]*>/g, ""); +const contentHTML = sanitizeHtml(post.content?.rendered ?? "", { + allowedTags: sanitizeHtml.defaults.allowedTags.concat([ + "img", + "figure", + "figcaption", + "h1", + "h2", + "h3", + "span", + "iframe", + ]), + allowedAttributes: { + a: ["href", "name", "target", "rel"], + img: ["src", "alt", "loading", "decoding", "width", "height", "srcset", "sizes"], + iframe: ["src", "width", "height", "allow", "allowfullscreen", "frameborder"], + "*": ["class", "id", "style"], + }, + allowedSchemes: ["http", "https", "mailto"], +});Note: add sanitize-html to deps: npm i sanitize-html (or pnpm add sanitize-html). I can open a quick PR if helpful.
55-55: Sanitize post body before injecting HTMLInjecting post.content.rendered directly is a high-impact XSS risk. Use the sanitized content.
- <div set:html={post.content.rendered} /> + <div set:html={contentHTML} />
🧹 Nitpick comments (5)
landing-panda/src/pages/[slug].astro (5)
4-4: Remove unused or invalid import: previewpreview is not used here and is not a typical Astro export for pages. Drop it to avoid dead code or build warnings.
-import { preview } from "astro";If you intended a preview-only behavior, point me to it and I can help wire it safely behind dev guards.
27-27: Declare document languageAdd lang for accessibility and SEO.
-<html> +<html lang="en">
29-31: Add responsive viewport metaWithout it, mobile layout may render poorly.
<head> <title>{post.title.rendered}</title> <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> </head>
46-51: Stabilize date rendering across environmentsUse date_gmt when available and pin the timeZone to avoid build-machine drift.
- new Date(post.date).toLocaleDateString("en-US", { + new Date(post.date_gmt ?? post.date).toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric", + timeZone: "UTC", })
27-90: Route design: consider scoping blog to /blog/[slug] to avoid future collisionsA top-level dynamic route ([slug].astro) can shadow future top-level pages. Static routes win today for known pages, but scoping blog posts under /blog/ reduces risk and improves URL clarity.
If you want, I can propose the minimal move: rename this file to pages/blog/[slug].astro and update internal links (e.g., to /blog/{slug}).
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
landing-panda/src/pages/[slug].astro(1 hunks)landing-panda/src/styles/mylanding.css(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- landing-panda/src/styles/mylanding.css
🧰 Additional context used
📓 Path-based instructions (1)
landing-panda/src/pages/**/*.astro
📄 CodeRabbit inference engine (.cursorrules)
Create landing pages as Astro files under landing-panda/src/pages/
Files:
landing-panda/src/pages/[slug].astro
🧠 Learnings (1)
📚 Learning: 2025-08-15T14:47:01.751Z
Learnt from: CR
PR: AkongaLabs/akongalabs-beta#0
File: .cursorrules:0-0
Timestamp: 2025-08-15T14:47:01.751Z
Learning: Applies to landing-panda/src/pages/**/*.astro : Create landing pages as Astro files under landing-panda/src/pages/
Applied to files:
landing-panda/src/pages/[slug].astro
🔇 Additional comments (3)
landing-panda/src/pages/[slug].astro (3)
1-1: Location and file type align with guidelinesFile is correctly added under landing-panda/src/pages/ as an Astro page, per the coding guideline.
57-61: External script: verify CSP allowlist and consider perf guardrailsConfirm CSP includes akongalabs.kit.com. If this is non-critical, consider deferring load until after main content or behind an interaction.
Would you like me to check/update the CSP and suggest a safer loading strategy (e.g., data- attributes plus a small consent/interaction gate)?
65-76: Harden prev/next navigation and improve accessibility
- Sanitize post titles in the nav links to avoid unescaped HTML and potential XSS
- Add a descriptive
aria-labelon the<nav>container- Explicitly mark links with
rel="prev"andrel="next"for proper semantic relationships- Note: the WordPress REST API’s
/wp/v2/postsendpoint returns posts in descending date order by default (orderby=date,order=desc), so here
prevPost = posts[index + 1]→ older postsnextPost = posts[index - 1]→ newer posts
Confirm these align with your intended “Previous”/“Next” labels (developer.wordpress.org).Suggest applying this diff:
- <nav class="blog-navigation"> + <nav class="blog-navigation" aria-label="Post navigation"> <div class="nav-links"> - {prevPost && ( - <a href={`/${prevPost.slug}`}> - Previous: <span set:html={prevPost.title.rendered} /> + {prevPost && ( + <a href={`/${prevPost.slug}`} rel="prev"> + Previous: <span>{(prevPost.title?.rendered ?? "").replace(/<[^>]*>/g, "")}</span> </a> )} - {nextPost && ( - <a href={`/${nextPost.slug}`}> - Next: <span set:html={nextPost.title.rendered} /> + {nextPost && ( + <a href={`/${nextPost.slug}`} rel="next"> + Next: <span>{(nextPost.title?.rendered ?? "").replace(/<[^>]*>/g, "")}</span> </a> )}
| <h1 set:html={post.title.rendered} /> | ||
| <img src={post.jetpack_featured_media_url} /> | ||
| <p class="author-date"> | ||
| <span class="author">{post._embedded?.author?.[0]?.name}</span> |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Render a safe title and harden featured image (a11y + perf)
- Avoid set:html for the title; use plain text.
- Add alt text and lazy/async hints; render image only if URL exists.
- <h1 set:html={post.title.rendered} />
- <img src={post.jetpack_featured_media_url} />
+ <h1>{titleText}</h1>
+ {
+ post.jetpack_featured_media_url && (
+ <img
+ src={post.jetpack_featured_media_url}
+ alt={titleText}
+ loading="lazy"
+ decoding="async"
+ />
+ )
+ }Consider adding width/height to reduce CLS if dimensions are known.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <h1 set:html={post.title.rendered} /> | |
| <img src={post.jetpack_featured_media_url} /> | |
| <p class="author-date"> | |
| <span class="author">{post._embedded?.author?.[0]?.name}</span> | |
| <h1>{titleText}</h1> | |
| {post.jetpack_featured_media_url && ( | |
| <img | |
| src={post.jetpack_featured_media_url} | |
| alt={titleText} | |
| loading="lazy" | |
| decoding="async" | |
| /> | |
| )} | |
| <p class="author-date"> | |
| <span class="author">{post._embedded?.author?.[0]?.name}</span> |
🤖 Prompt for AI Agents
In landing-panda/src/pages/[slug].astro around lines 40-43, replace the unsafe
set:html title with a plain-text title binding (so the title is escaped and not
injected as HTML); render the featured image only when
post.jetpack_featured_media_url exists; add an alt attribute (preferably from
post._embedded?.author? or post.jetpack_featured_media_caption, falling back to
post.title.rendered or an empty string), and add loading="lazy" and
decoding="async" attributes for a11y and perf; if image width/height metadata is
available (e.g. post.jetpack_featured_media_width/height or similar), include
those attributes to reduce CLS.
Improvements and Bug Fixes
Summary
This PR adds support for rendering blog snippets and full blog content from markdown files using Astro. It includes:
Summary by CodeRabbit
New Features
Style
Chores
Security