PageSourceSearch

https://fwywd.com/tech/tags/instant%20search

html fwywd.com collected 2026-10-04 07:49:17 UTC 229,492 bytes, 8 lines download raw bytes

1<!DOCTYPE html><html lang="ja"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><link rel="preload" as="image" imagesrcset="/_next/image?url=%2Fimg%2Fcommon%2Flogo.png&amp;w=256&amp;q=100 1x, /_next/image?url=%2Fimg%2Fcommon%2Flogo.png&amp;w=640&amp;q=100 2x"/><meta name="robots" content="noindex"/><title>Instant Searchのタグ一覧 | fwywd(フュード)</title><meta title="Instant Searchのタグ一覧 | fwywd(フュード)"/><meta name="description" content="Instant Searchのタグ一覧 | fwywd(フュード) タグの特集ページです。"/><meta property="og:description" content="Instant Searchのタグ一覧 | fwywd(フュード) タグの特集ページです。"/><meta property="og:site_name" content="Instant Searchのタグ一覧 | fwywd(フュード)"/><meta property="og:type" content="article"/><meta property="og:url" content="https://fwywd.com/tech/tags/instant%2520search"/><meta property="og:title" content="Instant Searchのタグ一覧 | fwywd(フュード)"/><meta property="og:image" content="https://fwywd.com/img/ogp.png"/><meta name="facebook-domain-verification" content="e7bpyf73x7npm0sjrmkypd661bwi9g"/><link rel="canonical" href="https://fwywd.com/tech/tags/instant%2520search"/><meta name="next-head-count" content="15"/>
vendor: 66 bytes, line 1
1<script async="" src="https://www.googletagmanager.com/gtag/js?id=
1UA-90878820-10
vendor: 11 bytes, line 1
1"></script>
1<script>
2            
vendor: 163 bytes, lines 2-5
2window.dataLayer = window.dataLayer || [];
3            function gtag(){dataLayer.push(arguments);}
4            gtag('js', new Date());
5            gtag('config', '
5UA-90878820-10
vendor: 80 bytes, lines 5-8
5', {
6              page_path: window.location.pathname,
7            });
8        
8</script>
8<meta name="twitter:card" content="summary_large_image"/><meta property="article:publisher" content="https://www.facebook.com/kikagaku.co.jp"/><meta property="fb:app_id" content="293896155660080"/><link rel="shortcut icon" href="/favicon.ico"/><link rel="preload" href="/_next/static/css/5645facba0c4f0d8.css" as="style"/><link rel="stylesheet" href="/_next/static/css/5645facba0c4f0d8.css" data-n-g=""/><link rel="preload" href="/_next/static/css/605f94f12e5d18a9.css" as="style"/><link rel="stylesheet" href="/_next/static/css/605f94f12e5d18a9.css" data-n-p=""/><noscript data-n-css=""></noscript>
8<script defer="" nomodule="" src="/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js"></script>
8<script src="/_next/static/chunks/webpack-7a4556bda6d2aa7a.js" defer=""></script>
8<script src="/_next/static/chunks/framework-79bce4a3a540b080.js" defer=""></script>
8<script src="/_next/static/chunks/main-8929b355bf712381.js" defer=""></script>
8<script src="/_next/static/chunks/pages/_app-3aa92feca933b46c.js" defer=""></script>
8<script src="/_next/static/chunks/9545-f02c20dae96fa048.js" defer=""></script>
8<script src="/_next/static/chunks/6499-0fc93911ad26607a.js" defer=""></script>
8<script src="/_next/static/chunks/pages/tech/tags/%5Bid%5D-62381bd2b7a3262d.js" defer=""></script>
8<script src="/_next/static/8g7VE4IFZHCF7i2FMUki4/_buildManifest.js" defer=""></script>
8<script src="/_next/static/8g7VE4IFZHCF7i2FMUki4/_ssgManifest.js" defer=""></script>
8</head><body><div id="__next" data-reactroot=""><style data-emotion="css-global ay0t7w">:host,:root,[data-theme]{--chakra-ring-inset:var(--chakra-empty,/*!*/ /*!*/);--chakra-ring-offset-width:0px;--chakra-ring-offset-color:#fff;--chakra-ring-color:rgba(66, 153, 225, 0.6);--chakra-ring-offset-shadow:0 0 #0000;--chakra-ring-shadow:0 0 #0000;--chakra-space-x-reverse:0;--chakra-space-y-reverse:0;--chakra-colors-transparent:transparent;--chakra-colors-current:currentColor;--chakra-colors-black-dark:#000000;--chakra-colors-black-light:#333333;--chakra-colors-white:#FFFFFF;--chakra-colors-whiteAlpha-50:rgba(255, 255, 255, 0.04);--chakra-colors-whiteAlpha-100:rgba(255, 255, 255, 0.06);--chakra-colors-whiteAlpha-200:rgba(255, 255, 255, 0.08);--chakra-colors-whiteAlpha-300:rgba(255, 255, 255, 0.16);--chakra-colors-whiteAlpha-400:rgba(255, 255, 255, 0.24);--chakra-colors-whiteAlpha-500:rgba(255, 255, 255, 0.36);--chakra-colors-whiteAlpha-600:rgba(255, 255, 255, 0.48);--chakra-colors-whiteAlpha-700:rgba(255, 255, 255, 0.64);--chakra-colors-whiteAlpha-800:rgba(255, 255, 255, 0.80);--chakra-colors-whiteAlpha-900:rgba(255, 255, 255, 0.92);--chakra-colors-blackAlpha-50:rgba(0, 0, 0, 0.04);--chakra-colors-blackAlpha-100:rgba(0, 0, 0, 0.06);--chakra-colors-blackAlpha-200:rgba(0, 0, 0, 0.08);--chakra-colors-blackAlpha-300:rgba(0, 0, 0, 0.16);--chakra-colors-blackAlpha-400:rgba(0, 0, 0, 0.24);--chakra-colors-blackAlpha-500:rgba(0, 0, 0, 0.36);--chakra-colors-blackAlpha-600:rgba(0, 0, 0, 0.48);--chakra-colors-blackAlpha-700:rgba(0, 0, 0, 0.64);--chakra-colors-blackAlpha-800:rgba(0, 0, 0, 0.80);--chakra-colors-blackAlpha-900:rgba(0, 0, 0, 0.92);--chakra-colors-gray-50:#F7FAFC;--chakra-colors-gray-100:#EDF2F7;--chakra-colors-gray-200:#E2E8F0;--chakra-colors-gray-300:#CBD5E0;--chakra-colors-gray-400:#A0AEC0;--chakra-colors-gray-500:#718096;--chakra-colors-gray-600:#4A5568;--chakra-colors-gray-700:#2D3748;--chakra-colors-gray-800:#1A202C;--chakra-colors-gray-900:#171923;--chakra-colors-red-50:#FFF5F5;--chakra-colors-red-100:#FED7D7;--chakra-colors-red-200:#FEB2B2;--chakra-colors-red-300:#FC8181;--chakra-colors-red-400:#F56565;--chakra-colors-red-500:#E53E3E;--chakra-colors-red-600:#C53030;--chakra-colors-red-700:#9B2C2C;--chakra-colors-red-800:#822727;--chakra-colors-red-900:#63171B;--chakra-colors-orange-50:#FFFAF0;--chakra-colors-orange-100:#FEEBC8;--chakra-colors-orange-200:#FBD38D;--chakra-colors-orange-300:#F6AD55;--chakra-colors-orange-400:#ED8936;--chakra-colors-orange-500:#DD6B20;--chakra-colors-orange-600:#C05621;--chakra-colors-orange-700:#9C4221;--chakra-colors-orange-800:#7B341E;--chakra-colors-orange-900:#652B19;--chakra-colors-yellow-50:#FFFFF0;--chakra-colors-yellow-100:#FEFCBF;--chakra-colors-yellow-200:#FAF089;--chakra-colors-yellow-300:#F6E05E;--chakra-colors-yellow-400:#ECC94B;--chakra-colors-yellow-500:#D69E2E;--chakra-colors-yellow-600:#B7791F;--chakra-colors-yellow-700:#975A16;--chakra-colors-yellow-800:#744210;--chakra-colors-yellow-900:#5F370E;--chakra-colors-green-50:#F0FFF4;--chakra-colors-green-100:#C6F6D5;--chakra-colors-green-200:#9AE6B4;--chakra-colors-green-300:#68D391;
8--chakra-colors-green-400:#48BB78;--chakra-colors-green-500:#38A169;--chakra-colors-green-600:#2F855A;--chakra-colors-green-700:#276749;--chakra-colors-green-800:#22543D;--chakra-colors-green-900:#1C4532;--chakra-colors-teal-50:#E6FFFA;--chakra-colors-teal-100:#B2F5EA;--chakra-colors-teal-200:#81E6D9;--chakra-colors-teal-300:#4FD1C5;--chakra-colors-teal-400:#38B2AC;--chakra-colors-teal-500:#319795;--chakra-colors-teal-600:#2C7A7B;--chakra-colors-teal-700:#285E61;--chakra-colors-teal-800:#234E52;--chakra-colors-teal-900:#1D4044;--chakra-colors-blue-50:#ebf8ff;--chakra-colors-blue-100:#bee3f8;--chakra-colors-blue-200:#90cdf4;--chakra-colors-blue-300:#63b3ed;--chakra-colors-blue-400:#4299e1;--chakra-colors-blue-500:#3182ce;--chakra-colors-blue-600:#2b6cb0;--chakra-colors-blue-700:#2c5282;--chakra-colors-blue-800:#2a4365;--chakra-colors-blue-900:#1A365D;--chakra-colors-cyan-50:#EDFDFD;--chakra-colors-cyan-100:#C4F1F9;--chakra-colors-cyan-200:#9DECF9;--chakra-colors-cyan-300:#76E4F7;--chakra-colors-cyan-400:#0BC5EA;--chakra-colors-cyan-500:#00B5D8;--chakra-colors-cyan-600:#00A3C4;--chakra-colors-cyan-700:#0987A0;--chakra-colors-cyan-800:#086F83;--chakra-colors-cyan-900:#065666;--chakra-colors-purple-50:#FAF5FF;--chakra-colors-purple-100:#E9D8FD;--chakra-colors-purple-200:#D6BCFA;--chakra-colors-purple-300:#B794F4;--chakra-colors-purple-400:#9F7AEA;--chakra-colors-purple-500:#805AD5;--chakra-colors-purple-600:#6B46C1;--chakra-colors-purple-700:#553C9A;--chakra-colors-purple-800:#44337A;--chakra-colors-purple-900:#322659;--chakra-colors-pink-50:#FFF5F7;--chakra-colors-pink-100:#FED7E2;--chakra-colors-pink-200:#FBB6CE;--chakra-colors-pink-300:#F687B3;--chakra-colors-pink-400:#ED64A6;--chakra-colors-pink-500:#D53F8C;--chakra-colors-pink-600:#B83280;--chakra-colors-pink-700:#97266D;--chakra-colors-pink-800:#702459;--chakra-colors-pink-900:#521B41;--chakra-colors-linkedin-50:#E8F4F9;--chakra-colors-linkedin-100:#CFEDFB;--chakra-colors-linkedin-200:#9BDAF3;--chakra-colors-linkedin-300:#68C7EC;--chakra-colors-linkedin-400:#34B3E4;--chakra-colors-linkedin-500:#00A0DC;--chakra-colors-linkedin-600:#008CC9;--chakra-colors-linkedin-700:#0077B5;--chakra-colors-linkedin-800:#005E93;--chakra-colors-linkedin-900:#004471;--chakra-colors-facebook-50:#E8F4F9;--chakra-colors-facebook-100:#D9DEE9;--chakra-colors-facebook-200:#B7C2DA;--chakra-colors-facebook-300:#6482C0;--chakra-colors-facebook-400:#4267B2;--chakra-colors-facebook-500:#385898;--chakra-colors-facebook-600:#314E89;--chakra-colors-facebook-700:#29487D;--chakra-colors-facebook-800:#223B67;--chakra-colors-facebook-900:#1E355B;--chakra-colors-messenger-50:#D0E6FF;--chakra-colors-messenger-100:#B9DAFF;--chakra-colors-messenger-200:#A2CDFF;--chakra-colors-messenger-300:#7AB8FF;--chakra-colors-messenger-400:#2E90FF;--chakra-colors-messenger-500:#0078FF;--chakra-colors-messenger-600:#0063D1;--chakra-colors-messenger-700:#0052AC;--chakra-colors-messenger-800:#003C7E;--chakra-colors-messenger-900:#002C5C;--chakra-colors-whatsapp-50:#dffeec;--chakra-colors-whatsapp-100:#b9f5d0;--chakra-colors-whatsapp-200:#90edb3;--chakra-colors-whatsapp-300:#65e495;--chakra-colors-whatsapp-400:#3cdd78;--chakra-colors-whatsapp-500:#22c35e;--chakra-colors-whatsapp-600:#179848;--chakra-colors-whatsapp-700:#0c6c33;--chakra-colors-whatsapp-800:#01421c;--chakra-colors-whatsapp-900:#001803;--chakra-colors-twitter-50:#E5F4FD;--chakra-colors-twitter-100:#C8E9FB;--chakra-colors-twitter-200:#A8DCFA;--chakra-colors-twitter-300:#83CDF7;--chakra-colors-twitter-400:#57BBF5;--chakra-colors-twitter-500:#1DA1F2;--chakra-colors-twitter-600:#1A94DA;--chakra-colors-twitter-700:#1681BF;--chakra-colors-twitter-800:#136B9E;--chakra-colors-twitter-900:#0D4D71;--chakra-colors-telegram-50:#E3F2F9;--chakra-colors-telegram-100:#C5E4F3;--chakra-colors-telegram-200:#A2D4EC;--chakra-colors-telegram-300:#7AC1E4;--chakra-colors-telegram-400:#47A9DA;--chakra-colors-telegram-500:#0088CC;--chakra-colors-telegram-600:#007AB8;--chakra-colors-telegram-700:#006BA1;--chakra-colors-telegram-800:#005885;--chakra-colors-telegram-900:#003F5E;--chakra-colors-primary-base:#179ACA;--chakra-colors-primary-light:#15B7C1;--chakra-borders-none:0;--chakra-borders-1px:1px solid;--chakra-borders-2px:2px solid;--chakra-borders-4px:4px solid;--chakra-borders-8px:8px solid;--chakra-fonts-heading:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--chakra-fonts-body:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--chakra-fonts-mono:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--chakra-fontSizes-xs:0.75rem;--chakra-fontSizes-sm:0.875rem;--chakra-fontSizes-md:1rem;--chakra-fontSizes-lg:1.125rem;--chakra-fontSizes-xl:1.25rem;--chakra-fontSizes-2xl:1.5rem;--chakra-fontSizes-3xl:1.875rem;--chakra-fontSizes-4xl:2.25rem;--chakra-fontSizes-5xl:3rem;--chakra-fontSizes-6xl:3.75rem;--chakra-fontSizes-7xl:4.5rem;--chakra-fontSizes-8xl:6rem;--chakra-fontSizes-9xl:8rem;--chakra-fontWeights-hairline:100;--chakra-fontWeights-thin:200;--chakra-fontWeights-light:300;--chakra-fontWeights-normal:400;--chakra-fontWeights-medium:500;--chakra-fontWeights-semibold:600;--chakra-fontWeights-bold:700;--chakra-fontWeights-extrabold:800;--chakra-fontWeights-black:900;--chakra-letterSpacings-tighter:-0.05em;
8--chakra-letterSpacings-tight:-0.025em;--chakra-letterSpacings-normal:0;--chakra-letterSpacings-wide:0.025em;--chakra-letterSpacings-wider:0.05em;--chakra-letterSpacings-widest:0.1em;--chakra-lineHeights-3:.75rem;--chakra-lineHeights-4:1rem;--chakra-lineHeights-5:1.25rem;--chakra-lineHeights-6:1.5rem;--chakra-lineHeights-7:1.75rem;--chakra-lineHeights-8:2rem;--chakra-lineHeights-9:2.25rem;--chakra-lineHeights-10:2.5rem;--chakra-lineHeights-normal:normal;--chakra-lineHeights-none:1;--chakra-lineHeights-shorter:1.25;--chakra-lineHeights-short:1.375;--chakra-lineHeights-base:1.5;--chakra-lineHeights-tall:1.625;--chakra-lineHeights-taller:2;--chakra-radii-none:0;--chakra-radii-sm:0.125rem;--chakra-radii-base:0.25rem;--chakra-radii-md:0.375rem;--chakra-radii-lg:0.5rem;--chakra-radii-xl:0.75rem;--chakra-radii-2xl:1rem;--chakra-radii-3xl:1.5rem;--chakra-radii-full:9999px;--chakra-space-1:0.25rem;--chakra-space-2:0.5rem;--chakra-space-3:0.75rem;--chakra-space-4:1rem;--chakra-space-5:1.25rem;--chakra-space-6:1.5rem;--chakra-space-7:1.75rem;--chakra-space-8:2rem;--chakra-space-9:2.25rem;--chakra-space-10:2.5rem;--chakra-space-12:3rem;--chakra-space-14:3.5rem;--chakra-space-16:4rem;--chakra-space-20:5rem;--chakra-space-24:6rem;--chakra-space-28:7rem;--chakra-space-32:8rem;--chakra-space-36:9rem;--chakra-space-40:10rem;--chakra-space-44:11rem;--chakra-space-48:12rem;--chakra-space-52:13rem;--chakra-space-56:14rem;--chakra-space-60:15rem;--chakra-space-64:16rem;--chakra-space-72:18rem;--chakra-space-80:20rem;--chakra-space-96:24rem;--chakra-space-px:1px;--chakra-space-0-5:0.125rem;--chakra-space-1-5:0.375rem;--chakra-space-2-5:0.625rem;--chakra-space-3-5:0.875rem;--chakra-shadows-xs:0 0 0 1px rgba(0, 0, 0, 0.05);--chakra-shadows-sm:0 1px 2px 0 rgba(0, 0, 0, 0.05);--chakra-shadows-base:0 1px 3px 0 rgba(0, 0, 0, 0.1),0 1px 2px 0 rgba(0, 0, 0, 0.06);--chakra-shadows-md:0 4px 6px -1px rgba(0, 0, 0, 0.1),0 2px 4px -1px rgba(0, 0, 0, 0.06);--chakra-shadows-lg:0 10px 15px -3px rgba(0, 0, 0, 0.1),0 4px 6px -2px rgba(0, 0, 0, 0.05);--chakra-shadows-xl:0 20px 25px -5px rgba(0, 0, 0, 0.1),0 10px 10px -5px rgba(0, 0, 0, 0.04);--chakra-shadows-2xl:0 25px 50px -12px rgba(0, 0, 0, 0.25);--chakra-shadows-outline:0 0 0 3px rgba(66, 153, 225, 0.6);--chakra-shadows-inner:inset 0 2px 4px 0 rgba(0,0,0,0.06);--chakra-shadows-none:none;--chakra-shadows-dark-lg:rgba(0, 0, 0, 0.1) 0px 0px 0px 1px,rgba(0, 0, 0, 0.2) 0px 5px 10px,rgba(0, 0, 0, 0.4) 0px 15px 40px;--chakra-sizes-1:0.25rem;--chakra-sizes-2:0.5rem;--chakra-sizes-3:0.75rem;--chakra-sizes-4:1rem;--chakra-sizes-5:1.25rem;--chakra-sizes-6:1.5rem;--chakra-sizes-7:1.75rem;--chakra-sizes-8:2rem;--chakra-sizes-9:2.25rem;--chakra-sizes-10:2.5rem;--chakra-sizes-12:3rem;--chakra-sizes-14:3.5rem;--chakra-sizes-16:4rem;--chakra-sizes-20:5rem;--chakra-sizes-24:6rem;--chakra-sizes-28:7rem;--chakra-sizes-32:8rem;--chakra-sizes-36:9rem;--chakra-sizes-40:10rem;--chakra-sizes-44:11rem;--chakra-sizes-48:12rem;--chakra-sizes-52:13rem;--chakra-sizes-56:14rem;--chakra-sizes-60:15rem;--chakra-sizes-64:16rem;--chakra-sizes-72:18rem;--chakra-sizes-80:20rem;--chakra-sizes-96:24rem;--chakra-sizes-px:1px;--chakra-sizes-0-5:0.125rem;--chakra-sizes-1-5:0.375rem;--chakra-sizes-2-5:0.625rem;--chakra-sizes-3-5:0.875rem;--chakra-sizes-max:max-content;--chakra-sizes-min:min-content;--chakra-sizes-full:100%;--chakra-sizes-3xs:14rem;--chakra-sizes-2xs:16rem;--chakra-sizes-xs:20rem;--chakra-sizes-sm:24rem;--chakra-sizes-md:28rem;--chakra-sizes-lg:32rem;--chakra-sizes-xl:36rem;--chakra-sizes-2xl:42rem;--chakra-sizes-3xl:48rem;--chakra-sizes-4xl:56rem;--chakra-sizes-5xl:64rem;--chakra-sizes-6xl:72rem;--chakra-sizes-7xl:80rem;--chakra-sizes-8xl:90rem;--chakra-sizes-container-sm:640px;--chakra-sizes-container-md:768px;--chakra-sizes-container-lg:1024px;--chakra-sizes-container-xl:1280px;--chakra-zIndices-hide:-1;--chakra-zIndices-auto:auto;--chakra-zIndices-base:0;--chakra-zIndices-docked:10;--chakra-zIndices-dropdown:1000;--chakra-zIndices-sticky:1100;--chakra-zIndices-banner:1200;--chakra-zIndices-overlay:1300;--chakra-zIndices-modal:1400;--chakra-zIndices-popover:1500;--chakra-zIndices-skipLink:1600;--chakra-zIndices-toast:1700;--chakra-zIndices-tooltip:1800;--chakra-transition-property-common:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform;--chakra-transition-property-colors:background-color,border-color,color,fill,stroke;--chakra-transition-property-dimensions:width,height;--chakra-transition-property-position:left,right,top,bottom;--chakra-transition-property-background:background-color,background-image,background-position;--chakra-transition-easing-ease-in:cubic-bezier(0.4, 0, 1, 1);--chakra-transition-easing-ease-out:cubic-bezier(0, 0, 0.2, 1);--chakra-transition-easing-ease-in-out:cubic-bezier(0.4, 0, 0.2, 1);--chakra-transition-duration-ultra-fast:50ms;--chakra-transition-duration-faster:100ms;--chakra-transition-duration-fast:150ms;--chakra-transition-duration-normal:200ms;--chakra-transition-duration-slow:300ms;--chakra-transition-duration-slower:400ms;--chakra-transition-duration-ultra-slow:500ms;--chakra-blur-none:0;--chakra-blur-sm:4px;--chakra-blur-base:8px;--chakra-blur-md:12px;--chakra-blur-lg:16px;
8--chakra-blur-xl:24px;--chakra-blur-2xl:40px;--chakra-blur-3xl:64px;}</style><style data-emotion="css-global 1jqlf9g">html{line-height:1.5;-webkit-text-size-adjust:100%;font-family:system-ui,sans-serif;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;-moz-osx-font-smoothing:grayscale;touch-action:manipulation;}body{position:relative;min-height:100%;font-feature-settings:'kern';}*,*::before,*::after{border-width:0;border-style:solid;box-sizing:border-box;}main{display:block;}hr{border-top-width:1px;box-sizing:content-box;height:0;overflow:visible;}pre,code,kbd,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:1em;}a{background-color:transparent;color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit;}abbr[title]{border-bottom:none;-webkit-text-decoration:underline;text-decoration:underline;-webkit-text-decoration:underline dotted;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;}b,strong{font-weight:bold;}small{font-size:80%;}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}sub{bottom:-0.25em;}sup{top:-0.5em;}img{border-style:none;}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0;}button,input{overflow:visible;}button,select{text-transform:none;}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{border-style:none;padding:0;}fieldset{padding:0.35em 0.75em 0.625em;}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal;}progress{vertical-align:baseline;}textarea{overflow:auto;}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0;}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{-webkit-appearance:none!important;}input[type="number"]{-moz-appearance:textfield;}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px;}[type="search"]::-webkit-search-decoration{-webkit-appearance:none!important;}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit;}details{display:block;}summary{display:-webkit-box;display:-webkit-list-item;display:-ms-list-itembox;display:list-item;}template{display:none;}[hidden]{display:none!important;}body,blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0;}button{background:transparent;padding:0;}fieldset{margin:0;padding:0;}ol,ul{margin:0;padding:0;}textarea{resize:vertical;}button,[role="button"]{cursor:pointer;}button::-moz-focus-inner{border:0!important;}table{border-collapse:collapse;}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit;}button,input,optgroup,select,textarea{padding:0;line-height:inherit;color:inherit;}img,svg,video,canvas,audio,iframe,embed,object{display:block;}img,video{max-width:100%;height:auto;}[data-js-focus-visible] :focus:not([data-focus-visible-added]){outline:none;box-shadow:none;}select::-ms-expand{display:none;}</style><style data-emotion="css-global 1baqkrf">body{font-family:var(--chakra-fonts-body);color:var(--chakra-colors-gray-800);background:var(--chakra-colors-white);transition-property:background-color;transition-duration:var(--chakra-transition-duration-normal);line-height:var(--chakra-lineHeights-base);}*::-webkit-input-placeholder{color:var(--chakra-colors-gray-400);}*::-moz-placeholder{color:var(--chakra-colors-gray-400);}*:-ms-input-placeholder{color:var(--chakra-colors-gray-400);}*::placeholder{color:var(--chakra-colors-gray-400);}*,*::before,::after{border-color:var(--chakra-colors-gray-200);word-wrap:break-word;}</style><div class="font-sans text-primary"><header class="pb-[67.44px] sm:pb-0"><div class="fixed z-20 w-full bg-white border-b-2 border-[#e3efef] sm:static"><div class="flex items-center justify-between mx-auto sm:max-w-screen-sm md:max-w-screen-md lg:max-w-screen-lg xl:max-w-screen-xl 2xl:max-w-screen-2xl"><div class="w-32 py-2 mx-4 sm:py-3 sm:mx-10"><a class="hover:opacity-75" href="/"><span style="box-sizing:border-box;display:inline-block;overflow:hidden;width:initial;height:initial;background:none;opacity:1;border:0;margin:0;padding:0;position:relative;max-width:100%"><span style="box-sizing:border-box;display:block;width:initial;height:initial;background:none;opacity:1;border:0;margin:0;padding:0;max-width:100%"><img style="display:block;max-width:100%;width:initial;height:initial;background:none;opacity:1;border:0;margin:0;padding:0" alt="" aria-hidden="true" src="data:image/svg+xml,%3csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20version=%271.1%27%20width=%27200%27%20height=%2771%27/%3e"/></span><img alt="fwywd" srcSet="/_next/image?url=%2Fimg%2Fcommon%2Flogo.png&amp;w=256&amp;q=100 1x, /_next/image?url=%2Fimg%2Fcommon%2Flogo.png&amp;w=640&amp;q=100 2x" src="/_next/image?url=%2Fimg%2Fcommon%2Flogo.png&amp;w=640&amp;q=100" decoding="async" data-nimg="intrinsic" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%"/></span></a></div><nav class="flex items-center gap-4"><div class="items-center hidden lg:flex divide-x"><a class="px-4 py-2 font-bold tracking-widest cursor-pointer duration-300 hover:text-primary-base" href="/">HOME</a><a class="px-4 py-2 font-bold tracking-widest cursor-pointer duration-300 hover:text-primary-base" href="/concept">コンセプト</a><a href="https://www.kikagaku.co.jp" target="_blank" class="px-4 py-2 font-bold tracking-widest cursor-pointer duration-300 hover:text-primary-base" rel="noreferrer">運営会社</a></div><div class="px-2"><button class="flex items-center px-4 py-3 text-sm text-gray-500 rounded-full shadow w-28 focus:outline-none sm:w-72 hover:bg-[#f1f7f8] hover:text-primary-dark hover:shadow-lg hover:duration-500"><svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 " fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg><p class="ml-2"><span class="hidden sm:inline">記事を</span>検索</p></button></div></nav></div></div></header><ul class="scrollbar_scroll__aiwBC flex flex-row px-4 overflow-x-scroll space-x-4 xl:px-6 xl:space-x-6 bg-primary-lighter"><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/new"><span>New</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/popular"><span>Popular</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/tailwind%20css"><span>Tailwind CSS</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/tailwind%20ui"><span>Tailwind UI</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/syntax"><span>Syntax</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/markdoc"><span>Markdoc</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/markdown"><span>Markdown</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/azure"><span>Azure</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/azure%20app%20service"><span>Azure App Service</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/express.js"><span>Express.js</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/nestjs"><span>NestJS</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/next.js"><span>Next.js</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%83%9E%E3%83%BC%E3%82%B1%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0"><span>マーケティング</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/fwywd"><span>fwywd</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E8%B5%B7%E6%A5%AD"><span>起業</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E7%BE%A4%E3%81%AB%E5%AF%BE%E3%81%99%E3%82%8B%E6%95%99%E8%82%B2"><span>群に対する教育</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E4%BA%95%E3%81%AE%E4%B8%AD%E3%81%AE%E8%9B%99"><span>井の中の蛙</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E5%80%8B%E4%BA%BA%E4%BA%8B%E6%A5%AD%E4%B8%BB"><span>個人事業主</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E5%AD%A6%E7%BF%92"><span>学習</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0"><span>プログラミング</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%88%E3%82%A2%E3%83%83%E3%83%97"><span>スタートアップ</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%83%94%E3%83%83%E3%83%81"><span>ピッチ</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E6%8A%95%E8%B3%87"><span>投資</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E5%AD%A6%E3%81%B3%E6%96%B9"><span>学び方</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E8%B5%B7%E6%A5%AD%E5%AE%B6"><span>起業家</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E7%B5%84%E7%B9%94%E4%BD%9C%E3%82%8A"><span>組織作り</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%83%AB%E3%83%BC%E3%83%AB"><span>ルール</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3"><span>デザイン</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%82%A2%E3%82%A4%E3%83%87%E3%82%A2"><span>アイデア</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/studio"><span>STUDIO</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E6%8A%80%E8%A1%93%E9%81%B8%E5%AE%9A"><span>技術選定</span></a>
8</li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2"><span>エンジニア</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%83%93%E3%82%B8%E3%83%8D%E3%82%B9"><span>ビジネス</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/lpo"><span>LPO</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E8%A7%A3%E8%AA%AC%E8%A8%98%E4%BA%8B"><span>解説記事</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/google%20%E5%BA%83%E5%91%8A"><span>Google 広告</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/google%20tag%20manager"><span>Google Tag Manager</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E6%84%8F%E6%80%9D%E6%B1%BA%E5%AE%9A"><span>意思決定</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E8%A8%AD%E8%A8%88"><span>設計</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2"><span>ソフトウェア</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E4%BB%95%E6%A7%98%E6%9B%B8"><span>仕様書</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%83%86%E3%82%AF%E3%83%8E%E3%83%AD%E3%82%B8%E3%83%BC"><span>テクノロジー</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E6%8A%80%E8%A1%93"><span>技術</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/podcast"><span>Podcast</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%82%BB%E3%83%BC%E3%83%AB%E3%82%B9"><span>セールス</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/react"><span>React</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/aadb2c"><span>AADB2C</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E8%AA%8D%E8%A8%BC%E3%83%BB%E8%AA%8D%E5%8F%AF"><span>認証・認可</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/idaas"><span>IDaaS</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E8%AA%8D%E8%A8%BC"><span>認証</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E8%AA%8D%E5%8F%AF"><span>認可</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E5%89%B5%E6%A5%AD%E8%80%85"><span>創業者</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E7%B5%8C%E5%96%B6%E8%80%85"><span>経営者</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%82%AD%E3%83%A3%E3%83%AA%E3%82%A2"><span>キャリア</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%82%A2%E3%82%A4%E3%83%87%E3%82%A3%E3%82%A2"><span>アイディア</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E5%87%BA%E3%81%97%E6%96%B9"><span>出し方</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E5%8E%9F%E4%BD%93%E9%A8%93"><span>原体験</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%81%8A%E3%81%99%E3%81%99%E3%82%81"><span>おすすめ</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%82%A2%E3%83%B3%E3%83%88%E3%83%AC%E3%83%97%E3%83%AC%E3%83%8A%E3%83%BC"><span>アントレプレナー</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E8%B1%86%E7%9F%A5%E8%AD%98"><span>豆知識</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E7%94%A8%E8%AA%9E"><span>用語</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E8%8B%B1%E8%AA%9E"><span>英語</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E6%95%99%E8%82%B2"><span>教育</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E7%A4%BE%E4%BC%9A%E8%AA%B2%E9%A1%8C"><span>社会課題</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E6%88%A6%E7%95%A5"><span>戦略</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E8%B3%87%E6%9C%AC%E4%B8%BB%E7%BE%A9"><span>資本主義</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E6%9B%B8%E7%B1%8D"><span>書籍</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E6%80%9D%E8%80%83"><span>思考</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E6%B7%A1%E8%B7%AF%E5%B3%B6"><span>淡路島</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E5%9C%B0%E6%96%B9%E5%89%B5%E7%94%9F"><span>地方創生</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/sdgs"><span>SDGs</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%83%91%E3%82%BD%E3%83%8A%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97"><span>パソナグループ</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/c
8hakra%20ui"><span>Chakra UI</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/stylelint"><span>Stylelint</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/prettier"><span>Prettier</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/typescript"><span>TypeScript</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/eslint"><span>ESLint</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/rss"><span>RSS</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/feed"><span>feed</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/google%20analytics"><span>Google Analytics</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%83%86%E3%82%B9%E3%83%88%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA"><span>テスト駆動開発</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/jest"><span>Jest</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/node.js"><span>Node.js</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/chart.js"><span>Chart.js</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/react-chartjs-2"><span>react-chartjs-2</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/microsoft"><span>Microsoft</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/microsoft%20azure"><span>Microsoft Azure</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/azure%20functions"><span>Azure Functions</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/textlint"><span>textlint</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/lint"><span>Lint</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E6%96%87%E7%AB%A0"><span>文章</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E6%8B%AC%E5%BC%A7"><span>括弧</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E5%8F%A5%E8%AA%AD%E7%82%B9"><span>句読点</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/github"><span>GitHub</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/git"><span>Git</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/husky"><span>husky</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/lint-staged"><span>lint-staged</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/testing"><span>Testing</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/github%20actions"><span>GitHub Actions</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%82%B5%E3%82%A4%E3%83%88%E3%83%9E%E3%83%83%E3%83%97"><span>サイトマップ</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/seo"><span>SEO</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/algolia"><span>algolia</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/instant%20search"><span>Instant Search</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/headless%20ui"><span>Headless UI</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0"><span>
8環境変数</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/env%20%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB"><span>env ファイル</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/active%20directory%20b2c"><span>Active Directory B2C</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/auth"><span>Auth</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/javascript"><span>JavaScript</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%89"><span>エンコード</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/git%20flow"><span>Git Flow</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%83%A2%E3%83%87%E3%83%AB"><span>ブランチモデル</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/vscode"><span>VSCode</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%83%91%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%B3%E3%82%B9"><span>パフォーマンス</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/react.memo"><span>React.memo</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/react-syntax-highlighter"><span>react-syntax-highlighter</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/atom"><span>Atom</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/next-sitemap"><span>next-sitemap</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/react-scroll"><span>react-scroll</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/atom"><span>ATOM</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/slack"><span>Slack</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/vue.js"><span>Vue.js</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/nuxt.js"><span>Nuxt.js</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E9%96%8B%E7%99%BA%E4%BD%93%E5%88%B6"><span>開発体制</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E6%8E%A1%E7%94%A8%E8%A9%A6%E9%A8%93"><span>採用試験</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E6%96%B0%E8%A6%8F%E4%BA%8B%E6%A5%AD"><span>新規事業</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/react%20testing%20library"><span>React Testing Library</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/storybook"><span>Storybook</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/cms"><span>CMS</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%82%B3%E3%83%B3%E3%82%BB%E3%83%97%E3%83%88"><span>コンセプト</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/web"><span>Web</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E3%83%97%E3%83%A9%E3%82%A4%E3%83%90%E3%82%B7%E3%83%BC%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC"><span>プライバシーポリシー</span></a></li><li class="my-2 xl:my-3"><a class="py-1 text-xs font-bold border rounded-full cursor-pointer xl:text-sm whitespace-nowrap border-primary-base px-7 text-primary-dark transition-all duration-250 hover:bg-primary-base hover:text-white tag_tag__wWcwT" href="/tech/tags/%E6%8A%80%E8%A1%93%E7%B4%B9%E4%BB%8B"><span>技術紹介</span></a></li></ul><div class="px-4"><div class="pb-6 mx-auto my-8 lg:w-[1000px] xl:w-[1200px] 2xl:w-[1500px]"><div class="lg:grid lg:grid-cols-3 lg:gap-6 xl:gap-8"><div class="col-span-2"><nav class="flex" aria-label="Breadcrumb"><ul class="flex items-center list-none space-x-4"><li><a class="text-gray-400 hover:text-gray-500" href="/"><svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"></path></svg><span class="sr-only">Home</span></a></li><li><div class="flex items-center"><div class="text-gray-400"><svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path></svg></div><p class="ml-4 text-sm font-medium text-gray-500">タグ</p></div></li></ul></nav><h2 class="py-8 text-3xl font-bold text-center md:py-12">Instant Search</h2><div class="grid md:grid-cols-2 gap-4 lg:gap-6 xl:gap-8"><div class="relative block w-full h-full bg-white rounded-lg shadow-md cursor-pointer duration-300 hover:opacity-75"><a href="/tech/next-algolia"><span style="box-sizing:border-box;display:block;overflow:hidden;width:initial;height:initial;background:none;opacity:1;border:0;margin:0;padding:0;position:relative"><span style="box-sizing:border-box;display:block;width:initial;height:initial;background:none;opacity:1;border:0;margin:0;padding:0;padding-top:52.5%"></span><img alt="React / Next.js に algolia を導入して検索機能を追加しよう" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" decoding="async" data-nimg="responsive" class="object-cover w-full h-auto" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%"/><noscript><img alt="React / Next.js に algolia を導入して検索機能を追加しよう" sizes="100vw" srcSet="/_next/image?url=%2Fimg%2Fpages%2Ftech%2Fnext-algolia%2Fogp.png&amp;w=340&amp;q=75 340w, /_next/image?url=%2Fimg%2Fpages%2Ftech%2Fnext-algolia%2Fogp.png&amp;w=640&amp;q=75 640w, /_next/image?url=%2Fimg%2Fpages%2Ftech%2Fnext-algolia%2Fogp.png&amp;w=768&amp;q=75 768w, /_next/image?url=%2Fimg%2Fpages%2Ftech%2Fnext-algolia%2Fogp.png&amp;w=1024&amp;q=75 1024w, /_next/image?url=%2Fimg%2Fpages%2Ftech%2Fnext-algolia%2Fogp.png&amp;w=1280&amp;q=75 1280w, /_next/image?url=%2Fimg%2Fpages%2Ftech%2Fnext-algolia%2Fogp.png&amp;w=1440&amp;q=75 1440w, /_next/image?url=%2Fimg%2Fpages%2Ftech%2Fnext-algolia%2Fogp.png&amp;w=1980&amp;q=75 1980w" src="/_next/image?url=%2Fimg%2Fpages%2Ftech%2Fnext-algolia%2Fogp.png&amp;w=1980&amp;q=75" decoding="async" data-nimg="responsive" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%" class="object-cover w-full h-auto" loading="lazy"/></noscript></span><div class="px-6 py-6 whitespace-normal border-t"><div class="relative"><p class="text-sm font-normal text-gray-light">2021/06/01</p><div class="absolute bottom-0 right-0 w-18"><div class="w-12 h-12 mx-auto border rounded-full border-primary-base lg:w-14 lg:h-14"><span style="box-sizing:border-box;display:block;overflow:hidden;width:initial;height:initial;background:none;opacity:1;border:0;margin:0;padding:0;position:relative"><span style="box-sizing:border-box;display:block;width:initial;height:initial;background:none;opacity:1;border:0;margin:0;padding:0;padding-top:100%"></span><img alt="yoshizaki" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" decoding="async" data-nimg="responsive" class="w-16 h-16 border-2 rounded-full" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%"/><noscript><img alt="yoshizaki" sizes="100vw" srcSet="/_next/image?url=%2Fimg%2Fauthors%2Fyoshizaki.jpg&amp;w=340&amp;q=75 340w, /_next/image?url=%2Fimg%2Fauthors%2Fyoshizaki.jpg&amp;w=640&amp;q=75 640w, /_next/image?url=%2Fimg%2Fauthors%2Fyoshizaki.jpg&amp;w=768&amp;q=75 768w, /_next/image?url=%2Fimg%2Fauthors%2Fyoshizaki.jpg&amp;w=1024&amp;q=75 1024w, /_next/image?url=%2Fimg%2Fauthors%2Fyoshizaki.jpg&amp;w=1280&amp;q=75 1280w, /_next/image?url=%2Fimg%2Fauthors%2Fyoshizaki.jpg&amp;w=1440&amp;q=75 1440w, /_next/image?url=%2Fimg%2Fauthors%2Fyoshizaki.jpg&amp;w=1980&amp;q=75 1980w" src="/_next/image?url=%2Fimg%2Fauthors%2Fyoshizaki.jpg&amp;w=1980&amp;q=75" decoding="async" data-nimg="responsive" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%" class="w-16 h-16 border-2 rounded-full" loading="lazy"/></noscript></span></div><p class="text-sm font-bold text-center">吉崎 亮介</p></div></div><div class="pt-2"><h3 class="font-bold text-strong text-black-base line-clamp-2">React / Next.js に algolia を導入して検索機能を追加しよう</h3><ul class="inline-block pt-3 -mb-3"><li class="inline-block mb-3 mr-3"><span class="px-2 py-1 font-bold border text-[0.8125rem] border-primary-base text-primary-base rounded-[0.3125rem]">React</span></li><li class="inline-block mb-3 mr-3"><span class="px-2 py-1 font-bold border text-[0.8125rem] border-primary-base text-primary-base rounded-[0.3125rem]">Next.js</span></li><li class="inline-block mb-3 mr-3"><span class="px-2 py-1 font-bold border text-[0.8125rem] border-primary-base text-primary-base rounded-[0.3125rem]">TypeScript</span></li><li class="inline-block mb-3 mr-3"><span class="px-2 py-1 font-bold border text-[0.8125rem] border-primary-base text-primary-base rounded-[0.3125rem]">algolia</span></li><li class="inline-block mb-3 mr-3"><span class="px-2 py-1 font-bold border text-[0.8125rem] border-primary-base text-primary-base rounded-[0.3125rem]">Instant Search</span></li><li class="inline-block mb-3 mr-3"><span class="px-2 py-1 font-bold border text-[0.8125rem] border-primary-base text-primary-base rounded-[0.3125rem]">Headless UI</span></li><li class="inline-block mb-3 mr-3"><span class="px-2 py-1 font-bold border text-[0.8125rem] border-primary-base text-primary-base rounded-[0.3125rem]">Tailwind CSS</span></li></ul></div></div></a></div></div></div><div class="mt-10 lg:mt-0 lg:col-span-1 space-y-5"><aside class="lg:h-full"><div class="pb-5"><h3 class="flex items-center text-lg font-bold tracking-widest">新着記事<span class="pl-3 text-sm font-normal tracking-wider up
8percase text-primary-dark">new</span></h3><div class="mt-4 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-1 space-y-3"><a class="items-center cursor-pointer grid grid-cols-4 transition-shadow duration-500 ease-in-out hover:opacity-75" href="/tech/markdown-viewer-by-markdoc"><div class="relative col-span-1"><span style="box-sizing:border-box;display:block;overflow:hidden;width:initial;height:initial;background:none;opacity:1;border:0;margin:0;padding:0;position:relative"><span style="box-sizing:border-box;display:block;width:initial;height:initial;background:none;opacity:1;border:0;margin:0;padding:0;padding-top:100%"></span><img alt="Markdoc (Tailwind UI の Syntax ベース)による Markdown Viewer の実装" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" decoding="async" data-nimg="responsive" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%;object-fit:cover"/><noscript><img alt="Markdoc (Tailwind UI の Syntax ベース)による Markdown Viewer の実装" sizes="100vw" srcSet="/_next/image?url=%2Fimg%2Fpages%2Ftech%2Fmarkdown-viewer-by-markdoc%2Fogp.png&amp;w=340&amp;q=95 340w, /_next/image?url=%2Fimg%2Fpages%2Ftech%2Fmarkdown-viewer-by-markdoc%2Fogp.png&amp;w=640&amp;q=95 640w, /_next/image?url=%2Fimg%2Fpages%2Ftech%2Fmarkdown-viewer-by-markdoc%2Fogp.png&amp;w=768&amp;q=95 768w, /_next/image?url=%2Fimg%2Fpages%2Ftech%2Fmarkdown-viewer-by-markdoc%2Fogp.png&amp;w=1024&amp;q=95 1024w, /_next/image?url=%2Fimg%2Fpages%2Ftech%2Fmarkdown-viewer-by-markdoc%2Fogp.png&amp;w=1280&amp;q=95 1280w, /_next/image?url=%2Fimg%2Fpages%2Ftech%2Fmarkdown-viewer-by-markdoc%2Fogp.png&amp;w=1440&amp;q=95 1440w, /_next/image?url=%2Fimg%2Fpages%2Ftech%2Fmarkdown-viewer-by-markdoc%2Fogp.png&amp;w=1980&amp;q=95 1980w" src="/_next/image?url=%2Fimg%2Fpages%2Ftech%2Fmarkdown-viewer-by-markdoc%2Fogp.png&amp;w=1980&amp;q=95" decoding="async" data-nimg="responsive" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%;object-fit:cover" loading="lazy"/></noscript></span></div><div class="w-full px-3 col-span-3"><div class="text-sm font-bold tracking-wide sm:text-base line-clamp-3 lg:line-clamp-2 2xl:line-clamp-3 leading-5">Markdoc (Tailwind UI の Syntax ベース)による Markdown Viewer の実装</div><div class="flex justify-between pt-3"><span class="text-xs tracking-wide text-gray-light">2022/08/09</span><span class="text-xs font-bold tracking-widest underline uppercase text-primary-base">▶︎ view more</span></div></div></a><a class="items-center cursor-pointer grid grid-cols-4 transition-shadow duration-500 ease-in-out hover:opacity-75" href="/tech/deployment-by-azure-app-service-for-nodejs"><div class="relative col-span-1"><span style="box-sizing:border-box;display:block;overflow:hidden;width:initial;height:initial;background:none;opacity:1;border:0;margin:0;padding:0;position:relative"><span style="box-sizing:border-box;display:block;width:initial;height:initial;background:none;opacity:1;border:0;margin:0;padding:0;padding-top:100%"></span><img alt="GitHub Actions を利用して継続デプロイしてみよう" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" decoding="async" data-nimg="responsive" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%;object-fit:cover"/><noscript><img alt="GitHub Actions を利用して継続デプロイしてみよう" sizes="100vw" srcSet="/_next/image?url=%2Fimg%2Fpages%2Ftech%2Fdeployment-by-azure-app-service-for-nodejs%2Fogp.png&amp;w=340&amp;q=95 340w, /_next/image?url=%2Fimg%2Fpages%2Ftech%2Fdeployment-by-azure-app-service-for-nodejs%2Fogp.png&amp;w=640&amp;q=95 640w, /_next/image?url=%2Fimg%2Fpages%2Ftech%2Fdeployment-by-azure-app-service-for-nodejs%2Fogp.png&amp;w=768&amp;q=95 768w, /_next/image?url=%2Fimg%2Fpages%2Ftech%2Fdeployment-by-azure-app-service-for-nodejs%2Fogp.png&amp;w=1024&amp;q=95 1024w, /_next/image?url=%2Fimg%2Fpages%2Ftech%2Fdeployment-by-azure-app-service-for-nodejs%2Fogp.png&amp;w=1280&amp;q=95 1280w, /_next/image?url=%2Fimg%2Fpages%2Ftech%2Fdeployment-by-azure-app-service-for-nodejs%2Fogp.png&amp;w=1440&amp;q=95 1440w, /_next/image?url=%2Fimg%2Fpages%2Ftech%2Fdeployment-by-azure-app-service-for-nodejs%2Fogp.png&amp;w=1980&amp;q=95 1980w" src="/_next/image?url=%2Fimg%2Fpages%2Ftech%2Fdeployment-by-azure-app-service-for-nodejs%2Fogp.png&amp;w=1980&amp;q=95" decoding="async" data-nimg="responsive" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%;object-fit:cover" loading="lazy"/></noscript></span></div><div class="w-full px-3 col-span-3"><div class="text-sm font-bold tracking-wide sm:text-base line-clamp-3 lg:line-clamp-2 2xl:line-clamp-3 leading-5">【Azure App Service | Node.js】GitHub Actions を利用して継続デプロイしてみよう【 トラブルガイド付】</div><div class="flex justify-between pt-3"><span class="text-xs tracking-wide text-gray-light">2022/08/06</span><span class="text-xs font-bold tracking-widest underline uppercase text-primary-base">▶︎ view more</span></div></div></a><a class="items-center cursor-pointer grid grid-cols-4 transition-shadow duration-500 ease-in-out hover:opacity-75" href="/blog/how-to-write-sentenses"><div class="relative col-span-1"><span style="box-sizing:border-box;display:block;overflow:hidden;width:initial;height:initial;background:none;opacity:1;border:0;margin:0;padding:0;position:relative"><span style="box-sizing:border-box;display:block;width:initial;height:initial;background:none;opacity:1;border:0;margin:0;padding:0;padding-top:100%"></span><img alt="ライター直伝!読みやすさに差をつける文章濃縮術" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" decoding="async" data-nimg="responsive" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%;object-fit:cover"/>
8<noscript><img alt="ライター直伝!読みやすさに差をつける文章濃縮術" sizes="100vw" srcSet="/_next/image?url=%2Fimg%2Fpages%2Fblog%2Fhow-to-write-sentenses%2Fogp.png&amp;w=340&amp;q=95 340w, /_next/image?url=%2Fimg%2Fpages%2Fblog%2Fhow-to-write-sentenses%2Fogp.png&amp;w=640&amp;q=95 640w, /_next/image?url=%2Fimg%2Fpages%2Fblog%2Fhow-to-write-sentenses%2Fogp.png&amp;w=768&amp;q=95 768w, /_next/image?url=%2Fimg%2Fpages%2Fblog%2Fhow-to-write-sentenses%2Fogp.png&amp;w=1024&amp;q=95 1024w, /_next/image?url=%2Fimg%2Fpages%2Fblog%2Fhow-to-write-sentenses%2Fogp.png&amp;w=1280&amp;q=95 1280w, /_next/image?url=%2Fimg%2Fpages%2Fblog%2Fhow-to-write-sentenses%2Fogp.png&amp;w=1440&amp;q=95 1440w, /_next/image?url=%2Fimg%2Fpages%2Fblog%2Fhow-to-write-sentenses%2Fogp.png&amp;w=1980&amp;q=95 1980w" src="/_next/image?url=%2Fimg%2Fpages%2Fblog%2Fhow-to-write-sentenses%2Fogp.png&amp;w=1980&amp;q=95" decoding="async" data-nimg="responsive" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%;object-fit:cover" loading="lazy"/></noscript></span></div><div class="w-full px-3 col-span-3"><div class="text-sm font-bold tracking-wide sm:text-base line-clamp-3 lg:line-clamp-2 2xl:line-clamp-3 leading-5">ライター直伝!読みやすさに差をつける文章濃縮術</div><div class="flex justify-between pt-3"><span class="text-xs tracking-wide text-gray-light">2022/07/28</span><span class="text-xs font-bold tracking-widest underline uppercase text-primary-base">▶︎ view more</span></div></div></a><a class="items-center cursor-pointer grid grid-cols-4 transition-shadow duration-500 ease-in-out hover:opacity-75" href="/blog/educational-design-for-groups"><div class="relative col-span-1"><span style="box-sizing:border-box;display:block;overflow:hidden;width:initial;height:initial;background:none;opacity:1;border:0;margin:0;padding:0;position:relative"><span style="box-sizing:border-box;display:block;width:initial;height:initial;background:none;opacity:1;border:0;margin:0;padding:0;padding-top:100%"></span><img alt="井の中の蛙が人の力を引き出す、群に対する教育の設計術 ~ 専門家が怖くて発言できない、こんな世の中に ~" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" decoding="async" data-nimg="responsive" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%;object-fit:cover"/><noscript><img alt="井の中の蛙が人の力を引き出す、群に対する教育の設計術 ~ 専門家が怖くて発言できない、こんな世の中に ~" sizes="100vw" srcSet="/_next/image?url=%2Fimg%2Fpages%2Fblog%2Feducational-design-for-groups%2Fogp.png&amp;w=340&amp;q=95 340w, /_next/image?url=%2Fimg%2Fpages%2Fblog%2Feducational-design-for-groups%2Fogp.png&amp;w=640&amp;q=95 640w, /_next/image?url=%2Fimg%2Fpages%2Fblog%2Feducational-design-for-groups%2Fogp.png&amp;w=768&amp;q=95 768w, /_next/image?url=%2Fimg%2Fpages%2Fblog%2Feducational-design-for-groups%2Fogp.png&amp;w=1024&amp;q=95 1024w, /_next/image?url=%2Fimg%2Fpages%2Fblog%2Feducational-design-for-groups%2Fogp.png&amp;w=1280&amp;q=95 1280w, /_next/image?url=%2Fimg%2Fpages%2Fblog%2Feducational-design-for-groups%2Fogp.png&amp;w=1440&amp;q=95 1440w, /_next/image?url=%2Fimg%2Fpages%2Fblog%2Feducational-design-for-groups%2Fogp.png&amp;w=1980&amp;q=95 1980w" src="/_next/image?url=%2Fimg%2Fpages%2Fblog%2Feducational-design-for-groups%2Fogp.png&amp;w=1980&amp;q=95" decoding="async" data-nimg="responsive" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%;object-fit:cover" loading="lazy"/></noscript></span></div><div class="w-full px-3 col-span-3"><div class="text-sm font-bold tracking-wide sm:text-base line-clamp-3 lg:line-clamp-2 2xl:line-clamp-3 leading-5">井の中の蛙が人の力を引き出す、群に対する教育の設計術 ~ 専門家が怖くて発言できない、こんな世の中に ~</div><div class="flex justify-between pt-3"><span class="text-xs tracking-wide text-gray-light">2022/07/28</span><span class="text-xs font-bold tracking-widest underline uppercase text-primary-base">▶︎ view more</span></div></div></a><a class="items-center cursor-pointer grid grid-cols-4 transition-shadow duration-500 ease-in-out hover:opacity-75" href="/blog/2022072704"><div class="relative col-span-1"><span style="box-sizing:border-box;display:block;overflow:hidden;width:initial;height:initial;background:none;opacity:1;border:0;margin:0;padding:0;position:relative"><span style="box-sizing:border-box;display:block;width:initial;height:initial;background:none;opacity:1;border:0;margin:0;padding:0;padding-top:100%"></span><img alt="想像していたよりもはるか簡単に社長になった話" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" decoding="async" data-nimg="responsive" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%;object-fit:cover"/>
8<noscript><img alt="想像していたよりもはるか簡単に社長になった話" sizes="100vw" srcSet="/_next/image?url=%2Fimg%2Fpages%2Fblog%2F2022072704%2Fogp.png&amp;w=340&amp;q=95 340w, /_next/image?url=%2Fimg%2Fpages%2Fblog%2F2022072704%2Fogp.png&amp;w=640&amp;q=95 640w, /_next/image?url=%2Fimg%2Fpages%2Fblog%2F2022072704%2Fogp.png&amp;w=768&amp;q=95 768w, /_next/image?url=%2Fimg%2Fpages%2Fblog%2F2022072704%2Fogp.png&amp;w=1024&amp;q=95 1024w, /_next/image?url=%2Fimg%2Fpages%2Fblog%2F2022072704%2Fogp.png&amp;w=1280&amp;q=95 1280w, /_next/image?url=%2Fimg%2Fpages%2Fblog%2F2022072704%2Fogp.png&amp;w=1440&amp;q=95 1440w, /_next/image?url=%2Fimg%2Fpages%2Fblog%2F2022072704%2Fogp.png&amp;w=1980&amp;q=95 1980w" src="/_next/image?url=%2Fimg%2Fpages%2Fblog%2F2022072704%2Fogp.png&amp;w=1980&amp;q=95" decoding="async" data-nimg="responsive" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%;object-fit:cover" loading="lazy"/></noscript></span></div><div class="w-full px-3 col-span-3"><div class="text-sm font-bold tracking-wide sm:text-base line-clamp-3 lg:line-clamp-2 2xl:line-clamp-3 leading-5">想像していたよりもはるか簡単に社長になった話</div><div class="flex justify-between pt-3"><span class="text-xs tracking-wide text-gray-light">2022/07/27</span><span class="text-xs font-bold tracking-widest underline uppercase text-primary-base">▶︎ view more</span></div></div></a></div></div></aside></div></div></div></div><div class="pt-6 pb-24 text-white xl:py-12 bg-footer"><div class="max-w-sm mx-auto md:max-w-lg"><div class="flex justify-center text-xs text-center xl:text-sm"><p class="px-2 py-2 md:px-4 hover:opacity-50"><a href="https://www.kikagaku.co.jp">運営会社</a></p><p class="py-2">|</p><p class="px-2 py-2 md:px-4 hover:opacity-50"><a href="/privacypolicy">プライバシーポリシー</a></p><p class="py-2">|</p><p class="px-2 py-2 md:px-4 hover:opacity-50"><a href="https://share.hsforms.com/1TnFZX_WgSxaaKJzPZuCY7A3zqie">お問い合わせ</a></p></div><div class="w-16 py-4 mx-auto md:py-8 xl:w-24 hover:opacity-75"><a href="/"><span style="box-sizing:border-box;display:block;overflow:hidden;width:initial;height:initial;background:none;opacity:1;border:0;margin:0;padding:0;position:relative"><span style="box-sizing:border-box;display:block;width:initial;height:initial;background:none;opacity:1;border:0;margin:0;padding:0;padding-top:120%"></span><img alt="fwywd white logo" sizes="100vw" srcSet="/_next/image?url=%2Fimg%2Fcommon%2Flogo_white.png&amp;w=340&amp;q=75 340w, /_next/image?url=%2Fimg%2Fcommon%2Flogo_white.png&amp;w=640&amp;q=75 640w, /_next/image?url=%2Fimg%2Fcommon%2Flogo_white.png&amp;w=768&amp;q=75 768w, /_next/image?url=%2Fimg%2Fcommon%2Flogo_white.png&amp;w=1024&amp;q=75 1024w, /_next/image?url=%2Fimg%2Fcommon%2Flogo_white.png&amp;w=1280&amp;q=75 1280w, /_next/image?url=%2Fimg%2Fcommon%2Flogo_white.png&amp;w=1440&amp;q=75 1440w, /_next/image?url=%2Fimg%2Fcommon%2Flogo_white.png&amp;w=1980&amp;q=75 1980w" src="/_next/image?url=%2Fimg%2Fcommon%2Flogo_white.png&amp;w=1980&amp;q=75" decoding="async" data-nimg="responsive" style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%"/></span></a></div><div class="flex justify-center gap-x-3"><a href="https://twitter.com/intent/tweet?url=https://fwywd.com/tech/tags/instant%2520search&amp;hashtags=fwywd,キカガク" target="_blank" class="text-white fill-current transition-all duration-250 hover:opacity-75" rel="noopener noreferrer"><svg id="Layer_1" enable-background="new 0 0 100 100" height="20" viewBox="0 0 100 100" width="20" xmlns="http://www.w3.org/2000/svg"><path id="_x30_4.Twitter" d="m89.9 25.2c-3 1.3-6.1 2.2-9.4 2.6 3.4-2 6-5.2 7.2-9.1-3.2 1.9-6.7 3.2-10.4 4-3-3.2-7.3-5.2-12-5.2-9.1 0-16.4 7.4-16.4 16.4 0 1.3.1 2.5.4 3.7-13.6-.6-25.6-7.2-33.7-17.1-5.8 10.4.7 19 5 21.9-2.6 0-5.2-.8-7.4-2 0 8.1 5.7 14.8 13.1 16.3-1.6.5-5.2.8-7.4.3 2.1 6.5 8.2 11.3 15.3 11.4-5.6 4.4-13.8 7.9-24.3 6.8 7.3 4.7 15.9 7.4 25.2 7.4 30.2 0 46.6-25 46.6-46.6 0-.7 0-1.4-.1-2.1 3.4-2.5 6.2-5.4 8.3-8.7z"></path></svg></a><a href="https://www.facebook.com/sharer/sharer.php?u=https://fwywd.com/tech/tags/instant%2520search" target="_blank" class="text-white fill-current transition-all duration-250 hover:opacity-75" rel="noopener noreferrer"><svg id="Layer_1" height="20" viewBox="0 0 512 512" width="20" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1"><path d="m255.1824 7.7579q69.23.79 125.0851 34.0293a249.7343 249.7343 0 0 1 88.8909 89.4346q33.0371 56.1914 33.8244 125.8428-1.962 95.3-60.1167 162.791c-38.77 44.9941-88.425 72.83-139.8274 83.5009v-178.1275h48.5969l10.99-70h-73.5869v-45.8481a39.844 39.844 0 0 1 8.4739-26.3232q8.8275-11.2527 31.0895-11.8287h44.4366v-61.3184q-.9563-.3077-18.15-2.4336a360.7434 360.7434 0 0 0 -39.16-2.4336q-44.4328.205-70.2811 25.0674-25.8488 24.8554-26.4085 71.9209v53.1973h-56v70h56v178.1275c-63.1149-10.6709-112.77-38.5068-151.54-83.5009s-58.808-99.2578-60.1162-162.791q.7851-69.6546 33.8236-125.8428a249.7389 249.7389 0 0 1 88.8917-89.4346q55.8534-33.2329 125.0842-34.0293z" fill-rule="evenodd"></path></svg></a></div><div class="flex justify-center"><p class="mt-6 text-xs uppercase xl:text-lg">©︎ 2021 kikagaku</p></div></div></div></div><span></span></div>
8<script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"tags":[{"name":"New","path":"/tech/tags/new"},{"name":"Popular","path":"/tech/tags/popular"},{"name":"Tailwind CSS","path":"/tech/tags/tailwind%20css"},{"name":"Tailwind UI","path":"/tech/tags/tailwind%20ui"},{"name":"Syntax","path":"/tech/tags/syntax"},{"name":"Markdoc","path":"/tech/tags/markdoc"},{"name":"Markdown","path":"/tech/tags/markdown"},{"name":"Azure","path":"/tech/tags/azure"},{"name":"Azure App Service","path":"/tech/tags/azure%20app%20service"},{"name":"Express.js","path":"/tech/tags/express.js"},{"name":"NestJS","path":"/tech/tags/nestjs"},{"name":"Next.js","path":"/tech/tags/next.js"},{"name":"マーケティング","path":"/tech/tags/%E3%83%9E%E3%83%BC%E3%82%B1%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0"},{"name":"fwywd","path":"/tech/tags/fwywd"},{"name":"起業","path":"/tech/tags/%E8%B5%B7%E6%A5%AD"},{"name":"群に対する教育","path":"/tech/tags/%E7%BE%A4%E3%81%AB%E5%AF%BE%E3%81%99%E3%82%8B%E6%95%99%E8%82%B2"},{"name":"井の中の蛙","path":"/tech/tags/%E4%BA%95%E3%81%AE%E4%B8%AD%E3%81%AE%E8%9B%99"},{"name":"個人事業主","path":"/tech/tags/%E5%80%8B%E4%BA%BA%E4%BA%8B%E6%A5%AD%E4%B8%BB"},{"name":"学習","path":"/tech/tags/%E5%AD%A6%E7%BF%92"},{"name":"プログラミング","path":"/tech/tags/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0"},{"name":"スタートアップ","path":"/tech/tags/%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%88%E3%82%A2%E3%83%83%E3%83%97"},{"name":"ピッチ","path":"/tech/tags/%E3%83%94%E3%83%83%E3%83%81"},{"name":"投資","path":"/tech/tags/%E6%8A%95%E8%B3%87"},{"name":"学び方","path":"/tech/tags/%E5%AD%A6%E3%81%B3%E6%96%B9"},{"name":"起業家","path":"/tech/tags/%E8%B5%B7%E6%A5%AD%E5%AE%B6"},{"name":"組織作り","path":"/tech/tags/%E7%B5%84%E7%B9%94%E4%BD%9C%E3%82%8A"},{"name":"ルール","path":"/tech/tags/%E3%83%AB%E3%83%BC%E3%83%AB"},{"name":"デザイン","path":"/tech/tags/%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3"},{"name":"アイデア","path":"/tech/tags/%E3%82%A2%E3%82%A4%E3%83%87%E3%82%A2"},{"name":"STUDIO","path":"/tech/tags/studio"},{"name":"技術選定","path":"/tech/tags/%E6%8A%80%E8%A1%93%E9%81%B8%E5%AE%9A"},{"name":"エンジニア","path":"/tech/tags/%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2"},{"name":"ビジネス","path":"/tech/tags/%E3%83%93%E3%82%B8%E3%83%8D%E3%82%B9"},{"name":"LPO","path":"/tech/tags/lpo"},{"name":"解説記事","path":"/tech/tags/%E8%A7%A3%E8%AA%AC%E8%A8%98%E4%BA%8B"},{"name":"Google 広告","path":"/tech/tags/google%20%E5%BA%83%E5%91%8A"},{"name":"Google Tag Manager","path":"/tech/tags/google%20tag%20manager"},{"name":"意思決定","path":"/tech/tags/%E6%84%8F%E6%80%9D%E6%B1%BA%E5%AE%9A"},{"name":"設計","path":"/tech/tags/%E8%A8%AD%E8%A8%88"},{"name":"ソフトウェア","path":"/tech/tags/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2"},{"name":"仕様書","path":"/tech/tags/%E4%BB%95%E6%A7%98%E6%9B%B8"},{"name":"テクノロジー","path":"/tech/tags/%E3%83%86%E3%82%AF%E3%83%8E%E3%83%AD%E3%82%B8%E3%83%BC"},{"name":"技術","path":"/tech/tags/%E6%8A%80%E8%A1%93"},{"name":"Podcast","path":"/tech/tags/podcast"},{"name":"セールス","path":"/tech/tags/%E3%82%BB%E3%83%BC%E3%83%AB%E3%82%B9"},{"name":"React","path":"/tech/tags/react"},{"name":"AADB2C","path":"/tech/tags/aadb2c"},{"name":"認証・認可","path":"/tech/tags/%E8%AA%8D%E8%A8%BC%E3%83%BB%E8%AA%8D%E5%8F%AF"},{"name":"IDaaS","path":"/tech/tags/idaas"},{"name":"認証","path":"/tech/tags/%E8%AA%8D%E8%A8%BC"},{"name":"認可","path":"/tech/tags/%E8%AA%8D%E5%8F%AF"},{"name":"創業者","path":"/tech/tags/%E5%89%B5%E6%A5%AD%E8%80%85"},{"name":"経営者","path":"/tech/tags/%E7%B5%8C%E5%96%B6%E8%80%85"},{"name":"キャリア","path":"/tech/tags/%E3%82%AD%E3%83%A3%E3%83%AA%E3%82%A2"},{"name":"アイディア","path":"/tech/tags/%E3%82%A2%E3%82%A4%E3%83%87%E3%82%A3%E3%82%A2"},{"name":"出し方","path":"/tech/tags/%E5%87%BA%E3%81%97%E6%96%B9"},{"name":"原体験","path":"/tech/tags/%E5%8E%9F%E4%BD%93%E9%A8%93"},{"name":"おすすめ","path":"/tech/tags/%E3%81%8A%E3%81%99%E3%81%99%E3%82%81"},{"name":"アントレプレナー","path":"/tech/tags/%E3%82%A2%E3%83%B3%E3%83%88%E3%83%AC%E3%83%97%E3%83%AC%E3%83%8A%E3%83%BC"},{"name":"豆知識","path":"/tech/tags/%E8%B1%86%E7%9F%A5%E8%AD%98"},{"name":"用語","path":"/tech/tags/%E7%94%A8%E8%AA%9E"},{"name":"英語","path":"/tech/tags/%E8%8B%B1%E8%AA%9E"},{"name":"教育","path":"/tech/tags/%E6%95%99%E8%82%B2"},{"name":"社会課題","path":"/tech/tags/%E7%A4%BE%E4%BC%9A%E8%AA%B2%E9%A1%8C"},{"name":"戦略","path":"/tech/tags/%E6%88%A6%E7%95%A5"},{"name":"資本主義","path":"/tech/tags/%E8%B3%87%E6%9C%AC%E4%B8%BB%E7%BE%A9"},{"name":"書籍","path":"/tech/tags/%E6%9B%B8%E7%B1%8D"},{"name":"思考","path":"/tech/tags/%E6%80%9D%E8%80%83"},{"name":"淡路島","path":"/tech/tags/%E6%B7%A1%E8%B7%AF%E5%B3%B6"},{"name":"地方創生","path":"/tech/tags/%E5%9C%B0%E6%96%B9%E5%89%B5%E7%94%9F"},{"name":"SDGs","path":"/tech/tags/sdgs"},{"name":"パソナグループ","path":"/tech/tags/%E3%83%91%E3%82%BD%E3%83%8A%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97"}
8,{"name":"Chakra UI","path":"/tech/tags/chakra%20ui"},{"name":"Stylelint","path":"/tech/tags/stylelint"},{"name":"Prettier","path":"/tech/tags/prettier"},{"name":"TypeScript","path":"/tech/tags/typescript"},{"name":"ESLint","path":"/tech/tags/eslint"},{"name":"RSS","path":"/tech/tags/rss"},{"name":"feed","path":"/tech/tags/feed"},{"name":"Google Analytics","path":"/tech/tags/google%20analytics"},{"name":"テスト駆動開発","path":"/tech/tags/%E3%83%86%E3%82%B9%E3%83%88%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA"},{"name":"Jest","path":"/tech/tags/jest"},{"name":"Node.js","path":"/tech/tags/node.js"},{"name":"Chart.js","path":"/tech/tags/chart.js"},{"name":"react-chartjs-2","path":"/tech/tags/react-chartjs-2"},{"name":"Microsoft","path":"/tech/tags/microsoft"},{"name":"Microsoft Azure","path":"/tech/tags/microsoft%20azure"},{"name":"Azure Functions","path":"/tech/tags/azure%20functions"},{"name":"textlint","path":"/tech/tags/textlint"},{"name":"Lint","path":"/tech/tags/lint"},{"name":"文章","path":"/tech/tags/%E6%96%87%E7%AB%A0"},{"name":"括弧","path":"/tech/tags/%E6%8B%AC%E5%BC%A7"},{"name":"句読点","path":"/tech/tags/%E5%8F%A5%E8%AA%AD%E7%82%B9"},{"name":"GitHub","path":"/tech/tags/github"},{"name":"Git","path":"/tech/tags/git"},{"name":"husky","path":"/tech/tags/husky"},{"name":"lint-staged","path":"/tech/tags/lint-staged"},{"name":"Testing","path":"/tech/tags/testing"},{"name":"GitHub Actions","path":"/tech/tags/github%20actions"},{"name":"サイトマップ","path":"/tech/tags/%E3%82%B5%E3%82%A4%E3%83%88%E3%83%9E%E3%83%83%E3%83%97"},{"name":"SEO","path":"/tech/tags/seo"},{"name":"algolia","path":"/tech/tags/algolia"},{"name":"Instant Search","path":"/tech/tags/instant%20search"},{"name":"Headless UI","path":"/tech/tags/headless%20ui"},{"name":"環境変数","path":"/tech/tags/%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0"},{"name":"env ファイル","path":"/tech/tags/env%20%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB"},{"name":"Active Directory B2C","path":"/tech/tags/active%20directory%20b2c"},{"name":"Auth","path":"/tech/tags/auth"},{"name":"JavaScript","path":"/tech/tags/javascript"},{"name":"エンコード","path":"/tech/tags/%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%89"},{"name":"Git Flow","path":"/tech/tags/git%20flow"},{"name":"ブランチモデル","path":"/tech/tags/%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%83%A2%E3%83%87%E3%83%AB"},{"name":"VSCode","path":"/tech/tags/vscode"},{"name":"パフォーマンス","path":"/tech/tags/%E3%83%91%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%B3%E3%82%B9"},{"name":"React.memo","path":"/tech/tags/react.memo"},{"name":"react-syntax-highlighter","path":"/tech/tags/react-syntax-highlighter"},{"name":"Atom","path":"/tech/tags/atom"},{"name":"next-sitemap","path":"/tech/tags/next-sitemap"},{"name":"react-scroll","path":"/tech/tags/react-scroll"},{"name":"ATOM","path":"/tech/tags/atom"},{"name":"Slack","path":"/tech/tags/slack"},{"name":"Vue.js","path":"/tech/tags/vue.js"},{"name":"Nuxt.js","path":"/tech/tags/nuxt.js"},{"name":"開発体制","path":"/tech/tags/%E9%96%8B%E7%99%BA%E4%BD%93%E5%88%B6"},{"name":"採用試験","path":"/tech/tags/%E6%8E%A1%E7%94%A8%E8%A9%A6%E9%A8%93"},{"name":"新規事業","path":"/tech/tags/%E6%96%B0%E8%A6%8F%E4%BA%8B%E6%A5%AD"},{"name":"React Testing Library","path":"/tech/tags/react%20testing%20library"},{"name":"Storybook","path":"/tech/tags/storybook"},{"name":"CMS","path":"/tech/tags/cms"},{"name":"コンセプト","path":"/tech/tags/%E3%82%B3%E3%83%B3%E3%82%BB%E3%83%97%E3%83%88"},{"name":"Web","path":"/tech/tags/web"},{"name":"プライバシーポリシー","path":"/tech/tags/%E3%83%97%E3%83%A9%E3%82%A4%E3%83%90%E3%82%B7%E3%83%BC%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC"},{"name":"技術紹介","path":"/tech/tags/%E6%8A%80%E8%A1%93%E7%B4%B9%E4%BB%8B"}],"tagName":"Instant Search","tagPosts":[{"id":"/tech/next-algolia","data":{"title":"React / Next.js に algolia を導入して検索機能を追加しよう","date":"2021-06-01T20:00:00.000+0900","img_path":"/img/pages/tech/next-algolia/ogp.png","img_alt":"React / Next.js に algolia を導入して検索機能を追加しよう","description":"React や Next.js を採用して Web アプリケーションを開発していく際に必ず欲しくなる検索機能ですが、自前での実装は意外と困難です。   その一方で、algolia や Elastic Search を用いることで比較的用意に実装が可能かつある一定量までã
8¯ç„¡æ–™ã§ä½¿ç”¨ã§ãã‚‹ãŸã‚ã€åˆæœŸã®ãƒ—ロダクトへの導入がオススメです。 今回は fwywd(フュード)のページへの検索機能を追加する具体的な手順を解説します。","tags":["React","Next.js","TypeScript","algolia","Instant Search","Headless UI","Tailwind CSS"],"prev_title":"Next.js における環境変数 (env) の基本的な設定方法","prev_link":"/tech/next-ga-pv","next_title":"Web 開発者のための GitHub Actions 入門","next_link":"/tech/introduction-to-github-actions","author":"yoshizaki"},"content":"\n## はじめに\n\n### 概要\n\n**React** や **Next.js** を採用して Web アプリケーションを開発していく際に必ず欲しくなる**検索機能**ですが、自前での実装は意外と困難です。  \nその一方で、**algolia** や **Elastic Search** を用いることで比較的用意に実装が可能かつある一定量までは無料で使用できるため、初期のプロダクトへの導入がオススメです。\n今回は [**fwywd(フュード)**](/) のページへの検索機能を追加する具体的な手順を解説します。\n\n### 成果物\n\n今回は以下のように [**fwywd(フュード)**](/) 内の記事を検索して遷移できる機能を実装していきます。\n\n![modal02](/img/pages/tech/next-algolia/modal02.gif)\n\n### バージョン情報\n\n- Node.js:15.11.0\n- React:17.0.2\n- Next.js:10.2.2\n- remove-markdown:0.3.0\n- algoliasearch:4.0.0\n- react-instantsearch-dom:6.10.0\n- instantsearch.css:6.10.0\n- @algolia/client-search:4.9.1\n- @headlessui/react:1.2.0\n\n## algolia\n\n### algolia とは?\n\n![algolia01](/img/pages/tech/next-algolia/algolia01.png)\n出典:[algolia 公式ページ](https://www.algolia.com/)\n\n[**algolia**](https://www.algolia.com/) は簡単に検索機能を実装することができるサービスです。  \n[**Contentful**](https://www.contentful.com/) や [**microCMS**](https://microcms.io/) といった**ヘッドレス CMS** とも相性が良く、**手軽なブログサービスで algolia が利用されている場面**を多く見かけます。\n\n基本的な検索機能以外にも、**AI によるパーソナライズ機能**なども用意されているようです。\n\n![algolia02](/img/pages/tech/next-algolia/algolia02.png)\n\n開発者目線では、**ドキュメントが豊富に用意されていること**と、JavaScript/TypeScript 以外のプログラミング言語でも利用できるため**汎用性が高いこと**の2点が魅力的だと思います。\n\n![algolia03](/img/pages/tech/next-algolia/algolia03.png)\n\n### algolia 以外のサービスと比較\n\n検索系のサービスは他にもありますが、今回 algolia を採用した一番の理由は [**Tailwind CSS の公式ページ**](https://tailwindcss.com/) で採用されていたためです。\n\n![tailwind](/img/pages/tech/next-algolia/tailwind.png)\n\nalgolia の比較対象としては [**Elasticsearch**](https://www.elastic.co/jp/elasticsearch/) があるようです。  \nこれらのサービスを比較している記事があり内容を抜粋すると以下のように選ぶと良さそうです。\n\n- 検索対象数が少なく手軽に実装したい時は algoria\n- 検索の質を重視したい場合は Elasticsearch\n\n\u003e Algolia は運用コストが低く、日本語の検索や各種高度な機能にもかなり対応しているなと思いました。 検索対象数がそれほど多くない場合や、検索はあくまで補足的な機能ということであれば Algolia で十分だなと思いました(若干値段は高いと思いますが)。  \n\u003e 一方で、より検索の質を重視したい・幅広い要件に対応したい・検索機能の優劣がサービスの競合優位性になりうるということであれば自由度の高い Elasticsearch を使うのが良さそうと思いました。\n\n引用:[Elasticsearch と Algolia の比較検討](https://saitoxu.io/2
8020/03/elasticsearch-and-algolia)\n\n今回は**まず手軽に検索機能を実装したい**という要件ですので algolia の方が良さそうです。\n\nまた、将来的な話をしておくと、[**fwywd(フュード)**](/) では algolia から [**Azure Cognitive Search**](https://azure.microsoft.com/ja-jp/services/search/) へ検索機能を移行していく予定です。  \n検索では**インデックス付け**という検索対象のデータを渡す過程があり、**fwywd** ではデータベース(**Azure Cosmos DB**)を含めたバックエンドを **Microsoft Azure** で構築していきます。  \n**Cosmos DB から自動的にインデックス付けをほぼ実装なしで GUI 操作**により行うことができ、**データ保存から検索までの連携がシームレス**であることが大きな理由です。\n\n![cognitive](/img/pages/tech/next-algolia/cognitive.png)\n出典:[Azure Cognitive Search](https://azure.microsoft.com/ja-jp/services/search/)\n\nただし、最初のデータベースの設計など開発コストがかかりますので、この移行や手順については後々に紹介していきます。  \n**Microsoft Azure** というベンダーロックインも生まれますので、そういったケースを避けたい方は algolia を使い続けることも有力だと思います。\n\nこの点を付け加えると、以下の方に algolia はオススメです。\n\n- **検索対象数が少なく手軽に実装したい時は algoria** に加えて\n  - **ベンダーロックインしたくない**\n  - **データベースでなくローカルファイルやヘッドレス CMS からデータを取得している**\n\n### algolia を使う上で知っておきたいこと\n\n一番気になることは**費用**ですよね。  \n初期のプロダクトや個人開発レベルではおそらく**無料**で使用できる範囲内だと想定しています。\n\n![algolia04](/img/pages/tech/next-algolia/algolia04.png)\n\n**10 units** という単位まで無料で、**1unit が 1000 回の検索リクエスト**であるため、**10,000 回の検索までは無料**ということになります。  \n**1 日に 3000 回の検索があったとしても無料**の範囲内ですので、個人のブログや小規模なプロダクトでは余裕で大丈夫でã
8¯ãªã„でしょうか。\n\n![algolia05](/img/pages/tech/next-algolia/algolia05.png)\n\nそこから先も見据えた時に、**月間 100 万回(約 33,000 回/日)の検索リクエスト**があった場合の費用を確認してみると上記の通りで**約 93,000 円(3,100 円/日)** です。  \n月間 100 万回の検索があるようなサービスは相当大規模かと予想されますので、それでもこのぐらいの費用感だということは**規模が大きくなっても使い続けられるサービス**であることもわかります。\n\nプランは Free, Standard, Premium とあり、10 units までは Free, それ以上は Standard, Personalization などの機能を追加したい場合は Premium と選択は簡単そうです。\n\n![algolia06](/img/pages/tech/next-algolia/algolia06.png)\n\nおそらく途中でプランのアップグレードやダウングレードができると思われますので、**まずは Free** から始めていきましょう。\n\n### ユーザー登録\n\n[**algolia 公式ページ**](https://www.algolia.com/) から始めましょう。  \n特に変わった操作はありませんので、表示される指示にしたがって進めましょう。\n\n![signup01](/img/pages/tech/next-algolia/signup01.png)\n![signup02](/img/pages/tech/next-algolia/signup02.png)\n![signup03](/img/pages/tech/next-algolia/signup03.png)\n![signup04](/img/pages/tech/next-algolia/signup04.png)\n![signup05](/img/pages/tech/next-algolia/signup05.png)\n\n## インデックス\n\n### 前提\n\n[**fwywd(フュード)**](/) では現状ヘッドレス CMS を使用せず、記事のデータはローカルファイルを参照しています。  \nContentful などのヘッドレス CMS を利用する場合は以下の記事も参考にしながら進めると良いでしょう。\n\n参考:[Contentful の記事を Algolia のインデックスに登録する](https://sunday-morning.app/posts/2021-03-27-generate-contentful-algolia-index)\n\n### インデックスの作成\n\nalgolia のページからインデックスの名前を指定して作成しましょう。\n\n![index01](/img/pages/tech/next-algolia/index01.png)\n\nインデックスの追加にはいくつかの方法があり、JSON ファイルを手動でアップロードすることもできます。\n\n![index02](/img/pages/tech/next-algolia/index02.png)\n\nその他にも API 経由での追加もでき、こちらを選択すると、API での追加手順が表示されます。\n\n![index03](/img/pages/tech/next-algolia/index03.png)\n\n今後**ビルドのタイミングで自動的にインデックスの追加を行う運用**を考えると API 経由が望ましいため、今回はこちらを選択します。\n\n### インデックスの形式\n\n作成するインデックスは以下のような形式を目標とします。  \nここで、`objectID` が Algolia 特有のもので、それ以外は必要に応じて変更することができます。\n\n```json\n{\n  \"objectID\": \"記事ID\",\n  \"url\": \"記事URL\",\n  \"title\": \"タイトル\",\n  \"description\": \"記事概要\",\n  \"content\": \"MarkdownをPlainTextに変換した記事本文\"\n}\n```\n\n`objectID` を指定しない場合は自動で生成することもできますが、指定しておく方が運用上楽です。  \nその理由は、記事を作成するたびにインデックスの差分を Algolia 側に通知しないといけないのですが、差分を抽出するコードを実装するよりも、すべての記事を Algolia に伝えるコードをかいておいて、`objectID` が同じであれば変更分は追加や更新がされて、それ以外の重複分は無視されるので楽です。  \n差分だけ送る方が API の通信量を削減できますが、その辺りはリファクタリングのタイミングで良いでしょう。\n\n### インデックスに必要な情報の整形\n\n[**fwywd**](/) のトップページは現状 **SSG** で構成しており、`getStaticProps` に**インデックス情報ã
8®æ•´å½¢** + **API で情報の送信**の機能を実装していきましょう。  \nまずはインデックスに必要な情報の整形を行います。\n\n私は以下のような実装を行いました。\n\n```typescript\n// src/lib/algolia.ts\n\nimport removeMd from 'remove-markdown';\n\nexport const generateIndex = async (): Promise\u003cvoid\u003e =\u003e {\n  // ローカル or ヘッドレス CMS 経由で記事の情報を取得\n  // 各自で実装が必要\n  const posts = async getPosts(...);\n\n  // posts のプロパティ例\n  //   id, title, description, content\n  const objects = posts.map((post) =\u003e {\n    return {\n      objectID: post.id,\n      url: `https://fwywd.com/${post.id}`,\n      title: post.title,\n      description: post.description,\n      content: removeMd(post.content),  // markdown =\u003e plaintext\n    };\n  });\n\n  // 内容の確認\n  console.log(objects)\n};\n```\n\nここで、Markdown のファイルを読み込んで `post.content` に格納しており、alogolia では Platin Text の形式が望ましいため、`remove-markdown` をインストールして利用しています。\n\n```bash\n# npm の場合\nnpm install --save-dev remove-markdown\n\n# yarn の場合\nyarn add --dev remove-markdown\n```\n\nこちらをトップページの `getStaticProps` に
8追加して、トップページにアクセスし、ログを確認してみましょう。\n\n```tsx\n// src/page/index.tsx\n\n...\nimport { generateIndex } from 'lib/algolia';\n...\n\nexport default function Index(): JSX.Element {\n  return (\n    \u003c\u003e...\u003c/\u003e\n  );\n}\n\nexport const getStaticProps: GetStaticProps = async () =\u003e {\n  await generateIndex();\n  ...\n  return { props: { ... } };\n};\n```\n\n以下のように、表示を確認できれば情報の整形が完了です。\n\n```bash\n[{\n    objectID: 'blog/publish',\n    url: 'https://fwywd.com/blog/publish',\n    title: '新事業の fwywd をついに公開しました!',\n    description: 'みなさん、こんにちは。株式会社キカガク代表取締役会長の吉崎です。新しく開設した fwywd(フュード)へお越しいただきまして、誠にありがとうございます。本日 2021 年 5 月 17 日にキカガクの新事業である fwywd を公開することができました。構想から発表まで約5ヶ月の仕込みがありましたので、発表まで辿り着くことができ、大変嬉しく思います。今日まで支えてくださったキカガクのメンバーに改めてお礼を申し上げます。',\n    content: '\\n' +\n      '事業領域の拡大への一歩\\n' +\n  ...\n}]\n```\n\n### API 経由でのインデックスの追加\n\n次に、alogolia の API 経由で整形した情報を送信しましょう。  \nalgolia 用のパッケージが用意されているため、この実装も非常に簡単です。\n\n```bash\n# npm の場合\nnpm install --save-dev algoliasearch\n\n# yarn の場合\nyarn add --dev algoliasearch\n```\n\nAPI を使用する場合には **API キー**が必要となり、algolia のダッシュボード画面から確認することができます。  \n**Appilcation ID** と **Admin API Key** の 2 つが必要となります。\n\n![api01](/img/pages/tech/next-algolia/api01.png)\n\nこの情報を用いて、以下のように API 経由で情報を送信しましょう。\n\n```typescript\n// src/lib/algolia.ts\n\nimport removeMd from 'remove-markdown';\nimport algoliasearch from 'algoliasearch';  // 追加\n\nexport const generateIndex = async (): Promise\u003cvoid\u003e =\u003e {\n  const posts = async getPosts(...);\n  const objects = posts.map((post) =\u003e {\n    return {\n      objectID: post.id,\n      url: `https://fwywd.com/${post.id}`,\n      title: post.title,\n      description: post.description,\n      content: removeMd(post.content),\n    };\n  });\n\n  // 追加\n  const client = algoliasearch('Application ID', 'Admin API Key');\n  const index = client.initIndex('新規で作成した index の名前:今回の例では fwywd');\n  await index.saveObjects(objects, { autoGenerateObjectIDIfNotExist: true });\n};\n```\n\n変更を加えたあとに、トップページへアクセスします。  \nうまく API 経由でインデックスの情報が送信できていれば、以下のように algolia のダッシュボード情報が更新されます。\n\n![api02](/img/pages/tech/next-algolia/api02.png)\n\n`getStaticProps` に
8追加したため、Vercel へデプロイする時に自動的に最新のインデックス情報が更新されるようになります。  \nISR や SSR を使われる方はこの点が異なるため注意が必要です。  \nまた、ヘッドレス CMS を使われる方は **Webhook** の機能を利用しても良いでしょう。\n\n参考:[Contentful の記事を Algolia のインデックスに登録する](https://sunday-morning.app/posts/2021-03-27-generate-contentful-algolia-index)\n\n### 本番環境でのみインデックス作成\n\nインデックスの作成方法がわかり、実際に API 経由でインデックスのデータを送信することができましたが、現状の実装では無駄があります。  \nそれはローカルの開発環境でもトップページにアクセスするたびにインデックスの情報を送ってしまっています。  \n本来は本番環境でのビルド時のみで良いため、環境変数の `NODE_ENV` が `production` のときのみ、インデックス作成および API 経由での情報の送信を行うように条件を分岐しておきましょう。\n\n```tsx\n// src/page/index.tsx\n\n...\nimport { generateIndex } from 'lib/algolia';\n...\n\nexport default function Index(): JSX.Element {\n  return (\n    \u003c\u003e...\u003c/\u003e\n  );\n}\n\nexport const getStaticProps: GetStaticProps = async () =\u003e {\n  // 条件分岐を追記\n  if (process.env.NODE_ENV === 'production') {\n    await generateIndex();\n  }\n  ...\n  return { props: { ... } };\n};\n```\n\n## 検索画面の UI 実装\n\n### 最もシンプルな検索画面\n\n[**公式ページのドキュメント**](https://www.algolia.com/doc/guides/building-search-ui/getting-started/react/#welcome-to-react-instantsearch)では、[**React InstantSearch**](https://github.com/algolia/react-instantsearch) というパッケージを利用しています。\n\n参考:[GUIDES / BUILDING SEARCH UI - Getting Started](https://www.algolia.com/doc/guides/building-search-ui/getting-started/react/#welcome-to-react-instantsearch)\n\n[**React InstantSearch**](https://github.com/algolia/react-instantsearch) は algolia 公式が作っているみたいですね。\n\n```bash\n# npm の場合\nnpm install --save-dev react-instantsearch-dom\n\n# yarn の場合\nyarn add --dev react-instantsearch-dom\n```\n\n[**React InstantSearch**](https://github.com/algolia/react-instantsearch) のページで書かれている **Get Started** を参考に、最も簡単な UI を作ってみましょう。\n\n検索時に API の情報が必要となるため、下記の画面から確認しておきましょう。\n\n![ui01](/img/pages/tech/next-algolia/ui01.png)\n\n下記のように `Search` コンポーネントを作成し、ヘッダー位置に挿入しました。\n\n```tsx\n// components/common/Search.tsx\n\nimport algoliasearch from 'algoliasearch/lite';\nimport { InstantSearch, SearchBox, Hits } from 'react-instantsearch-dom';\n\nexport default function Search(): JSX.Element {\n  const searchClient = algoliasearch('Application ID', 'Search-Only API Key');\n  const indexName = '新規で作成した index の名前:今回の例では fwywd';\n  return (\n    \u003cdiv\u003e\n      \u003cInstantSearch indexName={indexName} searchClient={searchClient}\u003e\n        \u003cSearchBox /\u003e\n        \u003cHits /\u003e\n      \u003c/InstantSearch\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\nこちらで結果を確認してみると以下のようにかなりの表示崩れはありますが、API 経由で情報を取得して、一応検索機能も動作していることがわかります。\n\n![ui02](/img/pages/tech/next-algolia/ui02.png)\n![ui03](/img/pages/tech/next-algolia/ui03.png)\n\n### 検索結果を加工\n\n検索結果が `{\"hit\": {\"url\": ...}` となっており、現状では検索結果として使いにくいため、まずは**タイトル**だけを抽出して、その **URL** をリンクとして設定できるようにしましょう。  \nここをどう表現すべきかが少し難しいのですが、色々調査して、`Hits` コンポーネントの引数に `hitComponent` を指定すると良いことがわかり、以下のように書くところに辿り着きました。\n\n\u003e 補足:環境変数  \n\u003e ここから API キーなどは `.env` ファイルに格納してå
8‚照しています。  \n\u003e `Admin API Key` のみサーバーサイドで隠蔽したいため、`NEXT_PUBLIC_` を外しています。\n\u003e 参考記事:[Next.js における環境変数 (env) の基本的な設定方法](/tech/next-env)\n\n```bash\n# .env.development\n\n# 追記\nNEXT_PUBLIC_ALGOLIA_APPLICATION_ID='Application ID'\nNEXT_PUBLIC_ALGOLIA_INDEX='IndexName'\nNEXT_PUBLIC_ALGOLIA_SEARCH_API_KEY='Search API Key'\nALGOLIA_ADMIN_API_KEY='Admin API Key'\n```\n\n```tsx\n// src/components/common/Search.tsx\n\nimport algoliasearch from 'algoliasearch/lite';\nimport { hitComponent } from 'components/common/HitComponent';\nimport { InstantSearch, SearchBox, Hits } from 'react-instantsearch-dom';\n\nexport default function Search(): JSX.Element {\n  const searchClient = algoliasearch(\n    process.env.NEXT_PUBLIC_ALGOLIA_APPLICATION_ID || '',\n    process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_API_KEY || '',\n  );\n  const indexName = process.env.NEXT_PUBLIC_ALGOLIA_INDEX || '';\n\n  return (\n    \u003cdiv\u003e\n      \u003cInstantSearch indexName={indexName} searchClient={searchClient}\u003e\n        \u003cSearchBox /\u003e\n        \u003cHits hitComponent={hitComponent} /\u003e\n      \u003c/InstantSearch\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\nここで使用している `hitComponent` が検索結果に対して操作ができるもので、以下のように定義しています。\n\n```tsx\n// src/components/common/HitComponent\n\nimport Link from 'next/link';\nimport { Hit } from 'react-instantsearch-core';\n\ninterface HitDoc {\n  objectID: string;\n  url: string;\n  title: string;\n  description: string;\n  content: string;\n}\n\ninterface Props {\n  hit: Hit\u003cHitDoc\u003e;\n}\n\ninterface HitComponentProps extends Props {\n  onClick: () =\u003e void;\n}\n\nfunction HitComponent({ hit }: HitComponentProps): JSX.Element {\n  return (\n    \u003cdiv\u003e\n      \u003cLink href={hit.url}\u003e\n        \u003ca className=\"hover:text-[#06bbbc]\"\u003e{hit.title}\u003c/a\u003e\n      \u003c/Link\u003e\n    \u003c/div\u003e\n  );\n}\n\nexport const hitComponent = ({ hit }: Props): JSX.Element =\u003e (\n  \u003cHitComponent hit={hit} onClick={() =\u003e null} /\u003e\n);\n```\n\n`Hits` コンポーネントの引数がちょっと特殊であるため最初はわかりにくいかも知れませんが、一度設定してしまえば、あとは `HitComponent` を編集すれば OK です。\n\n以下のように、タイトルのみが表示されるようになりました。\n\n![ui04](/img/pages/tech/next-algolia/ui04.png)\n![ui05](/img/pages/tech/next-algolia/ui05.png)\n\n少しずつ形になってきました。\n\n### 検索結果のヒット数を制限\n\n現状では、ヒットした全てが表示されてしまっているため、**上位5件**の表示に制限してみましょう。  \n`Configure` コンポーネントを追加するだけでとても簡単です。\n\n```tsx\n// src/components/common/Search.tsx\n\nimport algoliasearch from 'algoliasearch/lite';\nimport { hitComponent } from 'components/common/HitComponent';\nimport { InstantSearch, SearchBox, Hits, Configure } from 'react-instantsearch-dom';\n\nexport default function Search(): JSX.Element {\n  const searchClient = algoliasearch(\n    process.env.NEXT_PUBLIC_ALGOLIA_APPLICATION_ID || '',\n    process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_API_KEY || '',\n  );\n  const indexName = process.env.NEXT_PUBLIC_ALGOLIA_INDEX || '';\n\n  return (\n    \u003cdiv\u003e\n      \u003cInstantSearch indexName={indexName} searchClient={searchClient}\u003e\n        \u003cConfigure hitsPerPage={5} /\u003e {/* \u003c== 追記 */}\n        \u003cSearchBox /\u003e\n        \u003cHits hitComponent={hitComponent} /\u003e\n      \u003c/InstantSearch\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n![configure01](/img/pages/tech/next-algolia/configure01.png)\n\n### ページネーションの設定\n\n検索結果を制限した関係で上位 5 件しか表示されなくなりました。  \n5 件目以降の検索結果にアクセスするために**ページネーション**を追加しましょう。  \nこちらも `Pagination` コンポーネントを追加するだけで良いため簡単です。\n\n```tsx\n// src/components/common/Search.tsx\n\nimport algoliasearch from 'algoliasearch/lite';\nimport { hitComponent } from 'components/common/HitComponent';\nimport { InstantSearch, SearchBox, Hits, Configure, Pagination } from 'react-instantsearch-dom';
8\n\nexport default function Search(): JSX.Element {\n  const searchClient = algoliasearch(\n    process.env.NEXT_PUBLIC_ALGOLIA_APPLICATION_ID || '',\n    process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_API_KEY || '',\n  );\n  const indexName = process.env.NEXT_PUBLIC_ALGOLIA_INDEX || '';\n\n  return (\n    \u003cdiv\u003e\n      \u003cInstantSearch indexName={indexName} searchClient={searchClient}\u003e\n        \u003cConfigure hitsPerPage={5} /\u003e\n        \u003cSearchBox /\u003e\n        \u003cHits hitComponent={hitComponent} /\u003e\n        \u003cPagination /\u003e {/* \u003c== 追記 */}\n      \u003c/InstantSearch\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n![pagination01](/img/pages/tech/next-algolia/pagination01.png)\n\n### CSS を適用\n\nそれぞれの役割が少しずつ把握できてきたところで、表示崩れを解消するための CSS を適用しましょう。  \n標準の CSS が用意されているため、以下のようにインストールしましょう。\n\n```bash\n# npm の場合\nnpm install instantsearch.css\n\n# yarn の場合\nyarn add instantsearch.css\n```\n\nこれで `node_modules/instantsearch.css` 下に CSS を含んだパッケージがインストールされます。\n\n標準的な `algolia.css`、別パターンの `satellite.css` が用意されています。  \n全て準備したい人向けの `reset.css` もあります。\nそれぞれにファイルを最小化 `min` 版がありますので、こちらを使うと良いでしょう。\n\n```tsx\n// src/components/common/Search.tsx\n\nimport algoliasearch from 'algoliasearch/lite';\nimport { hitComponent } from 'components/common/HitComponent';\nimport { InstantSearch, SearchBox, Hits, Configure, Pagination } from 'react-instantsearch-dom';\nimport 'instantsearch.css/themes/algolia-min.css'; // \u003c== 追記:使いたいスタイルに合わせて変更\n\nexport default function Search(): JSX.Element {\n  const searchClient = algoliasearch(\n    process.env.NEXT_PUBLIC_ALGOLIA_APPLICATION_ID || '',\n    process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_API_KEY || '',\n  );\n  const indexName = process.env.NEXT_PUBLIC_ALGOLIA_INDEX || '';\n\n  return (\n    \u003cdiv\u003e\n      \u003cInstantSearch indexName={indexName} searchClient={searchClient}\u003e\n        \u003cConfigure hitsPerPage={5} /\u003e\n        \u003cSearchBox /\u003e\n        \u003cHits hitComponent={hitComponent} /\u003e\n        \u003cPagination /\u003e\n      \u003c/InstantSearch\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n![css01](/img/pages/tech/next-algolia/css01.png)\n![css02](/img/pages/tech/next-algolia/css02.png)\n![css03](/img/pages/tech/next-algolia/css03.png)\n\n[**fwywd(フュード)**](/) では `satellite-min.css` を使用することにしました。  \nCSS を適用するだけで、検索機能としてそれらしくなってきましたね。\n\n参考にした記事では `Search` のコンポーネント自体で読み込むのではなく、`_app.tsx` でグローバルに読み込んでいました。  \nこれはテーマの CSS を上書きしたい場合に必要であり、詳しい理由はまた必要な場面で紹介しますのでご安心ください。\n\n参考:[Next.js + Algolia で全文検索 UI を実装する](https://sunday-morning.app/posts/2021-03-28-next-js-algolia-search-ui)\n\n## UI の詳細なカスタマイズ\n\n### 初期状態で検索結果を表示しない\n\n現状では初期状態の空文字に対しても検索を行っています。  \n空文字では検索を行わないように設定を行います。\n\n詳細な設定の場合は別途 `@algolia/*` で定義されているパッケージが必要となります。\n\n参考:[algoliasearch-client-javascript/packages/](https://github.com/algolia/algoliasearch-client-javascript/tree/3aec216a9704f818b4faaa8b97d988ec2794f9da/packages)\n\n```bash\n# npm の場合\nnpm install --save-dev @algolia/client-search\n\n# yarn の場合\nyarn add --dev @algolia/client-search\n```\n\nまずは検索に関する設定を行うための雛形を作成しておきます。\n\n参考:[Conditional Requests - algolia](https://www.algolia.com/doc/guides/building-search-ui/going-further/conditional-requests/react/)\n\n```tsx\n// src/components/common/Search.tsx\n\nimport { MultipleQueriesQuery } from '@algolia/client-search'; // \u003c== 追記\nimport algoliasearch from 'algoliasearch/lite';\nimport { hitComponent } from 'components/common/HitComponent';\nimport { InstantSearch, SearchBox, Hits, Configure, Pagination } from 'react-instantsearch-dom';\nimport 'instantsearch.css/themes/satellite-min.css';\n\nexport default function Search(): JSX.Element {\n  const indexName = process.env.NEXT_PUBLIC_ALGOLIA_INDEX || '';
8\n  const algoliaClient = algoliasearch(\n    process.env.NEXT_PUBLIC_ALGOLIA_APPLICATION_ID || '',\n    process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_API_KEY || '',\n  ); // \u003c== 名称を変更\n\n  // こちらに設定を追記していく\n  const searchClient = {\n    ...algoliaClient,\n    search(requests: MultipleQueriesQuery[]) {\n      return algoliaClient.search(requests);\n    },\n  };\n\n  return (\n    \u003cdiv\u003e\n      \u003cInstantSearch indexName={indexName} searchClient={searchClient}\u003e\n        \u003cConfigure hitsPerPage={5} /\u003e\n        \u003cSearchBox /\u003e\n        \u003cHits hitComponent={hitComponent} /\u003e\n        \u003cPagination /\u003e\n      \u003c/InstantSearch\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\nそして、空文字 `!params?.query` の場合には検索結果が何もないとモックした情報 `mock` を送ります。  \n書き方のお作法は以下の公式ページを参考にしており、思いつきで書いたわけではありません。\n\n参考:[Conditional Requests - algolia](https://www.algolia.com/doc/guides/building-search-ui/going-further/conditional-requests/react/)\n\n```tsx\n// src/components/common/Search.tsx\n\nimport { MultipleQueriesQuery } from '@algolia/client-search';\n\nimport algoliasearch from 'algoliasearch/lite';\nimport { hitComponent } from 'components/common/HitComponent';\nimport { InstantSearch, SearchBox, Hits, Configure, Pagination } from 'react-instantsearch-dom';\nimport 'instantsearch.css/themes/satellite-min.css';\n\nexport default function Search(): JSX.Element {\n  const indexName = process.env.NEXT_PUBLIC_ALGOLIA_INDEX || '';\n  const algoliaClient = algoliasearch(\n    process.env.NEXT_PUBLIC_ALGOLIA_APPLICATION_ID || '',\n    process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_API_KEY || '',\n  );\n\n  // 検索結果なしのモック情報\n  const mock = {\n    hits: [],\n    nbHits: 0,\n    nbPages: 0,\n    page: 0,\n    processingTimeMS: 0,\n  };\n\n  // 空文字の場合は何もない情報をモックして渡す\n  const searchClient = {\n    ...algoliaClient,\n    search(requests: MultipleQueriesQuery[]) {\n      if (requests.every(({ params }) =\u003e !params?.query)) {\n        return Promise.resolve(mock);\n      }\n      return algoliaClient.search(requests);\n    },\n  };\n\n  return (\n    \u003cdiv\u003e\n      \u003cInstantSearch indexName={indexName} searchClient={searchClient}\u003e\n        \u003cConfigure hitsPerPage={5} /\u003e\n        \u003cSearchBox /\u003e\n        \u003cHits hitComponent={hitComponent} /\u003e\n        \u003cPagination /\u003e\n      \u003c/InstantSearch\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n参考記事では `Promise.resolve` の中を `map` で配列を返すように指定していましたが、無駄なページネーションが表示されるため、この点は変更しています。  \n特に今のところは問題がありませんが、また問題があれば参考記事の形式に合わせようと思います。\n\n![mock](/img/pages/tech/next-algolia/mock.png)\n\nここで、`searchClient` 周りも情報が多くなってきたため、管理がしやすいように切り出しておきましょう。\n\n```typescript\n// src/lib/searchClient.ts\n\nimport { MultipleQueriesQuery } from '@algolia/client-search';\nimport algoliasearch from 'algoliasearch/lite';\n\nexport const indexName = process.env.NEXT_PUBLIC_ALGOLIA_INDEX || '';\nexport const algoliaClient = algoliasearch(\n  process.env.NEXT_PUBLIC_ALGOLIA_APPLICATION_ID || '',\n  process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_API_KEY || '',\n);\n\n// 空文字の場合は何もない情報をモックして渡す\nexport const searchClient = {\n  ...algoliaClient,\n  search(requests: MultipleQueriesQuery[]) {\n    if (requests.every(({ params }) =\u003e !params?.query)) {\n      return Promise.resolve(mock);\n    }\n    return algoliaClient.search(requests);\n  },\n};\n\n// 検索結果なしのモック情報\nconst mock = {\n  hits: [],\n  nbHits: 0,\n  nbPages: 0,\n  page: 0,\n  processingTimeMS: 0,\n};\n```\n\n```tsx\n// src/component/common/Search.tsx\n\nimport { hitComponent } from 'components/common/HitComponent';\nimport { indexName, searchClient } from 'lib/searchClient';\nimport { InstantSearch, SearchBox, Hits, Configure, Pagination } from 'react-instantsearch-dom';\nimport 'instantsearch.css/themes/satellite-min.css';\n\nexport default function Search(): JSX.Element {\n  return (\n    \u003cdiv\u003e\n      \u003cInstantSearch indexName={indexName} searchClient={searchClient}\u003e\n        \u003cConfigure hitsPerPage={5} /\u003e\n        \u003cSearchBox /\u003e\n        \u003cHits hitComponent={hitComponent} /\u003e\n        \u003cPagination /\u003e\n      \u003c/InstantSearch\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\nだいぶスッキリと書くことができました。\n\n### 検索結果ã
8Œæ®‹ã‚‹å•é¡Œã‚’解消\n\n内部リンクを利用する `Link` コンポーネントで遷移をさせると、ページ遷移後も検索結果が残ってしまうことがあります。\n\n![reset01](/img/pages/tech/next-algolia/reset01.png)\n![reset02](/img/pages/tech/next-algolia/reset02.png)\n\nこちらの参考記事いわく、`connectSearchBox` を利用すると良さそうです。\n\n参考:[Algolia Instantsearch で、検索結果クリック時にキーワードをリセットする](https://wp-kyoto.net/algolia-instantsearch-reset-serchword-by-custom-event/)\n\nまずは全体の雛形を作っていきます。  \n`Hits` コンポーネントを `SearchResult` コンポーネント内に格納しただけで、特に動作の変更はまだありません。\n\n```tsx\n// src/component/common/Search.tsx\n\nimport { indexName, searchClient } from 'lib/searchClient';\nimport { InstantSearch, SearchBox, Configure, Pagination } from 'react-instantsearch-dom';\nimport 'instantsearch.css/themes/satellite-min.css';\nimport { SearchResult } from './HitComponent'; // \u003c== 変更\n\nexport default function Search(): JSX.Element {\n  return (\n    \u003cdiv\u003e\n      \u003cInstantSearch indexName={indexName} searchClient={searchClient}\u003e\n        \u003cConfigure hitsPerPage={5} /\u003e\n        \u003cSearchBox /\u003e\n        \u003cSearchResult /\u003e {/* Hits =\u003e SearchResult */}\n        \u003cPagination /\u003e\n      \u003c/InstantSearch\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n```tsx\n// src/components/common/HitComponent.tsx\n\nimport Link from 'next/link';\nimport { Hit } from 'react-instantsearch-core';\nimport { Hits, connectSearchBox } from 'react-instantsearch-dom';\n\ninterface HitDoc {\n  objectID: string;\n  url: string;\n  title: string;\n  description: string;\n  content: string;\n}\n\ninterface Props {\n  hit: Hit\u003cHitDoc\u003e;\n}\n\ninterface HitComponentProps extends Props {\n  onClick: () =\u003e void;\n}\n\nfunction HitComponent({ hit }: HitComponentProps): JSX.Element {\n  return (\n    \u003cdiv\u003e\n      \u003cLink href={hit.url}\u003e\n        \u003ca className=\"hover:text-[#06bbbc]\"\u003e{hit.title}\u003c/a\u003e\n      \u003c/Link\u003e\n    \u003c/div\u003e\n  );\n}\n\n// 初期の雛形\nexport const SearchResult = connectSearchBox(({ refine, currentRefinement }) =\u003e {\n  const hitComponent = ({ hit }: Props): JSX.Element =\u003e (\n    \u003cHitComponent hit={hit} onClick={() =\u003e null} /\u003e\n  );\n\n  return \u003cHits hitComponent={hitComponent} /\u003e;\n});\n```\n\nここから、少し飛躍がありますが、以下のように変更していきます。\n\n```tsx\n// src/components/common/HitComponent.tsx\n\nimport Link from 'next/link';\nimport { useEffect, useState, useCallback } from 'react'; // 追加\nimport { Hit } from 'react-instantsearch-core';\nimport { Hits, connectSearchBox } from 'react-instantsearch-dom';\n\ninterface HitDoc {\n  objectID: string;\n  url: string;\n  title: string;\n  description: string;\n  content: string;\n}\n\ninterface Props {\n  hit: Hit\u003cHitDoc\u003e;\n}\n\ninterface HitComponentProps extends Props {\n  onClick: () =\u003e void;\n}\n\nfunction HitComponent({ hit, onClick }: HitComponentProps): JSX.Element {\n  return (\n    \u003cdiv\u003e\n      \u003cLink href={hit.url}\u003e\n        \u003cbutton className=\"hover:text-[#06bbbc]\" onClick={onClick}\u003e\n          {hit.title}\n        \u003c/button\u003e\n      \u003c/Link\u003e\n    \u003c/div\u003e\n  );\n}\n\nexport const SearchResult = connectSearchBox(({ refine, currentRefinement }) =\u003e {\n  // refine: function =\u003e 現状のクエリを変更\n  // currentRefinement: string =\u003e 現状のクエリ\n\n  const [isShow, setShow] = useState\u003cboolean\u003e(false);\n\n  // マウント時に実行\n  useEffect(() =\u003e {\n    // !! は currentRefinement が空文字か判定 (true or false)\n    setShow(!!currentRefinement); // =\u003e 空文字は表示しないようにセットされる\n  }, [currentRefinement]);
8 // currentRefinement に変化があれば再度実行\n\n  // リセットと同時に useCallback でメモ化して無駄なレンダリングを防ぐ\n  const handleResetSearchWords = useCallback(() =\u003e {\n    refine(''); // クエリを空文字に指定してリセット\n  }, [refine]);\n\n  const hitComponent = ({ hit }: Props): JSX.Element =\u003e (\n    \u003cHitComponent hit={hit} onClick={handleResetSearchWords} /\u003e\n  );\n\n  if (!isShow) return null;\n  return \u003cHits hitComponent={hitComponent} /\u003e;\n});\n```\n\nそれぞれの役割はコメントアウトしておきました。\nまた、`connectSearchBox` の引数 `refine` と `currentRefinement` は公式ページから役割を確認しました。\n\n参考:[SearchBox - algolia](https://www.algolia.com/doc/api-reference/widgets/search-box/react/)\n\n少し手間がかかる方法ですが、検索結果をマウント時にリセットすることができました。\n\n![reset03](/img/pages/tech/next-algolia/reset03.png)\n\n\u003e **補足**\n\u003e 最終的な成果物には `Link` コンポーネントを使わずに `a` タグでの遷移に切り替えており、この処理は動作的には必要なくなりました。  \n\u003e ただし、もう状態管理など少し込みいった実装を行えば、この方法のまま進めることができ、こちらがベストですので知っておいて損はありません。\n\nただし、不要なページネーションが設定されてしまっています。  \nそこで、`Pagination` コンポーネントも `SearchResult` コンポーネントに包含してしまいましょう。\n\n以下が最終的な全体像です。  \n`HitComponent.tsx` から `SearchResult.tsx` にファイル名を変更しているところも注意です。\n\n```tsx\n// src/components/common/Search.tsx\n\nimport SearchResult from 'components/common/SearchResult';\nimport { indexName, searchClient } from 'lib/searchClient';\nimport { InstantSearch, SearchBox, Configure } from 'react-instantsearch-dom';\nimport 'instantsearch.css/themes/satellite-min.css';\n\nexport default function Search(): JSX.Element {\n  return (\n    \u003cdiv\u003e\n      \u003cInstantSearch indexName={indexName} searchClient={searchClient}\u003e\n        \u003cConfigure hitsPerPage={5} /\u003e\n        \u003cSearchBox /\u003e\n        \u003cSearchResult /\u003e\n      \u003c/InstantSearch\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n```tsx\n// src/components/common/SearchResult.tsx\n\nimport Link from 'next/link';\nimport { useEffect, useState, useCallback } from 'react';\nimport { Hit } from 'react-instantsearch-core';\nimport { Hits, connectSearchBox, Pagination } from 'react-instantsearch-dom';\n\ninterface HitDoc {\n  objectID: string;\n  url: string;\n  title: string;\n  description: string;\n  content: string;\n}\n\ninterface Props {\n  hit: Hit\u003cHitDoc\u003e;\n}\n\ninterface HitComponentProps extends Props {\n  onClick: () =\u003e void;\n}\n\nfunction HitComponent({ hit, onClick }: HitComponentProps): JSX.Element {\n  return (\n    \u003cdiv\u003e\n      \u003cLink href={hit.url}\u003e\n        \u003cbutton className=\"hover:text-[#06bbbc]\" onClick={onClick}\u003e\n          {hit.title}\n        \u003c/button\u003e\n      \u003c/Link\u003e\n    \u003c/div\u003e\n  );\n}\n\nconst SearchResult = connectSearchBox(({ refine, currentRefinement }) =\u003e {\n  const [isShow, setShow] = useState\u003cboolean\u003e(false);\n\n  useEffect(() =\u003e {\n    setShow(!!currentRefinement);\n  }, [currentRefinement]);\n\n  const handleResetSearchWords = useCallback(() =\u003e {\n    refine('');\n  }, [refine]);\n\n  const hitComponent = ({ hit }: Props): JSX.Element =\u003e (\n    \u003cHitComponent hit={hit} onClick={handleResetSearchWords} /\u003e\n  );\n\n  if (!isShow) return null;\n  return (\n    \u003c\u003e\n      \u003cHits hitComponent={hitComponent} /\u003e\n      \u003cPagination /\u003e {/* 追加 */}\n    \u003c/\u003e\n  );\n});\n\nexport default SearchResult;\n```\n\nこれでページネーションが不要に表示される問題も解決されました。\n\n### 検索対象の設定\n\nここで少し実装から離れて algolia の設定を見直しましょう。  \n検索に使用する対象が定義したインデックスの全てになっていますが、今回はその中でも `title` と `description` のみを検索対象として絞ってみましょう。  \nこの動機として、`content` まで入れてしまうと `React` や `Next.js` といった用語がどのような記事でも必ず入ってしまうため、検索の質が落ちてしまうためです。  \n`content` を含めるかどうかは規模によっても変わってくるため、その状況に合わせて検討しましょう。\n\n![config01](/img/
8pages/tech/next-algolia/config01.png)\n![config02](/img/pages/tech/next-algolia/config02.png)\n![config03](/img/pages/tech/next-algolia/config03.png)\n\nまた、検索の言語を日本語にも設定しておくと良いでしょう。\n\n![config04](/img/pages/tech/next-algolia/config04.png)\n![config05](/img/pages/tech/next-algolia/config05.png)\n![config06](/img/pages/tech/next-algolia/config06.png)\n\n### 検索クエリをハイライト\n\n検索クエリと該当している箇所の色を変更するといった**ハイライト**も `Highlight` コンポーネントで簡単に実装できます。\n\n```tsx\n// 変更箇所\nfunction HitComponent({ hit, onClick }: HitComponentProps): JSX.Element {\n  return (\n    \u003cdiv\u003e\n      \u003cLink href={hit.url}\u003e\n        \u003cbutton className=\"hover:text-[#06bbbc]\" onClick={onClick}\u003e\n          \u003cHighlight attribute=\"title\" hit={hit} /\u003e {/* \u003c== title の属性を表示 */}\n        \u003c/button\u003e\n      \u003c/Link\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n全体像はこちらです。\n\n```tsx\n// src/components/common/SearchResult.tsx\n\nimport Link from 'next/link';\nimport { useEffect, useState, useCallback } from 'react';\nimport { Hit } from 'react-instantsearch-core';\nimport { Hits, connectSearchBox, Pagination, Highlight } from 'react-instantsearch-dom';\n\ninterface HitDoc {\n  objectID: string;\n  url: string;\n  title: string;\n  description: string;\n  content: string;\n}\n\ninterface Props {\n  hit: Hit\u003cHitDoc\u003e;\n}\n\ninterface HitComponentProps extends Props {\n  onClick: () =\u003e void;\n}\n\nfunction HitComponent({ hit, onClick }: HitComponentProps): JSX.Element {\n  return (\n    \u003cdiv\u003e\n      \u003cLink href={hit.url}\u003e\n        \u003cbutton className=\"hover:text-[#06bbbc]\" onClick={onClick}\u003e\n          \u003cHighlight attribute=\"title\" hit={hit} /\u003e\n        \u003c/button\u003e\n      \u003c/Link\u003e\n    \u003c/div\u003e\n  );\n}\n\nconst SearchResult = connectSearchBox(({ refine, currentRefinement }) =\u003e {\n  const [isShow, setShow] = useState\u003cboolean\u003e(false);\n\n  useEffect(() =\u003e {\n    setShow(!!currentRefinement);\n  }, [currentRefinement]);\n\n  const handleResetSearchWords = useCallback(() =\u003e {\n    refine('');\n  }, [refine]);\n\n  const hitComponent = ({ hit }: Props): JSX.Element =\u003e (\n    \u003cHitComponent hit={hit} onClick={handleResetSearchWords} /\u003e\n  );\n\n  if (!isShow) return null;\n  return (\n    \u003c\u003e\n      \u003cHits hitComponent={hitComponent} /\u003e\n      \u003cPagination /\u003e {/* 追加 */}\n    \u003c/\u003e\n  );\n});\n\nexport default SearchResult;\n```\n\nこれで簡単にハイライトが実装できました。\n\n![highlight](/img/pages/tech/next-algolia/highlight.png)\n\nハイライトの色などを変更したい場合は、属性を確認して aloglia の CSS を上書きすれば OK です。\n\n### 無料版は algolia のロゴを表示必須\n\nalgolia では無料版を使用している人は algolia のクレジット表示が必要です。\n\n\u003e Algolia requires that you use this widget if you only use your free usage credits, or are on a Community or Free legacy plan.\n\n引用:[poweredBy - algolia](https://www.algolia.com/doc/api-reference/widgets/powered-by/js/)\n\nこちらも `PowerdBy` コンポーネントが用意されているため、そちらを追加するだけです。  \n注意点として `Search` コンポーネント内に追加すると検索されていない時も表示されてしまうため、`SearchResult` コンポーネントないに追記しておくと良いでしょう。\n\n```tsx\n// 変更点\
8nreturn (\n  \u003c\u003e\n    \u003cHits hitComponent={hitComponent} /\u003e\n    \u003cPagination /\u003e\n    \u003cPoweredBy /\u003e {/* 追加 */}\n  \u003c/\u003e\n);\n```\n\n全体像はこちらです。\n\n```tsx\n// src/components/common/SearchResult.tsx\n\nimport Link from 'next/link';\nimport { useEffect, useState, useCallback } from 'react';\nimport { Hit } from 'react-instantsearch-core';\nimport { Hits, connectSearchBox, Pagination, Highlight, PoweredBy } from 'react-instantsearch-dom';\n\ninterface HitDoc {\n  objectID: string;\n  url: string;\n  title: string;\n  description: string;\n  content: string;\n}\n\ninterface Props {\n  hit: Hit\u003cHitDoc\u003e;\n}\n\ninterface HitComponentProps extends Props {\n  onClick: () =\u003e void;\n}\n\nfunction HitComponent({ hit, onClick }: HitComponentProps): JSX.Element {\n  return (\n    \u003cdiv\u003e\n      \u003cLink href={hit.url}\u003e\n        \u003cbutton className=\"hover:text-[#06bbbc]\" onClick={onClick}\u003e\n          \u003cHighlight attribute=\"title\" hit={hit} /\u003e\n        \u003c/button\u003e\n      \u003c/Link\u003e\n    \u003c/div\u003e\n  );\n}\n\nconst SearchResult = connectSearchBox(({ refine, currentRefinement }) =\u003e {\n  const [isShow, setShow] = useState\u003cboolean\u003e(false);\n\n  useEffect(() =\u003e {\n    setShow(!!currentRefinement);\n  }, [currentRefinement]);\n\n  const handleResetSearchWords = useCallback(() =\u003e {\n    refine('');\n  }, [refine]);\n\n  const hitComponent = ({ hit }: Props): JSX.Element =\u003e (\n    \u003cHitComponent hit={hit} onClick={handleResetSearchWords} /\u003e\n  );\n\n  if (!isShow) return null;\n  return (\n    \u003c\u003e\n      \u003cHits hitComponent={hitComponent} /\u003e\n      \u003cPagination /\u003e\n      \u003cPoweredBy /\u003e {/* 追加 */}\n    \u003c/\u003e\n  );\n});\n\nexport default SearchResult;\n```\n\n![poweredby](/img/pages/tech/next-algolia/poweredby.png)\n\n## モーダルウィンドウを表示\n\nTailwind CSS を確認していただくとわかる通り、ヘッダー内で検索の処理を行うよりも、**モーダルウィンドウ**に飛ばしてから検索結果を表示することが多いと思います。\n今回もヘッダーに検索画面を置いている以上、ヘッダーが伸び縮みしてしまい表示崩れが起こっていました。\n少し手間がかかりますが、モーダルウィンドウ内で検索画面を表示できるようにしていきましょう。\n\n### モーダルウィンドウの準備\n\n[**fwywd(フュード)**](/) のチームは Tailwind CSS をメインで使用しており、Tailwind CSS では [**Headless UI**](https://blog.tailwindcss.com/headless-ui-v1) というパッケージで分離してモーダルウィンドウなどが簡単に実装できるようになっています。\n\nまずは検索画面を押したらモーダルウィンドウが表示されるところまで作っていきましょう。  \n`PageHeader` に追加していた `Search` コンポーネントはモーダルウィンドウ内に移植するため、ひとまず除去して、その位置にこれから紹介する `SearchForm` を挿入しています。\n\n```bash\n# npm の場合\nnpm install --save-dev @headlessui/react\n\n# yarn の場合\nyarn add --dev @headlessui/react\n```\n\nスタイリングも含めて以下のように `Modal` 付きの検索ボタンを設定しました。  \nHeadless UI でのモーダルウィンドウの実装方法に慣れていない方は以下の参考記事を読むと良いでしょう。\n\n参考記事:[Dialog (Modal) - Headless UI](https://headlessui.dev/react/dialog)\n\n```tsx\n// src/components/common/SearchForm.tsx\n\nimport { Dialog, Transition } from '@headlessui/react';\nimport SearchIcon from 'components/icons/Search';\nimport { useState, Fragment } from 'react';\n\nexport default function SearchForm(): JSX.Element {\n  const [isOpen, setIsOpen] = useState\u003cboolean\u003e(false);\n  const openModal = () =\u003e setIsOpen(true);\n  const closeModal = () =\u003e setIsOpen(false);\n\n  return (\n    \u003c\u003e\n      \u003cbutton\n        onClick={openModal}\n        className=\"flex items-center px-4 py-3 text-sm text-gray-500 rounded-full shadow focus:outline-none w-72 hover:bg-[#f1f7f8] hover:text-primary-dark hover:shadow-lg hover:duration-500\"\n      \u003e\n        \u003cSearchIcon /\u003e\n        \u003cspan className=\"ml-2\"\u003e記事を検索\u003c/span\u003e\n      \u003c/button\u003e\n\n      \u003cTransition appear show={isOpen} as={Fragment}\u003e\n        \u003cDialog as=\"div\" className=\"fixed inset-0 z-10 overflow-y-auto\" onClose={closeModal}\u003e\n          \u003cdiv className=\"min-h-screen px-4 text-center\"\u003e\n            \u003cDialog.Overlay className=\"fixed inset-0 opacity-50 bg-primary-lightest\" /\u003e\n\n            \u003cTransition.Child\n              as={Fragment}\n              enter=\"ease-out duration-300\"\n              enterFrom=\"opacity-0 scale-95\"\n              enterTo=\"opacity-100 scale-100\"\n              leave=\"ease-in duration-200\"\n              leaveFrom=\"opacity-100 scale-100\"\n              leaveTo=\"opacity-0 scale-95\"\n            \u003e\n              \u003cdiv className=\"inline-block w-full max-w-md p-6 my-8 overflow-hidden text-left align-middle bg-white shadow-xl transition-all transform rounded-2xl\"\u003e\n                \u003cDialog.Title as=\"h3\" className=\"text-lg font-medium text-gray-900 leading-6\"\u003e\n                  検索結果\n                \u003c/Dialog.Title\u003e\n                \u003cdiv className=\"mt-2\"\u003e\n                  \u003cp className=\"text-sm text-gray-500\"\u003eここに検索結果を挿入していきます 。\u003c/p\u003e\n                \u003c/div\u003e\n\n                \u003cdiv className=\"mt-4\"\u003e\n                  \u003cbutton\n                    type=\"button\"\n                    className=\"inline-flex justify-center px-4 py-2 text-sm font-medium text-blue-900 bg-blue-100 border border-transparent roun
8ded-md hover:bg-blue-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-blue-500\"\n                    onClick={closeModal}\n                  \u003e\n                    閉じる\n                  \u003c/button\u003e\n                \u003c/div\u003e\n              \u003c/div\u003e\n            \u003c/Transition.Child\u003e\n          \u003c/div\u003e\n        \u003c/Dialog\u003e\n      \u003c/Transition\u003e\n    \u003c/\u003e\n  );\n}\n```\n\n![modal01](/img/pages/tech/next-algolia/modal01.gif)\n\nこれで動作を確認すると以下のように、検索ボタンを押すとモーダルウィンドウが表示されました。  \nここに検索結果を追加していきましょう。\n\n### 検索結果と統合して調整\n\n実装したコードの一式は後に回し、最終的に CSS を調整していき、以下のように検索機能を実装できました。\n\n![modal02](/img/pages/tech/next-algolia/modal02.gif)\n\nそれでは、実装したコード一式です。  \n最後に細かく調整したため、これまで解説してきたところと少し違っていますので、ぜひそれぞれを確認してみてください。\n\n\u003e **補足1**  \n\u003e 内部リンクからの検索結果が残る問題を解決してきましたが、その後、**モーダルウィンドウがページ遷移後も消えず**、泣く泣く `Link` コンポーネントを使わずに `a` タグへと変えました。  \n\u003e コンポーネント間で状態の共有ができれば `Link` での実装も可能ですが、`useContext` が煩わしいため、今回は動作優先としました。  \n\u003e 状態管理用の外部パッケージとして Atom などがあり、こちらを使うと非常に簡単ですので、近いうちにこちらでリファクタリングする予定です。\n\n\u003e **補足2**  \n\u003e `instantsearch.css` は `Search` コンポーネント内で読み込んでいましたが、CSS の上書きをするのであれば `_app.tsx` で読み込まないといけませんでした。  \n\u003e まず前提として、CSS Modules とは異なり、ビルドを行わない対象の CSS は `_app.tsx` でグローバルに読み込む必要があります。  \n\u003e algolia で指定されているクラス名に合わせるには CSS Modules が使えないため、必然的に上書き用の `algolia.css` は `_app.tsx` でグローバルに読み込む必要があります。  \n\u003e `Search` コンポーネント内で `instantsearch.css` を読み込むと、`_app.tsx` の後に読み込まれるため、自作した `algolia.css` で上書きすることができませんでした。  \n\u003e したがって、`_app.tsx` 内で `instantsearch.css` を読み込んだ後に自作した `algolia.css` を読み込むといった方法に限られるようです。\n\nこちらが使用したコード一式になります。  \n`SearchForm` をヘッダーに挿入しています。\n\n```tsx\n// src/components/common/Search.tsx\n\nimport SearchResult from 'components/common/SearchResult';\nimport { indexName, searchClient } from 'lib/searchClient';\nimport { InstantSearch, SearchBox, Configure } from 'react-instantsearch-dom';\n\nexport default function Search(): JSX.Element {\n  return (\n    \u003cdiv\u003e\n      \u003cInstantSearch indexName={indexName} searchClient={searchClient}\u003e\n        \u003cConfigure hitsPerPage={5} /\u003e\n        \u003cSearchBox /\u003e\n        \u003cSearchResult /\u003e\n      \u003c/InstantSearch\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n```tsx\n// src/components/common/SearchForm.tsx\n\nimport { Dialog, Transition } from '@headlessui/react';\nimport Search from 'components/common/Search';\nimport SearchIcon from 'components/icons/SearchIcon';\nimport { useState, Fragment } from 'react';\n\nexport default function SearchForm(): JSX.Element {\n  const [isOpen, setIsOpen] = useState\u003cboolean\u003e(false);\n  const openModal = () =\u003e setIsOpen(true);\n  const closeModal = () =\u003e setIsOpen(false);\n\n  return (\n    \u003c\u003e\n      \u003cbutton\n        onClick={openModal}\n        className=\"flex items-center px-4 py-3 text-sm text-gray-500 rounded-full shadow focus:outline-none w-72 hover:bg-[#f1f7f8] hover:text-primary-dark hover:shadow-lg hover:duration-500\"\n      \u003e\n        \u003cSearchIcon /\u003e\n        \u003cspan className=\"ml-2\"\u003e記事を検索\u003c/span\u003e\n      \u003c/button\u003e\n\n      \u003cTransition appear show={isOpen} as={Fragment}\u003e\n        \u003cDialog as=\"div\" className=\"fixed inset-0 z-10 overflow-y-auto\" onClose={closeModal}\u003e\n          \u003cdiv className=\"min-h-screen px-4 text-center\"\u003e\n            \u003cDialog.Overlay className=\"fixed inset-0 opacity-50 bg-primary-lightest\" /\u003e\n\n            \u003cTransition.Child\n              as={Fragment}\n              enter=\"ease-out duration-300\"\n              enterFrom=\"opacity-0 scale-95\"\n              enterTo=\"opacity-100 scale-100\"\n              leave=\"ease-in duration-200\"\n              leaveFrom=\"opacity-100 scale-100\"\n              leaveTo=\"opacity-0 scale-95\"\n            \u003e\n              \u003cdiv className=\"inline-block w-full max-w-2xl p-6 my-8 overflow-hidden text-left align-middle bg-white shadow-xl transition-all transform rounded-2xl\"\u003e\n                \u003cSearch /\u003e\n              \u003c/div\u003e\n            \u003c/Transition.Child\u003e\n          \u003c/div\u003e\n        \u003c/Dialog\u003e\n      \u003c/Transition\u003e\n    \u003c/\u003e\n  );\n}\n```\n\n```tsx\n// src/components/common/SearchResult.tsx\n\nimport { useEffect, useState, useCallback } from 'react';\nimport { Hit } from 'react-instantsearch-core';\nimport { Hits, connectSearchBox, Pagination, Highlight, PoweredBy } from 'react-instantsearch-dom';\n\ninterface HitDoc {\n  objectID: string;\n  url: string;\n  title: string;\n  description: string;\n  content: string;\n}\n\ninterface Props {\n  hit: Hit\u003cHitDoc\u003e;\n}\n\ninterface HitComponentProps extends Props {\n  onClick: () =\u003e void;\n}\n\nfunction HitComponent({ hit, onClick }: HitComponentProps): JSX.Element {\n  return (\n    \u003ca href={hit.url}\u003e\n      \u003cbutton onClick={onClick} className=\"flex justify-start w-full px-5 py-5\"\u003e\n        \u003cHighlight attribute=\"title\" hit={hit} /\u003e\n      \u003c/button\u003e\n    \u003c/a\u003e\n  );\n}\n\nconst SearchResult = connectSearchBox(({ refine, currentRefinement }) =\u003e {\n  const [isShow, setShow] = useState\u003cboolean\u003e(false);\n\n  useEffect(() =\u003e {\n    setShow(!!currentRefinement);\n  }, [currentRefinement]);\n\n  const handleResetSearchWords = useCallback(() =\u003e {\n    refine('');\n  }, [refine]);\n\n  const hitComponent = ({ hit }: Props): JSX.Element =\u003e (\n    \u003cHitComponent hit={hit} onClick={handleResetSearchWords} /\u003e\n  );\n\n  if (!isShow) return null;\n  return (\n    \u003c\u003e\n      \u003cp className=\"mt-5 text-sm font-semibold tracking-wider text-gray-500\"\u003e記事一覧\u003c/p\u003e\n      \u003cHits hitComponent={hitComponent} /\u003e\n      \u003cPagination /\u003e\n      \u003cPoweredBy /\u003e\n    \u003c/\u003e\n  );\n});\n\nexport default SearchResult;\n```\n\n```tsx\n// src/components/icons/SearchIcon.tsx\n\ninterface Props {\n  w?: number;\n  h?: number;\n}\n\nexport default function Search({ w = 6, h = 6 }: Props): JSX.Element {\n  return (\n    \u003csvg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      className={`w-${w} h-${h} `}
8\n      fill=\"none\"\n      viewBox=\"0 0 24 24\"\n      stroke=\"currentColor\"\n    \u003e\n      \u003cpath\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        strokeWidth={2}\n        d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\n      /\u003e\n    \u003c/svg\u003e\n  );\n}\n```\n\n```css\n/* src/styles/algolia.css */\n\n.ais-Hits-list {\n  padding: 5px 0;\n}\n\n.ais-Hits-item {\n  background-color: #fafafa;\n  border-radius: 5px;\n  box-shadow: none;\n  display: block;\n  margin: 10px 0;\n  padding: 0;\n}\n\n.ais-Hits-item:hover {\n  background-color: #d9ebeb;\n}\n\n.ais-Hits-item:first-of-type,\n.ais-InfiniteHits-item:first-of-type {\n  border-radius: 5px;\n}\n\n.ais-Highlight {\n  font-weight: 600;\n}\n\n.ais-Highlight-highlighted {\n  background-color: transparent;\n  color: #06bbbc;\n}\n\n.ais-Pagination {\n  display: flex;\n  justify-content: center;\n}\n\n.ais-PoweredBy {\n  display: flex;\n  justify-content: flex-end;\n}\n\n.ais-PoweredBy-text {\n  font-size: small;\n  margin-right: 5px;\n}\n```\n\n```tsx\nsrc/pages/_app.tsx\n\n...\nimport 'instantsearch.css/themes/satellite-min.css';\nimport 'styles/algolia.css';\n\nexport default function App({ Component, pageProps }: AppProps): JSX.Element {\n  ...\n  return \u003cComponent {...pageProps} /\u003e;\n}\n```\n\n## おわりに\n\n### algolia は検索の機能だけでなく UI まで作り込まれて優秀\n\nここまで一緒に実装してこられた方、本当にお疲れ様でした。\n今回はこれまでで最も長い記事となり、本当に大変だったと思います。\n\n私自身は記事を書きながら検証して実装する遅めのペースでした。  \nそれでも2日あれば終えることができたのは、やはり algolia が使いやすく、UI まで丁寧に作り込まれていたおかげです。  \nもう少しテストをちゃんと書いたり、まだまだリファクタリングが必要なところですが、まずは動作させてみることが大事ですので、その辺りの優先度は低めにしています。\n\n本来、検索といった機能を実装しようと思うとかなり大変ですので、この実装コストで UX が向上するのであれば、取り組んでみても良いと思います。  \n日本語でも記事があったã
8®ã§ã™ãŒã€åŸºæœ¬çš„には成果物ベースでの報告記事が多く、その間を埋めるところに公式ページを見て、ひとつずつ実装してみて...とこの点が結構大変でした。  \nその代わりに、私以降の人はなるべく調査する時間よりも実装しながら理解に重きを置けるような解説を作りましたので、ぜひご活用いただけますと幸いです。\n\n株式会社キカガク 代表取締役会長  \n吉崎 亮介  \ntwitter: [**@yoshizaki_91**](https://twitter.com/yoshizaki_91)\n"}],"newPosts":[{"id":"/tech/markdown-viewer-by-markdoc","data":{"title":"Markdoc (Tailwind UI の Syntax ベース)による Markdown Viewer の実装","date":"2022-08-09T17:30:00.000+0900","img_path":"/img/pages/tech/markdown-viewer-by-markdoc/ogp.png","img_alt":"Markdoc (Tailwind UI の Syntax ベース)による Markdown Viewer の実装","description":"fwywd チームでは新ブログを Tailwind UI の Syntax を使用して実装予定です。記事の表示と記事作成画面のプレビューを揃えたい \u0026 後々の Syntax 導入をスムーズにしたい目的で Tailwind UI の Syntax ベースで Markdown Viewer を実装しました!","tags":["Tailwind CSS","Tailwind UI","Syntax","Markdoc","Markdown"],"prev_title":"【Azure App Service | Node.js】GitHub Actions を利用して継続デプロイしてみよう【 トラブルガイド付】","prev_link":"/tech/deployment-by-azure-app-service-for-nodejs","next_title":"","next_link":"","author":"takahashi"},"content":"\nfwywd チームでは新ブログを Tailwind UI の Syntax を使用して実装予定です。\n\n[Syntax - Tailwind CSS Documentation Template](https://tailwindui.com/templates/syntax)\n\n記事の表示と記事作成画面のプレビューを揃えたい \u0026 後々の Syntax 導入をスムーズにしたい目的で Tailwind UI の Syntax ベースの Markdown Viewer を実装しました!\n\n## markdoc のライブラリをインストール\n\n```bash\nyarn add @markdoc/markdoc @markdoc/next.js -D\n```\n\n## next.config.js を書き換える\n\n括弧の位置を間違えやすいので注意が必要です。\n\n```jsx\n// next.config.js\n\nconst withMarkdoc = require('@markdoc/next.js');\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {\n  reactStrictMode: true,\n  images: {\n    deviceSizes: [340, 640, 768, 1024, 1280, 1440, 1980],\n    domains: [],\n  },\n  pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'md'],\n};\n\nmodule.exports = withMarkdoc()(nextConfig);\n```\n\n## Prose.tsx\n\nMarkdoc で変換したデータを children で渡し画面表示するコンポーネントです。\n\nTailwind CSS の prose というクラスによって余白や文字間を調節しています。\n\n下準備として、clsx, @tailwindcss/typography をインストールします。\n\n```bash\nyarn add clsx -D\n\nyarn add @tailwindcss/typography -D\n```\n\ntailwind.config.js に plugins を追記します。\n\n```jsx\nplugins: [require('@tailwindcss/typography')],\n```\n\nProse.tsx の内容は以下です。\n\n```tsx\n// Prose.tsx\n\nimport clsx from 'clsx';\nimport { ReactNode } from 'react';\n\ninterface ProseProps {\n  children: ReactNode;\n  className?: string;\n}\n\nexport const Prose: React.FC\u003cProseProps\u003e = ({ className, ...props }) =\u003e (\n  \u003cdiv\n    className={clsx(\n      className,\n      'dark:text-gray-400 prose prose-gray max-w-none dark:prose-invert',\n      // headings\n      'prose-headings:font-display prose-headings:scroll-mt-28 prose-headings:font-normal lg:prose-headings:scroll-mt-[8.5rem]',\n      // lead\n      'prose-lead:text-gray-700 dark:prose-lead:text-gray-700',\n      // links\n      'prose-a:font-semibold dark:prose-a:text-primary-500',\n      // link underline\n      'prose-a:no-underline prose-a:shadow-[inset_0_-2px_0_0_var(--tw-prose-background,#fff),inset_0_calc(-1*(var(--tw-prose-underline-size,4px)+2px))_0_0_var(--tw-prose-underline,theme(colors.primary.200))] hover:prose-a:[--tw-prose-underline-size:6px] dark:[--tw-prose-background:theme(colors.gray.9
800)] dark:prose-a:shadow-[inset_0_calc(-1*var(--tw-prose-underline-size,2px))_0_0_var(--tw-prose-underline,theme(colors.primary.800))] dark:hover:prose-a:[--tw-prose-underline-size:6px]',\n      // pre\n      'prose-pre:rounded-xl prose-pre:bg-gray-900 prose-pre:shadow-lg dark:prose-pre:bg-gray-800/60 dark:prose-pre:shadow-none dark:prose-pre:ring-1 dark:prose-pre:ring-gray-700/10',\n      // hr\n      'dark:prose-hr:border-gray-800',\n    )}\n    {...props}\n  /\u003e\n);\n```\n\nMarkdoc でデータを変換して Prose.tsx に渡すコンポーネントを作成します。\n\n```tsx\n// Markdown.tsx\n\nexport const Markdown = () =\u003e {\n  const doc = `\n  # heading 1\n  \n  ## heading 2\n\n  1. ol\n  1. ol\n\n  - ul\n  - ul\n`;\n\n  const ast = Markdoc.parse(doc);\n  const content = Markdoc.transform(ast);\n  const children = Markdoc.renderers.react(content, React);\n\n  return (\n    \u003cProse className={`${style.md} h-[600px] w-full overflow-auto border border-primary-800 p-2`}\u003e\n      {children}\n    \u003c/Prose\u003e\n  );\n};\n```\n\n余白や文字間は Tailwind CSS の prose でいい感じになっているのでテキストの大きさや色などの装飾を CSS モジュールで適用します。\n\nマークダウン表示できます。\n\n![1.png](/img/pages/tech/markdown-viewer-by-markdoc/1.png)\n\n## Fence.tsx\n\nマークダウンの表示はできましたがコードのハイライトはされない状態です。\n\nMarkdoc の Syntax highlighting を参考にして Tailwind UI の Syntax ベースでコードのハイライトを実装します。\n\n[Common examples](https://markdoc.io/docs/examples#syntax-highlighting)\n\n少し複雑でした。大まかな流れとしたら、\n\n1. code をハイライトする `Fence.tsx` を作成する\n2. code を取り出してハイライト適用するための config ファイル `node.ts` を作成する\n3. Markdoc でデータ変換する関数に `node.ts` から config を渡す\n\nといった流れです。\n\n### code をハイライトする Fence.tsx の作成\n\nコードをハイライトするための prism-react-renderer をインストールします。\n\n```bash\nyarn add prism-react-renderer -D\n```\n\nTailwind UI からそのまま持ってきて型付けをしています。\n\n`\u003cHighlight\u003e` に渡す code の children は String(children) としないと型のエラーが発生してしまうので注意です。\n\n```tsx\n// Fence.tsx\n\nimport { Fragment, ReactNode } from 'react';\nimport Highlight, { defaultProps, Language } from 'prism-react-renderer';\nimport vsDark from 'prism-react-renderer/themes/vsDark';\n\ninterface FenceProps {\n  children: ReactNode;\n  language: Language;\n}\n\nexport const Fence: React.FC\u003cFenceProps\u003e = ({ children, language }) =\u003e (\n  \u003cHighlight\n    {...defaultProps}\n    code={children === undefined ? '' : String(children).trimEnd()}\n    language={language}\n    theme={vsDark}\n  \u003e\n    {({ className, style, tokens, getTokenProps }) =\u003e (\n      \u003cpre className={className} style={style}\u003e\n        \u003ccode\u003e\n          {tokens.map((line, lineIndex) =\u003e (\n            \u003cFragment key={lineIndex}\u003e\n              {line\n                .filter((token) =\u003e !token.empty)\n                .map((token, tokenIndex) =\u003e (\n                  \u003cspan key={tokenIndex} {...getTokenProps({ token })} /\u003e\n                ))}\n              {'\\n'}\n            \u003c/Fragment\u003e\n          ))}\n        \u003c/code\u003e\n      \u003c/pre\u003e\n    )}\n  \u003c/Highlight\u003e\n);\n```\n\n### ハイライトを適用させるための node.ts を作成\n\n```tsx\n// markdoc/node.ts\n\nconst node = {\n  fence: {\n    render: 'Fence',\n    attributes: {\n      language: {\n        type: String,\n      },\n    },\n  },\n};\n\nexport default node;\n```\n\n### Markdoc でデータ変換する関数に config を渡す\n\n```tsx\n// Markdown.tsx\n\nconst ast = Markdoc.parse(doc);\nconst content = Markdoc.transform(ast, { nodes: node });\nconst children = Markdoc.renderers.react(content, React, {\n  
8components: { Fence },\n});\n```\n\ncode がハイライトされます。\n\n![2.png](/img/pages/tech/markdown-viewer-by-markdoc/2.png)\n\n## まとめ\n\nTypeScript の型付けと code のハイライト表示に苦戦しましたがなんとかなりました。\n\nなにより Tailwind CSS の prose が便利でした!\n\n少しマニアックなところですが参考になる方がいれば嬉しいです!\n"},{"id":"/tech/deployment-by-azure-app-service-for-nodejs","data":{"title":"【Azure App Service | Node.js】GitHub Actions を利用して継続デプロイしてみよう【 トラブルガイド付】","date":"2022-08-06T11:30:00.000+0900","img_path":"/img/pages/tech/deployment-by-azure-app-service-for-nodejs/ogp.png","img_alt":"GitHub Actions を利用して継続デプロイしてみよう","description":"Q. 「オンボーディングで最もしんどかった部分はどこでしたか?」答えは・・・\\ Azure App Service 一択ウ〜!/ Azure サービス群の中でも屈指の面倒臭さを誇る(当社比)Azure App Service でのデプロイ方法ガイド、始まり始まり。","tags":["Azure","Azure App Service","Express.js","NestJS","Next.js"],"prev_title":"コードを書けるエンジニアが STUDIO をビジネス向けに使ってわかったメリットとデメリット","prev_link":"/tech/why-adopt-studio","next_title":"Markdoc (Tailwind UI の Syntax ベース)による Markdown Viewer の実装","next_link":"/tech/markdown-viewer-by-markdoc","author":"furukawa"},"content":"\nQ. 「オンボーディングで最もしんどかった部分はどこでしたか?」\n\n\\ Azure App Service 一択ウ〜!/\n\nAzure サービス群の中でも屈指の面倒臭さを誇る(当社比)Azure App Service でのデプロイ方法ガイド、始まり始まり。\n\n本記事は[公式ドキュメント](https://docs.microsoft.com/ja-jp/learn/modules/javascript-deploy-expressjs-app-service/)を参考に作成しています。\n\n## 使用技術\n\n- Node.js\n- Express.js\n- Visual Studio Code\n- [GitLens](https://gitlens.amod.io/)(Visual Studio Code の拡張機能)\n- Azure App Service\n- GitHub\n- GitHub Actions\n\n## この記事を読んでわかること\n\nAzure App Service に GitHub Actions を使用してアプリケーションを継続的にデプロイするための具体的な手順。\n\nつまり「**main ブランチへ push するたび自動的に Azure App Service へデプロイする**」ことができるようになります。\n\n## この記事では説明しないこと\n\n- サブスクリプション、リソースグループ、リソースなど Azure 特有の用語の数々。詳しく知りたい方は[こちら](https://docs.microsoft.com/ja-jp/learn/modules/javascript-deploy-expressjs-app-service/use-resource-group)をまず読んでみてください。\n- Node.js や GitHub など使用技術に関する基礎知識\n\n## 大まかな手順の流れ\n\n1. デプロイしたいものを用意する\n2. リソースグループを作成する\n3. Azure App Service リソースを作成する\n4. GitHub Actions が使えるよう準備する\n5. CI/CD 経由でデプロイ\n\n## 1. デプロイしたいものを用意\n\nNode.js 製であればなんでも OK。基本の流れは同じです。\n\n今回は Express.js でささっと用意しちゃいます。\n\n[Azure が公式に用意しているサンプル](https://github.com/Azure-Samples/msdocs-javascript-nodejs-server)をクローン。\n\n![1.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/1.png)\n\n![2.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/2.png)\n\n![3.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/3.png)\n\n今回は「2-Deploy-app-to-azure」の中身だけ使用します。他は消しちゃって OK。\n\n![4.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/4.png)\n\n![4.5.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/4.5.png)\n\n## 2. Azure Portal からリソースグループを作成\n\nアカウント作成・サブスクリプションの設定についての説明・手順は省きます。\n\nまだの方は Azure 公式サイトより無料アカウントを作成し Azure Portal へアクセス・ログインしてサブスクリプションの用意まで行ってください。\n\n手順を詳しく知りたい人は[こちら](https://docs.microsoft.com/ja-jp/learn/modules/create-an-azure-account/)。\n\nAzure Portal からリソースグループを作成していきます。\n\n![5.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/5.png)\n\n![6.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/6.png)\n\n![7.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/7.png)\n\n![8.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/8.png)\n\n無事作成されれば成功。\n\n## 3. Azure App Service リソースの作成\n\n2で作成したリソースグループの中に Azure App Service リソースを作っていきます。\n\nまずはプランの作成から。\n\n![8.1.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/8.1.png)\n\n![9.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/9.png)\n\nAzure Service プランを選択し「作成」をクリック。\n\n![11.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/11.png)\n\n今回はさくっと試したいだけなので価格レベルを **Free F1** へ変更。**ここを変更しておかないと月額課金が発生するため注意!**\n\n「確認および作成」→「作成」でリソース作成が完了します。作成まで少し時間がかかることもあるのでコーヒーでも啜りながら待ちましょう。\n\n![12.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/12.png)\n\n完了したら App Service で Web アプリのリソースを作っていきます。\n\n![9.1.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/9.1.png)\n\n![9.2.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/9.2.png)\n\n![9.3.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/9.3.png)\n\n「確認および作成」→「作成」で完了。こちらも時間がかかるためコーヒーをひと啜りしながら待ちましょう。完了後リソースに移動するとこんな感じ。\n\n![9.4.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/9.4.png)\n\n## 4. GitHub Actions の準備をしよう\n\nまずは GitHub にレポジトリを作成しましょう。詳細な手順は省きます。GitHub アカウントを持っていない方は [GitHub 公式サイト](https://github.co.jp/)でアカウントを作成・ログインしてください。\n\nレポジトリの作成が完了したらこんな感じのページが広がっているはず。URL をコピーしておきます。\n\n![14.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/14.png)\n\n1で開いていた Visual Studio Code へ戻ります。リモート先を自身で作成したレポジトリへ変更しちゃいましょう。\n\n![16.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/16.png)\n\n※ REMOTES なんて見当たらないよ!という人は拡張機能「GitLens」を導入してください。\n\n![17.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/17.png)\n\nname: origin\n\nurl: コピーした URL を貼り付け\n\nå
8®Œäº†ã—たらさっそくコミット&ブランチの発行を試してみてください。最新のものに反映されていれば成功。\n\n![18.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/18.png)\n\nここからが本番。 GitHub Actions 経由でデプロイする準備を進めていきます。\n\n3で作成した App Service へ移動し、GitHub Actions と連携させていきます。\n\n![19.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/19.png)\n\n![20.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/20.png)\n\n保存するとあら便利、 GitHub 側で勝手に設定ファイルを生成してくれます。\n\n![22.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/22.png)\n\n## 5. CI/CD 経由でデプロイ\n\nさっそく GitHub Actions 経由でデプロイしてみましょう。\n\nやたら長ったらしい名前の `.github/workflows/main_fwywdazuredeployintro.yml`ファイルを `deploy.yml` へ名称変更しプッシュしてみます。\n\n![25.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/25.png)\n\ndeploy.yml のデフォルト設定では「main ブランチに push した際にデプロイが走る」ようになっています。デプロイが終わったらさっそく確認しにいきましょう。\n\n![23.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/23.png)\n\nおや・・・ Azure App Service くんのようすが・・・?\n\n![24.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/24.png)\n\n**出たよ。親の顔より見た光景。**\n\nアプリケーション起動時に出るエラー。Azure App Service 触ったことがある人は絶対に見たことあるやつです。私はもはや  :( を見ると首の後ろがキュッ・・・となります。\n\n## :( Application Error に遭遇した時の対処法\n\n基本は以下のステップで地道にエラーを潰していく形になります。\n\n1. ログを確認する\n2. 原因っぽい箇所を探して試行錯誤する\n\n### 1. ログを確認する\n\nAzure Portal で 該当する Azure App Service を開き「問題の診断と解決」を覗いてみましょう。下部にある「ウェブアプリダウン」をクリック。\n\n![33.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/33.png)\n\n現在7つの問題を抱えている模様。詳しく見ていきます。\n\n![26.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/26.png)\n\n### 2. 原因っぽい箇所を探して試行錯誤する\n\n7つの問題のうち直接アプリケーションエラーを引き起こしていそうなものを探しましょう。\n\n![27.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/27.png)\n\n下から4つは「有料プランにアップグレードしてほしいな❤️と言っているだけ」「警告で起動失敗に関するものではなさそう」っぽいことが読み取れます。上の3つがアプリケーションエラーに関わっていそうです。さらに分析するとサーバーエラーは起動に失敗しているがために出ているものと予想されます。ここから「**コンテナクラッシュ・コンテナの問題を解決すれば起動できそう!**」と算段がつけられますね。\n\n一番怪しげな「コンテナクラッシュ」から見ていくと・・・\n\n![28.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/28.png)\n\n原因がひとつ判明。**アプリをスタートさせるためのコマンドが設定されていない**ようです。さっそく設定しにいきましょう。左バーの設定内にある構成をクリックし全般設定を覗いてみます。\n\n![29.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/29.png)\n\n確かにスタートアップコマンドが空っぽになってますね。ではここに `npm start` ないし `yarn start` をいれよう!と通常はなるわけですが、**入れても動かないため注意**。直接 node コマンドを叩きます。`package.json` の start スクリプトを確認してみましょう。\n\n![30.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/30.png)\n\n`\"start\": \"cross-env-shell DEBUG=express:* node index.js\"`となってますね。`cross-env-shell DEBUG=express:*`はそれぞれ環境変数・デバッグに関するコマンドなので省略。`node index.js`だけ抜き出して入力・保存します。\n\n![31.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/31.png)\n\n「再起動しますか?」と聞かれるため了承して保存完了です。\n\nここで一度アプリを覗いてみましょう。\n\n![32.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/32.png)\n\n以前としてアプリケーションエラーは出たまま。まだ対処していないエラーが残っているからですね。もう一つの問題だった「コンテナの問題」を見てみます。\n\n![34.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/34.png)\n\nどうやらコンテナがタイムアウトしたせいで起動できていないみたい・・・というのが見て取れます。説明が若干分かり難いのですが、「アプリケーションの設定で`WEBSITES_CONTAINER_START_TIME_LIMIT`の設定時間を伸ばしてみてね」ということらしいです。さっそく変更しにいきます。\n\n![35.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/35.png)\n\n保存するとアプリケーションが再起動されます。これで正常に起動できるはずッ・・・\n\n![36.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/36.png)\n\n**で、できた〜〜〜!!!(クソデカボイス)**\nおつかれさまでした・・・!\n\n## トラブルガイド\n\n最後に Next.js で作ったアプリケーションと NestJS で作った API をそれぞれデプロイした時に遭遇したエラーと対処法をご紹介。\n同じ症状に苦しんでいるあなたに届きますように・・・!\n\n### デプロイに時間がかかりすぎる\n\nアプリケーションの容量が小さくない場合、デプロイまでã
8«å‡„まじい時間がかかります。私の場合 Next.js で作った簡単な Todo アプリをデプロイするのに**50分**かかりました。50分待った挙句デプロイに失敗した日には泡吹いて倒れそうになります・・・(実体験)。\n\n対処法として `deploy.yml` ファイルの中身をいじってアプリを zip 化→ GitHub Actions にアップロード→ zip を Azure App Service へアップロードするよう変更することが挙げられます。私はこれでデプロイ時間を**7分**まで短縮できました。恐るべきビフォーアフター!\n\n参考に Next.js をデプロイした時のコードの中身を載せておきます。\n\n```yaml\nname: Build and deploy Node.js app to Azure Web App - fwywdTodoAppApi\n\non:\n  push:\n    branches:\n      - main\n\n  workflow_dispatch:\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    env:\n      DATABASE_URL: ${{ secrets.DATABASE_URL }}\n      DB_PASSWORD: ${{ secrets.DB_PASSWORD }}\n      DB_USERNAME: ${{ secrets.DB_USERNAME }}\n\n    steps:\n      - uses: actions/checkout@v2\n\n      - name: Set up Node.js version\n        uses: actions/setup-node@v1\n        with:\n          node-version: '16.x'\n\n      - name: yarn install, build, and test\n        run: |\n          yarn install\n          yarn build\n          yarn test-setup\n          yarn test:unit \n          yarn test:integration\n\n      - name: delete node_modules dir\n        run: rm -rf node_modules\n\n      - name: Zip all files for upload between jobs\n        run: zip --symlinks -r next.zip ./*\n\n      - name: Upload artifact for deployment job\n        uses: actions/upload-artifact@v2\n        with:\n          name: node-app\n          path: next.zip\n\n  deploy:\n    runs-on: ubuntu-latest\n    needs: build\n    environment:\n      name: 'Production'\n      url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}\n\n    steps:\n      - name: Download artifact from build job\n        uses: actions/download-artifact@v2\n        with:\n          name: node-app\n\n      - name: yarn install production\n        run: yarn install --production\n\n      - name: 'Deploy to Azure Web App'\n        id: deploy-to-webapp\n        uses: azure/webapps-deploy@v2\n        with:\n          app-name: 'fwywdtodoapp'\n          slot-name: 'Production'\n          publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_630E8D07124C436791B1A377E09DC005}}\n          package: next.zip\n\n      - name: Delete zip file\n        run: rm next.zip\n```\n\n### デプロイが途中で止まる\n\nこちらもアプリケーションの容量がそこそこある時に発生。`node_modules` を `npm install` または `yarn install` する際ダウンロードに時間がかかりすぎてタイムアウトするパターンです。プロジェクトフォルダ直下に`.yarnrc` ファイルを作って以下を記述することにより回避可能。\n\n```yaml\nnetwork-timeout 600000\n```\n\n### スタートアップコマンドに関するエラー\n\n使用するフレームワークによってはデフォルトのスタートアップコマンドが効かないことがあります。私の場合は Azure App Service 内の構成→全般設定→スタートアップコマンドに以下を入力することで解決しました。参考にどうぞ。\n\nNext.js の場合・・・`node_modules/next/dist/bin/next start`\n\nNestJS の場合・・・`node dist/main`\n\n### 何が原因でエラーが起きているのかわからないとき\n\n「アプリケーションエラーが起きてる。問題の診断と解決を見たけどそれっぽいエラーが見つからない。なんでッ!?」\n\nこれもよく遭遇します。そんな時はログストリームをみるべし。\n\n![38.png](/img/pages/tech/deployment-by-azure-app-service-for-nodejs/38.png)\n\nアプリを再起動→ログストリーム(プレビュー)でリアルタイムにログ出力ができるためどこで失敗しているのかわかりやすくなります。\n\n## 番外編: NestJS デプロイで詰まった時の解決策(体験談)\n\n状況としては GitHub Actions で zip 形式でデプロイしただけの状態で Azure Portal で何も設定していない・・・という時間軸ã
8§ã™ã€‚\n\n経緯まで書くと大ボリュームになるので結論だけ置いときます。\n\n1. `deploy.yml` の中身はこちら(デプロイ時間が短縮できます)。\n\n```yaml\nname: Build and deploy Node.js app to Azure Web App - fwywdAzureDeployNest\n\non:\n  push:\n    branches:\n      - master\n  workflow_dispatch:\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v2\n\n      - name: Set up Node.js version\n        uses: actions/setup-node@v1\n        with:\n          node-version: '16.x'\n\n      - name: npm install, build, and test\n        run: |\n          npm install\n          npm run build --if-present\n          npm run test --if-present\n\n      - name: Zip all files for upload between jobs\n        run: zip --symlinks -r nest.zip ./*\n\n      - name: Upload artifact for deployment job\n        uses: actions/upload-artifact@v2\n        with:\n          name: node-app\n          path: nest.zip\n\n  deploy:\n    runs-on: ubuntu-latest\n    needs: build\n    environment:\n      name: 'Production'\n      url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}\n\n    steps:\n      - name: Download artifact from build job\n        uses: actions/download-artifact@v2\n        with:\n          name: node-app\n\n      - name: 'Deploy to Azure Web App'\n        id: deploy-to-webapp\n        uses: azure/webapps-deploy@v2\n        with:\n          app-name: 'fwywdAzureDeployNest'\n          slot-name: 'Production'\n          publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_2A62A5035C4241D78AC3A13D8D636DCA }}\n          package: nest.zip\n\n      - name: Delete zip file\n        run: rm nest.zip\n```\n\n2. 「Azure App Service 内の構成→全般設定→スタートアップコマンド に `node dist/main` と入力する\n3. 「Azure App Service 内の構成→ アプリケーションの設定→ 新しいアプリケーション設定」で「名前:WEBSITES_CONTAINER_START_TIME_LIMIT」「値:600」と設定\n4. `package.json` の script 内にあるコマンド `“start:prod”` を以下に置き換える\n\n```json\n\"start:prod\": \"yarn build \u0026\u0026 node dist/main\",\n```\n\n5. main.ts のポート設定を変更する\n\n```TypeScript\nimport { NestFactory } from '@nestjs/core';\nimport { AppModule } from './app.module';\n\nasync function bootstrap() {\n  const app = await NestFactory.create(AppModule);\n  const port = process.env.PORT || 3000;\n  await app.listen(port);\n}\nbootstrap();\n```\n\n## この3つを抑えていれば Azure App Service も怖くない(多分)\n\n- スタートアップコマンドが適切に設定されているか\n- コンテナがタイムアウトしていないか\n- その他、なんらかの理由でコンテナがクラッシュしていないか(ログストリームで確認可能)\n\n特に上2つは Node.js でのデプロイだと再現性高く目にするエラー(当社比)なので真っ先に確認してみる価値アリ。\nこの記事で Azure App Service アレルギーに罹っている人が1人でも減りますように・・・!"},{"id":"/blog/how-to-write-sentenses","data":{"title":"ライター直伝!読みやすさに差をつける文章濃縮術","date":"2022-07-28T12:48:00.000+0900","img_path":"/img/pages/blog/how-to-write-sentenses/ogp.png","img_alt":"ライター直伝!読みやすさに差をつける文章濃縮術","description":"時間をかけて書いたのに・・・「君の文、なんか読み辛いね(ズバア)」と言われた経験、ありませんか?記事の書き方ガイド第三弾!いよいよ本命の「文章力」を高める秘訣を前職ライターの私古川が直伝しちゃいます!","tags":["マーケティング","fwywd","起業"],"prev_title":"井の中の蛙が人の力を引き出す、群に対する教育の設計術 ~ 専門家が怖くて発言できない、こんな世の中に ~","prev_link":"/blog/educational-design-for-groups","next_title":"会社で活躍したい・起業を成功させたい人にプログラミング習得をオススメする理由","
8next_link":"/blog/active-entrepreneurship-programming","author":"furukawa"},"content":"\n\n時間をかけて書いたのに・・・\n\n「**君の文、なんか読み辛いね(ズバア)**」と言われた経験、ありませんか?\n\n記事の書き方ガイド第3弾!いよいよ本命の「文章力」を高める秘訣を前職ライターの私古川が直伝しちゃいます!\n\n【記事の書き方ガイドシリーズ】\n\n第1弾:[もう悩まない!PV数がぐんぐん伸びるタイトルの付け方ガイド](https://fwywd.com/blog/2022051001)\n\n第2弾:[適当につけてない?目を引く見出しで差をつけろ!記事の見出し整頓術3つのポイント](https://fwywd.com/blog/2022072702)\n\n## 対象読者\n\n記事や文章を書いた時に\n\n- 「何が言いたいのがよくわからない」と言われて悲しくなったことがある\n- 書いているうちに自分がこの文で何を言いたかったのかわからなくなってくる現象に悩まされている\n- 自分の文章を「より読みやすく、分かりやすく」改善したいが方法がわからず困っている\n\n人。\n\n## 本文の役割\n\n「より多くの人に読んでもらいたい」観点から記事内の重要な要素を3つ並べるとしたらどうなるか、皆さん考えたことはありますか?\n\n[適当につけてない?目を引く見出しで差をつけろ!記事の見出し整頓術3つのポイント](https://fwywd.com/blog/2022072702)\n\nで述べた通り私は「**タイトル\u003e見出し\u003e本文**」と思っています(詳しくは記事参照)。しかしながら当然「本文が担う役割」は非常に大きいです。タイトルと見出しが記事の初速をコントロールする担当であるとするなら、真に記事の価値を支えるのが本文と言ったところでしょうか。記事の内容はもちろんのこと、**文体が読み辛ければ読み手の離脱率は爆上がり**します。故に「読みやすく・分かりやすい・目が滑りにくい」文章を書けるようになることは記事を執筆していく上で非常に重要なわけです。\n\n## 読み辛い文の特徴3選\n\nこの特徴にひとつでも当てはまる文がずらずらと並んでいると文章全体の品質がダダ下がりします。自分の文章の中でこれらを発見したら直ちに改善すべきです。\n\n### 
81. 文法が明らかにおかしい\n\n私たちは人間なので書いているうちに誤字脱字が発生したり、ちょこっと助詞の使い方がおかしくなってしまったり・・・というハプニングは往々にして起こります。そういった「凡ミス」レベルの話でなくもっと大きい括りで「それはどう見ても変じゃない・・・?」と感じさせるような文法ミスがあった時、**書き手への信頼度は失墜**します。記事として致命傷となりかねないので最も気をつけたい部分です。\n\n最近よく見かける間違いナンバーワン(個人調べ)を一例として挙げておきます。「〜ですが、〜ですが」など逆説の接続詞を連続で並べるケースです。\n\n✖️「りんごはおいしいですが、みかんの方がもっと好きですが、酸っぱいです」\n\n○「りんごはおいしいですが、みかんの方がもっと好きです。あの酸っぱさが好きなんです。」\n\nNG 文で文の主旨が一気に迷子になったことに気づきましたか?「結局何が言いたいのか」非常に伝わり難くなります。やめましょう。\n\n### 2. 読点「、」乱れ打ち\n\n**0が理想、1個は OK、2個でギリギリ、3個以上でアウト**です。不要な読点は可読性を一気に引き下げます。たくさん読点を打ちたくなったときは1文の中に複数の主旨が混ざり込んでいないか確認してみましょう。1文1主旨が基本です。\n\n0個:「このりんごおいしいですね。さすが青森県産です。また買いたいです。ごちそうさまでした。」\n\n1個:「このりんごおいしいですね、さすが青森県産です。また買いたいです。ごちそうさまでした。」\n\n2個(ギリギリ):「このりんごおいしいですね、さすが青森県産、また買いたいです。ごちそうさまでした。」\n\n3個(アウト):「このりんごおいしいですね、さすが青森県産、また買いたいです、ごちそうさまでした。」\n\n下に行けば行くほど一目瞭然の読み辛さになっていくことがわかるかと思います。0個 or 1個で常に留めておけるとベスト。\n\n### 3. 1文の中に「言いたいこと」が複数混ざっている\n\n1文が超長い人にありがち。大事なことなのでもう一度言います。**1文1主旨が基本**です。「2. 読点乱れ打ち」とも関連しています。読点を乱れ打ちしした長〜い1文は言いたいことが大量に混在する最強に読みづらい文となりやすいです。稀に1文を長く取っているにも関わらず主旨の一貫性をきれいに保って非常に読みやすい文章を書く人もいますが、これは相当なやり手ライターさんのみができる芸当です(弊社吉崎がこのタイプだな〜といつも尊敬しています)。初心者はやめときましょう。\n\n### これだけは覚えて帰ってほしい10秒でわかる結論\n\n- 文法正しく\n- 1文1主旨\n- 読点2個まで\n\n## ライター直伝!読みやすい文章のヒケツ3選\n\n「NG な部分はわかった。けれどもっと自分の文を読みやすく改善したいんだ!」というあなたに。\n\n前職ライター  \u0026 記事校正・今もこうして記事をつらつら書いている私が常に気を付けている秘蔵の言葉ダイエット法、教えちゃいます!\n\n### 1. 基本は「徹底的に短く」\n\n私、文章の理想系は「100%濃縮ジュース」だと思っています。1文をぎゅっと、ぎゅーーーーーっと濃縮して濃厚エキスにしたものを皆さんに飲んでいただくようなイメージ。\n\n- なくても意味が伝わる単語\n- 短く言い換えることができる単語\n\nが存在しないか?常日頃から意識していくと徐々に身に付いてくるハズです。地道に取り組んでみてくださいね。\n\nまた手っ取り早く文を短くできる小技のひとつとして **「だ・である」調を採用する**のもオススメです。「です・ます」調に比べ自然と語数が少なくなるので労せずスッキリした文が書けます。採用 OK な環境であればぜひ試してみてください。ちなみに1記事の中で「だ・である」調と「です・ます」調をまぜまぜして使用するのは NG です。ご注意を。\n\n### 2. リズム感を意識する\n\nこれはかなり感覚的なものも含まれているのですが、**「頭の中で歯切れ良く読める文章」を意識する**と文全体が垢抜けて見えるようになります。実際読んでいても「読みやすい・わかりやすい」と感じること間違いなし。私は以下の2点を特に気を付けています。\n\n- 可能であれば「5・7・5」に\n- 韻を踏んでいるかどうか\n\n川柳やラップをイメージするとわかりやすいかもしれません。脳内でラッパーになって文章でラップバトルしてみましょう。「なんかリズムよく読めないな〜」と思ったら字を足し引きして整えてみてください。こちらも地道に行うことで頭ひとつ抜きん出た物書きになることができます。\n\n### 3. 「それだけ読めば8割わかる」部分を強調する\n\n記事を書いていると抜け落ちやすい悲しい事実ã€
8‚人はこちらが思っている以上に文章を読んでいないこともあるということ・・・。流し読みをされても記事の本質が伝わるよう、**「ここさえ読んでおけば意味は8割伝わる」部分を強調**しましょう。強調箇所が増えすぎると逆に可読性が下がってしまうため、見出しひとつにに1-2か所・多くても3か所ぐらいを目安にすると良いでしょう。\n\n## 「いかがでしたでしょうか」禁止令\n\n最後に個人的な意見100%で構成されている思いの丈を叫んで締めたいと思います。\n\n**記事の終わりに「いかがでしたでしょうか」を付けるのを今すぐやめてくれ。**\n\n一昔前に流行った暗黒の量産コピペまとめ記事が蔓延っていた時代を思い出すんですよ・・・(泣)文章術という観点から見ても、「いかがでしたでしょうか」が記事の本質を盛り上げる何かを担えているとは到底思えません。情報量0です。いち読者としては「いかがでしたでしょうか」より「あなたの今日の晩御飯は何か」が書いてあった方がよっぽど面白いな!と思います。今からお試しあれ!(圧)\n"},{"id":"/blog/educational-design-for-groups","data":{"title":"井の中の蛙が人の力を引き出す、群に対する教育の設計術 ~ 専門家が怖くて発言できない、こんな世の中に ~","date":"2022-07-28T12:15:00.000+0900","img_path":"/img/pages/blog/educational-design-for-groups/ogp.png","img_alt":"井の中の蛙が人の力を引き出す、群に対する教育の設計術 ~ 専門家が怖くて発言できない、こんな世の中に ~","description":"子供のときより目的意思を持って学べる大人の学びは楽しいですよね。でも、大人になってから学ぶことが億劫になったこともありました。その理由は学びを共有する相手がいないことです。もちろん今どきは SNS での繋がりで共有することもできますが、思わぬ落とし穴が...。気軽につぶやいたつもりが、専門家からマサカリと呼ばれる技術的な指摘が飛んでくることがあります。ツヨツヨな人の意見だけが飛び交う上級社会と化した SNS。子供のときほど無邪気に学べないこのご時世。専門家が怖くて発言できない、こんな世の中に。もっと大人が学びやすく、人の力を引き出すことができる教育のあり方があるのではないか。今回は教育系ベンチャー企業であるキカガク代表の私(吉崎)が、この答えの1つとして考える「群に対する教育」を紹介します。なんと「井の中の蛙」がヒントなんです。","tags":["fwywd","群に対する教育","井の中の蛙","起業"],"prev_title":"想像していたよりもはるか簡単に社長になった話","prev_link":"/blog/2022072704","next_title":"ライター直伝!読みやすさに差をつける文章濃縮術","next_link":"/blog/how-to-write-sentenses","author":"yoshizaki"},"content":"\n## 大人になってから学ぶの辛くないですか?\n\n子供のときより目的意思を持って学べる大人の学びは楽しいですよね。\n\nでも、大人になってから学ぶことが億劫になったこともありました。  \nその理由は**学びを共有する相手がいないこと**です。\n\nもちろん今どきは SNS での繋がりで共有することもできますが、思わぬ落とし穴が...。  \n気軽につぶやいたつもりが、専門家から**マサカリ**と呼ばれる技術的な指摘が飛んでくることがあります。\n\n**ツヨツヨな人の意見だけが飛び交う上級社会と化した SNS**\n\n子供のときほど無邪気に学べないこのご時世。  \n専門家が怖くて発言できない、こんな世の中に。  \nもっと大人が学びやすく、**人の力を引き出すことができる教育のあり方**があるのではないか。\n\n今回は**教育系ベンチャー企業**であるキカガク代表の私(吉崎)が、この答えの1つとして考える「**群に対する教育**」を紹介します。  \nなんと「**井の中の蛙**」がヒントなんです。\n\n## 個に対する教育の加速\n\n### オンライン動画でいつでもどこでも学べる時代へ\n\n![01](/img/
8pages/blog/educational-design-for-groups/01.jpg)\n\n私は 1991 年生まれ、現在 30 歳。  \n私が中学生のときには塾に行くか、進研ゼミや Z 会の通信教育の教材を定期購入するかしないと学校以外の学びの環境はありませんでした。  \n田舎でしたが親に送り迎えをしてもらい、クラスメイトの 9 割以上が塾に通っていた記憶があります。\n\nそれが7個下の弟の頃にはスタディサプリが登場し、スマホで動画を見ながら学ぶ時代に変わっていました。  \n今では教育系 YouTuber の登場により、無料でも学べる環境が増えました。  \n2次元だった教科書を時間軸も含めた3次元にするためには塾に通う必要がありましたが、それも動画教材の発展により家でも学べるようになりました。  \n「**どこでも**」に変わった瞬間です。\n\nそして、もう1つ変わったことが動画は「**いつでも**」視聴することができます。  \n塾の授業では決まった時間に行かないと受けられなった**同期的**なスタイルから、**非同期**で授業が受けられるようになりました。\n\nオンライン動画で学べる時代は「**いつでも、どこでも**」といった2つのパートで大きな変革をもたらします。\n\n### 大人の教育も C2C でさらに加速\n\n![02](/img/pages/blog/educational-design-for-groups/02.jpg)\n\n学生に対する教育の話でしたが、もちろん社会人である**大人の学びにもオンライン動画は変革をもたらします**。  \nしかも**大人の学びの方が相性が良いこと**もありました。\n\n高校生までの教材は文部科学省が定める方針をベースにしているため、カスタマイズできる範囲が狭く、オリジナルの教材が作りやすいです。  \nそれに対して、大人の学びは社会で求められるありとあらゆるテーマが対象であり、企業とはいえ簡単にオリジナルの教材を作ることができませんでした。  \n特に技術系などは日進月歩であり、コストを掛けて作ったコンテンツが翌年には使い物にならないこともあります。\n\nここに [**Udemy**](https://www.udemy.com/) を代表とした **Consumer to Consumer (C2C)** の教育サービスが登場します。  \n個人でコンテンツを作るため、教材の質とのトレードオフはあるも、**多種多様なテーマの教材が提供可能**になりました。  \n大人の学びに必要な需要を満たすことができ、私も多くの恩恵を受けました。\n\n### 実はオンライン動画の終了率は低いという事実\n\n![03](/img/pages/blog/educational-design-for-groups/03.jpg)\n\nそんな「**いつでも、どこでも**」に加えて「**多種多様なテーマ**」という素晴らしい教育環境を提供しているオンライン教育にも**とんでもない落とし穴**があるのです。\n\nそれは**終了率が異常なくらい低いこと**。\n\n以下の論文によると、ベンチマークとして大学の授業などを多く無料で提供している MOOCs (Massive Open Online Courses) の**平均終了率は 4~5%** なんです。  \n海外の大学の最高峰の内容を最高峰の教授陣が手掛ける授業でも**ほとんどが視聴完了されない**のです。\n\n▶ 参考文献:[組織を越えた Learning Analytics の可能性 − その批判的検討 − | 福井県立大学 山川修 氏 (2015)](https://www.jstage.jst.go.jp/article/konpyutariyoukyouiku/38/0/38_55/_pdf/-char/ja)\n\n### 良い教育の構成要素は「教材」と「講師」の質だけ?\n\n![04](/img/pages/blog/educational-design-for-groups/04.jpg)\n\n**良い教育とは何か?** とよくある議題ですが、わかりやすい構成要素が「**教材**」と「**講師**」です。  \n圧倒的にわかりやすい教材、そして圧倒的にわかりやすい解説をする講師。\n\n恥ずかしながら、以前の私もこの2つを極めることが教育企業としての行く先だと思っていました。  \nそういった意
8味では、これまでに累計 50,000 名を超えた方に受講していただいた AI の基礎を学べる [**[キカガク流] 人工知能・機械学習脱ブラックボックスコース**](https://www.kikagaku.ai/) は1つの完成形と言えるかも知れません。\n\nただし、このコースも**平均終了率は 約 10%** でした。  \n先述した MOOCs の例よりは2倍程度の終了率となっていますが、それでも **90% の人は終了していません**。  \n「**教材**」と「**講師**」が良い教育に対して寄与率の高い構成要素であれば、これを極めた結果としては **80~90%** の方が視聴完了するはずです。\n\nつまり、**視聴完了してもらうためにはもっと他に寄与率の高い構成要素**があるのです。\n\n\u003e **補足 1**  \n\u003e 視聴完了だけを教育のゴールとして設計しているわけではなく、受講した人材の活躍を計測しています。多くのケースが視聴完了後から次のステップへ進むと想定されるため、活躍の前提として視聴完了を据えています。\n\n\u003e **補足 2**  \n\u003e ごく一部のオンライン配信でも学習が完了できる人には「教材」と「講師」の質が非常に重要と言えるため、弊社ではこれからもこの2点も追い求め続けます。これ以降は多くの人に目を向けるため、この視聴完了が高い人は議論の対象外とします。\n\n### オンラインでもリアルタイムのライブオン研修がずっと人気な理由\n\n![05](/img/pages/blog/educational-design-for-groups/05.jpg)\n\nコロナ禍で教室に集まって学べる環境が提供できなくなりました。  \nこれにより、Zoom や Teams などのオンライン環境で講義を提供するように変わります。\n\nオンラインであれば動画を撮影して、YouTube や Netflix のように**オンデマンド配信**で良いのでは?と仮説がありました。  \nそこで、**リアルタイムで時間を拘束するライブオン研修**と、**いつでもどこでも受けられるオンデマンド配信の研修**の両方を提供してみます。  \nもちろん値段はオンデマンド配信の方が安くライブオン研修の 1/2 ~ 1/3 程度です。\n\n社会人向けの研修という前提ですが、どちらが人気だったかというと、圧倒的に**ライブオン研修**でした。  \n**平均終了率は 95% 以上**と非常に高く、仕事の都合でどうしても抜けないといけない場合を除き、みなさんきっちりと終了されます。  \nつまり、このライブオン研修にこそ、視聴完了してもらうために寄与率が高い構成要素が含まれているのです。\n\n受講生へヒアリングを行い、なぜ視聴が完了できたのかを要素分解すると以下の3つがありました。\n\n1. **時間の確保**(チームからの理解もある)\n2. **仲間の存在**(モチベーションの維持)\n3. **質疑応答**\n\n3 番目の質疑応答に関しては、オンライン配信系のサービスでは Q\u0026A を作って対応していることもあります。  \nしかし、これがあっても終了率はそこまで高まっていないことを考えると寄与率はそこまで高くなさそうです。\n\nつまり、**時間の確保**と**仲間**の2つが鍵であることが推測できます。  \nしかも、同じ時間に学ぶという時間を確保すれば、必然的に同じタイミングで学ぶ仲間が生まれるので、これらは同時に満たすことができます。\n\nここから見えてきた教育に必要な構成要素として面白いのが、オンライン教育によって得られていた「**いつでも**」というパートを多くの人が本当は求めていなかったのです。\n\n## 「個」から「群」に対する教育へ\n\n### ずっと受けてきた学校の教育は群であった\n\n![06](/img/
8pages/blog/educational-design-for-groups/06.jpg)\n\nオンライン教育の加速は「**いつでもどこでも**」という視点以外に「**個人で学ぶ**」とも捉えることができます。\n\n振り返ってみると、私達が学校や塾で受けてきた教育は常に集団、つまり「**群で学ぶ**」ように設計されていました。  \nこの学び方が平均終了率が高いという現代のオンライン教育の変遷から導かれたものではないと思いますが、原点回帰しています。  \nただし、昔と異なるのは「**どこでも**」という要素に関してはメリットが大きく、オンラインの恩恵は大きくあります。\n\n大学も高いお金を払って一人暮らしをしなくても通えるようになりましたし、地方と都会の情報格差も減っています。  \nまた嬉しかった声としては、お子さんがいらっしゃる家庭でも自宅から受講できることで、学びに来てくれる方が多くなったことです。\n\nこれからの時代の教育は「**オンライン × 仲間**」といった**同期的な要素**も含んだものになると予想しています。\n\n### 群に対する教育は経営目線の組織論がヒント\n\n![07](/img/pages/blog/educational-design-for-groups/07.jpg)\n\n「オンライン × 仲間」というと**オンラインサロン**がこの条件を満たしています。  \n教育という文脈では語られることが少ないオンラインサロンですが、教育とマッチすると考えています。  \n現在、私が主催している起業家コミュニティ [**fwywd(フュード)**](https://apply.fwywd.com) も**オンラインサロン**に近しいと言えます。\n\nただし、多くのオンラインサロンと異なる点もあります。  \n私の知る限り多くのオンラインサロンは企画の発端であるリーダー格の人がいて、その人との繋がりを求める人が集まる**ぶら下がり型**です。  \n**芸能人のファンクラブ**というとわかりやすいですね。\n\n[**fwywd(フュード)**](https://apply.fwywd.com) では私との繋がりという面もありますが、それよりもコミュニティ間の会話を中心としています。  \nこれは私がこれまで作ってきた経営の経験に基づき**組織論**から設計しています。\n\n### コミュニケーションには適切なサイズ設計が必要\n\n![08](/img/pages/blog/educational-design-for-groups/08.jpg)\n\n今の段階では以下のような構造を作っています。\n\n1. チーム(5~8 人)→ 最も密に**同期**的にコミュニケーションを取る集団\n2. バンド(30~40 人)→ **非同期**でコミュニケーションを取る集団(6 チーム程度のまとまり)\n3. コミュニティ(全員)→ イベント等で出会う集団\n\n人数が多くなってくると、バンドよりも大きな単位を随時作っていきます。  \nこの辺りはすでに**経営としての組織論**として適切なサイズ設計が議論されているため、先人の知恵をお借りするだけです。  \n教育の問題は教育カテゴリーで議論したり調査しがちですが、結局は**組織が一番人を成長させており、経営の組織論で教育を見るべき**だと現在では私は考えています。\n\nコミュニティとして全てをまとめないことには私の**失敗談**があります。\n\n[**fwywd(フュード)**](https://apply.fwywd.com) の1期では合格した人から順次 Slack で作っていたコミュニティに参加してもらいました。  \n最初は盛り上がったのですが、後から入ってくる人がコミュニティの適性の有無を問わず、ほとんど会話に参加できなかったのです。  \nそれも当然で、会話には**文脈** (**context**) の理解が不可欠であり、これがない状態だったと言えます。\n\nどれだけ大きなコミュニティであったとしても、会話しているのはごく一部という経験がなã
8„でしょうか。  \nこれは後から参加した人の能力が低いのではありません。  \n**会話に必要な構成要素を欠いている結果**なのです。\n\nこの失敗談から文脈を共有しやすいように、**目的を持った小さな単位のチームに分ける**こと。  \nそして、**チームの始まりのタイミングを一斉にスタート(同期)すること**に決めました。\n\nその結果、現在の [**fwywd(フュード)**](https://apply.fwywd.com) はコミュニケーションが以前よりも遥かに多くなりました。  \nまた、コミュニティオーナーの私一強のぶら下がり型からも徐々に解放されていき、望ましいコミュニティの形へ遷移しつつあります。\n\n### 井の中の蛙が人の可能性を開花させる\n\n![09](/img/pages/blog/educational-design-for-groups/09.jpg)\n\nここでようやく本題であった「**井の中の蛙**」です。\n\nコミュニティ内のチームのサイズを小さく設計したデメリットは情報の正しさが確保しにくくなることです。  \n答えを持たない素人同士の議論ではカオスになることがありますよね。\n\nここへの対策もあります。  \nチームで解決できないことは1階層上のバンドに投げかけて解決していけるような流れがあります。  \nまた最終的には私が解決に手を貸すこともあります。\n\nチーム内での議論がカオスになるデメリットもありますが、本当はメリットの方が大きいと思っています。  \n**素人同士でも自信を持って議論することって大切じゃないですか**。  \n**専門家に見張られていると、怖くて自分の意見って出せなくなりませんか?**\n\n情報の成否は別としても自信を持って話ができることで主体性が高まり、情報を調べる感度が高まり、結果的に正しい情報にたどり着きやすくなると予想しています。  \nこれがまさに「**井の中の蛙**」です。  \n最初から**海王類ばかりの大海原**に放たれると怖くて何もできなくないですか。  \nそれだったら、世間知らずかも知れないですが、まずは守られた井戸の中で成長できた方がよっぽど良いと思っています。  \n成長したら次のもう少しだけ大きな井戸に入りかえることを繰り返せば良いじゃないですか。  \nルフィもそうやって七武海と戦えるレベルになっていき、今や四皇と戦うまでになりました。  \n最初の島にいる敵から四皇のカイドウやビッグマムだったら、ワンピースはそうそうに終わっていたはずです。\n\n**海王類ばかりの大海原**とワンピースの例えましたが、私達の学校教育もそうなっていました。  \n私は超田舎の学校に入ったお陰で、成績優秀という位置づけをもらうことができ、だからこそ勉強が楽しかった記憶があります。  \nまさに井の中の蛙で、高専に入ったら上には上がいて、京大に入ったらさらに上には上がいて...。  \nそれでも順番に上がっていけたから、なんとか今に繋がっています。\n\n「**井の中の蛙**」って、実はどんなヒーローの物語にもあるのではないかと思います。\n\n## 海王類ばかりの大海原よりも身の丈にあった井戸から\n\n![10](/img/pages/blog/educational-design-for-groups/10.jpg)\n\nTwitter で AI やソフトウェア・エンジニアリング、起業など専門分野について発言をするのは私でも恐怖でしかありません。  \nこんな環境では**超一強**だけが育ち、それ以外の人は餌にすぎないとさえ感じます。\n\n**ツヨツヨな人の意見だけが飛び交う上級社会と化した SNS**。  \nまさに、海王類ばかりの大海原のようです。\n\nいつの日か、こんな
8大海原でも暴れまわれる存在になるために、まずは**小さな井戸**から始めてみませんか。\n\n詳しくは ↓↓ でお待ちしております。\n\n▶ [**【次期受講生募集】起業家精神 × 学び方改革 = fwywd(フュード)| 挑戦しないことがリスクになる時代へ**](https://apply.fwywd.com/)\n\n長文お読みいただき、誠にありがとうございました。\n\n株式会社キカガク 代表取締役会長  \n吉崎 亮介\n"},{"id":"/blog/2022072704","data":{"title":"想像していたよりもはるか簡単に社長になった話","date":"2022-07-27T17:48:00.000+0900","img_path":"/img/pages/blog/2022072704/ogp.png","img_alt":"想像していたよりもはるか簡単に社長になった話","description":"今まで社長とか個人事業主は自分には縁のないものと思っていました。しかしある人の一言がきっかけで私は社長デビューを果たします。","tags":["個人事業主","fwywd","起業"],"prev_title":"挫折よ、さらば。未経験からエンジニアになった私のプログラミング独学サイクル","prev_link":"/blog/2022072703","next_title":"井の中の蛙が人の力を引き出す、群に対する教育の設計術 ~ 専門家が怖くて発言できない、こんな世の中に ~","next_link":"/blog/educational-design-for-groups","author":"takahashi"},"content":"\nこんにちは! fwywd 運営チームの高橋です!\n\n私は2021年に個人事業主として開業しました!今まで社長とか個人事業主は自分には縁のないものと思っていました。しかしある人の一言がきっかけで私は社長デビューを果たします。\n\nその一言とは「**開業すれば経費申請できるよ!青色申告オススメ!**」でした。素直な私は「**なるほど!開業しよう!**」と早速行動に移したのです。(実際のところ、ただ単に開業するだけでは青色申告できません)\n\n## Web サービスを利用して開業届を出せば30分であなたも社長\n\n夢の経費申請に向けて私はインターネットで調べました。検索ワードは「個人事業主 開業」。どうやら開業するには難しい書類に難しいことを書いて難しい行政機関に提出しないといけない…わけではありませんでした。\n\n開業するための手助けをしてくれる Web サービスで、**フォームに必要事項を入力し出来上がった書類をコンビニで印刷し郵送**するだけで開業ができてしまうのです!あなたはここに郵送してね!と送付先住所まで教えてくれます。スムーズ!私は [freee 開業](https://www.freee.co.jp/kaigyou/)といったサービスを利用しました。\n\n入力で唯一悩んだのが「会社名」です。ここはぜひ存分に悩んでください。答えはあなたの心のなかに。\n\nそして無事に書類を郵送して私は思ったのです。「えっ!これで自分も社長!?」\n\n約一週間後、無事に税務署から開業が完了したとの書類が届きました。\n\n**みなさん、簡単になれますよ!社長に!!**\n\n## 開業することで売上を上げる手段や簿記について考える機会になった\n\nさて、無事開業が完了して社長になりました。めでたしめでたし。とはいきません。当たり前のことですが社長になったからといって勝手に売上が上がるわけではないのです。\n\n売上がないのに経費ばっかり申請していると脱税を疑われます。**事業を行っている実態がないと言われてしまう**わけですね。どうやったら自分の持っているスキルで売上を上げられるんだろう。どんなスキルを身につければ売上を上げられるんだろう。誰がそのスキルを買ってくれるんだろう。と考えるきっかけになりました。\n\nまた経費申請も領収証をもらっておけば OK ! なんてことはありません。青色申告するためには**複式簿記という形式で帳簿を提出する必要があります**。確定申告の Web サービスなどである程度簡単にできますが、それでも一定の知識が必要になります。\n\n実際に開業していなければこのあたりを考えることもなく過ごしていたので、とてもいい機会になりました。\n\n## 社長になってからが本当のスタート\n\n実際に開業届を出して社長(個人事業主)になるのは本当に簡単でした。\n\nそれと同時に売上を上げるためのハードルの高さを感じました。**1円を稼ぐことすら難しい**のです。\n\n**人の課題を解決するためのスキル。スキルを必要としている人に届けるためのマーケティング。経理や資金面のファイナンス知識。**\n\nやらないといけないことは膨大ですが、これらのスキルを身につけることができればこれからの厳しい時代を生き抜いていけるという確信もありました。\n\nfwywd はそれらの力を身につけることができる環境があります!\n\n- **技術(スキル)**\n- **売る力(マーケティング)**\n- **戦略(ファイナンス)**\n\nこれらの力を身に着けて**自由に生きるために挑戦してみませんか?**\n\nちょっと興味があるなーという方、以下のリンクから詳しく見てみてください!\n\n[挑戦しないことがリスクになる時代へ、学び方の革命を。fwywd(フュード)次期受講生募集中!](https://apply.fwywd.com/)\n"}],"popularPosts":[]},"__N_SSG":true},"page":"/tech/tags/[id]","query":{"id":"instant%20search"},"buildId":"8g7VE4IFZHCF7i2FMUki4","isFallback":false,"gsp":true,"scriptLoader":[]}</script>
8</body></html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.