├── styled-jsx.png ├── withLayout.png ├── styled-jsx-no-highlighting.png ├── styled-jsx-with-syntax-highlighting.png └── README.md /styled-jsx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziad-saab/wordpress-api-nextjs-theme/HEAD/styled-jsx.png -------------------------------------------------------------------------------- /withLayout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziad-saab/wordpress-api-nextjs-theme/HEAD/withLayout.png -------------------------------------------------------------------------------- /styled-jsx-no-highlighting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziad-saab/wordpress-api-nextjs-theme/HEAD/styled-jsx-no-highlighting.png -------------------------------------------------------------------------------- /styled-jsx-with-syntax-highlighting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziad-saab/wordpress-api-nextjs-theme/HEAD/styled-jsx-with-syntax-highlighting.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Let's make a WordPress-based blog with React and NodeJS 2 | 3 | In this workshop, we are going to make a blog. To manage the content of our blog, we will be using 4 | WordPress, one of the leading content management systems today. However, contrary to most WordPress 5 | blogs in existence today, we will not be using PHP to create the theme for our blog. Instead, we are 6 | going to manage the front-end with a variety of modern web technologies: JavaScript, React, and some 7 | NodeJS. 8 | 9 | ## Why choose this tech stack? :question: 10 | It's important to note that this way of doing things is not for everyone. As always, our 11 | technology choices will have some upsides and some downsides. In the case of choosing React, here 12 | are, in no particular order, a few pros and cons: 13 | 14 | * :fire: Pros: 15 | * Extremely rapid feedback during the development cycle 16 | * The resulting single-page application can have faster loading times and navigation 17 | * Great ability and ease to add interactive features like infinite scrolling 18 | * Ability to get going without having to learn PHP 19 | * Even greater separation between back-end and front-end 20 | * Ease of managing different development environments without copying WordPress data 21 | * :poop: Cons: 22 | * Some complexity will be introduced by having two different technologies – PHP and JavaScript 23 | * Having a build process for the front-end complicates things 24 | * The need to have two hosting environments, one for WordPress and one for our “theme” 25 | * The reduced number of people who can help us due to our non-conventional setup 26 | 27 | Now that that's out of the way, let's not come back to it and concentrate on the task at hand. 28 | 29 |
30 |
31 |
38 |
39 | In order to successfully complete this workshop, you will need:
40 |
41 | * A computer with an internet connection
42 | * The software mentioned in the [next section](#required-software)
43 | * Some familiarity with modern JavaScript, React and NodeJS
44 | * Some familiarity with the command line interface of your machine
45 | * Familiarity with Git is optional, but you should use it to track your progress!
46 |
47 | ---
48 |
49 | ## Thanks :two_hearts:
50 | Before moving forward with the workshop, I'd like to express my thanks to the people who
51 | helped make this possible:
52 |
53 | - [Nathaniel Kitzke](https://github.com/nk1tz): for TAing and fixing a thousand typos
54 | - [Timothy Mulqueen](https://github.com/multimo): for TAing and fixing some glaring mistakes
55 | - [Paule Lepage](https://github.com/nyanofthemoon): for TAing and moral support
56 |
57 |
58 |
59 |
118 |
119 |
194 |
195 |
234 |
235 |
If you’re the kind of person who will arrive at the airport without charging your phone or laptop, you are also the kind of person who will forget to charge the battery bank in your smart luggage. I discovered this when a three-hour delay kicked off my weekend trip with Incase’s NoviConnected carry-on suitcase. Sorry, but it’s true.
\nAt home, it took six hours of wall charging at home to get the NoviConnected’s 10,050-mAh battery up to 100%. A few days later, I packed my bag, headed to the airport and waited at the gate. By the time I realized I needed to charge my phone, the suitcase’s battery had gone down to 76% after doing nothing, with an estimated one hour and 23 minutes’ worth of juice.
\nCharging my phone back up to 80% took the suitcase’s battery down to 19%. What about charging a laptop? Forget about it. The bag’s battery bank is strictly for small devices only and it’s best conserved for an emergency situation. Since everything from your boarding pass to your hotel reservation is on your phone, you’ll need that to be juiced up, so it’s not a total loss. Like the rest of the bag’s smart features, it may promise more than it can actually deliver.
\nFor example, take the suitcase’s Smart Luggage tracker. It uses Bluetooth and has a range of up to 33 feet. On a full flight, I ended up checking my carry-on at the airline’s request. When I got to baggage claim, I glanced at the Incase app to determine my luggage’s whereabouts and found out that my bag was out of range. For fifteen minutes, I waited at the baggage carousel like an ordinary plebe, trapped in a seemingly endless purgatory, mired in deep existential uncertainty.
\nEven walking across my house prompted a notification from my phone, alerting me that the suitcase—safely in my office—was no longer within range. If you want a smart luggage tracker, it should probably use GPS instead of Bluetooth.
\n\nBeautiful. Durable. Hubless wheels roll smoothly and easily and are easily replaceable. Battery bank will save you in a pinch. Comes with rain cover.
\n\t\tBluetooth tracker makes no sense. No side handle. Battery life was disappointing.
\n\t\tBut as a piece of ordinary luggage, the bag performed admirably. It has a simple, durable makrolon polycarbonate shell that showed little wear after a few trips around the baggage carousel. The navy color of my sample case was elegant and surprisingly distinctive among a billion black bags. The interior, with mesh zip pockets and an included laundry bag, easily accommodated several days’ worth of clothes and shoes.
\nThe bag was impossible to tip over, even with a tote bag hooked on top. The hubless wheels rolled smoothly—almost a little too smoothly, as the suitcase escaped me when my attention wandered on a slanting parking lot garage floor—and it’s simple to pop the wheels on and off if you need to fit the suitcase into an overhead compartment. This model also carries a lifetime warranty from Incase, so the wheels are covered if they break (the power bank’s embedded battery has a two-year limited warranty).
\nThe integrated TSA-approved lock works like you’d expect, and it proved useful when I ended up checking my carry-on to save overhead space on two packed flights. However, I would have appreciated a side handle to make it easier to hoist around.
\nAs holiday travel season approaches, you do have to find a way to get all your stuff from Point A to Point B without carrying it all in your arms. Incase is known for their attractive, Apple-compatible accessories and bags, and the NoviConnected is no exception. It’s elegant, rolls with ease, and has the capacity to save your tuchus right when you need it most—when your phone is about to die and you have no way to text your ride or check your car rental confirmation number.
\nBut there are just too many other moderately-priced smart carry-ons out there right now with features that make a bit more sense, like a true GPS locator that can tell you if your baggage has made it to your destination. Or just bring your own spare battery and pop a Tile tracker into your current luggage and call it a day.
\n" 269 | }, 270 | "excerpt": { 271 | "rendered": "A great piece of luggage is brought down by its poor smart features.
\n" 272 | }, 273 | "author": 609, 274 | "featured_media": 2267773, 275 | "comment_status": "open", 276 | "ping_status": "closed", 277 | "sticky": false, 278 | "format": "standard", 279 | "categories": [ 280 | 36, 281 | 83082, 282 | 4 283 | ], 284 | "tags": [ 285 | 106059, 286 | 106060 287 | ], 288 | "series": [], 289 | "admin-settings": [], 290 | "_links": { 291 | "self": [ 292 | { 293 | "href": "https://www.wired.com/wp-json/wp/v2/posts/2267743" 294 | } 295 | ], 296 | "collection": [ 297 | { 298 | "href": "https://www.wired.com/wp-json/wp/v2/posts" 299 | } 300 | ], 301 | "about": [ 302 | { 303 | "href": "https://www.wired.com/wp-json/wp/v2/types/post" 304 | } 305 | ], 306 | "author": [ 307 | { 308 | "embeddable": true, 309 | "href": "https://www.wired.com/wp-json/wp/v2/users/609" 310 | } 311 | ], 312 | "replies": [ 313 | { 314 | "embeddable": true, 315 | "href": "https://www.wired.com/wp-json/wp/v2/comments?post=2267743" 316 | } 317 | ], 318 | "version-history": [ 319 | { 320 | "href": "https://www.wired.com/wp-json/wp/v2/posts/2267743/revisions" 321 | } 322 | ], 323 | "wp:featuredmedia": [ 324 | { 325 | "embeddable": true, 326 | "href": "https://www.wired.com/wp-json/wp/v2/media/2267773" 327 | } 328 | ], 329 | "wp:attachment": [ 330 | { 331 | "href": "https://www.wired.com/wp-json/wp/v2/media?parent=2267743" 332 | } 333 | ], 334 | "wp:term": [ 335 | { 336 | "taxonomy": "category", 337 | "embeddable": true, 338 | "href": "https://www.wired.com/wp-json/wp/v2/categories?post=2267743" 339 | }, 340 | { 341 | "taxonomy": "post_tag", 342 | "embeddable": true, 343 | "href": "https://www.wired.com/wp-json/wp/v2/tags?post=2267743" 344 | }, 345 | { 346 | "taxonomy": "series", 347 | "embeddable": true, 348 | "href": "https://www.wired.com/wp-json/wp/v2/series?post=2267743" 349 | }, 350 | { 351 | "taxonomy": "admin-settings", 352 | "embeddable": true, 353 | "href": "https://www.wired.com/wp-json/wp/v2/admin-settings?post=2267743" 354 | } 355 | ], 356 | "curies": [ 357 | { 358 | "name": "wp", 359 | "href": "https://api.w.org/{rel}", 360 | "templated": true 361 | } 362 | ] 363 | } 364 | } 365 | ``` 366 | 367 |
368 |
369 |
370 | Get it? JASON 🤣
371 |
If you’re the kind of person who will arrive at the airport without charging your phone or laptop, you are also the kind of person who will forget to charge the battery bank in your smart luggage. I discovered this when a three-hour delay kicked off my weekend trip with Incase’s NoviConnected carry-on suitcase. Sorry, but it’s true.
\nAt home, it took six hours of wall charging at home to get the NoviConnected’s 10,050-mAh battery up to 100%. A few days later, I packed my bag, headed to the airport and waited at the gate. By the time I realized I needed to charge my phone, the suitcase’s battery had gone down to 76% after doing nothing, with an estimated one hour and 23 minutes’ worth of juice.
\nCharging my phone back up to 80% took the suitcase‚Äôs battery down to 19%. What about charging a laptop? Forget about it. The bag‚Äôs battery bank is strictly for small devices only and it’s best conserved for an emergency situation. Since everything from your boarding pass to your hotel reservation is on your phone, you’ll need that to be juiced up, so it’s not a total loss. Like the rest of the bag‚Äôs smart features, it may promise more than it can actually deliver.
\nFor example, take the suitcase’s Smart Luggage tracker. It uses Bluetooth and has a range of up to 33 feet. On a full flight, I ended up checking my carry-on at the airline’s request. When I got to baggage claim, I glanced at the Incase app to determine my luggage’s whereabouts and found out that my bag was out of range. For fifteen minutes, I waited at the baggage carousel like an ordinary plebe, trapped in a seemingly endless purgatory, mired in deep existential uncertainty.
\nEven walking across my house prompted a notification from my phone, alerting me that the suitcase—safely in my office—was no longer within range. If you want a smart luggage tracker, it should probably use GPS instead of Bluetooth.
\n\nBeautiful. Durable. Hubless wheels roll smoothly and easily and are easily replaceable. Battery bank will save you in a pinch. Comes with rain cover.
\n\t\tBluetooth tracker makes no sense. No side handle. Battery life was disappointing.
\n\t\tBut as a piece of ordinary luggage, the bag performed admirably. It has a simple, durable makrolon polycarbonate shell that showed little wear after a few trips around the baggage carousel. The navy color of my sample case was elegant and surprisingly distinctive among a billion black bags. The interior, with mesh zip pockets and an included laundry bag, easily accommodated several days’ worth of clothes and shoes.
\nThe bag was impossible to tip over, even with a tote bag hooked on top. The hubless wheels rolled smoothly‚Äîalmost a little too smoothly, as the suitcase escaped me when my attention wandered on a slanting parking lot garage floor‚Äîand it‚Äôs simple to pop the wheels on and off if you need to fit the suitcase into an overhead compartment. This model also carries a lifetime warranty from Incase, so the wheels are covered if they break (the power bank’s embedded battery has a two-year limited warranty).
\nThe integrated TSA-approved lock works like you’d expect, and it proved useful when I ended up checking my carry-on to save overhead space on two packed flights. However, I would have appreciated a side handle to make it easier to hoist around.
\nAs holiday travel season approaches, you do have to find a way to get all your stuff from Point A to Point B without carrying it all in your arms. Incase is known for their attractive, Apple-compatible accessories and bags, and the NoviConnected is no exception. It’s elegant, rolls with ease, and has the capacity to save your tuchus right when you need it most—when your phone is about to die and you have no way to text your ride or check your car rental confirmation number.
\nBut there are just too many other moderately-priced smart carry-ons out there right now with features that make a bit more sense, like a true GPS locator that can tell you if your baggage has made it to your destination. Or just bring your own spare battery and pop a Tile tracker into your current luggage and call it a day.
\n" 395 | }, 396 | "excerpt": { 397 | "rendered": "A great piece of luggage is brought down by its poor smart features.
\n" 398 | }, 399 | "author": 609, 400 | "featured_media": 2267773, 401 | "comment_status": "open", 402 | "ping_status": "closed", 403 | "sticky": false, 404 | "format": "standard", 405 | "categories": [ 406 | 36, 407 | 83082, 408 | 4 409 | ], 410 | "tags": [ 411 | 106059, 412 | 106060 413 | ], 414 | "series": [], 415 | "admin-settings": [], 416 | "_links": { 417 | "self": [ 418 | { 419 | "href": "https://www.wired.com/wp-json/wp/v2/posts/2267743" 420 | } 421 | ], 422 | "collection": [ 423 | { 424 | "href": "https://www.wired.com/wp-json/wp/v2/posts" 425 | } 426 | ], 427 | "about": [ 428 | { 429 | "href": "https://www.wired.com/wp-json/wp/v2/types/post" 430 | } 431 | ], 432 | "author": [ 433 | { 434 | "embeddable": true, 435 | "href": "https://www.wired.com/wp-json/wp/v2/users/609" 436 | } 437 | ], 438 | "replies": [ 439 | { 440 | "embeddable": true, 441 | "href": "https://www.wired.com/wp-json/wp/v2/comments?post=2267743" 442 | } 443 | ], 444 | "version-history": [ 445 | { 446 | "href": "https://www.wired.com/wp-json/wp/v2/posts/2267743/revisions" 447 | } 448 | ], 449 | "wp:featuredmedia": [ 450 | { 451 | "embeddable": true, 452 | "href": "https://www.wired.com/wp-json/wp/v2/media/2267773" 453 | } 454 | ], 455 | "wp:attachment": [ 456 | { 457 | "href": "https://www.wired.com/wp-json/wp/v2/media?parent=2267743" 458 | } 459 | ], 460 | "wp:term": [ 461 | { 462 | "taxonomy": "category", 463 | "embeddable": true, 464 | "href": "https://www.wired.com/wp-json/wp/v2/categories?post=2267743" 465 | }, 466 | { 467 | "taxonomy": "post_tag", 468 | "embeddable": true, 469 | "href": "https://www.wired.com/wp-json/wp/v2/tags?post=2267743" 470 | }, 471 | { 472 | "taxonomy": "series", 473 | "embeddable": true, 474 | "href": "https://www.wired.com/wp-json/wp/v2/series?post=2267743" 475 | }, 476 | { 477 | "taxonomy": "admin-settings", 478 | "embeddable": true, 479 | "href": "https://www.wired.com/wp-json/wp/v2/admin-settings?post=2267743" 480 | } 481 | ], 482 | "curies": [ 483 | { 484 | "name": "wp", 485 | "href": "https://api.w.org/{rel}", 486 | "templated": true 487 | } 488 | ] 489 | }, 490 | "_embedded": { 491 | "author": [ 492 | { 493 | "id": 609, 494 | "name": "Adrienne So", 495 | "url": "", 496 | "description": "", 497 | "link": "https://www.wired.com/author/adrienne-so/", 498 | "slug": "adrienne-so", 499 | "avatar_urls": { 500 | "24": "https://secure.gravatar.com/avatar/7c93ee8a4e06687ba5bf692dedc794b6?s=24&d=mm&r=g", 501 | "48": "https://secure.gravatar.com/avatar/7c93ee8a4e06687ba5bf692dedc794b6?s=48&d=mm&r=g", 502 | "96": "https://secure.gravatar.com/avatar/7c93ee8a4e06687ba5bf692dedc794b6?s=96&d=mm&r=g" 503 | }, 504 | "_links": { 505 | "self": [ 506 | { 507 | "href": "https://www.wired.com/wp-json/wp/v2/users/609" 508 | } 509 | ], 510 | "collection": [ 511 | { 512 | "href": "https://www.wired.com/wp-json/wp/v2/users" 513 | } 514 | ] 515 | } 516 | } 517 | ], 518 | "wp:featuredmedia": [ 519 | { 520 | "id": 2267773, 521 | "date": "2017-11-10T16:10:13", 522 | "slug": "incase-fa", 523 | "type": "attachment", 524 | "link": "https://www.wired.com/2017/11/review-incase-noviconnected-travel-roller/incase-fa/", 525 | "title": { 526 | "rendered": "incase-FA.jpg" 527 | }, 528 | "author": 10393, 529 | "alt_text": "", 530 | "media_type": "image", 531 | "mime_type": "image/jpeg", 532 | "media_details": { 533 | "width": 2236, 534 | "height": 1119, 535 | "file": "2017/11/incase-FA.jpg", 536 | "sizes": { 537 | "thumbnail": { 538 | "file": "incase-FA-150x150-e1510348383201.jpg", 539 | "width": 150, 540 | "height": 150, 541 | "mime_type": "image/jpeg", 542 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-150x150-e1510348383201.jpg" 543 | }, 544 | "medium": { 545 | "file": "incase-FA-300x150.jpg", 546 | "width": 300, 547 | "height": 150, 548 | "mime_type": "image/jpeg", 549 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-300x150.jpg" 550 | }, 551 | "medium_large": { 552 | "file": "incase-FA-768x384.jpg", 553 | "width": 768, 554 | "height": 384, 555 | "mime_type": "image/jpeg", 556 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-768x384.jpg" 557 | }, 558 | "large": { 559 | "file": "incase-FA-1024x512.jpg", 560 | "width": 1024, 561 | "height": 512, 562 | "mime_type": "image/jpeg", 563 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-1024x512.jpg" 564 | }, 565 | "200-100-thumbnail": { 566 | "file": "incase-FA-200x100-e1510348370909.jpg", 567 | "width": 200, 568 | "height": 100, 569 | "mime_type": "image/jpeg", 570 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-200x100-e1510348370909.jpg" 571 | }, 572 | "200-200-thumbnail": { 573 | "file": "incase-FA-200x200-e1510348352675.jpg", 574 | "width": 200, 575 | "height": 200, 576 | "mime_type": "image/jpeg", 577 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-200x200-e1510348352675.jpg" 578 | }, 579 | "500-500-thumbnail": { 580 | "file": "incase-FA-500x500-e1510348327817.jpg", 581 | "width": 500, 582 | "height": 500, 583 | "mime_type": "image/jpeg", 584 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-500x500-e1510348327817.jpg" 585 | }, 586 | "660-single-full": { 587 | "file": "incase-FA-660x330.jpg", 588 | "width": 660, 589 | "height": 330, 590 | "mime_type": "image/jpeg", 591 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-660x330.jpg" 592 | }, 593 | "315-single-full": { 594 | "file": "incase-FA-315x158.jpg", 595 | "width": 315, 596 | "height": 158, 597 | "mime_type": "image/jpeg", 598 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-315x158.jpg" 599 | }, 600 | "thumbnail-post": { 601 | "file": "incase-FA-300x150-e1510348340197.jpg", 602 | "width": 300, 603 | "height": 150, 604 | "mime_type": "image/jpeg", 605 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-300x150-e1510348340197.jpg" 606 | }, 607 | "600-338-full": { 608 | "file": "incase-FA-600x338-e1510348316142.jpg", 609 | "width": 600, 610 | "height": 338, 611 | "mime_type": "image/jpeg", 612 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-600x338-e1510348316142.jpg" 613 | }, 614 | "600-450-full": { 615 | "file": "incase-FA-600x450-e1510348304347.jpg", 616 | "width": 600, 617 | "height": 450, 618 | "mime_type": "image/jpeg", 619 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-600x450-e1510348304347.jpg" 620 | }, 621 | "929-697-full": { 622 | "file": "incase-FA-929x697-e1510348296219.jpg", 623 | "width": 929, 624 | "height": 697, 625 | "mime_type": "image/jpeg", 626 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-929x697-e1510348296219.jpg" 627 | }, 628 | "125-94-thumbnail": { 629 | "file": "incase-FA-125x94-e1510348402271.jpg", 630 | "width": 125, 631 | "height": 94, 632 | "mime_type": "image/jpeg", 633 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-125x94-e1510348402271.jpg" 634 | }, 635 | "929-523-full": { 636 | "file": "incase-FA-929x523-e1510348287351.jpg", 637 | "width": 929, 638 | "height": 523, 639 | "mime_type": "image/jpeg", 640 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-929x523-e1510348287351.jpg" 641 | }, 642 | "default-top-art": { 643 | "file": "incase-FA-582x291.jpg", 644 | "width": 582, 645 | "height": 291, 646 | "mime_type": "image/jpeg", 647 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-582x291.jpg" 648 | }, 649 | "wide-image": { 650 | "file": "incase-FA-932x466.jpg", 651 | "width": 932, 652 | "height": 466, 653 | "mime_type": "image/jpeg", 654 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-932x466.jpg" 655 | }, 656 | "inset-image": { 657 | "file": "incase-FA-289x145.jpg", 658 | "width": 289, 659 | "height": 145, 660 | "mime_type": "image/jpeg", 661 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-289x145.jpg" 662 | }, 663 | "text-column-width": { 664 | "file": "incase-FA-482x241.jpg", 665 | "width": 482, 666 | "height": 241, 667 | "mime_type": "image/jpeg", 668 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-482x241.jpg" 669 | }, 670 | "facebook-og": { 671 | "file": "incase-FA-1200x630-e1510348277739.jpg", 672 | "width": 1200, 673 | "height": 630, 674 | "mime_type": "image/jpeg", 675 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA-1200x630-e1510348277739.jpg" 676 | }, 677 | "full": { 678 | "file": "incase-FA.jpg", 679 | "width": 2236, 680 | "height": 1119, 681 | "mime_type": "image/jpeg", 682 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA.jpg" 683 | } 684 | }, 685 | "image_meta": { 686 | "aperture": "0", 687 | "credit": "", 688 | "camera": "", 689 | "caption": "", 690 | "created_timestamp": "0", 691 | "copyright": "", 692 | "focal_length": "0", 693 | "iso": "0", 694 | "shutter_speed": "0", 695 | "title": "", 696 | "orientation": "0", 697 | "keywords": [] 698 | } 699 | }, 700 | "source_url": "https://www.wired.com/wp-content/uploads/2017/11/incase-FA.jpg", 701 | "_links": { 702 | "self": [ 703 | { 704 | "href": "https://www.wired.com/wp-json/wp/v2/media/2267773" 705 | } 706 | ], 707 | "collection": [ 708 | { 709 | "href": "https://www.wired.com/wp-json/wp/v2/media" 710 | } 711 | ], 712 | "about": [ 713 | { 714 | "href": "https://www.wired.com/wp-json/wp/v2/types/attachment" 715 | } 716 | ], 717 | "author": [ 718 | { 719 | "embeddable": true, 720 | "href": "https://www.wired.com/wp-json/wp/v2/users/10393" 721 | } 722 | ], 723 | "replies": [ 724 | { 725 | "embeddable": true, 726 | "href": "https://www.wired.com/wp-json/wp/v2/comments?post=2267773" 727 | } 728 | ] 729 | } 730 | } 731 | ], 732 | "wp:term": [ 733 | [ 734 | { 735 | "id": 36, 736 | "link": "https://www.wired.com/category/gear/reviews/accessories/", 737 | "name": "Accessories", 738 | "slug": "accessories", 739 | "taxonomy": "category", 740 | "_links": { 741 | "self": [ 742 | { 743 | "href": "https://www.wired.com/wp-json/wp/v2/categories/36" 744 | } 745 | ], 746 | "collection": [ 747 | { 748 | "href": "https://www.wired.com/wp-json/wp/v2/categories" 749 | } 750 | ], 751 | "about": [ 752 | { 753 | "href": "https://www.wired.com/wp-json/wp/v2/taxonomies/category" 754 | } 755 | ], 756 | "up": [ 757 | { 758 | "embeddable": true, 759 | "href": "https://www.wired.com/wp-json/wp/v2/categories/4" 760 | } 761 | ], 762 | "wp:post_type": [ 763 | { 764 | "href": "https://www.wired.com/wp-json/wp/v2/posts?categories=36" 765 | }, 766 | { 767 | "href": "https://www.wired.com/wp-json/wp/v2/video?categories=36" 768 | } 769 | ], 770 | "curies": [ 771 | { 772 | "name": "wp", 773 | "href": "https://api.w.org/{rel}", 774 | "templated": true 775 | } 776 | ] 777 | } 778 | }, 779 | { 780 | "id": 83082, 781 | "link": "https://www.wired.com/category/gear/", 782 | "name": "Gear", 783 | "slug": "gear", 784 | "taxonomy": "category", 785 | "_links": { 786 | "self": [ 787 | { 788 | "href": "https://www.wired.com/wp-json/wp/v2/categories/83082" 789 | } 790 | ], 791 | "collection": [ 792 | { 793 | "href": "https://www.wired.com/wp-json/wp/v2/categories" 794 | } 795 | ], 796 | "about": [ 797 | { 798 | "href": "https://www.wired.com/wp-json/wp/v2/taxonomies/category" 799 | } 800 | ], 801 | "wp:post_type": [ 802 | { 803 | "href": "https://www.wired.com/wp-json/wp/v2/posts?categories=83082" 804 | }, 805 | { 806 | "href": "https://www.wired.com/wp-json/wp/v2/video?categories=83082" 807 | } 808 | ], 809 | "curies": [ 810 | { 811 | "name": "wp", 812 | "href": "https://api.w.org/{rel}", 813 | "templated": true 814 | } 815 | ] 816 | } 817 | }, 818 | { 819 | "id": 4, 820 | "link": "https://www.wired.com/category/gear/reviews/", 821 | "name": "Reviews", 822 | "slug": "reviews", 823 | "taxonomy": "category", 824 | "_links": { 825 | "self": [ 826 | { 827 | "href": "https://www.wired.com/wp-json/wp/v2/categories/4" 828 | } 829 | ], 830 | "collection": [ 831 | { 832 | "href": "https://www.wired.com/wp-json/wp/v2/categories" 833 | } 834 | ], 835 | "about": [ 836 | { 837 | "href": "https://www.wired.com/wp-json/wp/v2/taxonomies/category" 838 | } 839 | ], 840 | "up": [ 841 | { 842 | "embeddable": true, 843 | "href": "https://www.wired.com/wp-json/wp/v2/categories/83082" 844 | } 845 | ], 846 | "wp:post_type": [ 847 | { 848 | "href": "https://www.wired.com/wp-json/wp/v2/posts?categories=4" 849 | }, 850 | { 851 | "href": "https://www.wired.com/wp-json/wp/v2/video?categories=4" 852 | } 853 | ], 854 | "curies": [ 855 | { 856 | "name": "wp", 857 | "href": "https://api.w.org/{rel}", 858 | "templated": true 859 | } 860 | ] 861 | } 862 | } 863 | ], 864 | [ 865 | { 866 | "id": 106059, 867 | "link": "https://www.wired.com/tag/incase/", 868 | "name": "incase", 869 | "slug": "incase", 870 | "taxonomy": "post_tag", 871 | "_links": { 872 | "self": [ 873 | { 874 | "href": "https://www.wired.com/wp-json/wp/v2/tags/106059" 875 | } 876 | ], 877 | "collection": [ 878 | { 879 | "href": "https://www.wired.com/wp-json/wp/v2/tags" 880 | } 881 | ], 882 | "about": [ 883 | { 884 | "href": "https://www.wired.com/wp-json/wp/v2/taxonomies/post_tag" 885 | } 886 | ], 887 | "wp:post_type": [ 888 | { 889 | "href": "https://www.wired.com/wp-json/wp/v2/posts?tags=106059" 890 | }, 891 | { 892 | "href": "https://www.wired.com/wp-json/wp/v2/podcast?tags=106059" 893 | }, 894 | { 895 | "href": "https://www.wired.com/wp-json/wp/v2/video?tags=106059" 896 | } 897 | ], 898 | "curies": [ 899 | { 900 | "name": "wp", 901 | "href": "https://api.w.org/{rel}", 902 | "templated": true 903 | } 904 | ] 905 | } 906 | }, 907 | { 908 | "id": 106060, 909 | "link": "https://www.wired.com/tag/luggage/", 910 | "name": "luggage", 911 | "slug": "luggage", 912 | "taxonomy": "post_tag", 913 | "_links": { 914 | "self": [ 915 | { 916 | "href": "https://www.wired.com/wp-json/wp/v2/tags/106060" 917 | } 918 | ], 919 | "collection": [ 920 | { 921 | "href": "https://www.wired.com/wp-json/wp/v2/tags" 922 | } 923 | ], 924 | "about": [ 925 | { 926 | "href": "https://www.wired.com/wp-json/wp/v2/taxonomies/post_tag" 927 | } 928 | ], 929 | "wp:post_type": [ 930 | { 931 | "href": "https://www.wired.com/wp-json/wp/v2/posts?tags=106060" 932 | }, 933 | { 934 | "href": "https://www.wired.com/wp-json/wp/v2/podcast?tags=106060" 935 | }, 936 | { 937 | "href": "https://www.wired.com/wp-json/wp/v2/video?tags=106060" 938 | } 939 | ], 940 | "curies": [ 941 | { 942 | "name": "wp", 943 | "href": "https://api.w.org/{rel}", 944 | "templated": true 945 | } 946 | ] 947 | } 948 | } 949 | ], 950 | [], 951 | [] 952 | ] 953 | } 954 | } 955 | ``` 956 | 957 | Notice that there is now an `_embed` section with the actual data for authors, categories, and tags. 958 | Later in the workshop, we will leverage this data to display our pages. 959 | 960 | In order to simplify things further, we will be using an NPM package called 961 | [wpapi](https://github.com/wp-api/node-wpapi). This package will allow us to call WordPress API 962 | endpoints through a set of simple functions. Let's install the package: 963 | 964 | ```sh 965 | yarn add wpapi 966 | ``` 967 | 968 | Then, create a file called `api.js` at the root of your project with the following code: 969 | 970 | ```js 971 | import WPAPI from 'wpapi'; 972 | 973 | let endpoint = 'https://www.wired.com/wp-json'; 974 | if (typeof window !== 'undefined') { 975 | endpoint = `https://cors-anywhere.herokuapp.com/${endpoint}`; 976 | } 977 | 978 | const api = new WPAPI({ endpoint }); 979 | export default api; 980 | ``` 981 | 982 | The `wpapi` package exposes a `WPAPI` constructor taking a base URL as parameter. In this case, we 983 | will be using the wired.com API as explained in the introduction. However, remember that this code 984 | will be running in the server *and* in the browser. If our browser tries to make an HTTP request to 985 | wired.com's WordPress API from a different origin – localhost:3000 – our browser will refuse to let 986 | us see the response due to cross-origin security rules. “Cors Anywhere” is a freely available proxy 987 | server that can take care of this by making the request on our behalf and adding the appropriate 988 | [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) headers to make our browser comply. 989 | Explaining CORS is beyond the scope of this workshop, but feel free to follow the links to learn 990 | more. The **TL;DR** is that the server will be using the straight URL, and the browser will go 991 | through a proxy server. 992 | 993 | :warning: **NOTE**: Ideally, we will have as little of this kind of “if server / if client” code in 994 | our application. Next.js should be able to deal with it for us in most cases. 995 | 996 | Once this file is created, let's use it in our `pages/blog.js` file. Overwrite the file with the 997 | following content: 998 | 999 | ```js 1000 | import React from 'react'; 1001 | import Link from 'next/link'; 1002 | import api from '../api'; 1003 | 1004 | class Blog extends React.Component { 1005 | static async getInitialProps() { 1006 | const posts = await api.posts().embed(); 1007 | return { posts }; 1008 | } 1009 | 1010 | render() { 1011 | const { posts } = this.props; 1012 | 1013 | return ( 1014 |{post.date}
1032 | { 1033 | !!post._embedded['wp:featuredmedia'] && 1034 |
1074 |
1075 |
{post.date}
1101 |By {post._embedded.author[0].name}
1102 | { 1103 | !!post._embedded['wp:featuredmedia'] && 1104 |
1129 |
1130 |
1256 |
1257 |
1336 |
1337 |
1434 |
1435 |
1475 |
1476 |
loading...
} 1550 | ``` 1551 | 1552 | 6. Finally, add the `loadMore` method as an instance method of the class: 1553 | 1554 | ```js 1555 | loadMore = async () => { 1556 | if (this.state.loading || !this.state.hasMore) { 1557 | return; 1558 | } 1559 | 1560 | this.setState({ loading: true}); 1561 | const posts = await api.posts().perPage(PER_PAGE).page(this.state.page + 1).embed(); 1562 | if (posts.length > 0) { 1563 | this.setState({ 1564 | posts: this.state.posts.concat(posts), 1565 | page: this.state.page + 1 1566 | }); 1567 | } 1568 | else { 1569 | this.setState({ hasMore: false }); 1570 | } 1571 | this.setState({ 1572 | loading: false 1573 | }); 1574 | } 1575 | ``` 1576 | 1577 | This function will be called by react-waypoint when the bottom of the page is reached. The logic is 1578 | quite straightforward: we load the next page of posts, and concat the result to the end of the posts 1579 | array in our state. If there are no more posts, setting `hasMore` to `false` will completely remove 1580 | the `
1593 |
1594 |
1613 |
1614 |