ããã«ã¡ã¯ããšãŸã ã§ãã
çãããæè¿è©±é¡ã® AI é§åéçºã詊ããŠããŸããïŒ
ç§ã¯æ®æ®µããªãŒã©ã³ã¹ã® Web ãšã³ãžãã¢ãšããŠæŽ»åããŠããããã¡ãã§ã¯ AI ãšãŒãžã§ã³ãããã«æŽ»çšããéçºãè¡ã£ãŠããŸãã
ãããŠæ¥åã ãã§ãªããå人éçºã®äžã§ã AI ãæŽ»çšããŠãéçºå¹çãåçã«åäžãããŠããŸãã
ãããªäžãå人éçºãšã㊠Cursor ãš Claude ããã«æŽ»çšããŠãããã°ã©ãã³ã°åŠç¿ãµã€ãã ãã£ã 1 ã¶æã§äœãåã ããšãã§ããŸããã
ä»åäœã£ãã®ã¯ãLearning Nextããšãããµã€ãã§ãããã°ã©ãã³ã°åŠç¿çšã®ããã¹ããç·Žç¿åé¡ãã©ã³ãã³ã°ããŠãŒã¶ãŒç»é²ãããã·ã¥ããŒããªã©ãæ¬æ ŒçãªåŠç¿ãã©ãããã©ãŒã ã«ãªã£ãŠããŸãã
æ¬èšäºã§ã¯ããããªäžã§ãã£ãŠããããšããå ·äœç㪠Cursor ã®èšå®æ¹æ³ãAI é§åéçºã®ããŠããŠããäŒãã§ããã°ãšæããŸãã
ã¡ãªã¿ã«ç§ã¯ Claude ã䜵çšããŸããããCursor ã ãã§ãååã«éçºã¯å¯èœã§ãã
ãŸããGitHub Copilot ã Cline ãªã©ãä»ã® AI ãšãŒãžã§ã³ãã§ãä»åã玹ä»ããæ¹æ³ã¯å¿çšå¯èœã§ãïŒ
ã远èšïŒç¶ç·šãæžããŸããã
ãã®èšäºã§ãããããš
- Cursor ãš Claude ã䜿ã£ãå¹çç㪠AI é§åéçºã®ææ³
- å®éã«äœ¿ã£ã
.cursorrulesã®èšå®æ¹æ³ - ã¿ã¹ã¯åè§£ãšããã¥ã¡ã³ãåã§éçºãåæ»ã«é²ããæ¹æ³
- AI ãééãããããã€ã³ããšå¯Ÿç
- 1 ã¶æã§æ¬æ Œç㪠Web ã¢ããªãäœãããã®æŠç¥
ç¹ã« ãAI ã䜿ã£ãéçºã«èå³ããããã©ãã©ããã£ãŠå§ããã°ãããããããªãã ãšããæ¹ã«ã¯ãå ·äœçãªããŠããŠããäŒãã§ãããšæããŸãã
å¿ãã人ã®ããã«èŠçŽ
- Cursor ãš Claude ã䜿ã£ãŠã1 ã¶æã§ããã°ã©ãã³ã°åŠç¿ãµã€ããéçº
- Cursor ã®
.cursorrulesã玹ä»ããã®ã§åèã«ããŠã - AI é§åéçºã®ãã€ã³ãã¯ãã¿ã¹ã¯åè§£ããšãããã¥ã¡ã³ãåã
- èŠä»¶å®çŸ©ãšèšèšãäºåã«è¡ãããšã§ãAI ã®èª€è§£ãæžãã
- â ãããŸãããªãããã®ããã³ããã玹ä»ããŠãã
- ã³ã³ããŒãã³ãã®ç²åºŠããã¶ã€ã³ã®çµ±äžæã®èгç¹ã§åçç¹ãããããå šäœçã«ã¯æå
ä»åäœã£ã Learning Next ã®æ©èœ
ãŸããã©ããªãµã€ããäœã£ãã®ãããããŠæè¡çãªãã€ã³ããç°¡åã«ç޹ä»ããŸãã
æè¡çãªãã€ã³ãããå人éçºã§ã®æ©èœèšèšã®èãæ¹ãªã©ãå«ããŠãäŒãããŸãã®ã§ãå人éçºã«èå³ãããæ¹ã¯ãã²æåŸãŸã§èªãã§ã¿ãŠãã ããã
æ¬æ¥ã§æ°åäžã®ãŠãŒã¶ãŒãæ±ãã Web ãµã€ãéçºã«æºãã£ãŠããçµéšã掻ãããŠããŸãã
ïŒAI é§åéçºã®è©±ã ããç¥ããããšããæ¹ã¯èªã¿é£ã°ããŠããã£ãŠã倧äžå€«ã§ãïŒ
åŠç¿ã³ã³ãã³ãæ©èœ
RubyãRailsãRSpecãJavaScriptãReact ã®åŠç¿ããã¹ã
åœãµã€ãã®ã¡ã€ã³åŠç¿ã³ã³ãã³ãã§ãã
åè¶ãªãã Udemy ã§ãã¹ãã»ã©ãŒã®è¬åž«ãããŠããç§ããå®éã®è¬åº§ã§äœ¿ã£ãŠããããã¹ããããŒã¹ã«ããŠããŸãã
ïŒããã¹ãèªäœã¯ãããŸã§å°éã«äœã£ãŠãããã®ã§ãããAI é§åéçºãšã¯é¢ä¿ãªãã®ã§å²æïŒ
ä»å㯠React Markdown ã䜿ã£ãŠå®è£ ããŸããã
綺éºãªã³ãŒããããã¯ããããã¹ããå¹ ã«å¯Ÿå¿ãããªã©ã¯æå€ãšå€§å€ã ã£ãã®ã§ãããããããŒã¯ããŠã³å¯Ÿå¿ã®ãµã€ããäœãæ¹ã¯è¡šç€ºãã¹ãã«æéããããããšãããããããŸãã
åèïŒReact Markdown çšã«ã«ã¹ã¿ãã€ãºããã³ã³ããŒãã³ã
'use client';
import Prism from 'prismjs';
import 'prismjs/themes/prism-tomorrow.css';
import React, { useCallback, useEffect, useRef } from 'react';
import ReactMarkdown from 'react-markdown';
import rehypeRaw from 'rehype-raw';
import remarkGfm from 'remark-gfm';
// å¿
èŠãªèšèªãã€ã³ããŒã
import 'prismjs/components/prism-bash';
import 'prismjs/components/prism-css';
import 'prismjs/components/prism-java';
import 'prismjs/components/prism-javascript';
import 'prismjs/components/prism-jsx';
import 'prismjs/components/prism-python';
import 'prismjs/components/prism-ruby';
import 'prismjs/components/prism-tsx';
import 'prismjs/components/prism-typescript';
type MarkdownRendererProps = {
content: string;
className?: string;
};
// ã³ãŒãèŠçŽ ã®propsåãå®çŸ©
interface CodeProps {
className?: string;
children?: React.ReactNode;
[key: string]: unknown;
}
/**
* ããŒã¯ããŠã³ããŒã¿ã®ååŠç
* ãšã¹ã±ãŒããããæåãå®éã®æåã«å€æ
*/
function preprocessMarkdown(content: string): string {
return content
.replace(/\\n/g, '\n')
.replace(/\\t/g, '\t')
.replace(/\\r/g, '\r')
.replace(/\\\\/g, '\\')
.replace(/\\"/g, '"')
.replace(/\\'/g, "'");
}
/**
* æ±çšçãªããŒã¯ããŠã³ã¬ã³ããªã³ã°ã³ã³ããŒãã³ã
* å顿ã解説æãªã©ãæ§ã
ãªçšéã§äœ¿çšå¯èœ
*/
export default function MarkdownRenderer({ content, className = '' }: MarkdownRendererProps) {
const containerRef = useRef<HTMLDivElement>(null);
const highlightTimeoutRef = useRef<NodeJS.Timeout>();
// ããŒã¯ããŠã³ã³ã³ãã³ãã®ååŠç
const processedContent = React.useMemo(() => {
return preprocessMarkdown(content);
}, [content]);
// Prism.jsã§ãã€ã©ã€ããé©çšãã颿°
const highlightCode = useCallback(() => {
if (containerRef.current && typeof window !== 'undefined') {
// æ¢åã®ãã€ã©ã€ããã¯ãªã¢
const preElements = containerRef.current.querySelectorAll('pre');
preElements.forEach((pre) => {
const code = pre.querySelector('code');
if (code) {
// Prismã远å ããã¯ã©ã¹ãä¿æãã€ã€ãããŒã¯ã³ãã¯ãªã¢
const className = code.className;
const textContent = code.textContent || '';
code.innerHTML = '';
code.textContent = textContent;
code.className = className;
}
});
// æ°ãããã€ã©ã€ããé©çš
Prism.highlightAllUnder(containerRef.current);
}
}, []);
// ã³ã³ãã³ã倿޿ãšããŠã³ãæã«ãã€ã©ã€ããé©çš
useEffect(() => {
// æ¢åã®ã¿ã€ã ã¢ãŠããã¯ãªã¢
if (highlightTimeoutRef.current) {
clearTimeout(highlightTimeoutRef.current);
}
// è€æ°åã®ãã€ã©ã€ãé©çšã§ç¢ºå®æ§ãé«ãã
const applyHighlight = () => {
highlightCode();
// 远å ã®ä¿éºãšããŠãå°ãé
ããŠå床é©çš
highlightTimeoutRef.current = setTimeout(() => {
highlightCode();
}, 300);
};
// ååã®ãã€ã©ã€ãé©çš
const initialTimeout = setTimeout(applyHighlight, 50);
return () => {
clearTimeout(initialTimeout);
if (highlightTimeoutRef.current) {
clearTimeout(highlightTimeoutRef.current);
}
};
}, [processedContent, highlightCode]);
// MutationObserverã§DOM倿Žãç£èŠ
useEffect(() => {
if (!containerRef.current) return;
const observer = new MutationObserver((mutations) => {
// ã³ãŒããããã¯ã«é¢ãã倿Žããã£ãå Žåã®ã¿ãã€ã©ã€ããåé©çš
const hasCodeChanges = mutations.some((mutation) => {
if (mutation.type === 'childList') {
const addedNodes = Array.from(mutation.addedNodes);
const removedNodes = Array.from(mutation.removedNodes);
return [...addedNodes, ...removedNodes].some((node) => {
if (node.nodeType === Node.ELEMENT_NODE) {
const element = node as Element;
return (
element.tagName === 'PRE' ||
element.tagName === 'CODE' ||
element.querySelector('pre') ||
element.querySelector('code')
);
}
return false;
});
}
return false;
});
if (hasCodeChanges) {
highlightCode();
}
});
observer.observe(containerRef.current, {
childList: true,
subtree: true,
});
return () => {
observer.disconnect();
};
}, [highlightCode]);
return (
<div ref={containerRef} className={`prose max-w-none ${className}`}>
<div className="markdown-content">
<ReactMarkdown
remarkPlugins={[remarkGfm]}
rehypePlugins={[rehypeRaw]}
components={{
// ã³ãŒããããã¯ã®åŠç
pre: ({ children, ...props }) => {
const childArray = React.Children.toArray(children);
const codeElement = childArray.find((child) => React.isValidElement(child) && child.type === 'code');
if (codeElement && React.isValidElement(codeElement)) {
const codeProps = codeElement.props as CodeProps;
const className = codeProps.className || '';
// èšèªãšãã¡ã€ã«åã®æœåº
const languageMatch = className.match(/language-(\w+)(?::(.+))?/);
const language = languageMatch ? languageMatch[1] : 'plaintext'; // èšèªæå®ããªãå Žåã¯plaintext
const fileName = languageMatch && languageMatch[2] ? languageMatch[2] : '';
// codeElementã®propsããinline-codeãåé€ïŒã³ãŒããããã¯å
ã§ã¯äœ¿ããªãïŒ
const newCodeProps = { ...codeProps };
if (newCodeProps.className === 'inline-code') {
newCodeProps.className = 'language-plaintext';
}
return (
<div className={`code-block ${language === 'plaintext' ? 'code-block-plaintext' : ''}`}>
{fileName && (
<div className="code-filename">
<span>{fileName}</span>
</div>
)}
<pre {...props} className={`language-${language}`} data-prism-processed="false">
{React.cloneElement(codeElement, {
className: `language-${language}`,
...newCodeProps,
})}
</pre>
</div>
);
}
// èšèªæå®ã®ãªãpreã¿ã°ã¯ç¹å¥ãªã¯ã©ã¹ã§æ±ã
return (
<div className="code-block code-block-plaintext">
<pre {...props} className="language-plaintext" data-prism-processed="false">
{children}
</pre>
</div>
);
},
// ã€ã³ã©ã€ã³ã³ãŒãã®åŠç
code: ({ className, children, ...props }) => {
const content = String(children).replace(/\n$/, '');
const match = className?.match(/language-(\w+)/);
// 芪èŠçŽ ãpreãã©ããã確èªãã颿°
const isInsidePre = () => {
// ãã©ãŠã¶ç°å¢ã§ã®ã¿å€å®å¯èœ
if (typeof document !== 'undefined' && props.node) {
// ReactMarkdownã®nodeåã¯è€éãªã®ã§ãããå®å
šãªæ¹æ³ã§åŠç
type ReactMarkdownNode = {
parentNode?: {
tagName?: string;
};
};
// unknownãçµç±ããŠãã£ã¹ã
const node = props.node as unknown as ReactMarkdownNode;
if (node.parentNode?.tagName === 'PRE') {
return true;
}
}
// ã³ã³ãã³ãã®æ¹è¡æ°ã§å€æïŒè€æ°è¡ãªãã³ãŒããããã¯å
ãšæšæž¬ïŒ
const textContent = String(children);
return textContent.includes('\n') || textContent.length > 80;
};
// ã€ã³ã©ã€ã³ã³ãŒãã®å Žå
if (!match) {
// 芪ãpreã®å Žåã¯plaintextãšããŠæ±ã
if (isInsidePre()) {
return (
<code className="language-plaintext" {...props}>
{children}
</code>
);
}
// éåžžã®ã€ã³ã©ã€ã³ã³ãŒã
return (
<code className="inline-code" {...props}>
{children}
</code>
);
}
// ã³ãŒããããã¯å
ã®ã³ãŒãèŠçŽ
const language = match[1];
return (
<code className={`language-${language}`} {...props}>
{content}
</code>
);
},
// ãã®ä»ã®èŠçŽ ã®ã«ã¹ã¿ãã€ãºïŒãªãã·ã§ã³ïŒ
p: ({ children }) => <p className="mb-4 leading-relaxed text-gray-700 last:mb-0">{children}</p>,
h1: ({ children }) => <h1 className="mb-4 text-2xl font-bold text-gray-900 sm:text-3xl">{children}</h1>,
h2: ({ children }) => <h2 className="mb-3 text-xl font-semibold text-gray-900 sm:text-2xl">{children}</h2>,
h3: ({ children }) => <h3 className="mb-3 text-lg font-semibold text-gray-900 sm:text-xl">{children}</h3>,
ul: ({ children }) => <ul className="mb-4 space-y-1 pl-6">{children}</ul>,
ol: ({ children }) => <ol className="mb-4 space-y-1 pl-6">{children}</ol>,
li: ({ children }) => <li className="text-gray-700">{children}</li>,
blockquote: ({ children }) => (
<blockquote className="my-4 border-l-4 border-blue-400 bg-blue-50 py-2 pl-4 text-gray-700 italic">
{children}
</blockquote>
),
a: ({ children, href }) => (
<a
href={href}
className="text-blue-600 underline hover:text-blue-800 hover:no-underline"
target="_blank"
rel="noopener noreferrer"
>
{children}
</a>
),
}}
>
{processedContent}
</ReactMarkdown>
</div>
</div>
);
}
åŠç¿ç¶æ³ã®ããã·ã¥ããŒã
ãã°ã€ã³ããŠããã°ãèªåã®åŠç¿ç¶æ³ãããã·ã¥ããŒãã§ç¢ºèªã§ããŸãã
- Learning Next: åŠç¿é²æããã·ã¥ããŒã
äžéšãææãŠãŒã¶ãŒéå®ã®è©³çްã³ã³ãã³ã
åŸè¿°ããŸãããä»å㯠Clerk ã䜿ã£ãŠãŠãŒã¶ãŒèªèšŒãå®è£ ããç¡æãŠãŒã¶ãŒãšææãŠãŒã¶ãŒã®æš©éãåããŠããŸãã
ããã¹ãã¯äžéšãææãŠãŒã¶ãŒéå®ãšãªã£ãŠããã®ã§ãã²ã¹ããç¡æãŠãŒã¶ãŒã«å¯ŸããŠã¯ã³ã³ãã³ãã¬ãŒãããããŠããŸãã
ãã㯠Clerk ã® Protect ã³ã³ããŒãã³ãã䜿ã£ãŠå®è£ ããŠããŸãã
ãã å®å šã« Clerk ã«ãä»»ããšããããã§ã¯ãªããããŒãžããã©ã³ãããã«ã¯éšåçã«å¶åŸ¡ãè¡ããããå°çšã®ãŠãŒãã£ãªãã£é¢æ°ãäœæããŠãå¿ èŠãªéšåã§ã¬ãŒãããããŠããŸãã
äžéšãå®è£ ã玹ä»ããŸãã
/**
* ãŠãŒã¶ãŒãã©ã³ãšãã¹ããã¢ã¯ã»ã¹å¯åŠãå€å®ãã颿°
* @param planName - ãŠãŒã¶ãŒã®çŸåšã®ãã©ã³ ('basic', 'premium', ãŸã㯠null)
* @param path - çŸåšã®ãã¹
* @returns é²èЧå¯èœãã©ããã®çåœå€
*/
export const canAccessContent = (planName: string | null, path: string): boolean => {
const requiredPlan = getRequiredPlan(path) // å
éšé¢æ°ã§ãã¹ã«å¿ããå¿
èŠãã©ã³ãååŸ
// ã¢ã¯ã»ã¹å¶éããªãå Žåã¯èª°ã§ãé²èЧå¯èœ
if (!requiredPlan) {
return true
}
// ãŠãŒã¶ãŒã«ãã©ã³ããªãå Žåã¯ã¢ã¯ã»ã¹äžå¯
if (!planName) {
return false
}
// ãã©ã³éå±€ã«åºã¥ããã¢ã¯ã»ã¹å¶åŸ¡
if (requiredPlan === PLAN_SLUG.STARTER) {
// starter以äžã®ãã©ã³ãæã€ãŠãŒã¶ãŒãã¢ã¯ã»ã¹å¯èœ
return [PLAN_SLUG.STARTER, PLAN_SLUG.BASIC, PLAN_SLUG.PREMIUM].includes(planName as PlanLevel)
}
// ...
ä»åã®èšèšãšããŠã¯ãã§ããã ãã¢ããªã«ãããéèŠããžãã¯ã¯ã³ã³ããŒãã³ãã®å€ãã€ãŸããŠãŒãã£ãªãã£é¢æ°ããµãŒãã¹å±€ã§å®è£
ããã³ã³ããŒãã³ã㯠UI 衚瀺ã«å°å¿µãã圢ããšã£ãŠããŸãã
ãããªãã«å·šå€§ãªã¢ããªã±ãŒã·ã§ã³ã«ãªã£ãŠããã®ã§ãã³ã³ããŒãã³ãã®è²¬åãæç¢ºã«åããããšã§ãä¿å®æ§ãé«ããŠããŸãã
ç·Žç¿å顿©èœ
ããŠãLearning Next ã®ã¡ã€ã³æ©èœã®äžã€ã ç·Žç¿åé¡ ã§ãã
- Learning Next: ç·Žç¿åé¡äžèЧ
çŸåšã¯ 1,300 åä»¥äž ã®åé¡ãçšæããŠãããåã³ãŒã¹ããšã«åé¡ãåºé¡ãããŸãã
åéã RubyãRailsãRSpecãJavaScriptãReactãTypeScript ãªã©å€å²ã«ããã£ãŠãããçŸåš Python ãæºåäžã§ãã
ä»åŸã¯ãåé¡ã«å¯ŸããŠãŠãŒã¶ãŒããã®ãã£ãŒãããã¯ãåãä»ããããèšè¿°åŒã®åé¡ã远å ããããšèããŠããŸãã
ã³ãŒã¹ããããã¯ãäžæ£è§£ã§ãã£ã«ã¿ãªã³ã°
åé¡ã¯ã³ãŒã¹ããããã¯ããšã«ãã£ã«ã¿ãªã³ã°ã§ããããã«äžæ£è§£ã®åé¡ã ããéäžçã«åŠç¿ããããšãå¯èœã§ãã
åéããšã«å®çžŸãããã·ã¥ããŒã管ç
ãã°ã€ã³ããŠç·Žç¿åé¡ãè§£ããšç·Žç¿åé¡ããšã«æ£èª€ãèšé²ãããã®ã§ãããã·ã¥ããŒãã§ååéã®åŠç¿é²æãæ£è§£çã確èªã§ããŸãã
- Learning Next: ç·Žç¿åé¡ããã·ã¥ããŒã
ïŒè©³çްã¯åŸè¿°ïŒ
ã¿ã€ã ã¢ã¿ãã¯ã¢ãŒã
ãã ã¯ã€ãºãè§£ãã ãã§ãªããã¿ã€ã ã¢ã¿ãã¯ã¢ãŒã ãçšæããŠãããã³ã³ãã¯ãã« 1 åé ã§ã®ã¹ã³ã¢ãç«¶ãããšãã§ããŸãã
- Learning Next: ã¿ã€ã ã¢ã¿ãã¯
è§£ããåŸã¯ TechRate ãšããç¬èªã¹ã³ã¢ãèšç®ãããã©ã³ãã³ã°ã«åæ ãããŠä»ãŠãŒã¶ãŒãšç«¶ãããšãã§ããŸãã
ãã åŠç¿ããã ããããªããã²ãŒããã£ã±ãŒã·ã§ã³èŠçŽ ããã£ããæ¥œãããšæããã¹ããã© SP ã®ãäžçæŠéåãããçæ³ãåŸãŠå®è£ ããŸããã
ã¡ãªã¿ã«ãæ£è§£æ°ãã ãã§ã¯ãªããæ£è§£çããªã©ãèæ ®ããŠããã®ã§ãåœãŠãã£ãœãã§ã¯ãªããçæéã§ä»¥äžã«æ£ç¢ºã«è§£ããããéèŠã§ãã
ã©ã³ãã³ã°æ©èœ
äžäººã§åŠç¿ããã ãã§ã¯ãªããä»ã®ãŠãŒã¶ãŒãšç«¶ãåãããã®ã©ã³ãã³ã°æ©èœãå®è£ ããŠããŸãã
- Learning Next: ã©ã³ãã³ã°
ç·åã©ã³ãã³ã°ã»ã³ãŒã¹å¥ã©ã³ãã³ã°
ãŸãã¯ãç·Žç¿åé¡ã®æ£è§£æ°ãéèšãã ç·åã©ã³ãã³ã° ãšãåã³ãŒã¹ããšã® ã³ãŒã¹å¥ã©ã³ãã³ã° ã§ãã
çŽç²ã«åŠç¿éãå€ããŠãŒã¶ãŒãäžäœã«æ¥ãã®ã§ãåŠç¿ã®ã¢ãããŒã·ã§ã³ã«ãªãããšæããŸãã
ä»ãªããŠãŒã¶ãŒãå°ãªããã©ã³ã«ãŒã«ãªããããã®ã§ææŠããŠã¿ãŸãããïŒïŒïŒã宣äŒïŒ
ã¿ã€ã ã¢ã¿ãã¯ã®ã¹ã³ã¢ã©ã³ãã³ã°
ã¿ã€ã ã¢ã¿ãã¯ã¢ãŒãã§ã®ã¹ã³ã¢ãç«¶ã TechRate ã©ã³ãã³ã° ãçšæããŠããŸãã
ããã§ãã ãã£ãã®ã¯ãæ°èŠãŠãŒã¶ãŒã§ãã©ã³ãã³ã°ã«èŒããã£ã³ã¹ãäœãããšãã§ãã
å€åãããŒã£ãšäžäœãç¬å ããŠããŸããšãæ°èŠãŠãŒã¶ãŒã«ãšã£ãŠã¢ãããŒã·ã§ã³ã«ãªãã¥ããã§ããããïŒ
ãã®ããããæéå¥ãããã³ãŒã¹å¥ããªã©ããã现ååããããšã§ã誰ã§ãäžäœã«å ¥ãããã£ã³ã¹ãäœããŸããã
äœè«ïŒããŒã¿ããŒã¹ã®ã»ãã¥ãªãã£
Learning Next ã§ã¯ããŒã¿ããŒã¹ã« Supabase ã䜿ã£ãŠããŸãã
Supabase ã§ã¯ RLS ïŒRow Level SecurityïŒã䜿ã£ãŠããŠãŒã¶ãŒããšã«ããŒã¿ã®ã¢ã¯ã»ã¹å¶åŸ¡ãè¡ã£ãŠããã®ã§ãããã©ã³ãã³ã°ã®ããã«ä»ãŠãŒã¶ãŒã®ããŒã¿ãåç §ããå ŽåãRLS ã®èšå®ãå°ãè€éã«ãªããŸãã
ãã®ãããã现ããèšå®ããã®ã¯å€§å€ãªã®ã§ãã©ã³ãã³ã°ã®ããŒã¿ã¯ããã¥ãŒãã䜿ã£ãŠããŠãŒã¶ãŒããšã«å¿ èŠãªããŒã¿ã ããéèšããŠè¡šç€ºããŠããŸãã
ãã¥ãŒãšã¯ç°¡åã«èšããšãäºåã«å®çŸ©ããã¯ãšãªã®çµæãããŒãã«ã®ããã«æ±ãããã®ã§ãã
äŸïŒå®éã®ãã¥ãŒãšã¯éããŸãïŒ
CREATE VIEW user_rankings AS
SELECT user_id, COUNT(*) AS correct_answers
FROM quiz_answers
WHERE is_correct = true
GROUP BY user_id
ãã®ããã«ãã¥ãŒã䜿ãããšã§ãRLS ã®å¶çŽãåããã«ãå¿ èŠãªããŒã¿ã ããç°¡åã«ååŸã§ããããã«ãªããŸãã
ãŸããå¿ ãåºå®ã®æ å ±ããååŸããªãã®ã§ãã»ãã¥ãªãã£çã«ãå®å¿ã§ãã
ä»åŸãSupabase ã䜿ã£ãŠãŠãŒã¶ãŒåå åã®ã¢ããªã±ãŒã·ã§ã³ãäœãå ŽåãRLS ãšãã¥ãŒã®çµã¿åããã¯éåžžã«æå¹ãªææ®µã ãšæããŸãã
ããã·ã¥ããŒãæ©èœ
Learning Next ã§ã¯ããŠãŒã¶ãŒãèªåã®åŠç¿ç¶æ³ãææ¡ã§ãã ããã·ã¥ããŒã æ©èœãå®è£ ããŠããŸãã
- Learning Next: ããã·ã¥ããŒã
éåžžã®ããã°ã©ãã³ã°åŠç¿ãµã€ããã¹ã¯ãŒã«ã§ã¯ãåŠç¿é²æã®å¯èŠåãªã©ã ãã§çµããããšãå€ãã§ãããLearning Next ã§ã¯ä»¥äžã®ãããªæ©èœãå®è£ ããŠããŸãã
ããã¹ãåŠç¿é²æã®å¯èŠå
ããã·ã¥ããŒãå ã§ãããã¹ãããŒã¹ã®åŠç¿é²æãå¯èŠåããæ©èœãæäŸããŠããŸããããã«ããããŠãŒã¶ãŒã¯èªåã®åŠç¿ç¶æ³ãäžç®ã§ææ¡ã§ããããã«ãªããŸãã
ã³ãŒã¹ããšãããã«ãã£ãã¿ãŒãã¬ãã¹ã³ããšã«åŠç¿é²æãå¯èŠåã§ããå šäœã®éæçãæªåŠç¿ã®ã¬ãã¹ã³ã確èªã§ããŸãã
ãåããã¹ãç®æãäžç®ã§ããããã®ã§ãåŠç¿ã®ã¢ãããŒã·ã§ã³ã«ãã€ãªããã®ã§ã¯ãªãããšæããŸãã
ã³ãŒã¹å¥ã®ç·Žç¿åé¡éæç
ããã·ã¥ããŒãã§ã¯ãåã³ãŒã¹ããšã®ç·Žç¿åé¡ã®éæçã衚瀺ããŠããŸãã
ãŸãããããã¯ããšã«åŠç¿é²æãå¯èŠåããã©ã®åéãåŸæã§ã©ã®åéãèŠæããææ¡ã§ããã®ã§ãããšã§éç¹çã«åŠç¿ããããšãã§ããŸãã
å人çã«ãã²ãŒã ã§ãå®çžŸãåããŠããã®ã倧奜ããªã®ã§ãäžçªãã ãã£ãæ©èœãããããŸããã
é£ç¶åŠç¿èšé²ïŒã¹ããªãŒã¯ïŒ
çããã¯ãã¹ããªãŒã¯ããšããèšèãèããããšããããŸããïŒ
ããã¯ãç®æšãéæããããã«ãé£ç¶ããŠè¡åãç¶ããããšããæãããã§ãã
2016 幎㫠Apple Design Award ãåè³ãã Streaks ãšããã¢ããªãæåã§ããŠãç§ãè±èªåŠç¿ã«æçšããŠããŸãã
æ©èœã¯è³ã£ãŠã·ã³ãã«ã§ã ãããããæ±ºããç®æšãæ¯æ¥ããªããç»é²ããã ã ã§ãã
1 æ¥ã®çµããã«ãªã£ãŠãç®æšãéæããŠããªãå Žåãã¢ããªãéç¥ã§ãªãã€ã³ãããŠãããŸãã
ããçšåºŠé£ç¶èšé²ã䌞ã³ãŠãããšãéåããããããªããšããå¿çãåãã®ã§ãæå°ã§ãç®æšãéæããããšããŸãã
ã©ããããããšãããšãåèš 20 æéã®é·è·é¢ãã©ã€ãç§»åãçµããåŸã§ãã空枯ã®ãã³ãã§ããããè±èªåŠç¿ãããŠãã¹ããªãŒã¯ãéåããããªãããã«ãããããã§ãã
ãããªå®äœéšãããšã«ãLearning Next ã§ã¯ãŠãŒã¶ãŒã® é£ç¶åŠç¿æ¥æ° ãããã·ã¥ããŒãã§å¯èŠåããŠããŸãã
åŠç¿èšé²ã䌞ã³ãŠãããšæ°åãã¢ã€ã³ã³ãå€åããŠãããéææãæããããããã«ãªã£ãŠããŸãã
ãã ãLearning Next ã¯ãããŸã§ Web ã¢ããªã§ãããããã·ã¥éç¥ãã§ããªãããããŠãŒã¶ãŒã«åŠç¿ãä¿ããªãã€ã³ããŒæ©èœã¯å®çŸã§ããŠããŸããã
ãã®ãããã¯ãã¯ãã¢ãã€ã«ã¢ããªã®æ¹ãåŸæãªãšããã§ããã
ãŠãŒã¶ãŒãžã®ãªãã€ã³ããŒæ©èœã¯ãä»åŸã®èª²é¡ãšããŠèããŠããŸãã
èªèšŒã»èª²éæ©èœ
ããŠããããŸã§ã¯ãæ©èœããäžå¿ã«ç޹ä»ããŠããŸããããLearning Next ã§ã¯ èªèšŒ 㚠課é ã®æ©èœãå®è£ ããŠããŸãã
Clerk ã«ããèªèšŒæ©èœ
èªèšŒåšãã¯å®å šã« Clerk ã«ãä»»ãããŠããŸãã
ãããã»ããšãŒãŒãŒãŒãŒã«æ¥œã§ããŠãã¢ãŒãã«ã§ã®æ°èŠç»é²ããã°ã€ã³ããã¹ã¯ãŒããªã»ãããªã©ãå¿ èŠãªæ©èœã¯å šãŠçšæãããŠããŸãã
å¿ èŠãªèšå®ãå°ãªãã15 åãããã°ä»¥äžã®ãããªã¢ãŒãã«å ãã°ã€ã³ããµã¯ããšå®è£ ã§ãã¡ãããŸãã
ããã GoogleãGitHubãApple ãªã©ã®å€éšèªèšŒãç°¡åã«çµã¿èŸŒããã®ã§ããŠãŒã¶ãŒã«ãšã£ãŠã䟿å©ã§ãã
ãã¡ãããã¢ãŒãã«å ã ãã§ãªããåå¥ããŒãžãšããŠã®æ°èŠç»é²ããã°ã€ã³ããŒãžãçšæã§ããŸãã
- Learning Next: ãã°ã€ã³ããŒãž
å¬ããã®ããããšãã° Next.js ã§ããã°ä»¥äžã®æ°è¡ã ãã§æäœéã®ãã°ã€ã³ããŒãžãäœãããšããããšã§ãã
import { SignIn } from '@clerk/nextjs';
export default function Page() {
return <SignIn />;
}
ãã¡ããããã¶ã€ã³ãæ©èœãã«ã¹ã¿ãã€ãºãããå Žåã¯ãClerk ã®ã³ã³ããŒãã³ãã䜿ã£ãŠèªç±ã«å®è£ ã§ããŸãã
ãã®ããæ¹ã Clerk ã®å ¬åŒããã¥ã¡ã³ãã«æžãããŠããŸãã
Next.js 以å€ã«ã React, iOS, Vue.js, Expo, Rails, Python, Go ãªã©ãªã©ãããŸããŸãªãã©ãããã©ãŒã ã§å©çšã§ããŸãã
ä»åŸãç§ãèªèšŒæ©èœãäœããšãªã£ãã Clerk ãéžã¶ãšæããŸãã
äžå¿ãæ¥æ¬èªåãã§ãããããªã®ã§ãããåŸè¿°ããèª²éæ©èœã¯æªå¯Ÿå¿ã®ããã§ãã«ã¹ã¿ãã€ãºãå¿ èŠããã ã£ãã®ã§äžæŠå°å ¥ã¯åŸåãã«ããŸããã
ãµãã¹ã¯ãªãã·ã§ã³èª²é
Learning Next ã§ã¯åŠç¿ããã¹ãã®äžéšãææåããŠããããµãã¹ã¯ãªãã·ã§ã³èª²é ãå®è£ ããŠããŸãã
æ¬æ¥ãStripe ã Pay.jp ãªã©ã®æ±ºæžãµãŒãã¹ã䜿ãããšãå€ãã®ã§ãããä»å㯠Clerk ã®ãµãã¹ã¯ãªãã·ã§ã³æ©èœãå©çšããŸããã
éåžžã§ããã°ãStripe ãªã©ã®æ±ºæžãµãŒãã¹ã䜿ãå Žåã以äžã®ãããªããšãèªåã§å®è£ ããå¿ èŠããããŸãã
- ãŠãŒã¶ãŒã®ãµãã¹ã¯ãªãã·ã§ã³ç¶æ ã®ç®¡ç
- 課éãã©ã³ã®äœæã»æŽæ°
- 課éå±¥æŽã®ç®¡ç
- 課é倱ææã®ãšã©ãŒãã³ããªã³ã°
- 課éæåæã®ãŠãŒã¶ãŒãžã®éç¥
- 課éãã©ã³ã®å€æŽããã£ã³ã»ã«ã®åŠç
- 幎éãã©ã³ã®å²åŒé©çš
äžæ¹ãClerk ã䜿ããšããããã®åŠçãã»ãšãã©èªåã§è¡ã£ãŠãããŸãã
Stripe ã¢ã«ãŠã³ãã®çšæã Clerk èšå®ã®äžéšãšããŠè¡ããã®ã§ãæéãå€§å¹ ã«åæžãããŸãã
ææ°æã¯ 0.7% (å·çæç¹) ã ãã§ãã®ã§ãéçºå·¥æ°ãèãããšãååã«ã³ã¹ãããã©ãŒãã³ã¹ãè¯ããšæããŸãã
çŸåšã¯ããŒã¿çãšããããšã§ãæ¥æ¬åã«ã¯å¯Ÿå¿ããŠããªãã£ããããã©ã³æéã®å€æŽã«å¶éããã£ããããŸãããä»åŸã®ã¢ããããŒãã«æåŸ ããŠããŸãã
ãŸãããã©ã³ããšã«ãã§ããããšããããã·ã¥ããŒãã§èšå®ã§ããã®ã楜ã¡ãã§ãã
ããã«å¬ããã®ãããµãã¹ã¯ãªãã·ã§ã³ç»é²ãªã©ã®ã³ã³ããŒãã³ããçšæãããŠããããšã§ãã
Clerk ã§èšå®ããæ å ±ãèªåçã«åæ ãããããªæãã®ç»é¢ãç°¡åã«å®è£ ã§ããŸãã
ã«ãŒãæ å ±ã®å ¥åã³ã³ããŒãã³ããªã©ãçšæãããŠããã®ã§ã決æžåšãã®å®è£ ã¯ãã¹ãŠ Clerk ã«ãä»»ãããŠããŸãã
äœè«ã§ãããæ¬æ¥ã®çŸå Žã§ Stripe ã®èª²éæ©èœãå®è£ ããããšãããã®ã§ãããããã¯æ¬åœã«å€§å€ã§ããã
絶察ã«ãã°ããã£ãŠã¯ãããªãããæ€èšŒã倧å€ã ãããµãã¹ã¯ãªãã·ã§ã³ã®æŽæ°ããã£ã³ã»ã«ã決æžå€±ææã®åŠçãªã©ãèæ ®ãã¹ãããšãå€ãããŠå°çã§ãã
ããã Clerk ãã»ãšãã©èªåã§ãã£ãŠãããã®ã§ãéçºè ãšããŠã¯æ¬åœã«å©ãããŸãã
å è¿°ã®éãããŒã¿çãšããããšããããã¡ãã£ãšç©è¶³ããªãç¹ã¯ãããã®ã®ã²ãšãŸãã¯ããã§ååã§ãã
æ©èœã®ãŸãšã
æ©èœç޹ä»ã¯ãããŸã§ã§ãã
Web ãšã³ãžãã¢ã®åãããã°ã©ãã³ã°ã¹ã¯ãŒã«è¬åž«ã Udemy ã§ããã°ã©ãã³ã°æè²ã«æºãã£ãŠããããšããã£ãŠãããªãç±ããããŠéçºããŸããã
å®ã¯ä»ã«ã ãšã³ãžãã¢é©è·èšºæ ã åŠç¿ããŒãããã ãªã©ã®æ©èœãæ¢ã«äœã£ãŠããã®ã§ãããUI ã®èª¿æŽãããŒã¿ã®æŽåããŸã çµãã£ãŠããªãã®ã§ãä»åã¯å²æããŸãã
ããã ãã®æ©èœã 1 ã¶æã§å®è£ ã§ããã®ã¯ãæ¬åœã« Cursor åãš Claude ã®ãããã ãšæã£ãŠããŸãã
ããããã¯ãå®éã«éçºãé²ããäžã§æããããšããAI é§åéçºã®ããŠããŠããäŒãããŸãã
AI é§åéçºã®åºæ¬æŠç¥
ãŸããç§ãä»åæ¡çšãã AI é§åéçºã®åºæ¬çãªæµãã説æããŸãã
éçºã®å¹çåãšå質åäžãå³ããŸããã®ã§ãä»åŸã®ãããžã§ã¯ãã«ãå¿çšã§ãããšæããŸãã
1. Claude ã§èŠä»¶å®çŸ©ã»åºæ¬èšèš
æåã« Claude ã䜿ã£ãŠã以äžã®ããšãæŽçããŸããã
- ãµãŒãã¹ã®å šäœåãšæ©èœèŠä»¶
- æè¡æ§æãšã¢ãŒããã¯ãã£
- ããŒã¿ããŒã¹èšèš
- API èšèš
ããšãã°ã以äžã®ãããªããã³ããã Claude ã«æããŠãèŠä»¶å®çŸ©ãè¡ããŸããã
ããã¯ç·Žç¿åé¡ã®é²æç®¡çããã·ã¥ããŒããäœã£ããšãã«ãå®éã«æããããã³ããã§ãã
# 圹å²
åªç§ãªãããã¯ããããŒãžã£ãŒ
# èæ¯
ããã°ã©ãã³ã°åŠç¿çšã«ãç·Žç¿åé¡ãè§£ãã Web ãµã€ããéå¶ããŠããŸãã
ãŠãŒã¶ãŒã¯ãRuby ã JavaScript ãªã©ã®åéããšã«ã¯ã€ãºã«ææŠããåŠç¿ãé²ããŠããŸãã
ãŠãŒã¶ãŒããšã«ãè§£ããåé¡ã®å±¥æŽã管çããããã·ã¥ããŒãã§ãã®é²æç¶æ³ã衚瀺ããæ©èœã远å ããããšèããŠããŸãã
é¢é£ããããŒãã«ã®æ§é ã¯ä»¥äžã®éãã§ãã
```sql
CREATE TABLE quizzes (
... å®éã«ã¯ããŒãã«æ§é ã® SQL å®çŸ©ãç¶ã ...
```
# ç®ç
ãŠãŒã¶ãŒãèªåã®åŠç¿é²æãææ¡ã§ãããããªããã·ã¥ããŒãæ©èœã®èŠä»¶ãšåºæ¬èšèšãäœãããšã
# åœä»€
äžèšã®èæ¯ãç®çãæºããããã®ããã·ã¥ããŒãæ©èœã®èŠä»¶ã以äžã®èгç¹ããèããŠãã ããã
- ãããŸã§è§£ããåé¡åæ°ïŒè§£ããå顿°ãã§ã¯ãªãã¯ã€ãºã«ãã£ã¬ã³ãžããåæ°ïŒã¯ããã
- ruby, rspec ãªã©åéããšã«äœåããããŠãããã®åé¡ã®ãã¡äœïŒ
ãè§£ããŠãããããããïŒã€ãŸããé²æç¶æ³ããããïŒ
- ããããåéããšã«ãé
åããªã©ãããã¯ãããã®ã§ãããããã鲿ãããã
- ã¬ãã«ãåçŽã»äžçŽã»äžçŽããšãããããŠãã®ã§ããããããã
- å
šäœãšããŠãèªåã®åŸæã»äžåŸæãããã
- é 匵ã£ãåã ãä»ã®äººã«èªæ
¢ããããªãããã«ããŠãæ¿èªæ¬²æ±ãæºãã
- Next.js ã®ç¹æ§ãå©çšããŠãã£ãã·ã¥ãé§äœ¿ããŠè¡šç€ºããã©ãŒãã³ã¹ãããã
- éšåçã«èªã¿èŸŒããªã©ãããã©ãŒãã³ã¹ãæèããèšèšã«ãã
- èªåã®åŠç¿ç¶æ³ãèŠãããããªã²ãŒããã£ã±ãŒã·ã§ã³èŠçŽ ã倧äºã«ããã
ãã¡ãããCursor ã§ãåæ§ã®èŠä»¶å®çŸ©ãè¡ãããšã¯ã§ããŸãããClaude ã¯é·ãæèã«ã察å¿ã§ããã®ã§ããã詳现ãªèŠä»¶ãåŒãåºãããšãã§ããŸãã
æ¬æ¥ã§ããã°ãããã£ãèŠä»¶å®çŸ©ã¯äººéãèãããã®ã§ããã人éã¯ãã¢ã€ãã¢ã®çš®ãã ããåºããŠãããšã¯ãããã¯ããããŒãžã£ãŒã«ãªããã£ã Claude ã«èããŠãããããšã§ãããå¹ççã«é²ããããšãã§ããŸããã
ãã®æ®µéã§ãã£ãããš èŠä»¶å®çŸ©ãšèšèšãåºãã ããšã§ãåŸã®å®è£ ãã¹ã ãŒãºã«ãªããŸãã
2. æ©èœããšã«ã¿ã¹ã¯åè§£
次ã«ã倧ããªæ©èœã 现ããªã¿ã¹ã¯ã«åè§£ ããŸããã
äŸãã°ãç·Žç¿å顿©èœããªãã以äžã®ããã«åè§£ããŸãã
- åé¡è¡šç€ºã³ã³ããŒãã³ã
- åçå ¥åã³ã³ããŒãã³ã
- çµæè¡šç€ºã³ã³ããŒãã³ã
- çµ±èšæ å ±ã³ã³ããŒãã³ã
- ã¿ã€ã ã¢ã¿ãã¯æ©èœ
ãã®ããã«ãäžã€äžã€ãç¬ç«ããŠå®è£ ã§ããã¬ãã« ãŸã§åè§£ããããšãéèŠã§ãã
ã¡ãªã¿ã«ãã¿ã¹ã¯åè§£ã Claude ã«ãé¡ãããŸããã
# 圹å²
åªç§ãªãããã¯ããããŒãžã£ãŒ
# èæ¯
ããã°ã©ãã³ã°åŠç¿çšã«ãç·Žç¿åé¡ãè§£ãã Web ãµã€ããéå¶ããŠããŸãã
ãŠãŒã¶ãŒã¯ãRuby ã JavaScript ãªã©ã®åéããšã«ã¯ã€ãºã«ææŠããåŠç¿ãé²ããããããã«ããŸãã
# ç®ç
ç·Žç¿å顿©èœãå®è£
ããããã®ã¿ã¹ã¯ãåè§£ããå®è£
ãããã圢ã«ããããšã
# åœä»€
ã¹ããããã€ã¹ãããã§å®è£
ãè¡ãããã«ãç·Žç¿å顿©èœãäœæããããã«ã¿ã¹ã¯ãåè§£ããŠãã ããã
# åè
é¢é£ããããŒãã«ã®æ§é ã¯ä»¥äžã®éãã§ãã
```sql
...
```
# å¶çŽäºé
- Next.js 15 (App Router) + TypeScript + Tailwind CSS ã䜿çš
- Supabase ãããã¯ãšã³ãã«äœ¿çš
- Clerk ãèªèšŒã«äœ¿çš
- ã³ã³ããŒãã³ãã¯é¢æ°ã³ã³ããŒãã³ã + hooks
- CSS 㯠Tailwind CSS ã®ã¿äœ¿çš
- TypeScript ã®åå®å
šæ§ãæåªå
- ãšã©ãŒãã³ããªã³ã°ã¯å¿
é
- ããŒãã£ã³ã°ç¶æ
ã® UI ãå®è£
- ã¬ã¹ãã³ã·ã察å¿ã¯å¿
é ïŒã¢ãã€ã«ãã¡ãŒã¹ãïŒ
ãã®ããã«ãClaude ã«ã¿ã¹ã¯åè§£ãæåã«ããŠããããšã§ãCursor ãè¿·ããã«å®è£ ã«åãæããããšãã§ããã®ã§ã¯ãªãããšæããŸãã
仿ãã°ããã®ã¿ã€ãã³ã°ã§ .cursorrules ã®äžèº«ãåãã㊠Claude ã«æž¡ãã°ãæ¢åã®èšèšãæ¹éã«åºã¥ããŠã¿ã¹ã¯åè§£ãããŠããããããããŸããã
3. Cursor ã«åºæ¬èšèšæžãæž¡ããŠå®è£
åã¿ã¹ã¯ã«ã€ããŠãCursor ã«ä»¥äžãæž¡ããŠå®è£ ããŠããããŸãã
- å
±éæç€ºæžïŒ
.cursorrulesïŒ - æ©èœããšã®åºæ¬èšèšæž
- åèã«ãã¹ãå ¬åŒããã¥ã¡ã³ã
ãã®æã®ãã€ã³ãã¯ãäžæ°ã«å šéšäœãããã®ã§ã¯ãªããæ©èœåäœã§åºåã ããšã§ãã
AI ãšãŒãžã§ã³ãã䜿ã£ãŠéçºãããããšããããããªããéäžã§èšèšã埮åŠã ã£ããšãã® ææ»ãå°ç ãçµéšããããšããããããããŸããã
ãã®ãããCursor ã«æž¡ãèšèšæžã¯ ã§ããã ãå
·äœçã« ããã〠å°ããªåäœã§å®è£
ãäŸé Œ ããããšãéèŠã§ãã
ãªããCursor ã«æž¡ãå
±éæç€ºæž .cursorrules ã«ã€ããŠã¯åŸè¿°ããŸãã
4. å®è£ åŸã®ããã¥ã¡ã³ãå
ãããäžçªãCursor ã®ãã㪠AI ãšãŒãžã§ã³ãã䜿ã£ãéçºã§éèŠãªãã€ã³ãã§ãã
æ©èœã宿ããããå¿ ã ããã¥ã¡ã³ãå ããããšãããããããŸãã
ç§ã®å Žåãããšãã° src/app/dashboard ãšãã£ãããŒãžãäœã£ãããããã« DASHBOARD_README.md ãšããããã¥ã¡ã³ãã眮ããŠããŸãã
ãã®ããã¥ã¡ã³ãã«ã¯ãå®è£
ããæ©èœã®æŠèŠãèšèšãäœ¿ãæ¹ãªã©ã詳ããæžããŠããŸãã
ããšãã°ã以äžã®ãããªç¹ãçã蟌ãã ããã¥ã¡ã³ãã Cursor ã«æžãããŸããã
- 䜿ã£ãŠããæè¡ã¹ã¿ãã¯
- æ©èœã®æŠèŠ
- èæ¯ã»ç®ç
- ã³ã³ããŒãã³ãèšèš
- ã§ããããšã»å¶éäºé
- ã³ã³ããŒãã³ãäœ¿çšæã®ãªãã·ã§ã³
- é¢é£ãã¡ã€ã«ã»ãã£ã¬ã¯ããªæ§é
- 泚æç¹
ãªãããã¥ã¡ã³ãåãéèŠããšãããšãAI ãšãŒãžã§ã³ã㯠äžåºŠå®è£
ããã³ãŒããå¿ããŠããŸã ããã§ãã
ãã®ãããåŸããåãæ©èœãä¿®æ£ããããå¥ã®ãããžã§ã¯ãã§åå©çšããéã«ãããã¥ã¡ã³ãããªããš äœãã©ãå®è£
ãããæãåºããªã ãšããäºæ
ã«ãªããŸãã
ã¡ãã£ãšäžæéã§ã¯ãããã§ãããããã¥ã¡ã³ãåãæ ããšãåŸã
ã®ä¿å®æ§ãåå©çšæ§ã«å€§ããªåœ±é¿ãåºãŸãã
ãã®ãããå®è£
åŸã¯å¿
ãããã¥ã¡ã³ãåããããšã匷ãããããããŸãã
ã¡ãªã¿ã«ç§ã¯ãäžéãæ©èœãå®è£ ããåŸã«ãCursor ã«ä»¥äžã®ãããªããã³ãããæããŠããã¥ã¡ã³ããæžãããŸããã
# 圹å²
åªç§ãªããã³ããšã³ããšã³ãžãã¢
# èæ¯
Learning Next ãšããããã°ã©ãã³ã°åŠç¿ãã©ãããã©ãŒã ãéçºããŠããŸãã
# ç®ç
Learning Next ã®ç·Žç¿å顿©èœã®å®è£
ãå®äºããŸããã
ãã®æ©èœã«ã€ããŠã以äžã®å
容ãå«ãããã¥ã¡ã³ããäœæããåŸã«ãšã³ãžãã¢ãæ©èœã®ä¿®æ£ã远å ãè¡ãéã«è¿·ããéçºã§ããããã«ããŸãã
# åœä»€
以äžã®å
容ãå«ãããã¥ã¡ã³ããäœæããŠãã ããã
- 䜿ã£ãŠããæè¡ã¹ã¿ãã¯
- æ©èœã®æŠèŠ
- èæ¯ã»ç®ç
- ã³ã³ããŒãã³ãèšèš
- ã§ããããšã»å¶éäºé
- ã³ã³ããŒãã³ãäœ¿çšæã®ãªãã·ã§ã³
- é¢é£ãã¡ã€ã«ã»ãã£ã¬ã¯ããªæ§é
- 泚æç¹
ããšããããã£ãããã¥ã¡ã³ããäœã£ãŠãããšäººéç®ç·ãšããŠãå©ãããŸããã
æ°æ¥çµã€ãšèªåãäœãèããŠå®è£ ããã®ãå¿ããŠããŸãã®ã§ãããã¥ã¡ã³ããèŠè¿ãããšã§ åœæã®æå³ãæãåºãã ã®ã¯å€§ããªã¡ãªããã§ãã
èŠä»¶å®çŸ©ã»åºæ¬èšèšæžã Cursor ã«æž¡ããŠå®è£ ãäŸé Œããæµã
è²ããªããæ¹ãããããšã¯æããŸãããç§ãä»åæ¡çšããæµãã¯ä»¥äžã®éãã§ãã
- Claude ã§èŠä»¶å®çŸ©ã»åºæ¬èšèšãè¡ã
- äœæããèšèšæžãããŒã¯ããŠã³ãã¡ã€ã«ãšããŠä¿å
- Cursor ã«
.cursorrulesãšèšèšæžãæž¡ããŠå®è£ ãäŸé Œ - å®è£ åŸãCursor ã«ããã¥ã¡ã³ãåãäŸé Œ
èšèšæžããã£ããããŠããã°ãCursor ã«æž¡ãããã³ããã¯æå°éã§æžã¿ãŸãã
ããšãã°ãæž¡ããŠããèšèšæžã«åºã¥ããŠãç·Žç¿å顿©èœãå®è£ ããŠãã ããããšãã£ãæãã§ãã
éã«èšããšãèšèšæžãäžååã ãš Cursor ãè¿·ã£ãŠããŸããå®è£ ãé²ãŸãªããªãå¯èœæ§ããããŸãã®ã§ãèšèšæžã¯ãã£ãããšäœæããŠããããšã倧äºã ãªãšæããŸããã
å®éã«äœ¿ã£ã .cursorrules ã®èšå®
ããããã¯ãå ·äœçãªããŠããŠããäŒãããŸãã
ãŸããCursor ã§ã®éçºãå¹çåããããã«èšå®ãã .cursorrules ã§ãã
ãããžã§ã¯ãéå§æã« Claude ãããŒã¹ã«äœæãã€ã€ãéçºéäžã§ Cursor åãã¢ãã¡ããã ã£ãç¹ãçã蟌ã¿ãªãã調æŽããŸããã
ãããã Next.js / Tailwind CSS / TypeScript / Supabase ãªã©ã䌌ããããªæè¡ã¹ã¿ãã¯ã§éçºããæ¹ã¯åèã«ãªãããšæããŸãã
ãšãŠãé·ãã®ã§æããããã§ãããŸããã
cursorrules
# Next.js + TypeScript ãããžã§ã¯ãã®ã³ãŒãã£ã³ã°èŠçŽ
## åææ¡ä»¶
- ãã®ãããžã§ã¯ãã¯ä»¥äžã®æè¡ã¹ã¿ãã¯ã䜿çšããŠããŸãïŒ
- Next.js 15 (App Router)
- TypeScript 5.4+
- Tailwind CSS (ã¹ã¿ã€ãªã³ã°)
- Lucide Icons (ã¢ã€ã³ã³)
- Devicon (éçºæè¡ã¢ã€ã³ã³)
## ãã£ã¬ã¯ããªæ§é
- `src/app`: Next.js App Router ã®ããŒãžæ§é
- `src/components`: React ã³ã³ããŒãã³ã
- `src/lib`: å€éšã©ã€ãã©ãªãšã®çµ±åã³ãŒã
- `src/hooks`: ã«ã¹ã¿ã React Hooks
- `src/types`: ã°ããŒãã«ãªåå®çŸ©
- `src/styles`: ã°ããŒãã«ã¹ã¿ã€ã«ã·ãŒã
- `src/utils`: ãŠãŒãã£ãªãã£é¢æ°
## åºæ¬ã³ãŒãã£ã³ã°èŠçŽ
### åå®å
šæ§
- 峿 Œãªåä»ããè¡ã£ãŠ
- å¿
èŠã«å¿ããŠåã¬ãŒãã䜿çš
- `any`åã®äœ¿çšã¯ååãšããŠé¿ããŠ
- ãã¹ãŠã®ã³ã³ããŒãã³ãã® props ã«ã¯åå®çŸ©ãè¡ã£ãŠ
- å€éšããŒã¿ã®åã¯`src/types`ãã£ã¬ã¯ããªã«å®çŸ©
### åœåèŠå
- ã³ã³ããŒãã³ã: `PascalCase.tsx`
- ãŠãŒãã£ãªãã£é¢æ°: `camelCase.ts`
- 宿°: `UPPER_SNAKE_CASE`
- App Router ã®ããŒãž: `page.tsx`
- ãã£ã¬ã¯ããªå: `kebab-case`
### ã³ãŒãã£ã³ã°ã¹ã¿ã€ã«
- ES2015 以éã®ã¢ãã³ãªæ§æã䜿çš
- 颿°ã¯ã¢ããŒé¢æ°ã§äœæ
- æšå¥š: `const sample = (value: string): string => value.toUpperCase();`
- éæšå¥š: `function sample(value: string) { return value.toUpperCase(); }`
- ã³ã³ããŒãã³ãã¯é¢æ°ã³ã³ããŒãã³ããšããŠå®è£
- å
¬é颿°ãã³ã³ããŒãã³ãã«ã¯ JSDoc ãèšè¿°
- ã¯ã©ã¹ã®ä»£ããã«é¢æ°ã䜿çš
### Next.js åºæã®ã¬ã€ãã©ã€ã³
- å¯èœãªéã Server Components ã䜿çš
- ã¯ã©ã€ã¢ã³ãã§ã®ç¶æ
管çãå¿
èŠãªå Žåã®ã¿`'use client'`ãã£ã¬ã¯ãã£ãã䜿çš
- ã¡ã¿ããŒã¿ã¯ export functions ã䜿ã£ãŠå®çŸ©
- ç»åæé©åã«ã¯å¿
ã`next/image`ã®`Image`ã³ã³ããŒãã³ãã䜿çš
- ãªã³ã¯ã«ã¯å¿
ã`next/link`ã®`Link`ã³ã³ããŒãã³ãã䜿çš
- Server Actions ã¯ãµãŒããŒã³ã³ããŒãã³ãã®ã¿ã§ Form ã§äœ¿çš
- Next.js 15 ã§ã¯`params`ãš`searchParams`ã`Promise`åã«ãªã£ããããããŒãžã³ã³ããŒãã³ãã§äœ¿çšããéã¯å¿
ã`await`
- äŸ: `const resolvedParams = await params`
- åå®çŸ©ã§ã¯`params: Promise<{ id: string }>`ã`searchParams: Promise<{ page?: string }>`ã®ããã«èšè¿°
### ã¹ã¿ã€ãªã³ã°
- `docs-copilot/design-rules/LN_DESIGN_GUIDE.md` ã®ãã¶ã€ã³ã¬ã€ãã©ã€ã³ã«åŸã
- ã¹ã¿ã€ãªã³ã°ã«ã¯ Tailwind CSS ã䜿çš
- ã«ã©ãŒã¯ Tailwind ã®ããã©ã«ãã«ã©ãŒãã¬ããã䜿çš
- ã¬ã¹ãã³ã·ããã¶ã€ã³ã«ã¯ Tailwind ã®ãã¬ãŒã¯ãã€ã³ãã䜿çš
### ããã©ãŒãã³ã¹æé©å
- äžèŠãªåã¬ã³ããªã³ã°ãé²ãããã«`useMemo`ãš`useCallback`ãé©åã«äœ¿çš
- 倧ããªã³ã³ããŒãã³ãã¯`React.lazy`ãš`Suspense`ã䜿çšããŠåçã€ã³ããŒã
- ã¯ã©ã€ã¢ã³ãã³ã³ããŒãã³ãã¯å¿
èŠãªå Žåã®ã¿ã«éå®
### ããŒã¿åŠçãšãšã©ãŒãã³ããªã³ã°
#### Supabase ã¯ãšãªã®ãã¹ããã©ã¯ãã£ã¹
- ããŒã¿ã®æŽåæ§ãä¿ã€ãããäžæ£ãªå€ãäºåã«ãã£ã«ã¿ãªã³ã°
- çµ±èšããŒã¿ååŸæã¯`null`å€ãé©åã«é€å€
- ãšã©ãŒãã³ããªã³ã°ã¯å¿
ãå®è£
ãããã©ãŒã«ããã¯å€ãæäŸ
```typescript
// æšå¥šïŒäžæ£ããŒã¿ãé€å€ããã¯ãšãª
const { data, error } = await supabase
.from('table_name')
.select('columns')
.not('important_field', 'is', null)
.order('created_at', { ascending: false });
if (error) {
console.error('ããŒã¿ååŸãšã©ãŒ:', error);
return fallbackValue; // å¿
ããã©ãŒã«ããã¯å€ãè¿ã
}
```
#### UI ã®å
ç¢æ§
- ããŒã¿ã®ç¶æ
ã«å¿ããé©åãªè¡šç€ºåå²ãå®è£
- ããŒãã£ã³ã°ç¶æ
ããšã©ãŒç¶æ
ãç©ºç¶æ
ãèæ
®
- ããŒã¿äžæŽåããã£ãŠãé©åãªã¡ãã»ãŒãžã衚瀺
```typescript
// æšå¥šïŒ3段éã®è¡šç€ºããžãã¯
{
data?.validField ? (
<NormalDisplay data={data} />
) : data?.partialField ? (
<PartialDisplay message="ããŒã¿æºåäž" />
) : (
<EmptyDisplay message="ããŒã¿ããããŸãã" />
);
}
```
#### çµ±èšããŒã¿ã®åŠç
- éèšåŠçã¯ããã³ããšã³ãã§è¡ãéãåå®å
šæ§ã確ä¿
- `Number()`ã䜿çšããå倿ã§ã¯`|| 0`ã§ãã©ãŒã«ããã¯å€ãèšå®
- æ¥ä»èšç®ã§ã¯`Date`ãªããžã§ã¯ãã®åŠ¥åœæ§ãæ€èšŒ
```typescript
// æšå¥šïŒå®å
šãªçµ±èšããŒã¿åŠç
data.forEach((session) => {
const techRate = Number(session.tech_rate) || 0;
const attempts = Number(session.total_attempts) || 0;
if (techRate > 0) {
// æå¹ãªå€ã®ã¿åŠç
// çµ±èšåŠç
}
});
```
## ãã¹ãã¬ã€ãã©ã€ã³
### åºæ¬æ¹é
- åºæ¬çãªãŠããããã¹ããå®è£
- React Testing Library ã䜿çšããŠã³ã³ããŒãã³ãããã¹ã
- å€éšãµãŒãã¹ã®åŒã³åºãã¯ã¢ãã¯ã䜿çš
### Supabase ã®ãã¹ã
#### ã¢ãã¯åã®åºæ¬æ§é
```typescript
// Supabaseã¯ã©ã€ã¢ã³ãã®ã¢ãã¯å
jest.mock('@/lib/supabase', () => ({
supabase: {
from: jest.fn(),
},
}));
```
#### ã¯ãšãªãã§ãŒã³ã®ã¢ãã¯å
Supabase ã®ã¯ãšãªã¯`.select().eq().order()`ã®ããã«ãã§ãŒã³ãããããåã¡ãœããã§`mockReturnThis()`ã䜿çšïŒ
```typescript
const mockSelect = jest.fn().mockReturnThis();
const mockEq = jest.fn().mockReturnThis();
const mockNot = jest.fn().mockReturnThis();
const mockOrder = jest.fn().mockResolvedValue({
data: mockData,
error: null,
});
(supabase.from as jest.Mock).mockReturnValue({
select: mockSelect,
eq: mockEq,
not: mockNot,
order: mockOrder,
});
```
#### ãšã©ãŒãã³ããªã³ã°ã®ãã¹ã
æ£åžžç³»ã ãã§ãªãã以äžã®ãšã©ãŒã±ãŒã¹ãå¿
ããã¹ãïŒ
- ããŒã¿ãååšããªãå ŽåïŒ`data: []`ïŒ
- ããŒã¿ã null ã®å ŽåïŒ`data: null`ïŒ
- Supabase ãšã©ãŒã®å ŽåïŒ`error: { message: 'Database error' }`ïŒ
- äŸå€ãçºçããå ŽåïŒ`throw new Error()`ïŒ
#### æ¥ä»åŠçã®ãã¹ã
åºå®æ¥æã§ã®ãã¹ãã«ã¯`jest.useFakeTimers()`ã䜿çšïŒ
```typescript
beforeEach(() => {
jest.useFakeTimers();
jest.setSystemTime(new Date('2024-01-20T12:00:00Z'));
});
afterEach(() => {
jest.useRealTimers();
});
```
### ããŒã¿äžæŽåãžã®å¯Ÿå¿
#### 衚瀺ããžãã¯ã®å
ç¢æ§
ããŒã¿ããŒã¹ã«äžæŽåããŒã¿ïŒäŸïŒ`tech_rate`ã null ã®ã»ãã·ã§ã³ïŒããã£ãŠããUI ãé©åã«åäœãããã 3 段éã®è¡šç€ºããžãã¯ãå®è£
ïŒ
```typescript
// äŸïŒã¿ã€ã ã¢ã¿ãã¯çµ±èšã®è¡šç€º
{
courseStats?.bestTechRate ? (
// 1. ãã¹ãã¹ã³ã¢ãã â æ£åžžãªè¡šç€º
<BestScoreDisplay />
) : courseStats?.totalSessions > 0 ? (
// 2. ã»ãã·ã§ã³ã¯ãããã¹ã³ã¢ãªã â ãèšé²æŽæ°äžã衚瀺
<InProgressDisplay />
) : (
// 3. ã»ãã·ã§ã³ãªã â ãååææŠã衚瀺
<FirstTimeDisplay />
);
}
```
#### ããŒã¿ãã£ã«ã¿ãªã³ã°
çµ±èšé¢æ°ã§ã¯äžæ£ãªããŒã¿ãäºåã«é€å€ïŒ
```typescript
// tech_rateãnullã§ãªãã¬ã³ãŒãã®ã¿ååŸ
const { data, error } = await supabase
.from('time_attack_sessions')
.select('course, tech_rate, created_at')
.eq('user_id', userId)
.not('tech_rate', 'is', null) // éèŠïŒäžæ£ããŒã¿ãé€å€
.order('created_at', { ascending: false });
```
### ãã¹ããã¡ã€ã«ã®åœåãšé
眮
- ãã¹ããã¡ã€ã«ïŒ`src/lib/__tests__/ãã¡ã€ã«å.test.ts`
- ã³ã³ããŒãã³ããã¹ãïŒ`src/components/__tests__/ã³ã³ããŒãã³ãå.test.tsx`
- çµ±åãã¹ãïŒ`src/__tests__/integration/`
## æææ©èœã»èªèšŒã«é¢ããæ
å ±
ããã°ã©ãã³ã°åŠç¿ã®ããã®ææãµãã¹ã¯ãªãã·ã§ã³ã³ã³ãã³ããæäŸãããŠã§ããµã€ããæ§ç¯ããŸããNext.js ãš Clerk Billing ãçµã¿åãããã·ã³ãã«ãªèªèšŒãšãµãã¹ã¯ãªãã·ã§ã³ç®¡çãå®çŸããŸãã
### ã·ã¹ãã æ§æ
- ããã³ããšã³ãïŒããã¯ãšã³ã: Next.js (App Router)
- ãã¹ãã£ã³ã°: Vercel
- èªèšŒïŒãµãã¹ã¯ãªãã·ã§ã³ç®¡ç: Clerk Billing
### åºæ¬ã³ã³ã»ãã
- ã·ã³ãã«ãªå®è£
ãåªå
- å¯èœãªéãå€éšãµãŒãã¹ã®ããã©ã«ãæ©èœã掻çš
- TypeScript ã«ããåå®å
šæ§ã®ç¢ºä¿
- èšå®ããŒã¹ã®ã¢ã¯ã»ã¹å¶åŸ¡
### å®è£
ã«ãããéèŠãªæèš
#### ããŒã¿äžæŽåãžã®å¯Ÿå¿
å®éã®éçšã§ã¯ã以äžã®ãããªããŒã¿äžæŽåãçºçããå¯èœæ§ãããïŒ
- ã¿ã€ã ã¢ã¿ãã¯éäžã§ã®é¢è±ïŒ`tech_rate`ã`null`ã®ã»ãã·ã§ã³ïŒ
- ãšã©ãŒã«ããäžå®å
šãªããŒã¿ä¿å
- ç°ãªãããŒãžã§ã³éã§ã®ããŒã¿æ§é ã®éã
**察çïŒ**
- ããŒã¿ããŒã¹ã¯ãšãªã¬ãã«ã§ã®äžæ£ããŒã¿é€å€
- UI 衚瀺ããžãã¯ã§ã®å€æ®µéãã©ãŒã«ããã¯
- çµ±èšèšç®ã§ã®å®å
šãªå倿ãšããªããŒã·ã§ã³
#### ãŠãŒã¶ãŒäœéšã®åäž
```typescript
// â æªãäŸïŒãã€ããªãªè¡šç€ºå€å®
{
hasData ? <Content /> : <EmptyState />;
}
// â
è¯ãäŸïŒæ®µéçãªç¶æ
衚瀺
{
hasValidData ? (
<FullContent />
) : hasPartialData ? (
<PartialContent message="ããŒã¿æºåäž" />
) : (
<EmptyContent message="ãŸã ããŒã¿ããããŸãã" />
);
}
```
ããããŠæ¹ããŠèŠãŠã¿ããšãããªãèšå€§ã§ããã
ç¹ã« åå®å šæ§ ã ãšã©ãŒãã³ããªã³ã° ãªã©ã®éèŠãªãã€ã³ããæèšããŠããããšã§ãå質ã®é«ãã³ãŒããçæããããããªã£ãŠãããšæããŸãã
ã¡ãã£ãšãã¶ã€ã³é¢ã§ã®åçã¯ããã®ã§ãããããã¯ãŸãå¥ã®æ©äŒã«ãäŒãããŸãã
ã远èšïŒç¶ç·šãæžããŸããã
èŠä»¶å®çŸ©ã»åºæ¬èšèšæžã®å ·äœäŸ
ãããŸã§ã§ãClaude ã䜿ã£ãŠèŠä»¶å®çŸ©ãšåºæ¬èšèšãè¡ããCursor ã«å®è£
ãäŸé Œããæµãã説æããŸããã
次ã«ãå®éã«ã©ã®ãããªèšèšæžãäœæããããå
·äœçãªäŸã瀺ããŸãã
ããšãã°ã以äžã®ãããªèŠä»¶å®çŸ©æžã»åºæ¬èšèšæžã Claude ã«äœæããŠããããŸããã
# ç·Žç¿å顿©èœ èŠä»¶å®çŸ©æžã»åºæ¬èšèšæž
## èŠä»¶å®çŸ©æž
### 1. ãããžã§ã¯ãæŠèŠ
#### 1.1 ç®ç
Learning Next ãã©ãããã©ãŒã ã«ããŠãŒã¶ãŒã®ç解床ã確èªããããã®ç·Žç¿å顿©èœã远å ããã
#### 1.2 èæ¯ãšç®æš
- ãŠãŒã¶ãŒãåŠç¿ããå
容ãèªå·±è©äŸ¡ã§ããä»çµã¿ãå¿
èŠ
- ç¡æãŠãŒã¶ãŒã«ã䟡å€ãæäŸãã€ã€ãæææ©èœãæäŸããããšã§ããã«åŠç¿ã®æ·±åºŠãå¢ã
- Learning Next ãã©ãããã©ãŒã ã®æè²å¹æãé«ãã
#### 1.3 察象ãŠãŒã¶ãŒ
- Learning Next ãã©ãããã©ãŒã ã®ç¡æãŠãŒã¶ãŒ
- ææã³ãŒã¹ãåè¬äžã®ãŠãŒã¶ãŒïŒãããã¯å¥ã®åŠç¿é²æç¢ºèªçšïŒ
### 2. æ©èœèŠä»¶
#### 2.1 ç·Žç¿åé¡ããŒã¿ç®¡ç
- ç·Žç¿åé¡ã¯ã³ãŒã¹ïŒRubyãRailsãRSpecïŒããšã«åé¡
- ãããã¯ïŒé
åãããã·ã¥ãªã©ïŒã«ãã现åå
- é£æåºŠïŒåçŽãäžçŽãäžçŽïŒã«ããåé¡
- å顿ã¯ããŒã¯ããŠã³åœ¢åŒã§äœæïŒã³ãŒããããã¯å«ãïŒ
- 4 æåé¡ãšããã¹ãå
¥ååé¡ã® 2 çš®é¡ããµããŒã
#### 2.2 ç·Žç¿åé¡éžæã»ãã£ã«ã¿ãªã³ã°æ©èœ
- ã³ãŒã¹ããããã¯ãé£æåºŠãã¹ããŒã¿ã¹ïŒæªåç/äžæ£è§£/æ£è§£æžã¿ïŒã§ãã£ã«ã¿ãªã³ã°
- æå€§å顿°ã®éžæïŒ1ã3ã5ã10 åïŒ
- ãã£ã«ã¿çµæã«åºã¥ãåé¡äžèŠ§è¡šç€º
#### 2.3 ç·Žç¿åé¡åçæ©èœ
- éžæåŒåé¡ïŒ4 ã€ã®éžæè¢ããéžæïŒæ£è§£ã¯åžžã«äžã€ïŒ
- ããã¹ãå
¥ååé¡ïŒããã¹ãå
¥åã«ããåç
- 峿ãã£ãŒãããã¯ïŒæ£è§£/äžæ£è§£ã®è¡šç€ºïŒ
- æ£è§£ã®å ŽåïŒç·è²ã§æ£è§£è¡šç€º
- äžæ£è§£ã®å ŽåïŒéžæè¢ãèµ€è²è¡šç€ºãæ£è§£ãç·è²è¡šç€º
#### 2.4 解説ã»èªå°æ©èœ
- é¢é£ããã³ãŒã¹ã®ã¬ãã¹ã³ããŒãžãžã®ãªã³ã¯è¡šç€º
- å¥ã¿ãã§ã®è§£èª¬ããŒãžè¡šç€º
#### 2.5 ãŠãŒã¶ãŒé²æç®¡ç
- ãŠãŒã¶ãŒããšã®åçå±¥æŽã®ä¿å
- ã³ãŒã¹/ãããã¯å¥ã®æ£è§£ç衚瀺
- ãã€ããŒãžã§ã®é²æç¶æ³ç¢ºèª
#### 2.6 ã¢ã¯ã»ã¹å¶åŸ¡
- ç·Žç¿å顿©èœèªäœã¯ç¡æãŠãŒã¶ãŒãå©çšå¯èœ
- 解説ããŒãžã¯ææã³ã³ãã³ãã®å Žåãå¶éä»ã衚瀺
- ãŠãŒã¶ãŒé²æç®¡çæ©èœã¯ææãŠãŒã¶ãŒã®ã¿å©çšå¯èœ
---
## åºæ¬èšèšæž
### 1. ã·ã¹ãã æ§æ
#### 1.1 å
šäœæ§æ
- Learning Next ãã©ãããã©ãŒã ïŒNext.jsïŒïŒç·Žç¿åé¡ UI 衚瀺ãåçåŠç
- ç·Žç¿åé¡ããŒã¿ç®¡çã·ã¹ãã ïŒPythonïŒïŒåé¡ããŒã¿ã®ç®¡çãšã€ã³ããŒã
- SupabaseïŒããŒã¿ããŒã¹ïŒãŠãŒã¶ãŒåçå±¥æŽãç·Žç¿åé¡ããŒã¿ã®æ ŒçŽïŒ
#### 1.2 ã€ã³ãã©ã¹ãã©ã¯ãã£
```
+-----------------------+ +------------------+
| Learning Next | | ç·Žç¿åé¡ããŒã¿ç®¡ç |
| (Next.js) | | (Python) |
+-----------------------+ +------------------+
| |
| API | ã€ã³ããŒã
v v
+-----------------------+ +------------------+
| Supabase | | ç·Žç¿åé¡ããŒã¿ãã¡ã€ã«|
| (PostgreSQL) | <---- | (åé¢ãã¡ã€ã«æ¹åŒ) |
+-----------------------+ +------------------+
```
### 2. ããŒã¿èšèš
#### 2.1 ç·Žç¿åé¡ããŒã¿ãã¡ã€ã«æ§é
...以äžç¥
ãã£ãããšãããããããšãããããããšäŒããã ãã§ãClaude ãèŠä»¶å®çŸ©ãšåºæ¬èšèšæžãäœæããŠãããŸãã
ãã®æã«éèŠãªã®ã¯ããæ¢åã®å®è£ ãèšèšãç°¡æœã«äŒããããšããããŒã¿ããŒã¹ã®æ§é ã API ã®èšèšãå«ããŠå ·äœçã«äŒããããšãã§ãã
ããšãã°ç§ã®å Žåã¯ã以äžã®ãããªæ å ±ãé©å® Claude ã«æäŸããŸããã
# åè
## ããŒãã«æ§é
é¢é£ããããŒãã«ã®æ§é ã¯ä»¥äžã®éãã§ãã
```sql
...
```
## æ¢åã®ã³ã³ããŒãã³ã
ãxxxããšããæ©èœã«ãããŠã¯ãããšãã°ä»¥äžã®ãããªã³ã³ããŒãã³ããæ¢ã«å®è£
ãããŠããŸãã
åºæ¬èšèšã®éã«ã¯ããããã®ã³ã³ããŒãã³ããåèã«ããŠãã ããã
```tsx
// ...
```
ããããªããšãæ¢åã®å®è£ ã«å šãåã£ãŠããªãèšèšãäœæãããŠããŸãå¯èœæ§ããããŸãã
ããã Cursor ã«æž¡ããŠããå®è£ ãããŸããããªãããšãå€ãã®ã§ãæŽåæ§ãä¿ã€ããã«åèæ å ±ã¯ãã£ãããšæäŸããããšãéèŠã§ãã
1 ã¶æã§å®æãããããã®ã¿ã€ã ã©ã€ã³
æåŸã«ã1 ã¶æãšããçæéã§å®æãããããã«ã©ã®ãã§ãŒãºã§ãã©ã®æ©èœãå®è£ ããããã¿ã€ã ã©ã€ã³ã瀺ããŸãã
æåã«åºç€çãªéšåãåºããŠãããåŸã ã«æ©èœã远å ããŠãã圢ã§é²ããŸããã
åèãŸã§ã«ã1 ã¶æéã®éçºã®æµããšã¿ã€ã ã©ã€ã³ãã玹ä»ããŸãã
1 é±ç®ïŒåºç€æ§ç¯
ãŸãã¯åºç€ãåºããããšããå§ããŸããã
ãã¹ãŠã®æ©èœã«å
±éããéšåãæåã«å®è£
ããããšã§ãåŸã®éçºãã¹ã ãŒãºã«ãªããŸãã
- ãããžã§ã¯ãåæèšå®
- èªèšŒæ©èœïŒClerk 飿ºïŒ
- ããŒã¿ããŒã¹èšèšïŒSupabaseïŒ
- å ±éã³ã³ããŒãã³ã
2 é±ç®ïŒã³ã¢æ©èœå®è£
次ã«ãåœãµã€ãã«ãšã£ãŠéèŠãªã³ã¢æ©èœãå®è£ ããŸããã
äžå¿çãªæ©èœã§ãããšããçç±ãããäžæ¹ã仿©èœãšé£æºããŠããéšåãå€ããããæ©ãã«åºããŠããããšã«ããæãã§ãã
- åŠç¿ã³ã³ãã³ã衚瀺
- ç·Žç¿åé¡ã®åºæ¬æ©èœ
- ãŠãŒã¶ãŒåçå±¥æŽç®¡ç
- ãŠãŒã¶ãŒããã·ã¥ããŒã
3 é±ç®ïŒå¿çšæ©èœå®è£
ã³ã¢æ©èœã宿ããããæ¬¡ã¯å¿çšçãªæ©èœã远å ããŸããã
ã€ã¡ãŒãžãšããŠã¯ããªããŠãåããã©ããã£ãã䟿å©ãªæ©èœããäžå¿ã«å®è£ ããŸããã
- ã©ã³ãã³ã°æ©èœ
- ã¿ã€ã ã¢ã¿ãã¯æ©èœ
- çµ±èšã»åææ©èœ
4 é±ç®ïŒæé©åã»ãããã°
æåŸã«ãå šäœã®æé©åããã°ä¿®æ£ãè¡ããŸããã
- ã³ãŒããªãã¡ã¯ã¿ãªã³ã°ïŒã³ã³ããŒãã³ãåå²ãªã©ïŒ
- ããã©ãŒãã³ã¹æ¹å
- UI/UX 調æŽ
- ãã°ä¿®æ£
ãã ããªãã¡ã¯ã¿ãªã³ã°ãããã©ãŒãã³ã¹æ¹åã¯å ã«ãã£ãŠããã¹ãã ã£ããšåçããŠããŸãã
ãªããªãã°ãåŸãããããš ä¿®æ£ç®æãå€ããªããææ»ããçºçãããã ããã§ãã
詳现ã¯åŸè¿°ããŸãã
ä»åã®éçºã§æãã AI é§åéçºã®å¯èœæ§
1 ã¶æéãAI ãšäžç·ã«éçºãé²ããŠã¿ãŠãæ¬åœã«éçºå¹çãå€ãã£ã ãšå®æããŠããŸãã
仿Žãªãããä»åäœã£ããµãŒãã¹ã¯ã以åäœã£ãå人éçºã¢ããªããåŠç¿ç¹ååãã«ãããã®ã§ãã
â»åœæã®ããŠããŠãç¹ã« SEO 芳ç¹ãèšäºã«ããŠããã®ã§ããã£ããèªãã§ã¿ãŠãã ããã
è©±ãæ»ããŸããšã以åã AI ãšãŒãžã§ã³ãã䜿ã£ãŠéçºãããŠããŸããããä»åã®ããã« èŠä»¶å®çŸ©ããå®è£ ãããã¥ã¡ã³ãåãŸã§äžè²«ã㊠AI ãæ¬æ°ã§æŽ»çšããéçº ã¯åããŠã§ããã
ç¹ã«ãæ©èœã®ããã¥ã¡ã³ãåãè¡ãããšã§æ©èœã®è¿œå ã»ä¿®æ£ãéåžžã«ã¹ã ãŒãºã«ãªã£ãã®ã§ãçããã«ãããããããããã€ã³ãã§ã
å®éã«éçºããŠã¿ãŠæãã課é¡ãšåçç¹
AI é§åéçºã§ç¢ºãã«å¹çã¯äžãã£ããã§ãããå®éã«ãã£ãŠã¿ããš ãããŒãããã¯å€±æã ã£ããªã ãšæããã€ã³ããããã€ããããŸããã
ãã㯠Cursor ãªã©ãæªããšããããã§ã¯ãªããããããã°ããã£ããªããšèšããã€ã³ããªã®ã§ããããã AI é§åéçºã«ææŠããæ¹ã®åèã«ãªãã°ãšæããŸãã
Shadcn/ui ã¯å人çã«ã¯åããªãã£ã
æå㯠Shadcn/ui ã䜿ã£ãŠã¢ãã³ãª UI ãäœãããšæã£ããã§ããããããæ³å®ä»¥äžã«å€§å€ã§ããã
Cursor ãçæããã³ãŒãã ãšãååšããªããªãã·ã§ã³ã䜿ãããšããããå¿ èŠãª props ãè¶³ããŠããªã ããšãé »ç¹ã«ãã£ãããã§ãã
äŸãã°ãButton ã³ã³ããŒãã³ãã§ååšããªãããªã¢ã³ããæå®ããŠããããå¿ èŠãª props ãæããŠããããšãã£ãå ·åã§ãã
çµæçã«ã人åã§ã®èª¿æŽã«æéãåããã ããšãå€ããªã£ãŠããŸããéäžã§ããããããŠããŸããŸããã
ãã®ããéäžãã Tailwind CSS ã®ã¿ ã§ UI ãäœãããšã«åãæ¿ããŸããã
èŠãç®ã¯ Cursor ã«é 匵ã£ãŠãããå¿ èŠã¯ãããã®ã®ãã·ã³ãã«ãªã®ã§ Cursor ãšã®çžæ§ã¯æç¶è¯ãã£ãã§ãã
決ã㊠Shadcn ãæªããšããããã§ã¯ãªããäºã Shadcn ã«é¢ããããã¥ã¡ã³ãããã£ãããšæŽåããŠããã°ãCursor ãééãã«ããã£ããããããŸããã
ã¢ãã¯ïŒUI ã®ã€ã¡ãŒãžïŒãæåã«äœãã¹ãã ã£ã
ããã¯å®å šã«åçç¹ãªãã§ãããæ©èœéçºãš UI äœæãåæäžŠè¡ ã§ãã£ãŠããŸã£ããã§ãã
ãåãæ©èœãäœããªããèŠãç®ãæŽããŠãããããšããèãã ã£ããã§ãããããã ãã¡ããã¡ãå€§å€ ã§ããã
æ¬æ¥ãªããæåã« éçãªã¢ãã¯ïŒãã¶ã€ã³ã ãã®ããŒãžïŒ ãäœã£ãŠããæ©èœéçºã«å ¥ãã¹ãã§ããã
å®éã®æ¥åã§ããUI ãã¶ã€ããŒãå ã«ã¢ãã¯ãäœã£ãŠããéçºã«å ¥ãããšãå€ããšæããŸãã
ãŸããç»é¢ãäžæŠã¯éçãªïŒHTML ãš CSS ã ãã®ïŒããŒãžãäœã£ãŠãããŠãããã« Cursor ã§æ©èœã远å ããŠãã圢ã«ããã°ãCursor ããã©ã®éšåã«æ©èœã远å ããã°è¯ããããæç¢ºã«çè§£ã§ãã ã¯ãã§ãã
ä»å㯠ããšããããåããã®ãäœãã ãšããæ¹éã§é²ããŠããŸã£ããããåŸãã UI ã®èª¿æŽã倧å€ã§ããã
ç¹ã«ãUI 調æŽã«ãšããªã£ãŠã³ã³ããŒãã³ããçµã¿æ¿ããããå€§å¹ ãªãªãã¡ã¯ã¿ãªã³ã°ãå¿ èŠã«ãªã£ããããŠãCursor ãçæããã³ãŒãã ãå£ããããã ãšããåé¡ãçºçããŸããã
ãã®ããã
ãã¶ã€ã³ã¬ã€ããæåã«äœã£ãŠããã¹ãã ã£ã
ããã倧ããªåçç¹ã§ãã
æå㯠ããšããããåããã®ãäœããã ãšããå¢ãã§é²ãããã§ãããéäžã§è²ã®çµ±äžæããªãã£ãããäœçœããã©ãã©ã ã£ããããŠãåŸãã調æŽããã®ãå€§å€ ã§ããã
AI é§åéçºã ãšãã©ãã©ãæ©èœãã³ã³ããŒãã³ãã远å ããŠããã®ãåºæ¬ãªã®ã§ãå šäœãšããŠãã¶ã€ã³ã®çµ±äžæãä¿ã€ã®ãé£ããã®ã ãšæããŸãã
ãã®ãããæåã« ãã¶ã€ã³ã¬ã€ãã©ã€ã³ ãäœæããŠããã¹ãã§ããã
è¶£å³ã®å人éçºã ãšãã¶ã€ã³ã¬ã€ãã©ã€ã³ãŸã§çå®ããããšã¯å°ãªãããšæããŸãããããšãã°ä»¥äžã®ãããªå 容ãããã¥ã¡ã³ãåããŠãããšè¯ãã§ãããã
- é è²ã«ãŒã«ïŒãã©ã€ããªã«ã©ãŒãã»ã«ã³ããªã«ã©ãŒãªã©ïŒ
- äœçœã®åºæºïŒ8px åäœãšã 16px åäœãšãïŒ
- ãã©ã³ããµã€ãºã®éå±€
- ãã¿ã³ãã«ãŒãã®åºæ¬ãã¶ã€ã³
- ã¢ã€ã³ã³ã®äœ¿çšã«ãŒã«ïŒLucide Icons ã Devicon ã®äœ¿ãæ¹ïŒ
éäžã§æ°ã¥ããŠãClaude ã« ããµã€ãã®ã€ã¡ãŒãžããšãApple 颚ã®ãã¶ã€ã³ãããã¶ã€ã³ã«ãŒã«ãšããŠããã¥ã¡ã³ãå ããŠããã£ããã§ãããããããã£ããäžæ°ã«çµ±äžæãåºãŸããã
ãã®ãã¶ã€ã³ã¬ã€ãäœæã«ã€ããŠã¯ããŸãå¥ã®èšäºã§è©³ããæžãããšæããŸãã
ã³ã³ããŒãã³ãã¯çްããåå²ãã¹ã
ãã㯠AI ãšãŒãžã§ã³ãç¹æã®æè¡çãªåçç¹ã§ãã
æå㯠ãCursor ã«æž¡ããã¡ã€ã«æ°ãå°ãªããããã ãšæã£ãŠã1 ã€ã®ã³ã³ããŒãã³ãã倧ããã«äœã£ãŠãããã§ãã
ããããããšã§ãCursor ã«æž¡ããã¡ã€ã«ãå°ãªããªããAI ãçè§£ããããããªãšæã£ãããã§ãã
ã§ãããããè£ç®ã«åºãŸããã
ä¿®æ£éäžã§ ãã¡ã€ã«ãå£ããŠãäœåºŠããŒãããäœãçŽã ãšããäºæ ã«ãªã£ããã§ããç¹ã«è€éãªç¶æ 管çã絡ãã³ã³ããŒãã³ãã§é »çºããŸããã
ãããããCursor ã倧ããªå®è£ ãäžåºŠã«æ å ±ãšããŠä¿æãããããéäžã§æ å ±ã倱ãããŠããŸã£ãã®ã ãšæããŸãã
ãã®ãããæ©ãã« ã³ã³ããŒãã³ãã现ããåå² ããŠã1 ã€ã®ãã¡ã€ã«ã®è²¬ä»»ãå°ããããã¹ãã ã£ããšæããŸãã
ãã ããåå²ããæã¯ ã³ã³ããŒãã³ãæ§æã®ããã¥ã¡ã³ã ãäœãããããšãéèŠã§ããã
ããã®ã³ã³ããŒãã³ãã¯äœãããã®ãããã©ã®ã³ã³ããŒãã³ããšé£æºããã®ããã軜ãã§ãããã¥ã¡ã³ãåããŠãããšãåŸã®ä¿®æ£ãã¹ã ãŒãºã«ãªããŸãã
çµè«ïŒ AI é§åéçºã¯ãé©åœãããã¡ã
AI ã䜿ã£ãéçºã¯ç¢ºãã«å¹ççã§ãããåŸæ¥ã®éçºãšã¯éã£ãã³ã ãå¿ èŠã ãªãšæããŸããã
ç¹ã« ãAI ãééãã«ããç°å¢ãæŽããã ããšãããæ©èœã远å ã»ä¿®æ£ããããæºåãããŠããã ããšãéèŠã§ãã
ä»åã®çµéšãèžãŸããŠã次åã¯ãã£ãšã¹ã ãŒãºã«éçºã§ãããã§ãã
ãããã«
ä»åãCursor ãš Claude ã䜿ã£ã AI é§åéçºã§ã1 ã¶æãšããçæé ã§æ¬æ ŒçãªåŠç¿ãã©ãããã©ãŒã ãäœãããšãã§ããŸããã
æ¹ããŠæ¯ãè¿ããšã以äžã®ãã€ã³ããæåã®éµã ãšæããŠããŸãã
- èŠä»¶å®çŸ©ãšåºæ¬èšèšããã£ããè¡ã
- ããã¥ã¡ã³ãåã培åºãã
- AI ãšãŒãžã§ã³ãã«é©åãªæ å ±ãæäŸãã
- ã³ã³ããŒãã³ãã现ããåå²ãã責任ãæç¢ºã«ãã
- ãã¶ã€ã³ã¬ã€ãã©ã€ã³ãæåã«äœæãã
- AI ãšãŒãžã§ã³ããšã®ã³ãã¥ãã±ãŒã·ã§ã³ãå¯ã«ãã
- å®è£ åŸã®ããã¥ã¡ã³ãåãå¿ããªã
.cursorrulesãé©åã«èšå®ãã
AI é§åéçºã¯ããã¯ã ã詊ããŠã¿ããæ®µé ãè¶ ããŠããå®çšçã«æŽ»çšãããæ®µé ã«æ¥ãŠããŸãã
å®éãç§ã®æ¬æ¥ã®æ¹ã§ãã³ãŒãã¯ã»ãŒ AI ãšãŒãžã§ã³ãã«æžãããŠããŠãAI ãšãŒãžã§ã³ããçæããã³ãŒãã人éãã¬ãã¥ãŒãã圢ã§éçºãé²ããŠããŸãã
ãã²çããããä»å玹ä»ããããŠããŠãåèã«ãAI ãšäžç·ã«éçºããŠã¿ãŠãã ããïŒ
ãããŠãããããã°ã©ãã³ã°åŠç¿ã«èå³ãããæ¹ã¯ãä»åäœã£ã Learning Next ã詊ããŠããã ãããšå¬ããã§ãïŒïŒ
ç¹ã« ç·Žç¿å顿©èœ ã¯ã1,000 å以äžãçšæããŠããŠãRubyãRailsãJavaScriptãReact ãªã©ã®å®åã¢ããã«åœ¹ç«ã€ãšæããŸãïŒ
ãã®èšäºããAI é§åéçºã«ææŠããæ¹ã®åèã«ãªãã°å¹žãã§ãã
質åããã£ãŒãããã¯ãããã°ããã²ã³ã¡ã³ãã§æããŠãã ããïŒ
ãã®ä»ãX ã® DM ã§ãåãä»ããŠããŸãã®ã§ããæ°è»œã«ãé£çµ¡ããã ãããšå¬ããã§ãã























