12 KiB
12 KiB
| 1 | No | Category | Guideline | Description | Do | Don't | Code Good | Code Bad | Severity | Docs URL |
|---|---|---|---|---|---|---|---|---|---|---|
| 2 | 1 | Architecture | Use Islands Architecture | Astro's partial hydration only loads JS for interactive components | Interactive components with client directives | Hydrate entire page like traditional SPA | <Counter client:load /> | Everything as client component | High | https://docs.astro.build/en/concepts/islands/ |
| 3 | 2 | Architecture | Default to zero JS | Astro ships zero JS by default - add only when needed | Static components without client directive | Add client:load to everything | <Header /> (static) | <Header client:load /> (unnecessary) | High | https://docs.astro.build/en/basics/astro-components/ |
| 4 | 3 | Architecture | Choose right client directive | Different directives for different hydration timing | client:visible for below-fold client:idle for non-critical | client:load for everything | <Comments client:visible /> | <Comments client:load /> | Medium | https://docs.astro.build/en/reference/directives-reference/#client-directives |
| 5 | 4 | Architecture | Use content collections | Type-safe content management for blogs docs | Content collections for structured content | Loose markdown files without schema | const posts = await getCollection('blog') | import.meta.glob('./posts/*.md') | High | https://docs.astro.build/en/guides/content-collections/ |
| 6 | 5 | Architecture | Define collection schemas | Zod schemas for content validation | Schema with required fields and types | No schema validation | defineCollection({ schema: z.object({...}) }) | defineCollection({}) | High | https://docs.astro.build/en/guides/content-collections/#defining-a-collection-schema |
| 7 | 6 | Routing | Use file-based routing | Create routes by adding .astro files in pages/ | pages/ directory for routes | Manual route configuration | src/pages/about.astro | Custom router setup | Medium | https://docs.astro.build/en/basics/astro-pages/ |
| 8 | 7 | Routing | Dynamic routes with brackets | Use [param] for dynamic routes | Bracket notation for params | Query strings for dynamic content | pages/blog/[slug].astro | pages/blog.astro?slug=x | Medium | https://docs.astro.build/en/guides/routing/#dynamic-routes |
| 9 | 8 | Routing | Use getStaticPaths for SSG | Generate static pages at build time | getStaticPaths for known dynamic routes | Fetch at runtime for static content | export async function getStaticPaths() { return [...] } | No getStaticPaths with dynamic route | High | https://docs.astro.build/en/reference/api-reference/#getstaticpaths |
| 10 | 9 | Routing | Enable SSR when needed | Server-side rendering for dynamic content | output: 'server' or 'hybrid' for dynamic | SSR for purely static sites | export const prerender = false; | SSR for static blog | Medium | https://docs.astro.build/en/guides/server-side-rendering/ |
| 11 | 10 | Components | Keep .astro for static | Use .astro components for static content | Astro components for layout structure | React/Vue for static markup | <Layout><slot /></Layout> | <ReactLayout>{children}</ReactLayout> | High | |
| 12 | 11 | Components | Use framework components for interactivity | React Vue Svelte for complex interactivity | Framework component with client directive | Astro component with inline scripts | <ReactCounter client:load /> | <script> in .astro for complex state | Medium | https://docs.astro.build/en/guides/framework-components/ |
| 13 | 12 | Components | Pass data via props | Astro components receive props in frontmatter | Astro.props for component data | Global state for simple data | const { title } = Astro.props; | Import global store | Low | https://docs.astro.build/en/basics/astro-components/#component-props |
| 14 | 14 | Components | Colocate component styles | Scoped styles in component file | <style> in same .astro file | Separate CSS files for component styles | <style> .card { } </style> | import './Card.css' | Low | |
| 15 | 15 | Styling | Use scoped styles by default | Astro scopes styles to component automatically | <style> for component-specific styles | Global styles for everything | <style> h1 { } </style> (scoped) | <style is:global> for everything | Medium | https://docs.astro.build/en/guides/styling/#scoped-styles |
| 16 | 16 | Styling | Use is:global sparingly | Global styles only when truly needed | is:global for base styles or overrides | is:global for component styles | <style is:global> body { } </style> | <style is:global> .card { } </style> | Medium | |
| 17 | 17 | Styling | Integrate Tailwind properly | Use @astrojs/tailwind integration | Official Tailwind integration | Manual Tailwind setup | npx astro add tailwind | Manual PostCSS config | Low | https://docs.astro.build/en/guides/integrations-guide/tailwind/ |
| 18 | 18 | Styling | Use CSS variables for theming | Define tokens in :root | CSS custom properties for themes | Hardcoded colors everywhere | :root { --primary: #3b82f6; } | color: #3b82f6; everywhere | Medium | |
| 19 | 19 | Data | Fetch in frontmatter | Data fetching in component frontmatter | Top-level await in frontmatter | useEffect for initial data | const data = await fetch(url) | client-side fetch on mount | High | https://docs.astro.build/en/guides/data-fetching/ |
| 20 | 20 | Data | Use Astro.glob for local files | Import multiple local files | Astro.glob for markdown/data files | Manual imports for each file | const posts = await Astro.glob('./posts/*.md') | import post1; import post2; | Medium | |
| 21 | 21 | Data | Prefer content collections over glob | Type-safe collections for structured content | getCollection() for blog/docs | Astro.glob for structured content | await getCollection('blog') | await Astro.glob('./blog/*.md') | High | |
| 22 | 22 | Data | Use environment variables correctly | Import.meta.env for env vars | PUBLIC_ prefix for client vars | Expose secrets to client | import.meta.env.PUBLIC_API_URL | import.meta.env.SECRET in client | High | https://docs.astro.build/en/guides/environment-variables/ |
| 23 | 23 | Performance | Preload critical assets | Use link preload for important resources | Preload fonts above-fold images | No preload hints | <link rel="preload" href="font.woff2" as="font"> | No preload for critical assets | Medium | |
| 24 | 24 | Performance | Optimize images with astro:assets | Built-in image optimization | <Image /> component for optimization | <img> for local images | import { Image } from 'astro:assets'; | <img src="./image.jpg"> | High | https://docs.astro.build/en/guides/images/ |
| 25 | 25 | Performance | Use picture for responsive images | Multiple formats and sizes | <Picture /> for art direction | Single image size for all screens | <Picture /> with multiple sources | <Image /> with single size | Medium | |
| 26 | 26 | Performance | Lazy load below-fold content | Defer loading non-critical content | loading=lazy for images client:visible for components | Load everything immediately | <img loading="lazy"> | No lazy loading | Medium | |
| 27 | 27 | Performance | Minimize client directives | Each directive adds JS bundle | Audit client: usage regularly | Sprinkle client:load everywhere | Only interactive components hydrated | Every component with client:load | High | |
| 28 | 28 | ViewTransitions | Enable View Transitions | Smooth page transitions | <ViewTransitions /> in head | Full page reloads | import { ViewTransitions } from 'astro:transitions'; | No transition API | Medium | https://docs.astro.build/en/guides/view-transitions/ |
| 29 | 29 | ViewTransitions | Use transition:name | Named elements for morphing | transition:name for persistent elements | Unnamed transitions | <header transition:name="header"> | <header> without name | Low | |
| 30 | 30 | ViewTransitions | Handle transition:persist | Keep state across navigations | transition:persist for media players | Re-initialize on every navigation | <video transition:persist id="player"> | Video restarts on navigation | Medium | |
| 31 | 31 | ViewTransitions | Add fallback for no-JS | Graceful degradation | Content works without JS | Require JS for basic navigation | Static content accessible | Broken without ViewTransitions JS | High | |
| 32 | 32 | SEO | Use built-in SEO component | Head management for meta tags | Astro SEO integration or manual head | No meta tags | <title>{title}</title><meta name="description"> | No SEO tags | High | |
| 33 | 33 | SEO | Generate sitemap | Automatic sitemap generation | @astrojs/sitemap integration | Manual sitemap maintenance | npx astro add sitemap | Hand-written sitemap.xml | Medium | https://docs.astro.build/en/guides/integrations-guide/sitemap/ |
| 34 | 34 | SEO | Add RSS feed for content | RSS for blogs and content sites | @astrojs/rss for feed generation | No RSS feed | rss() helper in pages/rss.xml.js | No feed for blog | Low | https://docs.astro.build/en/guides/rss/ |
| 35 | 36 | Integrations | Use official integrations | Astro's integration system | npx astro add for integrations | Manual configuration | npx astro add react | Manual React setup | Medium | https://docs.astro.build/en/guides/integrations-guide/ |
| 36 | 37 | Integrations | Configure integrations in astro.config | Centralized configuration | integrations array in config | Scattered configuration | integrations: [react(), tailwind()] | Multiple config files | Low | |
| 37 | 38 | Integrations | Use adapter for deployment | Platform-specific adapters | Correct adapter for host | Wrong or no adapter | @astrojs/vercel for Vercel | No adapter for SSR | High | https://docs.astro.build/en/guides/deploy/ |
| 38 | 39 | TypeScript | Enable TypeScript | Type safety for Astro projects | tsconfig.json with astro types | No TypeScript | Astro TypeScript template | JavaScript only | Medium | https://docs.astro.build/en/guides/typescript/ |
| 39 | 40 | TypeScript | Type component props | Define prop interfaces | Props interface in frontmatter | Untyped props | interface Props { title: string } | No props typing | Medium | |
| 40 | 41 | TypeScript | Use strict mode | Catch errors early | strict: true in tsconfig | Loose TypeScript config | strictest template | base template | Low | |
| 41 | 42 | Markdown | Use MDX for components | Components in markdown content | @astrojs/mdx for interactive docs | Plain markdown with workarounds | <Component /> in .mdx | HTML in .md files | Medium | https://docs.astro.build/en/guides/integrations-guide/mdx/ |
| 42 | 43 | Markdown | Configure markdown plugins | Extend markdown capabilities | remarkPlugins rehypePlugins in config | Manual HTML for features | remarkPlugins: [remarkToc] | Manual TOC in every post | Low | |
| 43 | 44 | Markdown | Use frontmatter for metadata | Structured post metadata | Frontmatter with typed schema | Inline metadata | title date in frontmatter | # Title as first line | Medium | |
| 44 | 45 | API | Use API routes for endpoints | Server endpoints in pages/api | pages/api/[endpoint].ts for APIs | External API for simple endpoints | pages/api/posts.json.ts | Separate Express server | Medium | https://docs.astro.build/en/guides/endpoints/ |
| 45 | 46 | API | Return proper responses | Use Response object | new Response() with headers | Plain objects | return new Response(JSON.stringify(data)) | return data | Medium | |
| 46 | 47 | API | Handle methods correctly | Export named method handlers | export GET POST handlers | Single default export | export const GET = async () => {} | export default async () => {} | Low | |
| 47 | 48 | Security | Sanitize user content | Prevent XSS in dynamic content | set:html only for trusted content | set:html with user input | <Fragment set:html={sanitized} /> | <div set:html={userInput} /> | High | |
| 48 | 49 | Security | Use HTTPS in production | Secure connections | HTTPS for all production sites | HTTP in production | https://example.com | http://example.com | High | |
| 49 | 50 | Security | Validate API input | Check and sanitize all input | Zod validation for API routes | Trust all input | const body = schema.parse(data) | const body = await request.json() | High | |
| 50 | 51 | Build | Use hybrid rendering | Mix static and dynamic pages | output: 'hybrid' for flexibility | All SSR or all static | prerender per-page basis | Single rendering mode | Medium | https://docs.astro.build/en/guides/server-side-rendering/#hybrid-rendering |
| 51 | 52 | Build | Analyze bundle size | Monitor JS bundle impact | Build output shows bundle sizes | Ignore bundle growth | Check astro build output | No size monitoring | Medium | |
| 52 | 53 | Build | Use prefetch | Preload linked pages | prefetch integration | No prefetch for navigation | npx astro add prefetch | Manual prefetch | Low | https://docs.astro.build/en/guides/prefetch/ |