1<!doctype html> 2<html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <link rel="stylesheet" href="https://unpkg.com/[email protected]/build/pure-min.css" integrity="sha384-cg6SkqEOCV1NbJoCu11+bm0NvBRc8IYLRGXkmNrqUBfTjmMYwNKPWBTIKyw9mHNJ" crossorigin="anonymous"> 8 <link rel="stylesheet" href="https://unpkg.com/[email protected]/build/grids-responsive-min.css"> 9 <link rel="stylesheet" href="/assets/styles.css"><!-- Begin Jekyll SEO tag v2.8.0 --> 10<title>Tingâs Square | A web developer who loves bridging the gap between product ideation and implementation</title> 11<meta name="generator" content="Jekyll v3.10.0" /> 12<meta property="og:title" content="Tingâs Square" /> 13<meta name="author" content="Ting Hsu" /> 14<meta property="og:locale" content="en" /> 15<meta name="description" content="A web developer who loves bridging the gap between product ideation and implementation" /> 16<meta property="og:description" content="A web developer who loves bridging the gap between product ideation and implementation" /> 17<link rel="canonical" href="https://tingtinghsu.github.io/" /> 18<meta property="og:url" content="https://tingtinghsu.github.io/" /> 19<meta property="og:site_name" content="Tingâs Square" /> 20<meta property="og:type" content="website" /> 21<link rel="next" href="https://tingtinghsu.github.io/page2" /> 22<meta name="twitter:card" content="summary" /> 23<meta property="twitter:title" content="Tingâs Square" /> 24<meta name="twitter:site" content="@tingtingtour" /> 25<meta name="twitter:creator" content="@Ting Hsu" /> 26<meta name="google-site-verification" content="xxxxx" />
27<script type="application/ld+json"> 28{"@context":"https://schema.org","@type":"WebSite","author":{"@type":"Person","name":"Ting Hsu","url":"https://github.com/tingtinghsu/"},"description":"A web developer who loves bridging the gap between product ideation and implementation","headline":"Tingâs Square","name":"Ting Ting Hsu","publisher":{"@type":"Organization","logo":{"@type":"ImageObject","url":"https://tingtinghsu.github.io/logo.png"},"name":"Ting Hsu"},"sameAs":["https://twitter.com/tingtingtour","https://github.com/tingtinghsu","https://tingtingtour.wordpress.com/"],"url":"https://tingtinghsu.github.io/"}</script>
28 29<!-- End Jekyll SEO tag --> 30<link type="application/atom+xml" rel="alternate" href="https://tingtinghsu.github.io/feed.xml" title="Ting's Square" /> 31</head> 32 33 34 <body> 35 36 <div class="container pure-g"><div class="sidebar-left pure-u-1 pure-u-md-1-4" style="background-color: rgb(40, 73, 77); color: rgb(255, 255, 255); "><header class="masthead"> 37 <div class="avatar"><img src="/avatar.jpeg" class="avatar-image" alt="Ting Hsu"> 38 </div> 39 <div class="masthead-title"> 40 <a href="/" title="Home">Ting's Square</a> 41 </div> 42 <div class="masthead-tagline"> 43 <small>A web developer who loves bridging the gap between product ideation and implementation</small> 44 </div> 45</header> 46</div> 47 48 <div class="content pure-u-1 pure-u-md-1-2"><main> 49 <div class="home-header pure-menu pure-menu-horizontal"> 50 <div class="home-header-bar"> 51 52 </div> 53</div> 54 55 56<div class="home-controls"> 57 <button id="date-toggle-btn" class="date-filter-btn">ð Date</button> 58 <button id="tag-toggle-btn" class="tag-filter-btn">ð·ï¸ Tags</button> 59</div> 60 61<!-- Date Panel --> 62<div id="date-panel" class="filter-panel" style="display: none;"> 63 64 <div class="filter-header"> 65 <h2>ææ¥æç覽 / Browse by Date</h2> 66 <button class="close-btn" onclick="document.getElementById('date-panel').style.display='none'">â</button> 67 </div> 68 <div class="filter-content"> 69 70 <div class="date-year"> 71 <h3>2026</h3> 72 <div class="date-months"> 73 74 75 76 77 <a href="/dates/#2026-04" class="date-link"> 78 April (2) 79 </a> 80 81 </div> 82 </div> 83 84 <div class="date-year"> 85 <h3>2022</h3> 86 <div class="date-months"> 87 88 89 90 91 <a href="/dates/#2022-06" class="date-link"> 92 June (1) 93 </a> 94 95 </div> 96 </div> 97 98 <div class="date-year"> 99 <h3>2020</h3> 100 <div class="date-months"> 101 102 103 104 105 <a href="/dates/#2020-06" class="date-link"> 106 June (1) 107 </a> 108 109 110 111 <a href="/dates/#2020-07" class="date-link"> 112 July (1) 113 </a> 114 115 116 117 <a href="/dates/#2020-09" class="date-link"> 118 September (20) 119 </a> 120 121 122 123 <a href="/dates/#2020-10" class="date-link"> 124 October (10) 125 </a> 126 127 128 129 <a href="/dates/#2020-12" class="date-link"> 130 December (1) 131 </a> 132 133 </div> 134 </div> 135 136 <div class="date-year"> 137 <h3>2019</h3> 138 <div class="date-months"> 139 140 141 142 143 <a href="/dates/#2019-01" class="date-link"> 144 January (4) 145 </a> 146 147 148 149 <a href="/dates/#2019-02" class="date-link"> 150 February (3) 151 </a> 152 153 154 155 <a href="/dates/#2019-03" class="date-link"> 156 March (21) 157 </a> 158 159 160 161 <a href="/dates/#2019-04" class="date-link"> 162 April (2) 163 </a> 164 165 166 167 <a href="/dates/#2019-05" class="date-link"> 168 May (5) 169 </a> 170 171 </div> 172 </div> 173 174 <div class="date-year"> 175 <h3>2018</h3> 176 <div class="date-months"> 177 178 179 180 181 <a href="/dates/#2018-08" class="date-link"> 182 August (3) 183 </a> 184 185 186 187 <a href="/dates/#2018-09" class="date-link"> 188 September (20) 189 </a> 190 191 192 193 <a href="/dates/#2018-10" class="date-link"> 194 October (12) 195 </a> 196 197 198 199 <a href="/dates/#2018-11" class="date-link"> 200 November (2) 201 </a> 202 203 204 205 <a href="/dates/#2018-12" class="date-link"> 206 December (3) 207 </a> 208 209 </div> 210 </div> 211 212 </div> 213</div> 214 215<!-- Tags Panel --> 216<div id="tag-panel" class="filter-panel" style="display: none;"> 217 218 219 220 221 <div class="filter-header"> 222 <h2>ææ¨ç±¤ç覽 / Browse by Tag</h2> 223 <button class="close-btn" onclick="document.getElementById('tag-panel').style.display='none'">â</button> 224 </div> 225 <div class="filter-content tags-grid"> 226 227 <a href="/tag/career/" class="tag-link">career</a> 228 229 <a href="/tag/css/" class="tag-link">css</a> 230 231 <a href="/tag/front-end/" class="tag-link">front-end</a> 232 233 <a href="/tag/fullstack/" class="tag-link">fullstack</a> 234 235 <a href="/tag/git/" class="tag-link">git</a> 236 237 <a href="/tag/heroku/" class="tag-link">heroku</a> 238 239 <a href="/tag/interview/" class="tag-link">interview</a> 240 241 <a href="/tag/javascript/" class="tag-link">javascript</a> 242 243 <a href="/tag/jekyll/" class="tag-link">jekyll</a> 244 245 <a href="/tag/mongodb/" class="tag-link">mongodb</a> 246 247 <a href="/tag/nodejs/" class="tag-link">nodejs</a> 248 249 <a href="/tag/note/" class="tag-link">note</a> 250 251 <a href="/tag/rail/" class="tag-link">rail</a> 252 253 <a href="/tag/rails/" class="tag-link">rails</a> 254 255 <a href="/tag/react/" class="tag-link">react</a> 256
257 <a href="/tag/ruby/" class="tag-link">ruby</a> 258 259 <a href="/tag/rubygem/" class="tag-link">rubygem</a> 260 261 <a href="/tag/vue/" class="tag-link">vue</a> 262 263 </div> 264</div> 265 266<div class="posts"> 267 268 <section class="post-entry"> 269 <h3 class="post-title"> 270 <a href="/articles/2026-04-03"> 271 åå¾ç«¯åé¢å¯¦æ°ï¼äºï¼ï¼ç¨ React + Vite 建ç«äºåå端 272 </a> 273 </h3> 274 275 <div class="post-meta"> 276 <time datetime="2026-04-03T10:00:00+00:00">03 Apr 2026</time></div> 277 278 <p>ä¸ä¸ç¯æåç¨ Express + MongoDB 建好äºå¾ç«¯ APIã鿬¡ï¼AI 夥伴帶æç¹¼çºæå端è£å®ã 279 280</p> 281 </section> 282 283 <section class="post-entry"> 284 <h3 class="post-title"> 285 <a href="/articles/2026-04-02"> 286 åå¾ç«¯åé¢å¯¦æ°ï¼ç¨ Node.js + React + MongoDB 建ç«çè¨æç¨ 287 </a> 288 </h3> 289 290 <div class="post-meta"> 291 <time datetime="2026-04-02T15:23:06+00:00">02 Apr 2026</time></div> 292 293 <p>ä»å¤©è«æç AI 夥伴ç¨ç°¡å®ç demo project æææéº¼ä¸æ¥ä¸æ¥åãç¶éå¹¾åå°æçäºåååæå¯¦ä½ï¼çè§£äºåå¾ç«¯åé¢çæ ¸å¿æ¦å¿µï¼ä»¥åå¦ä½å¾é¶éå§å»ºç«ä¸å宿´çå ¨æ£§æç¨ã 294 295</p> 296 </section> 297 298 <section class="post-entry"> 299 <h3 class="post-title"> 300 <a href="/articles/2022-06-11"> 301 å®è£Rails 7 302 </a> 303 </h3> 304 305 <div class="post-meta"> 306 <time datetime="2022-06-11T03:56:00+00:00">11 Jun 2022</time></div> 307 308 <p>è¶ éä¸å¹´æ²å¯«blogå¦ï¼ä¾ç´éä¸ç¯å®è£Rails 7çblog 309 310</p> 311 </section> 312 313 <section class="post-entry"> 314 <h3 class="post-title"> 315 <a href="/articles/2020-12-19/my_route_of_becoming_a_ruby_on_rails_developer_1"> 316 Astro Camp ç´é - éåå·¥ç¨å¸«ä¹æ 317 </a> 318 </h3> 319 320 <div class="post-meta"> 321 <time datetime="2020-12-19T10:00:00+00:00">19 Dec 2020</time></div> 322 323 <p>æçºè»é«å·¥ç¨å¸«å¿«ä¸åæäºï¼æè¬äºåç´ å¯¶ç³çéè«æ°ç¨¿ï¼è®æè½æè½è·éç¨çé»é»æ»´æ»´è¨éä¸ä¾ï¼åå Astro Camp çµå°æ¯2020å¹´ææ£çæ±ºå®æ²æä¹ä¸ï¼ 324 325</p> 326 </section> 327 328 <section class="post-entry"> 329 <h3 class="post-title"> 330 <a href="/articles/2020-10-13"> 331 第12å±éµäººè³½Day 30 Railså°æ¡éç¼ - ç¶²ç«é¨ç½² + å®è³½æè¨ 332 </a> 333 </h3> 334 335 <div class="post-meta"> 336 <time datetime="2020-10-10T10:00:00+00:00">10 Oct 2020</time></div> 337 338 <p>ä»å¤©å°±æ¯ç¶²ç«é¨ç½²ãå ¬éä¸ç·çæ¥åäºï¼ 339 340</p> 341 </section> 342 </div> 343 344<div class="pagination"> 345 346 <a class="pagination-item older" href="/page2">Older</a> 347 348 349 <span class="pagination-item newer">Newer</span> 350 351</div> 352
353<script> 354 const dateToggleBtn = document.getElementById('date-toggle-btn'); 355 const tagToggleBtn = document.getElementById('tag-toggle-btn'); 356 const datePanel = document.getElementById('date-panel'); 357 const tagPanel = document.getElementById('tag-panel'); 358 359 dateToggleBtn.addEventListener('click', () => { 360 if (datePanel.style.display === 'none') { 361 datePanel.style.display = 'block'; 362 tagPanel.style.display = 'none'; 363 } else { 364 datePanel.style.display = 'none'; 365 } 366 }); 367 368 tagToggleBtn.addEventListener('click', () => { 369 if (tagPanel.style.display === 'none') { 370 tagPanel.style.display = 'block'; 371 datePanel.style.display = 'none'; 372 } else { 373 tagPanel.style.display = 'none'; 374 } 375 }); 376 377 // Close panels when clicking outside 378 document.addEventListener('click', (e) => { 379 if (!e.target.closest('.home-controls') && 380 !e.target.closest('.filter-panel')) { 381 datePanel.style.display = 'none'; 382 tagPanel.style.display = 'none'; 383 } 384 }); 385</script>
385 386 387</main> 388 389<footer class="footer"><small> 390 Powered by <a href="https://jekyllrb.com/">Jekyll</a> & <a href="https://github.com/vszhub/not-pure-poole">Not Pure Poole</a>. 391 © 2018 - 2026 <a href="https://github.com/tingtinghsu/">Ting Hsu</a>. 392 </small> 393</footer> 394</div> 395 <div class="sidebar-right pure-u-1 pure-u-md-1-4"> 396</div> 397 </div> 398 399
399<script async src="https://use.fontawesome.com/releases/v5.0.12/js/all.js"></script>
399<script> 400 function strip(str, remove) { 401 while (str.length > 0 && remove.indexOf(str.charAt(0)) != -1) { 402 str = str.substr(1); 403 } 404 while (str.length > 0 && remove.indexOf(str.charAt(str.length - 1)) != -1) { 405 str = str.substr(0, str.length - 1); 406 } 407 return str; 408 } 409 410 function scroll() { 411 console.log('scroll'); 412 window.scrollTo({ 413 left: 0, 414 top: window.innerHeight, 415 behavior: 'smooth' 416 }); 417 sessionStorage.removeItem('forceCheckScroll'); 418 } 419 420 const forceCheckScroll = sessionStorage.getItem('forceCheckScroll') === 'true'; 421 const checkScroll = strip(window.location.pathname, '/') !== strip('', '/'); 422 423 if (forceCheckScroll || checkScroll) { 424 const maxWidth = "(max-width: 48rem)"; 425 const result = window.matchMedia(maxWidth); 426 if (result.matches) { 427 scroll(); 428 } else { 429 result.addListener((match) => { 430 if (match.media == maxWidth) { 431 if (match.matches) { 432 scroll(); 433 } 434 } 435 }); 436 } 437 } 438</script>
438 439</body> 440</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.