├── .eslintrc.json ├── .gitignore ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── customtypes └── page │ ├── index.json │ └── mocks.json ├── next.config.mjs ├── package-lock.json ├── package.json ├── postcss.config.js ├── prismicio-types.d.ts ├── public ├── Soda-can.bin ├── Soda-can.gltf ├── fonts │ ├── Alpino-Variable.woff │ └── Alpino-Variable.woff2 ├── hdr │ ├── field.hdr │ └── lobby.hdr └── labels │ ├── cherry.png │ ├── grape.png │ ├── lemon-lime.png │ ├── strawberry.png │ └── watermelon.png ├── set-up-content.ts ├── slicemachine.config.json ├── src ├── app │ ├── [uid] │ │ └── page.tsx │ ├── api │ │ ├── exit-preview │ │ │ └── route.ts │ │ ├── preview │ │ │ └── route.ts │ │ └── revalidate │ │ │ └── route.ts │ ├── app.css │ ├── icon.svg │ ├── layout.tsx │ ├── page.tsx │ └── slice-simulator │ │ └── page.tsx ├── components │ ├── Bounded.tsx │ ├── Button.tsx │ ├── CircleText.tsx │ ├── FizziLogo.tsx │ ├── FloatingCan.tsx │ ├── Footer.tsx │ ├── Header.tsx │ ├── SodaCan.tsx │ ├── TextSplitter.tsx │ └── ViewCanvas.tsx ├── hooks │ ├── useMediaQuery.ts │ └── useStore.ts ├── prismicio.ts └── slices │ ├── AlternatingText │ ├── Scene.tsx │ ├── index.tsx │ ├── mocks.json │ ├── model.json │ └── screenshot-default.png │ ├── BigText │ ├── index.tsx │ ├── mocks.json │ ├── model.json │ └── screenshot-default.png │ ├── Carousel │ ├── ArrowIcon.tsx │ ├── WavyCircles.tsx │ ├── index.tsx │ ├── mocks.json │ ├── model.json │ └── screenshot-default.png │ ├── Hero │ ├── Bubbles.tsx │ ├── Scene.tsx │ ├── index.tsx │ ├── mocks.json │ ├── model.json │ └── screenshot-default.png │ ├── SkyDive │ ├── Scene.tsx │ ├── index.tsx │ ├── mocks.json │ ├── model.json │ └── screenshot-default.png │ └── index.ts ├── tailwind.config.js └── tsconfig.json /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .slicemachine 2 | .next -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["prettier-plugin-tailwindcss"] 3 | } 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Fizzi Website - Final code 2 | 3 | This is the final code for the YouTube tutorial course where we build a 3D animated e-commerce landing page for the fictional soda brand, Fizzi! 4 | 5 | For more information and to watch the course go to the [course documentation](https://dub.sh/fizzi). 6 | 7 | ## Skip the tutorial and launch the site 8 | 9 | If you don’t want to go through the tutorial, but want your own version of the website deployed on Prismic, follow these directions: 10 | 11 | 1. Clone the code: 12 | 13 | ```tsx 14 | npx @slicemachine/init@latest --starter course-fizzi-next 15 | ``` 16 | 17 | 2. Open the Prismic repository and select “English - United States”. 18 | 3. Run the content set up script: 19 | 20 | ```tsx 21 | npm run set-up-content 22 | ``` 23 | 24 | 4. Open the migration release and publish it. A URL will be printed on the screen. 25 | 5. Set up the slice simulator URL: `http://localhost:3000/slice-simulator` 26 | -------------------------------------------------------------------------------- /customtypes/page/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "page", 3 | "label": "Page", 4 | "format": "page", 5 | "repeatable": true, 6 | "status": true, 7 | "json": { 8 | "Main": { 9 | "uid": { 10 | "type": "UID", 11 | "config": { 12 | "label": "UID", 13 | "placeholder": "" 14 | } 15 | }, 16 | "title": { 17 | "type": "StructuredText", 18 | "config": { 19 | "label": "Title", 20 | "placeholder": "", 21 | "allowTargetBlank": true, 22 | "single": "heading1" 23 | } 24 | }, 25 | "slices": { 26 | "type": "Slices", 27 | "fieldset": "Slice Zone", 28 | "config": { 29 | "choices": { 30 | "big_text": { 31 | "type": "SharedSlice" 32 | }, 33 | "alternating_text": { 34 | "type": "SharedSlice" 35 | }, 36 | "carousel": { 37 | "type": "SharedSlice" 38 | }, 39 | "sky_dive": { 40 | "type": "SharedSlice" 41 | }, 42 | "hero": { 43 | "type": "SharedSlice" 44 | } 45 | } 46 | } 47 | } 48 | }, 49 | "SEO & Metadata": { 50 | "meta_title": { 51 | "type": "Text", 52 | "config": { 53 | "label": "Meta Title", 54 | "placeholder": "A title of the page used for social media and search engines" 55 | } 56 | }, 57 | "meta_description": { 58 | "type": "Text", 59 | "config": { 60 | "label": "Meta Description", 61 | "placeholder": "A brief summary of the page" 62 | } 63 | }, 64 | "meta_image": { 65 | "type": "Image", 66 | "config": { 67 | "label": "Meta Image", 68 | "constraint": { 69 | "width": 2400, 70 | "height": 1260 71 | }, 72 | "thumbnails": [] 73 | } 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /customtypes/page/mocks.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "uid": { 4 | "__TYPE__": "UIDContent", 5 | "value": "congress" 6 | }, 7 | "title": { 8 | "__TYPE__": "StructuredTextContent", 9 | "value": [ 10 | { 11 | "type": "heading1", 12 | "content": { 13 | "text": "Medicine" 14 | } 15 | } 16 | ] 17 | }, 18 | "slices": { 19 | "__TYPE__": "SliceContentType", 20 | "value": [ 21 | { 22 | "key": "rich_text$3e97d0df-9e9e-40c8-83ff-346f91aba429", 23 | "name": "rich_text", 24 | "widget": { 25 | "__TYPE__": "SharedSliceContent", 26 | "variation": "default", 27 | "primary": { 28 | "content": { 29 | "__TYPE__": "StructuredTextContent", 30 | "value": [ 31 | { 32 | "type": "paragraph", 33 | "content": { 34 | "text": "Aliquip veniam sit excepteur excepteur ut laborum exercitation duis incididunt." 35 | } 36 | } 37 | ] 38 | } 39 | }, 40 | "items": [ 41 | { 42 | "__TYPE__": "GroupItemContent", 43 | "value": [] 44 | } 45 | ] 46 | } 47 | } 48 | ] 49 | } 50 | } 51 | ] 52 | -------------------------------------------------------------------------------- /next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {}; 3 | 4 | export default nextConfig; 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fizzi", 3 | "version": "0.1.0", 4 | "private": true, 5 | "license": "Apache-2.0", 6 | "author": "Prismic (https://prismic.io)", 7 | "scripts": { 8 | "dev": "concurrently \"npm:next:dev\" \"npm:slicemachine\" --names \"next,slicemachine\" --prefix-colors blue,magenta", 9 | "next:dev": "next dev", 10 | "build": "next build", 11 | "start": "next start", 12 | "lint": "next lint", 13 | "slicemachine": "start-slicemachine", 14 | "format": "prettier --write .", 15 | "set-up-content": "npx tsx@latest set-up-content" 16 | }, 17 | "dependencies": { 18 | "@gsap/react": "^2.1.1", 19 | "@prismicio/client": "^7.11.0", 20 | "@prismicio/next": "^1.6.0", 21 | "@prismicio/react": "^2.8.0", 22 | "@react-three/drei": "^9.111.3", 23 | "@react-three/fiber": "^8.17.6", 24 | "@types/three": "^0.167.2", 25 | "clsx": "^2.1.1", 26 | "gsap": "^3.12.5", 27 | "next": "^14.2.4", 28 | "react": "^18.3.1", 29 | "react-dom": "^18.3.1", 30 | "three": "^0.167.1", 31 | "zustand": "^4.5.5" 32 | }, 33 | "devDependencies": { 34 | "@slicemachine/adapter-next": "^0.3.46", 35 | "@types/node": "^20.14.2", 36 | "@types/react": "^18.3.3", 37 | "@types/react-dom": "^18.3.0", 38 | "autoprefixer": "^10.4.20", 39 | "concurrently": "^8.2.2", 40 | "eslint": "^8.57.0", 41 | "eslint-config-next": "^14.2.4", 42 | "postcss": "^8.4.41", 43 | "prettier": "^3.3.3", 44 | "prettier-plugin-tailwindcss": "^0.6.6", 45 | "r3f-perf": "^7.2.1", 46 | "slice-machine-ui": "^2.5.0", 47 | "tailwindcss": "^3.4.10", 48 | "typescript": "^5.4.5" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /prismicio-types.d.ts: -------------------------------------------------------------------------------- 1 | // Code generated by Slice Machine. DO NOT EDIT. 2 | 3 | import type * as prismic from "@prismicio/client"; 4 | 5 | type Simplify = { [KeyType in keyof T]: T[KeyType] }; 6 | 7 | type PageDocumentDataSlicesSlice = 8 | | BigTextSlice 9 | | AlternatingTextSlice 10 | | CarouselSlice 11 | | SkyDiveSlice 12 | | HeroSlice; 13 | 14 | /** 15 | * Content for Page documents 16 | */ 17 | interface PageDocumentData { 18 | /** 19 | * Title field in *Page* 20 | * 21 | * - **Field Type**: Title 22 | * - **Placeholder**: *None* 23 | * - **API ID Path**: page.title 24 | * - **Tab**: Main 25 | * - **Documentation**: https://prismic.io/docs/field#rich-text-title 26 | */ 27 | title: prismic.TitleField; 28 | 29 | /** 30 | * Slice Zone field in *Page* 31 | * 32 | * - **Field Type**: Slice Zone 33 | * - **Placeholder**: *None* 34 | * - **API ID Path**: page.slices[] 35 | * - **Tab**: Main 36 | * - **Documentation**: https://prismic.io/docs/field#slices 37 | */ 38 | slices: prismic.SliceZone /** 39 | * Meta Title field in *Page* 40 | * 41 | * - **Field Type**: Text 42 | * - **Placeholder**: A title of the page used for social media and search engines 43 | * - **API ID Path**: page.meta_title 44 | * - **Tab**: SEO & Metadata 45 | * - **Documentation**: https://prismic.io/docs/field#key-text 46 | */; 47 | meta_title: prismic.KeyTextField; 48 | 49 | /** 50 | * Meta Description field in *Page* 51 | * 52 | * - **Field Type**: Text 53 | * - **Placeholder**: A brief summary of the page 54 | * - **API ID Path**: page.meta_description 55 | * - **Tab**: SEO & Metadata 56 | * - **Documentation**: https://prismic.io/docs/field#key-text 57 | */ 58 | meta_description: prismic.KeyTextField; 59 | 60 | /** 61 | * Meta Image field in *Page* 62 | * 63 | * - **Field Type**: Image 64 | * - **Placeholder**: *None* 65 | * - **API ID Path**: page.meta_image 66 | * - **Tab**: SEO & Metadata 67 | * - **Documentation**: https://prismic.io/docs/field#image 68 | */ 69 | meta_image: prismic.ImageField; 70 | } 71 | 72 | /** 73 | * Page document from Prismic 74 | * 75 | * - **API ID**: `page` 76 | * - **Repeatable**: `true` 77 | * - **Documentation**: https://prismic.io/docs/custom-types 78 | * 79 | * @typeParam Lang - Language API ID of the document. 80 | */ 81 | export type PageDocument = 82 | prismic.PrismicDocumentWithUID, "page", Lang>; 83 | 84 | export type AllDocumentTypes = PageDocument; 85 | 86 | /** 87 | * Item in *AlternatingText → Default → Primary → Text Group* 88 | */ 89 | export interface AlternatingTextSliceDefaultPrimaryTextGroupItem { 90 | /** 91 | * Heading field in *AlternatingText → Default → Primary → Text Group* 92 | * 93 | * - **Field Type**: Title 94 | * - **Placeholder**: *None* 95 | * - **API ID Path**: alternating_text.default.primary.text_group[].heading 96 | * - **Documentation**: https://prismic.io/docs/field#rich-text-title 97 | */ 98 | heading: prismic.TitleField; 99 | 100 | /** 101 | * Body field in *AlternatingText → Default → Primary → Text Group* 102 | * 103 | * - **Field Type**: Rich Text 104 | * - **Placeholder**: *None* 105 | * - **API ID Path**: alternating_text.default.primary.text_group[].body 106 | * - **Documentation**: https://prismic.io/docs/field#rich-text-title 107 | */ 108 | body: prismic.RichTextField; 109 | } 110 | 111 | /** 112 | * Primary content in *AlternatingText → Default → Primary* 113 | */ 114 | export interface AlternatingTextSliceDefaultPrimary { 115 | /** 116 | * Text Group field in *AlternatingText → Default → Primary* 117 | * 118 | * - **Field Type**: Group 119 | * - **Placeholder**: *None* 120 | * - **API ID Path**: alternating_text.default.primary.text_group[] 121 | * - **Documentation**: https://prismic.io/docs/field#group 122 | */ 123 | text_group: prismic.GroupField< 124 | Simplify 125 | >; 126 | } 127 | 128 | /** 129 | * Default variation for AlternatingText Slice 130 | * 131 | * - **API ID**: `default` 132 | * - **Description**: Default 133 | * - **Documentation**: https://prismic.io/docs/slice 134 | */ 135 | export type AlternatingTextSliceDefault = prismic.SharedSliceVariation< 136 | "default", 137 | Simplify, 138 | never 139 | >; 140 | 141 | /** 142 | * Slice variation for *AlternatingText* 143 | */ 144 | type AlternatingTextSliceVariation = AlternatingTextSliceDefault; 145 | 146 | /** 147 | * AlternatingText Shared Slice 148 | * 149 | * - **API ID**: `alternating_text` 150 | * - **Description**: AlternatingText 151 | * - **Documentation**: https://prismic.io/docs/slice 152 | */ 153 | export type AlternatingTextSlice = prismic.SharedSlice< 154 | "alternating_text", 155 | AlternatingTextSliceVariation 156 | >; 157 | 158 | /** 159 | * Default variation for BigText Slice 160 | * 161 | * - **API ID**: `default` 162 | * - **Description**: Default 163 | * - **Documentation**: https://prismic.io/docs/slice 164 | */ 165 | export type BigTextSliceDefault = prismic.SharedSliceVariation< 166 | "default", 167 | Record, 168 | never 169 | >; 170 | 171 | /** 172 | * Slice variation for *BigText* 173 | */ 174 | type BigTextSliceVariation = BigTextSliceDefault; 175 | 176 | /** 177 | * BigText Shared Slice 178 | * 179 | * - **API ID**: `big_text` 180 | * - **Description**: BigText 181 | * - **Documentation**: https://prismic.io/docs/slice 182 | */ 183 | export type BigTextSlice = prismic.SharedSlice< 184 | "big_text", 185 | BigTextSliceVariation 186 | >; 187 | 188 | /** 189 | * Primary content in *Carousel → Default → Primary* 190 | */ 191 | export interface CarouselSliceDefaultPrimary { 192 | /** 193 | * Heading field in *Carousel → Default → Primary* 194 | * 195 | * - **Field Type**: Title 196 | * - **Placeholder**: *None* 197 | * - **API ID Path**: carousel.default.primary.heading 198 | * - **Documentation**: https://prismic.io/docs/field#rich-text-title 199 | */ 200 | heading: prismic.TitleField; 201 | 202 | /** 203 | * Price Copy field in *Carousel → Default → Primary* 204 | * 205 | * - **Field Type**: Rich Text 206 | * - **Placeholder**: *None* 207 | * - **API ID Path**: carousel.default.primary.price_copy 208 | * - **Documentation**: https://prismic.io/docs/field#rich-text-title 209 | */ 210 | price_copy: prismic.RichTextField; 211 | } 212 | 213 | /** 214 | * Default variation for Carousel Slice 215 | * 216 | * - **API ID**: `default` 217 | * - **Description**: Default 218 | * - **Documentation**: https://prismic.io/docs/slice 219 | */ 220 | export type CarouselSliceDefault = prismic.SharedSliceVariation< 221 | "default", 222 | Simplify, 223 | never 224 | >; 225 | 226 | /** 227 | * Slice variation for *Carousel* 228 | */ 229 | type CarouselSliceVariation = CarouselSliceDefault; 230 | 231 | /** 232 | * Carousel Shared Slice 233 | * 234 | * - **API ID**: `carousel` 235 | * - **Description**: Carousel 236 | * - **Documentation**: https://prismic.io/docs/slice 237 | */ 238 | export type CarouselSlice = prismic.SharedSlice< 239 | "carousel", 240 | CarouselSliceVariation 241 | >; 242 | 243 | /** 244 | * Primary content in *Hero → Default → Primary* 245 | */ 246 | export interface HeroSliceDefaultPrimary { 247 | /** 248 | * Heading field in *Hero → Default → Primary* 249 | * 250 | * - **Field Type**: Title 251 | * - **Placeholder**: *None* 252 | * - **API ID Path**: hero.default.primary.heading 253 | * - **Documentation**: https://prismic.io/docs/field#rich-text-title 254 | */ 255 | heading: prismic.TitleField; 256 | 257 | /** 258 | * Subheading field in *Hero → Default → Primary* 259 | * 260 | * - **Field Type**: Rich Text 261 | * - **Placeholder**: *None* 262 | * - **API ID Path**: hero.default.primary.subheading 263 | * - **Documentation**: https://prismic.io/docs/field#rich-text-title 264 | */ 265 | subheading: prismic.RichTextField; 266 | 267 | /** 268 | * Body field in *Hero → Default → Primary* 269 | * 270 | * - **Field Type**: Rich Text 271 | * - **Placeholder**: *None* 272 | * - **API ID Path**: hero.default.primary.body 273 | * - **Documentation**: https://prismic.io/docs/field#rich-text-title 274 | */ 275 | body: prismic.RichTextField; 276 | 277 | /** 278 | * Button Text field in *Hero → Default → Primary* 279 | * 280 | * - **Field Type**: Text 281 | * - **Placeholder**: *None* 282 | * - **API ID Path**: hero.default.primary.button_text 283 | * - **Documentation**: https://prismic.io/docs/field#key-text 284 | */ 285 | button_text: prismic.KeyTextField; 286 | 287 | /** 288 | * Button Link field in *Hero → Default → Primary* 289 | * 290 | * - **Field Type**: Link 291 | * - **Placeholder**: *None* 292 | * - **API ID Path**: hero.default.primary.button_link 293 | * - **Documentation**: https://prismic.io/docs/field#link-content-relationship 294 | */ 295 | button_link: prismic.LinkField; 296 | 297 | /** 298 | * Cans Image field in *Hero → Default → Primary* 299 | * 300 | * - **Field Type**: Image 301 | * - **Placeholder**: *None* 302 | * - **API ID Path**: hero.default.primary.cans_image 303 | * - **Documentation**: https://prismic.io/docs/field#image 304 | */ 305 | cans_image: prismic.ImageField; 306 | 307 | /** 308 | * Second Heading field in *Hero → Default → Primary* 309 | * 310 | * - **Field Type**: Title 311 | * - **Placeholder**: *None* 312 | * - **API ID Path**: hero.default.primary.second_heading 313 | * - **Documentation**: https://prismic.io/docs/field#rich-text-title 314 | */ 315 | second_heading: prismic.TitleField; 316 | 317 | /** 318 | * Second Body field in *Hero → Default → Primary* 319 | * 320 | * - **Field Type**: Rich Text 321 | * - **Placeholder**: *None* 322 | * - **API ID Path**: hero.default.primary.second_body 323 | * - **Documentation**: https://prismic.io/docs/field#rich-text-title 324 | */ 325 | second_body: prismic.RichTextField; 326 | } 327 | 328 | /** 329 | * Default variation for Hero Slice 330 | * 331 | * - **API ID**: `default` 332 | * - **Description**: Default 333 | * - **Documentation**: https://prismic.io/docs/slice 334 | */ 335 | export type HeroSliceDefault = prismic.SharedSliceVariation< 336 | "default", 337 | Simplify, 338 | never 339 | >; 340 | 341 | /** 342 | * Slice variation for *Hero* 343 | */ 344 | type HeroSliceVariation = HeroSliceDefault; 345 | 346 | /** 347 | * Hero Shared Slice 348 | * 349 | * - **API ID**: `hero` 350 | * - **Description**: Hero 351 | * - **Documentation**: https://prismic.io/docs/slice 352 | */ 353 | export type HeroSlice = prismic.SharedSlice<"hero", HeroSliceVariation>; 354 | 355 | /** 356 | * Primary content in *SkyDive → Default → Primary* 357 | */ 358 | export interface SkyDiveSliceDefaultPrimary { 359 | /** 360 | * Sentence field in *SkyDive → Default → Primary* 361 | * 362 | * - **Field Type**: Text 363 | * - **Placeholder**: *None* 364 | * - **API ID Path**: sky_dive.default.primary.sentence 365 | * - **Documentation**: https://prismic.io/docs/field#key-text 366 | */ 367 | sentence: prismic.KeyTextField; 368 | 369 | /** 370 | * Flavor field in *SkyDive → Default → Primary* 371 | * 372 | * - **Field Type**: Select 373 | * - **Placeholder**: *None* 374 | * - **Default Value**: lemonLime 375 | * - **API ID Path**: sky_dive.default.primary.flavor 376 | * - **Documentation**: https://prismic.io/docs/field#select 377 | */ 378 | flavor: prismic.SelectField< 379 | "lemonLime" | "grape" | "blackCherry" | "strawberryLemonade" | "watermelon", 380 | "filled" 381 | >; 382 | } 383 | 384 | /** 385 | * Default variation for SkyDive Slice 386 | * 387 | * - **API ID**: `default` 388 | * - **Description**: Default 389 | * - **Documentation**: https://prismic.io/docs/slice 390 | */ 391 | export type SkyDiveSliceDefault = prismic.SharedSliceVariation< 392 | "default", 393 | Simplify, 394 | never 395 | >; 396 | 397 | /** 398 | * Slice variation for *SkyDive* 399 | */ 400 | type SkyDiveSliceVariation = SkyDiveSliceDefault; 401 | 402 | /** 403 | * SkyDive Shared Slice 404 | * 405 | * - **API ID**: `sky_dive` 406 | * - **Description**: SkyDive 407 | * - **Documentation**: https://prismic.io/docs/slice 408 | */ 409 | export type SkyDiveSlice = prismic.SharedSlice< 410 | "sky_dive", 411 | SkyDiveSliceVariation 412 | >; 413 | 414 | declare module "@prismicio/client" { 415 | interface CreateClient { 416 | ( 417 | repositoryNameOrEndpoint: string, 418 | options?: prismic.ClientConfig, 419 | ): prismic.Client; 420 | } 421 | 422 | namespace Content { 423 | export type { 424 | PageDocument, 425 | PageDocumentData, 426 | PageDocumentDataSlicesSlice, 427 | AllDocumentTypes, 428 | AlternatingTextSlice, 429 | AlternatingTextSliceDefaultPrimaryTextGroupItem, 430 | AlternatingTextSliceDefaultPrimary, 431 | AlternatingTextSliceVariation, 432 | AlternatingTextSliceDefault, 433 | BigTextSlice, 434 | BigTextSliceVariation, 435 | BigTextSliceDefault, 436 | CarouselSlice, 437 | CarouselSliceDefaultPrimary, 438 | CarouselSliceVariation, 439 | CarouselSliceDefault, 440 | HeroSlice, 441 | HeroSliceDefaultPrimary, 442 | HeroSliceVariation, 443 | HeroSliceDefault, 444 | SkyDiveSlice, 445 | SkyDiveSliceDefaultPrimary, 446 | SkyDiveSliceVariation, 447 | SkyDiveSliceDefault, 448 | }; 449 | } 450 | } 451 | -------------------------------------------------------------------------------- /public/Soda-can.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prismicio-community/course-fizzi-next/2760114f2647ebec8f63e0ecc2dc87a8cd4096ac/public/Soda-can.bin -------------------------------------------------------------------------------- /public/Soda-can.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "asset":{ 3 | "generator":"Khronos glTF Blender I/O v4.1.63", 4 | "version":"2.0" 5 | }, 6 | "extensionsUsed":[ 7 | "KHR_draco_mesh_compression" 8 | ], 9 | "extensionsRequired":[ 10 | "KHR_draco_mesh_compression" 11 | ], 12 | "scene":0, 13 | "scenes":[ 14 | { 15 | "name":"Scene", 16 | "nodes":[ 17 | 1 18 | ] 19 | } 20 | ], 21 | "nodes":[ 22 | { 23 | "mesh":0, 24 | "name":"Tab" 25 | }, 26 | { 27 | "children":[ 28 | 0 29 | ], 30 | "mesh":1, 31 | "name":"can" 32 | } 33 | ], 34 | "meshes":[ 35 | { 36 | "name":"CanTab", 37 | "primitives":[ 38 | { 39 | "attributes":{ 40 | "POSITION":0, 41 | "NORMAL":1, 42 | "TEXCOORD_0":2 43 | }, 44 | "extensions":{ 45 | "KHR_draco_mesh_compression":{ 46 | "bufferView":0, 47 | "attributes":{ 48 | "POSITION":0, 49 | "NORMAL":1, 50 | "TEXCOORD_0":2 51 | } 52 | } 53 | }, 54 | "indices":3, 55 | "mode":4 56 | } 57 | ] 58 | }, 59 | { 60 | "name":"cylinder", 61 | "primitives":[ 62 | { 63 | "attributes":{ 64 | "POSITION":4, 65 | "NORMAL":5, 66 | "TEXCOORD_0":6 67 | }, 68 | "extensions":{ 69 | "KHR_draco_mesh_compression":{ 70 | "bufferView":1, 71 | "attributes":{ 72 | "POSITION":0, 73 | "NORMAL":1, 74 | "TEXCOORD_0":2 75 | } 76 | } 77 | }, 78 | "indices":7, 79 | "mode":4 80 | }, 81 | { 82 | "attributes":{ 83 | "POSITION":8, 84 | "NORMAL":9, 85 | "TEXCOORD_0":10 86 | }, 87 | "extensions":{ 88 | "KHR_draco_mesh_compression":{ 89 | "bufferView":2, 90 | "attributes":{ 91 | "POSITION":0, 92 | "NORMAL":1, 93 | "TEXCOORD_0":2 94 | } 95 | } 96 | }, 97 | "indices":11, 98 | "mode":4 99 | } 100 | ] 101 | } 102 | ], 103 | "accessors":[ 104 | { 105 | "componentType":5126, 106 | "count":582, 107 | "max":[ 108 | 0.10328245908021927, 109 | 0.3453887701034546, 110 | 0.04695044457912445 111 | ], 112 | "min":[ 113 | -0.05091589689254761, 114 | 0.33007410168647766, 115 | -0.07133328169584274 116 | ], 117 | "type":"VEC3" 118 | }, 119 | { 120 | "componentType":5126, 121 | "count":582, 122 | "type":"VEC3" 123 | }, 124 | { 125 | "componentType":5126, 126 | "count":582, 127 | "type":"VEC2" 128 | }, 129 | { 130 | "componentType":5123, 131 | "count":3504, 132 | "type":"SCALAR" 133 | }, 134 | { 135 | "componentType":5126, 136 | "count":19321, 137 | "max":[ 138 | 0.19738179445266724, 139 | 0.35007044672966003, 140 | 0.19740863144397736 141 | ], 142 | "min":[ 143 | -0.1974184662103653, 144 | -0.3492709696292877, 145 | -0.19739161431789398 146 | ], 147 | "type":"VEC3" 148 | }, 149 | { 150 | "componentType":5126, 151 | "count":19321, 152 | "type":"VEC3" 153 | }, 154 | { 155 | "componentType":5126, 156 | "count":19321, 157 | "type":"VEC2" 158 | }, 159 | { 160 | "componentType":5123, 161 | "count":112464, 162 | "type":"SCALAR" 163 | }, 164 | { 165 | "componentType":5126, 166 | "count":4768, 167 | "max":[ 168 | 0.1988903284072876, 169 | 0.33093762397766113, 170 | 0.1989171802997589 171 | ], 172 | "min":[ 173 | -0.19892700016498566, 174 | -0.29022276401519775, 175 | -0.19890011847019196 176 | ], 177 | "type":"VEC3" 178 | }, 179 | { 180 | "componentType":5126, 181 | "count":4768, 182 | "type":"VEC3" 183 | }, 184 | { 185 | "componentType":5126, 186 | "count":4768, 187 | "type":"VEC2" 188 | }, 189 | { 190 | "componentType":5123, 191 | "count":25536, 192 | "type":"SCALAR" 193 | } 194 | ], 195 | "bufferViews":[ 196 | { 197 | "buffer":0, 198 | "byteLength":3360, 199 | "byteOffset":0 200 | }, 201 | { 202 | "buffer":0, 203 | "byteLength":67967, 204 | "byteOffset":3360 205 | }, 206 | { 207 | "buffer":0, 208 | "byteLength":20001, 209 | "byteOffset":71328 210 | } 211 | ], 212 | "buffers":[ 213 | { 214 | "byteLength":91332, 215 | "uri":"Soda-can.bin" 216 | } 217 | ] 218 | } 219 | -------------------------------------------------------------------------------- /public/fonts/Alpino-Variable.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prismicio-community/course-fizzi-next/2760114f2647ebec8f63e0ecc2dc87a8cd4096ac/public/fonts/Alpino-Variable.woff -------------------------------------------------------------------------------- /public/fonts/Alpino-Variable.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prismicio-community/course-fizzi-next/2760114f2647ebec8f63e0ecc2dc87a8cd4096ac/public/fonts/Alpino-Variable.woff2 -------------------------------------------------------------------------------- /public/hdr/field.hdr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prismicio-community/course-fizzi-next/2760114f2647ebec8f63e0ecc2dc87a8cd4096ac/public/hdr/field.hdr -------------------------------------------------------------------------------- /public/hdr/lobby.hdr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prismicio-community/course-fizzi-next/2760114f2647ebec8f63e0ecc2dc87a8cd4096ac/public/hdr/lobby.hdr -------------------------------------------------------------------------------- /public/labels/cherry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prismicio-community/course-fizzi-next/2760114f2647ebec8f63e0ecc2dc87a8cd4096ac/public/labels/cherry.png -------------------------------------------------------------------------------- /public/labels/grape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prismicio-community/course-fizzi-next/2760114f2647ebec8f63e0ecc2dc87a8cd4096ac/public/labels/grape.png -------------------------------------------------------------------------------- /public/labels/lemon-lime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prismicio-community/course-fizzi-next/2760114f2647ebec8f63e0ecc2dc87a8cd4096ac/public/labels/lemon-lime.png -------------------------------------------------------------------------------- /public/labels/strawberry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prismicio-community/course-fizzi-next/2760114f2647ebec8f63e0ecc2dc87a8cd4096ac/public/labels/strawberry.png -------------------------------------------------------------------------------- /public/labels/watermelon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prismicio-community/course-fizzi-next/2760114f2647ebec8f63e0ecc2dc87a8cd4096ac/public/labels/watermelon.png -------------------------------------------------------------------------------- /set-up-content.ts: -------------------------------------------------------------------------------- 1 | import { 2 | createClient, 3 | createWriteClient, 4 | createMigration, 5 | } from "@prismicio/client"; 6 | import { createPrismicAuthManager } from "@slicemachine/manager"; 7 | import sm from "./slicemachine.config.json"; 8 | import pkg from "./package.json"; 9 | 10 | main(); 11 | 12 | async function main() { 13 | const authManager = createPrismicAuthManager(); 14 | const isLoggedIn = await authManager.checkIsLoggedIn(); 15 | if (!isLoggedIn) { 16 | const sessionInfo = await authManager.getLoginSessionInfo(); 17 | await authManager.nodeLoginSession({ 18 | port: sessionInfo.port, 19 | onListenCallback() { 20 | console.log( 21 | `Open this URL in your browser and log in: ${sessionInfo.url}`, 22 | ); 23 | }, 24 | }); 25 | console.log("Logged in!"); 26 | } 27 | 28 | const sourceClient = createClient(pkg.name); 29 | console.log( 30 | `Fetching source documents from "${sourceClient.repositoryName}"...`, 31 | ); 32 | const allDocuments = await sourceClient.dangerouslyGetAll(); 33 | 34 | const client = createWriteClient(sm.repositoryName, { 35 | writeToken: await authManager.getAuthenticationToken(), 36 | }); 37 | 38 | const migration = createMigration(); 39 | for (const document of allDocuments) 40 | migration.createDocumentFromPrismic( 41 | document, 42 | (document.uid || document.type) 43 | .split(/ -/g) 44 | .map((part) => part.charAt(0).toUpperCase() + part.slice(1)) 45 | .join(" "), 46 | ); 47 | 48 | console.log(`Copying documents to "${client.repositoryName}"...`); 49 | await client.migrate(migration); 50 | 51 | console.log( 52 | `Done! Next, visit https://${sm.repositoryName}.prismic.io/builder/migration to publish your release.`, 53 | ); 54 | } 55 | -------------------------------------------------------------------------------- /slicemachine.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "repositoryName": "fizzi", 3 | "adapter": "@slicemachine/adapter-next", 4 | "libraries": ["./src/slices"], 5 | "localSliceSimulatorURL": "http://localhost:3000/slice-simulator", 6 | "apiEndpoint": "" 7 | } 8 | -------------------------------------------------------------------------------- /src/app/[uid]/page.tsx: -------------------------------------------------------------------------------- 1 | import { Metadata } from "next"; 2 | import { notFound } from "next/navigation"; 3 | 4 | import { SliceZone } from "@prismicio/react"; 5 | import * as prismic from "@prismicio/client"; 6 | 7 | import { createClient } from "@/prismicio"; 8 | import { components } from "@/slices"; 9 | 10 | type Params = { uid: string }; 11 | 12 | /** 13 | * This page renders a Prismic Document dynamically based on the URL. 14 | */ 15 | 16 | export async function generateMetadata({ 17 | params, 18 | }: { 19 | params: Params; 20 | }): Promise { 21 | const client = createClient(); 22 | const page = await client 23 | .getByUID("page", params.uid) 24 | .catch(() => notFound()); 25 | 26 | return { 27 | title: prismic.asText(page.data.title), 28 | description: page.data.meta_description, 29 | openGraph: { 30 | title: page.data.meta_title || undefined, 31 | images: [ 32 | { 33 | url: page.data.meta_image.url || "", 34 | }, 35 | ], 36 | }, 37 | }; 38 | } 39 | 40 | export default async function Page({ params }: { params: Params }) { 41 | const client = createClient(); 42 | const page = await client 43 | .getByUID("page", params.uid) 44 | .catch(() => notFound()); 45 | 46 | return ; 47 | } 48 | 49 | export async function generateStaticParams() { 50 | const client = createClient(); 51 | 52 | /** 53 | * Query all Documents from the API, except the homepage. 54 | */ 55 | const pages = await client.getAllByType("page", { 56 | predicates: [prismic.filter.not("my.page.uid", "home")], 57 | }); 58 | 59 | /** 60 | * Define a path for every Document. 61 | */ 62 | return pages.map((page) => { 63 | return { uid: page.uid }; 64 | }); 65 | } 66 | -------------------------------------------------------------------------------- /src/app/api/exit-preview/route.ts: -------------------------------------------------------------------------------- 1 | import { exitPreview } from "@prismicio/next"; 2 | 3 | /** 4 | * This endpoint exits a preview session. 5 | */ 6 | export function GET() { 7 | return exitPreview(); 8 | } 9 | -------------------------------------------------------------------------------- /src/app/api/preview/route.ts: -------------------------------------------------------------------------------- 1 | import { NextRequest } from "next/server"; 2 | import { redirectToPreviewURL } from "@prismicio/next"; 3 | 4 | import { createClient } from "@/prismicio"; 5 | 6 | /** 7 | * This endpoint handles previews that are launched from the Page Builder. 8 | */ 9 | export async function GET(request: NextRequest) { 10 | const client = createClient(); 11 | 12 | return await redirectToPreviewURL({ client, request }); 13 | } 14 | -------------------------------------------------------------------------------- /src/app/api/revalidate/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | import { revalidateTag } from "next/cache"; 3 | 4 | export async function POST() { 5 | revalidateTag("prismic"); 6 | 7 | return NextResponse.json({ revalidated: true, now: Date.now() }); 8 | } 9 | -------------------------------------------------------------------------------- /src/app/app.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /src/app/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import localFont from "next/font/local"; 2 | 3 | import { PrismicPreview } from "@prismicio/next"; 4 | import { repositoryName } from "@/prismicio"; 5 | 6 | import "./app.css"; 7 | import Header from "@/components/Header"; 8 | import ViewCanvas from "@/components/ViewCanvas"; 9 | import Footer from "@/components/Footer"; 10 | 11 | const alpino = localFont({ 12 | src: "../../public/fonts/Alpino-Variable.woff2", 13 | display: "swap", 14 | weight: "100 900", 15 | variable: "--font-alpino", 16 | }); 17 | 18 | export default function RootLayout({ 19 | children, 20 | }: Readonly<{ 21 | children: React.ReactNode; 22 | }>) { 23 | return ( 24 | 25 | 26 |
27 |
28 | {children} 29 | 30 |
31 |