From 00ee34a494dc696f407f2be042079e06e743d12b Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 19 May 2023 14:04:16 -0400 Subject: [PATCH 1/8] initial setup --- .../author/anthony-campolo/+page.md | 18 ++++++++ .../course/intro-to-solid-js/+page.md | 43 +++++++++++++++++-- .../lesson/01-intro/+page.md | 12 ------ .../lesson/02-locked/+page.md | 13 ------ .../intro-to-solid-js/lesson/basics/+page.md | 15 +++++++ .../lesson/fundamentals/+page.md | 11 +++++ 6 files changed, 83 insertions(+), 29 deletions(-) create mode 100644 apps/codingcatdev/src/routes/(content-single)/(non-course)/author/anthony-campolo/+page.md delete mode 100644 apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/01-intro/+page.md delete mode 100644 apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/02-locked/+page.md create mode 100644 apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md create mode 100644 apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md diff --git a/apps/codingcatdev/src/routes/(content-single)/(non-course)/author/anthony-campolo/+page.md b/apps/codingcatdev/src/routes/(content-single)/(non-course)/author/anthony-campolo/+page.md new file mode 100644 index 00000000..622e46f1 --- /dev/null +++ b/apps/codingcatdev/src/routes/(content-single)/(non-course)/author/anthony-campolo/+page.md @@ -0,0 +1,18 @@ +--- +type: guest +cover: 'https://media.codingcat.dev/image/upload/v1682988657/main-codingcatdev-photo/podcast-guest/ajcwebdev' +name: Anthony Campolo +published: published +slug: anthony-campolo +start: January 1, 2000 +picks: https://www.notion.so/Bo-Burnham-The-Inside-Outtakes-cac7d53f969a424d92a97a11f0f0fa59 +socials: + github: 'https://github.com/ajcwebdev' + twitter: 'https://twitter.com/ajcwebdev' +websites: + - https://ajcwebdev.com/ +--- + +### Profile + +Web developer, writer, speaker, and advocate. diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/+page.md index 1c1edc68..c69e3df7 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/+page.md +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/+page.md @@ -1,11 +1,46 @@ --- type: course authors: - - alex-patterson + - anthony-campolo cloudinary_convert: false +cover: https://media.codingcat.dev/image/upload/v1684518966/main-codingcatdev-photo/courses/solidjs-intro/SolidJSCourse.png +excerpt: 'In this course, you will learn everything you need to know to build user interfaces with SolidJS.' published: draft slug: intro-to-solid-js -start: December 20, 2022 11:15 AM +section: Intro +start: May 19, 2023 11:15 AM title: Intro to SolidJS -updated: October 26, 2022 11:15 AM ---- \ No newline at end of file +updated: +weight: 1 +--- + +SolidJS is a modern JavaScript library for building user interfaces. It is designed to be efficient, flexible, and easy to use. SolidJS is based on the idea of reactive state, which means that components are only updated when their state changes. This makes SolidJS very performant, even for large applications. + +SolidJS is also very flexible. It supports a wide range of features, including custom hooks, server-side rendering, and Suspense. This makes SolidJS a great choice for building a wide variety of web applications. + +SolidJS is easy to learn. It has a simple API that is similar to React. If you are already familiar with React, you will be able to pick up SolidJS quickly. + +In this course, you will learn everything you need to know to build user interfaces with SolidJS. You will learn about the basics of SolidJS, including its syntax, state management, and routing. You will also learn about more advanced topics, such as custom hooks, server-side rendering, and Suspense. + +By the end of this course, you will be able to build high-performance, flexible, and easy-to-use user interfaces with SolidJS. + +**What you will learn:** + +- The basics of SolidJS +- State management +- Routing +- Custom hooks +- Server-side rendering +- Suspense + +**Who is this course for?** + +This course is for web developers who want to learn how to build user interfaces with SolidJS. If you are already familiar with React, you will be able to pick up SolidJS quickly. + +**What you will need:** + +- A basic understanding of JavaScript +- A text editor or IDE (preferably VSCode) +- A Node.js environment + +**Go Pro and start learning SolidJS today!** diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/01-intro/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/01-intro/+page.md deleted file mode 100644 index 00064352..00000000 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/01-intro/+page.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -type: lesson -authors: - - alex-patterson -cloudinary_convert: false -published: draft -slug: intro -title: Intro to SolidJS -weight: 1 ---- - -This is the Intro lesson diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/02-locked/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/02-locked/+page.md deleted file mode 100644 index 7ab2c71b..00000000 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/02-locked/+page.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -type: lesson -authors: - - alex-patterson -cloudinary_convert: false -published: draft -slug: locked -locked: true -title: Example of locked course -weight: 2 ---- - -You should either be admin or a member to see this. diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md new file mode 100644 index 00000000..2a508115 --- /dev/null +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md @@ -0,0 +1,15 @@ +--- +type: lesson +authors: + - alex-patterson +cloudinary_convert: false +cover: https://media.codingcat.dev/image/upload/v1684519320/main-codingcatdev-photo/courses/solidjs-intro/basics.png +locked: locked +published: draft +section: Basics +slug: basics +title: SolidJS Basics +weight: 2 +--- + +This is the Intro lesson diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md new file mode 100644 index 00000000..cec039e6 --- /dev/null +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md @@ -0,0 +1,11 @@ +--- +type: lesson +authors: + - anthony-campolo +cloudinary_convert: false +cover: https://media.codingcat.dev/image/upload/v1684519320/main-codingcatdev-photo/courses/solidjs-intro/fundamentals.png +published: draft +section: Getting Started +title: Fundamentals +weight: 1 +--- From edb6145c9743c82137fad3926bbb9937cbbd5fe2 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 19 May 2023 14:13:01 -0400 Subject: [PATCH 2/8] add anthony's content --- .../intro-to-solid-js/lesson/basics/+page.md | 587 +++++++++++++++++- .../lesson/fundamentals/+page.md | 8 + 2 files changed, 593 insertions(+), 2 deletions(-) diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md index 2a508115..4f784ea4 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md @@ -8,8 +8,591 @@ locked: locked published: draft section: Basics slug: basics -title: SolidJS Basics +title: Solid Basics weight: 2 --- -This is the Intro lesson +## Project Structure and Vite Configuration + +```bash +mkdir ajcwebdev-solid +cd ajcwebdev-solid +pnpm init +pnpm add -D solid-js @solidjs/meta @solidjs/router vite vite-plugin-solid +``` + +Add `vite` scripts to `package.json`. + +```json +{ + "name": "", + "version": "1.0.0", + "description": "", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview" + }, + "keywords": ["SolidJS"], + "author": "FIRST_NAME LAST_NAME", + "license": "MIT", + "devDependencies": { + "@solidjs/meta": "^0.28.0", + "@solidjs/router": "^0.4.3", + "solid-js": "^1.5.5", + "vite": "^3.1.3", + "vite-plugin-solid": "^2.3.6" + } +} +``` + +Create a `vite.config.js` file. This will allow us to define our Vite Configuration with the Solid Plugin. + +```bash +echo > vite.config.js +``` + +Import `solidPlugin` from `vite-plugin-solid` and add it to the `plugins` array inside Vite's `defineConfig` helper. + +```jsx +// vite.config.js + +import { defineConfig } from 'vite'; +import solidPlugin from 'vite-plugin-solid'; + +export default defineConfig({ + plugins: [solidPlugin()] +}); +``` + +### HTML Entry Point + +Create an `index.html` file for our HTML entry point. + +```bash +echo > index.html +``` + +The root Solid component will be imported as an ESM module from `/src/root.jsx` and set to the `src` attribute on `script`. + +```html + + + + + + + + + A First Look at Solid + + + + +
+ + + +``` + +### Render Function + +```bash +mkdir src +echo > src/root.jsx +``` + +```jsx +// src/root.jsx + +/* @refresh reload */ +import { render } from 'solid-js/web'; + +function App() { + return ( +
+
+

A First Look at Solid

+ + Learn Solid + +
+
+ ); +} + +render(() => , document.getElementById('root')); +``` + +### Start Development Server + +```bash +pnpm dev # or npm run dev | yarn dev +``` + +Open [localhost:5173](http://localhost:5173/) to view the running application in your browser. The page will reload if you make edits. + +![Showing SolidJS running on localhost:5173](https://media.codingcat.dev/image/upload/v1684519512/main-codingcatdev-photo/courses/solidjs-intro/01-solid-home-page-on-localhost-5173.png) + +## File System Based Routing + +```bash +mkdir src/routes +echo > src/routes/index.jsx +``` + +```jsx +// src/routes/index.jsx + +export default function App() { + return ( +
+
+

A First Look at Solid

+ + Learn Solid + +
+
+ ); +} +``` + +## Styling + +```bash +echo > src/root.css +``` + +```css +/* src/root.css */ + +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', + 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.App { + text-align: center; +} + +.header { + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; +} + +.link { + color: #b318f0; +} +``` + +Import `App` component into `root.jsx` file. + +```jsx +// src/root.jsx + +/* @refresh reload */ +import { render } from 'solid-js/web'; +import App from './routes/index'; +import './root.css'; + +render(() => , document.getElementById('root')); +``` + +![A page showing A First Look at Solid text](https://media.codingcat.dev/image/upload/v1684519512/main-codingcatdev-photo/courses/solidjs-intro/02-solid-home-page-with-styling.png) + +## Components and Reactive Primitives + +When building applications with Solid, there are two foundational concepts that form the building blocks at the core of the framework. These are **Components** and the **Reactive Primitives** including Signals, Effects, and Memos. Before diving into the first Reactive Primitive, let's cover components briefly. + +```bash +mkdir src/components +echo > src/components/Counter.jsx +``` + +A Component is a function that accepts a `props` object and returns JSX elements. It is a lightweight factory functions that does not hold state itself. + +```jsx +// src/components/Counter.jsx + +import { createSignal } from 'solid-js'; + +const BasicComponent = (props) => { + const value = () => props.value || 'default'; + return
{value}
; +}; + +export default function Counter() { + return ( +
+ +
+ ); +} +``` + +```jsx +// src/components/Counter.jsx + +import { createSignal } from 'solid-js'; + +const BasicComponent = (props) => { + const value = () => props.value || 'default'; + return
{value}
; +}; + +export default function Counter() { + const [value, setValue] = createSignal(''); + + return ( +
+ + setValue(e.currentTarget.value)} /> +
+ ); +} +``` + +## Create Signal + +**[Signals](https://www.solidjs.com/tutorial/introduction_signals)** are the most basic reactive primitive and all reactivity in Solid is based around them. So what are Signals exactly? Signals contain values that change over time. Changing values are tracked by the framework and broadcast to the rest of interface. A signal automatically updates anything tracking it every time the signal's value is changed. + +This ensures the changing values are reflected in real time. The value being tracked can be any JavaScript object. These trackable signals require observers that can be updated by those trackable values. The `createSignal` function takes an `initialValue` as its first argument and returns a getter and a setter which together form a pair of functions as a two-element array. + +```jsx +// src/components/Counter.jsx + +import { createSignal } from 'solid-js'; + +const initialValue = 0; + +export default function Counter() { + const [getValue, setValue] = createSignal(initialValue); + + console.log(getValue()); // getValue() == 0 + + return
Value: {getValue()}
; +} +``` + +Import the `Counter` component to `src/routes/index.jsx` and return `` underneath the heading and link tag. + +```jsx +// src/routes/index.jsx + +import Counter from '../components/Counter'; + +export default function App() { + return ( +
+
+

A First Look at Solid

+ + Learn Solid + + +
+
+ ); +} +``` + +```jsx +// src/components/Counter.jsx + +import { createSignal } from 'solid-js'; + +const initialValue = 0; +const newValue = 1; + +export default function Counter() { + const [getValue, setValue] = createSignal(initialValue); + + setValue(newValue); + console.log(getValue()); // getValue() == 1 + + return
Value: {getValue()}
; +} +``` + +## Create Effect + +An **[Effect](https://www.solidjs.com/tutorial/introduction_effects)** is an example of an observer that runs a side effect depending on a signal. Effects are a way to make general, arbitrary code (also known as side effects) run whenever dependencies change. `[createEffect](https://www.solidjs.com/docs/latest#createeffect)` creates a new computation (for example to modify the DOM manually) and runs the given function in a tracking scope. + +```jsx +// src/components/Counter.jsx + +import { createSignal, createEffect } from 'solid-js'; + +export default function Counter() { + const [count, setCount] = createSignal(0); + createEffect(() => count()); + return ( + <> + + +
The count is now: {count()}
+ + ); +} +``` + +This automatically tracks the dependencies and reruns the function whenever the dependencies update. + +![A browser showing a Click Me Button with a count of 1](https://media.codingcat.dev/image/upload/v1684519511/main-codingcatdev-photo/courses/solidjs-intro/04-create-effect-button.png) + +## Create Resource + +```bash +echo > src/components/Users.jsx +``` + +```jsx +// src/components/Users.jsx + +import { createResource, createSignal, For } from 'solid-js'; + +const fetchUser = async () => + (await fetch(`https://jsonplaceholder.typicode.com/users?_limit=5`)).json(); + +export default function Users() { + const [user] = createResource(fetchUser); + const [users, setUsers] = createSignal([]); + + return ( +
+ {user.loading && 'Loading...'} +
+
{JSON.stringify(user(), null, 2)}
+
+ + Loading...

}> + {(user) =>
{user.name}
} +
+
+ ); +} +``` + +```jsx +// src/routes/index.jsx + +import Counter from '../components/Counter'; +import Users from '../components/Users'; + +export default function App() { + return ( +
+

A First Look at Solid

+ + Learn Solid + + + + +
+ ); +} +``` + +![Browser window showing a count of 1 with a list of names](https://media.codingcat.dev/image/upload/v1684519512/main-codingcatdev-photo/courses/solidjs-intro/05-onmount-displaying-users.png) + +## Deployment + +You can deploy the `dist` folder to any static host provider. + +```bash +pnpm build +``` + +```bash +git init +git add . +git commit -m "solid" +gh repo create ajcwebdev-solid \ + --description="An example SolidJS application deployed on Netlify" \ + --public \ + --push \ + --source=. \ + --remote=upstream +``` + +```bash +echo > netlify.toml +pnpm add -D netlify-cli +``` + +```toml +# netlify.toml + +[build] + command = "npm run build" + publish = "dist" +``` + +``` +pnpm ntl login +pnpm ntl init +``` + +``` +? What would you like to do? + Create & configure a new site +? Team: Anthony Campolo's team +? Site name (you can change it later): ajcwebdev-solid + +Site Created + +Admin URL: +URL: +Site ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + +Linked to ajcwebdev-solid + +? Your build command (hugo build/yarn run build/etc): npm run build +? Directory to deploy (blank for current dir): dist + +Adding deploy key to repository... +Deploy key added! + +Creating Netlify GitHub Notification Hooks... +Netlify Notification Hooks configured! + +Success! Netlify CI/CD Configured! + +This site is now configured to automatically deploy from github branches & pull requests + +Next steps: + + git push Push to your git repository to trigger new site builds + netlify open Open the Netlify admin URL of your site + +``` + +Open [ajcwebdev-solid.netlify.app](https://ajcwebdev-solid.netlify.app/). + +## SolidStart + +## Project Setup + +```json +{ + "type": "module", + "scripts": { + "dev": "solid-start dev", + "build": "solid-start build", + "start": "solid-start start" + } +} +``` + +```jsx +// vite.config.js + +import { defineConfig } from 'vite'; +import solid from 'solid-start/vite'; +// import solidPlugin from "vite-plugin-solid" + +export default defineConfig({ + plugins: [solid()] + // plugins: [solidPlugin()] +}); +``` + +## Client and Server Entry + +```bash +echo > src/entry-client.jsx +echo > src/entry-server.jsx +``` + +```jsx +// src/entry-client.jsx + +import { mount, StartClient } from 'solid-start/entry-client'; + +mount(() => , document); +``` + +```jsx +// src/entry-server.jsx + +import { StartServer, createHandler, renderAsync } from 'solid-start/entry-server'; + +export default createHandler(renderAsync((event) => )); +``` + +### Root + +```jsx +// src/root.jsx + +// @refresh reload +import { Suspense } from 'solid-js'; +import { Body, ErrorBoundary, FileRoutes, Head, Html, Meta, Routes, Scripts } from 'solid-start'; +import './root.css'; + +export default function Root() { + return ( + + + + + + + + + + + + + + + + + ); +} +``` + +Start development server + +```bash +pnpm dev +``` + +Open [localhost:3000](http://localhost:3000/). + +## Deployment Adapters + +```bash +pnpm add -D solid-start-netlify +``` + +```toml +# netlify.toml + +[build] + command = "npm run build" + publish = "netlify" +``` + +```jsx +// vite.config.js + +import { defineConfig } from 'vite'; +import solid from 'solid-start/vite'; +import netlify from 'solid-start-netlify'; + +export default defineConfig({ + plugins: [solid({ adapter: netlify({ edge: true }) })] +}); +``` diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md index cec039e6..be72da87 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md @@ -9,3 +9,11 @@ section: Getting Started title: Fundamentals weight: 1 --- + +## What is Solid? + +Solid VSCode Extensions and Settings + +What are the Benefits of Solid? + +What is SolidStart? From 73c459c693c2ac9ae7e3d274cc017604e38439c9 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 19 May 2023 14:39:17 -0400 Subject: [PATCH 3/8] fix createEffect link --- .../course/intro-to-solid-js/lesson/basics/+page.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md index 4f784ea4..957e293d 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md @@ -327,7 +327,7 @@ export default function Counter() { ## Create Effect -An **[Effect](https://www.solidjs.com/tutorial/introduction_effects)** is an example of an observer that runs a side effect depending on a signal. Effects are a way to make general, arbitrary code (also known as side effects) run whenever dependencies change. `[createEffect](https://www.solidjs.com/docs/latest#createeffect)` creates a new computation (for example to modify the DOM manually) and runs the given function in a tracking scope. +An **[Effect](https://www.solidjs.com/tutorial/introduction_effects)** is an example of an observer that runs a side effect depending on a signal. Effects are a way to make general, arbitrary code (also known as side effects) run whenever dependencies change. [createEffect](https://www.solidjs.com/docs/latest#createeffect) creates a new computation (for example to modify the DOM manually) and runs the given function in a tracking scope. ```jsx // src/components/Counter.jsx From 07d929ff7c6161dc308f34e68e4c03687089f60b Mon Sep 17 00:00:00 2001 From: Anthony Campolo <12433465+ajcwebdev@users.noreply.github.com> Date: Thu, 13 Jul 2023 02:29:36 -0500 Subject: [PATCH 4/8] first rough draft --- .../course/intro-to-solid-js/+page.md | 12 +- .../intro-to-solid-js/lesson/basics/+page.md | 598 +++++------------- .../lesson/deployment/+page.md | 66 ++ .../lesson/fundamentals/+page.md | 159 ++++- .../lesson/solidstart/+page.md | 178 ++++++ 5 files changed, 562 insertions(+), 451 deletions(-) create mode 100644 apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md create mode 100644 apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/solidstart/+page.md diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/+page.md index c69e3df7..249fbf81 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/+page.md +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/+page.md @@ -14,15 +14,17 @@ updated: weight: 1 --- -SolidJS is a modern JavaScript library for building user interfaces. It is designed to be efficient, flexible, and easy to use. SolidJS is based on the idea of reactive state, which means that components are only updated when their state changes. This makes SolidJS very performant, even for large applications. +## What is Solid? -SolidJS is also very flexible. It supports a wide range of features, including custom hooks, server-side rendering, and Suspense. This makes SolidJS a great choice for building a wide variety of web applications. +SolidJS is a modern JavaScript library for building user interfaces. It was created by Ryan Carniato in 2018 and has gained a strong following in the open source JavaScript and web development community. SolidJS is based on the idea of reactive state, which means that components are only updated when their state changes. -SolidJS is easy to learn. It has a simple API that is similar to React. If you are already familiar with React, you will be able to pick up SolidJS quickly. +### What are the Benefits of Solid? -In this course, you will learn everything you need to know to build user interfaces with SolidJS. You will learn about the basics of SolidJS, including its syntax, state management, and routing. You will also learn about more advanced topics, such as custom hooks, server-side rendering, and Suspense. +It is designed to be efficient, flexible, and easy to use. SolidJS's reactivity gives SolidJS an advantage when it comes to performance, even for large applications. With support for a wide range of features including custom hooks, SSR, and Suspense, SolidJS is a great choice for building a wide variety of web apps. -By the end of this course, you will be able to build high-performance, flexible, and easy-to-use user interfaces with SolidJS. +The framework aims to have a simple API that is similar to React and easy to learn. If you are already familiar with React, you will be able to pick up SolidJS fairly quickly after learning a few quirks in their differences. + +In this course, you will learn everything you need to know to build user interfaces with SolidJS. You will learn the basics of SolidJS's syntax and router along with more advanced topics, such as custom hooks, state management, SSR, and Suspense. By the end of this course, you will be able to build performant, flexible, and intuitive user interfaces with SolidJS. **What you will learn:** diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md index 957e293d..20a5b573 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md @@ -1,7 +1,7 @@ --- type: lesson authors: - - alex-patterson + - anthony-campolo cloudinary_convert: false cover: https://media.codingcat.dev/image/upload/v1684519320/main-codingcatdev-photo/courses/solidjs-intro/basics.png locked: locked @@ -12,276 +12,157 @@ title: Solid Basics weight: 2 --- -## Project Structure and Vite Configuration - -```bash -mkdir ajcwebdev-solid -cd ajcwebdev-solid -pnpm init -pnpm add -D solid-js @solidjs/meta @solidjs/router vite vite-plugin-solid -``` - -Add `vite` scripts to `package.json`. - -```json -{ - "name": "", - "version": "1.0.0", - "description": "", - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "serve": "vite preview" - }, - "keywords": ["SolidJS"], - "author": "FIRST_NAME LAST_NAME", - "license": "MIT", - "devDependencies": { - "@solidjs/meta": "^0.28.0", - "@solidjs/router": "^0.4.3", - "solid-js": "^1.5.5", - "vite": "^3.1.3", - "vite-plugin-solid": "^2.3.6" - } -} -``` - -Create a `vite.config.js` file. This will allow us to define our Vite Configuration with the Solid Plugin. - -```bash -echo > vite.config.js -``` - -Import `solidPlugin` from `vite-plugin-solid` and add it to the `plugins` array inside Vite's `defineConfig` helper. - -```jsx -// vite.config.js - -import { defineConfig } from 'vite'; -import solidPlugin from 'vite-plugin-solid'; - -export default defineConfig({ - plugins: [solidPlugin()] -}); -``` - -### HTML Entry Point - -Create an `index.html` file for our HTML entry point. - -```bash -echo > index.html -``` - -The root Solid component will be imported as an ESM module from `/src/root.jsx` and set to the `src` attribute on `script`. - -```html - - - - - - - - - A First Look at Solid - - - - -
- - - -``` - -### Render Function - -```bash -mkdir src -echo > src/root.jsx -``` - -```jsx -// src/root.jsx - -/* @refresh reload */ -import { render } from 'solid-js/web'; - -function App() { - return ( -
-
-

A First Look at Solid

- - Learn Solid - -
-
- ); -} +## File System Based Routing -render(() => , document.getElementById('root')); -``` +File System Based Routing is a popular approach for managing routes in modern JavaScript frameworks, including SolidJS. It simplifies the process of defining routes by mapping URL paths to files in your project's directory structure. -### Start Development Server +The framework auto-generates routes based on the file and directory naming/structure. Something like a `pages` or `routes` folder is usually used and each page will be a file inside of the directory. For example, `routes/about.js` would correspond to the `"/about"` route. ```bash -pnpm dev # or npm run dev | yarn dev +mkdir src/routes +echo > src/routes/index.jsx ``` -Open [localhost:5173](http://localhost:5173/) to view the running application in your browser. The page will reload if you make edits. +The `@solidjs/router` library is available to handle routing in your SolidJS applications. This library allows you to explicitly define routes and associate them with components that should be rendered when those routes are matched. -![Showing SolidJS running on localhost:5173](https://media.codingcat.dev/image/upload/v1684519512/main-codingcatdev-photo/courses/solidjs-intro/01-solid-home-page-on-localhost-5173.png) +This example is currently showing how to install and create your routing setup from scratch. Later in the tutorial we will use SolidStart which has `@solidjs/router` included by default. -## File System Based Routing - -```bash -mkdir src/routes -echo > src/routes/index.jsx -``` +Create and export an `App` component that displays a header and link to the SolidJS GitHub repository. ```jsx // src/routes/index.jsx export default function App() { - return ( -
-
-

A First Look at Solid

- - Learn Solid - -
-
- ); + return ( +
+
+

A First Look at Solid

+ + Learn Solid + +
+
+ ) } ``` ## Styling +While Solid can be used with popular styling libraries or framework like [Tailwind](https://tailwindcss.com/docs/guides/solidjs), this example will only use vanilla CSS. Create a file called `root.css` in `src` to hold all global styles. + ```bash echo > src/root.css ``` +Include the following CSS in that file: + ```css /* src/root.css */ body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', - 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } .App { - text-align: center; + text-align: center; } .header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; } .link { - color: #b318f0; + color: #b318f0; } ``` -Import `App` component into `root.jsx` file. +Import the `App` component into `root.jsx` file. ```jsx // src/root.jsx /* @refresh reload */ -import { render } from 'solid-js/web'; -import App from './routes/index'; -import './root.css'; +import { render } from 'solid-js/web' +import App from './routes/index' +import './root.css' -render(() => , document.getElementById('root')); +render( + () => , document.getElementById('root') +) ``` ![A page showing A First Look at Solid text](https://media.codingcat.dev/image/upload/v1684519512/main-codingcatdev-photo/courses/solidjs-intro/02-solid-home-page-with-styling.png) ## Components and Reactive Primitives -When building applications with Solid, there are two foundational concepts that form the building blocks at the core of the framework. These are **Components** and the **Reactive Primitives** including Signals, Effects, and Memos. Before diving into the first Reactive Primitive, let's cover components briefly. +When building applications with Solid, there are two foundational concepts that form the building blocks at the core of the framework. These are **Components** and the **Reactive Primitives** which include Signals, Effects, and Memos. Before diving into the first Reactive Primitive, let's cover components briefly. ```bash mkdir src/components echo > src/components/Counter.jsx ``` -A Component is a function that accepts a `props` object and returns JSX elements. It is a lightweight factory functions that does not hold state itself. +A Component is a function that accepts a `props` object and returns JSX elements. It is a lightweight factory function that does not hold state itself. ```jsx // src/components/Counter.jsx -import { createSignal } from 'solid-js'; +import { createSignal } from 'solid-js' const BasicComponent = (props) => { - const value = () => props.value || 'default'; - return
{value}
; -}; + const value = () => props.value || 'default' + return
{value}
+} export default function Counter() { - return ( -
- -
- ); + return ( +
+ +
+ ) } ``` +Add an `input` tag after `BasicComponent` so you can change the value being passed as `props`. + ```jsx // src/components/Counter.jsx -import { createSignal } from 'solid-js'; - -const BasicComponent = (props) => { - const value = () => props.value || 'default'; - return
{value}
; -}; - -export default function Counter() { - const [value, setValue] = createSignal(''); - - return ( -
- - setValue(e.currentTarget.value)} /> -
- ); -} + + setValue(e.currentTarget.value)} /> ``` -## Create Signal +### Create Signal + +**[Signals](https://www.solidjs.com/tutorial/introduction_signals)** are the most basic reactive primitive and all reactivity in Solid is based around them. So what are Signals exactly? Signals contain values that change over time. The framework tracks these changing values and broadcasts them to the rest of interface. -**[Signals](https://www.solidjs.com/tutorial/introduction_signals)** are the most basic reactive primitive and all reactivity in Solid is based around them. So what are Signals exactly? Signals contain values that change over time. Changing values are tracked by the framework and broadcast to the rest of interface. A signal automatically updates anything tracking it every time the signal's value is changed. +A signal automatically updates anything tracking it every time the signal's value is changed. This ensures the changing values are reflected in real time. The value being tracked can be any JavaScript object. These trackable signals require observers that can be updated by those trackable values. -This ensures the changing values are reflected in real time. The value being tracked can be any JavaScript object. These trackable signals require observers that can be updated by those trackable values. The `createSignal` function takes an `initialValue` as its first argument and returns a getter and a setter which together form a pair of functions as a two-element array. +The `createSignal` function takes an `initialValue` as its first argument and returns a getter and a setter. Together, these form a pair of functions as a two-element array, which in this example contain `getValue` and `setValue`. ```jsx // src/components/Counter.jsx -import { createSignal } from 'solid-js'; +import { createSignal } from 'solid-js' -const initialValue = 0; +const initialValue = 0 export default function Counter() { - const [getValue, setValue] = createSignal(initialValue); + const [getValue, setValue] = createSignal(initialValue) + console.log(getValue()) + // getValue() == 0 - console.log(getValue()); // getValue() == 0 - - return
Value: {getValue()}
; + return
Value: {getValue()}
} ``` @@ -290,60 +171,70 @@ Import the `Counter` component to `src/routes/index.jsx` and return ` ```jsx // src/routes/index.jsx -import Counter from '../components/Counter'; +import Counter from '../components/Counter' export default function App() { - return ( -
-
-

A First Look at Solid

- - Learn Solid - - -
-
- ); + return ( +
+
+

A First Look at Solid

+ + Learn Solid + + +
+
+ ) } ``` +This modifies the state directly by running `getValue` as a function. Change the `Counter` component so the value will be changed with `setValue`. + ```jsx // src/components/Counter.jsx -import { createSignal } from 'solid-js'; +import { createSignal } from 'solid-js' -const initialValue = 0; -const newValue = 1; +const initialValue = 0 +const newValue = 1 export default function Counter() { - const [getValue, setValue] = createSignal(initialValue); + const [getValue, setValue] = createSignal(initialValue) + setValue(newValue) + console.log(getValue()) // getValue() == 1 - setValue(newValue); - console.log(getValue()); // getValue() == 1 - - return
Value: {getValue()}
; + return ( + <> + Value: {getValue()} + + ) } ``` -## Create Effect +### Create Effect -An **[Effect](https://www.solidjs.com/tutorial/introduction_effects)** is an example of an observer that runs a side effect depending on a signal. Effects are a way to make general, arbitrary code (also known as side effects) run whenever dependencies change. [createEffect](https://www.solidjs.com/docs/latest#createeffect) creates a new computation (for example to modify the DOM manually) and runs the given function in a tracking scope. +An **[Effect](https://www.solidjs.com/tutorial/introduction_effects)** is an example of an observer that runs a side effect depending on a signal. Effects are a way to make general, arbitrary code (also known as side effects) run whenever dependencies change. + +[createEffect](https://www.solidjs.com/docs/latest#createeffect) creates a new computation (for example to modify the DOM manually) and runs the given function in a tracking scope. ```jsx // src/components/Counter.jsx -import { createSignal, createEffect } from 'solid-js'; +import { createSignal, createEffect } from 'solid-js' export default function Counter() { - const [count, setCount] = createSignal(0); - createEffect(() => count()); - return ( - <> - - -
The count is now: {count()}
- - ); + const [count, setCount] = createSignal(0) + createEffect(() => count()) + + return ( + <> + + +
The count is now: {count()}
+ + ) } ``` @@ -351,248 +242,71 @@ This automatically tracks the dependencies and reruns the function whenever the ![A browser showing a Click Me Button with a count of 1](https://media.codingcat.dev/image/upload/v1684519511/main-codingcatdev-photo/courses/solidjs-intro/04-create-effect-button.png) -## Create Resource +### Create Resource + +The `createResource` function is designed for asynchronous data handling in your application. It is invoked with an asynchronous fetcher function and returns a signal that updates with the fetched data when the operation completes. The fetcher function can be anything that returns a promise, such as a function to fetch data from a server. Create a component file called `Users.jsx` that will fetch users from the `jsonplaceholder.typicode.com` API. ```bash echo > src/components/Users.jsx ``` +`createResource` can be used in two different ways: + +1. You can pass only the fetcher function as an argument. In this scenario, the fetcher function will be invoked only once when the resource is created. +2. You can pass a source signal as the first argument, followed by the fetcher function. In this case, whenever the source signal changes, it will trigger the fetcher function again. The source signal's value will be passed as an argument to the fetcher function. + ```jsx // src/components/Users.jsx -import { createResource, createSignal, For } from 'solid-js'; +import { createResource, createSignal, For } from 'solid-js' -const fetchUser = async () => - (await fetch(`https://jsonplaceholder.typicode.com/users?_limit=5`)).json(); +const fetchUser = async () => ( + await fetch(`https://jsonplaceholder.typicode.com/users?_limit=5`) +).json() export default function Users() { - const [user] = createResource(fetchUser); - const [users, setUsers] = createSignal([]); - - return ( -
- {user.loading && 'Loading...'} -
-
{JSON.stringify(user(), null, 2)}
-
- - Loading...

}> - {(user) =>
{user.name}
} -
-
- ); + const [user] = createResource(fetchUser) + const [users, setUsers] = createSignal([]) + + return ( +
+ {user.loading && 'Loading...'} + +
+
{JSON.stringify(user(), null, 2)}
+
+ + Loading...

}> + {(user) =>
{user.name}
} +
+
+ ) } ``` +This demonstrates the first way of using `createResource` since it involves passing the fetcher function (`fetchUser` in this case) as the sole argument to `createResource`. The fetcher function is only invoked once when the resource is created and does not re-run based on changes to any signals. To run the fetcher function, import the `Users` component in the `App` component. + ```jsx // src/routes/index.jsx -import Counter from '../components/Counter'; -import Users from '../components/Users'; +import Counter from '../components/Counter' +import Users from '../components/Users' export default function App() { - return ( -
-

A First Look at Solid

- - Learn Solid - - - - -
- ); + return ( +
+

A First Look at Solid

+ + Learn Solid + + + + +
+ ) } ``` ![Browser window showing a count of 1 with a list of names](https://media.codingcat.dev/image/upload/v1684519512/main-codingcatdev-photo/courses/solidjs-intro/05-onmount-displaying-users.png) -## Deployment - -You can deploy the `dist` folder to any static host provider. - -```bash -pnpm build -``` - -```bash -git init -git add . -git commit -m "solid" -gh repo create ajcwebdev-solid \ - --description="An example SolidJS application deployed on Netlify" \ - --public \ - --push \ - --source=. \ - --remote=upstream -``` - -```bash -echo > netlify.toml -pnpm add -D netlify-cli -``` - -```toml -# netlify.toml - -[build] - command = "npm run build" - publish = "dist" -``` - -``` -pnpm ntl login -pnpm ntl init -``` - -``` -? What would you like to do? + Create & configure a new site -? Team: Anthony Campolo's team -? Site name (you can change it later): ajcwebdev-solid - -Site Created - -Admin URL: -URL: -Site ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - -Linked to ajcwebdev-solid - -? Your build command (hugo build/yarn run build/etc): npm run build -? Directory to deploy (blank for current dir): dist - -Adding deploy key to repository... -Deploy key added! - -Creating Netlify GitHub Notification Hooks... -Netlify Notification Hooks configured! - -Success! Netlify CI/CD Configured! - -This site is now configured to automatically deploy from github branches & pull requests - -Next steps: - - git push Push to your git repository to trigger new site builds - netlify open Open the Netlify admin URL of your site - -``` - -Open [ajcwebdev-solid.netlify.app](https://ajcwebdev-solid.netlify.app/). - -## SolidStart - -## Project Setup - -```json -{ - "type": "module", - "scripts": { - "dev": "solid-start dev", - "build": "solid-start build", - "start": "solid-start start" - } -} -``` - -```jsx -// vite.config.js - -import { defineConfig } from 'vite'; -import solid from 'solid-start/vite'; -// import solidPlugin from "vite-plugin-solid" - -export default defineConfig({ - plugins: [solid()] - // plugins: [solidPlugin()] -}); -``` - -## Client and Server Entry - -```bash -echo > src/entry-client.jsx -echo > src/entry-server.jsx -``` - -```jsx -// src/entry-client.jsx - -import { mount, StartClient } from 'solid-start/entry-client'; - -mount(() => , document); -``` - -```jsx -// src/entry-server.jsx - -import { StartServer, createHandler, renderAsync } from 'solid-start/entry-server'; - -export default createHandler(renderAsync((event) => )); -``` - -### Root - -```jsx -// src/root.jsx - -// @refresh reload -import { Suspense } from 'solid-js'; -import { Body, ErrorBoundary, FileRoutes, Head, Html, Meta, Routes, Scripts } from 'solid-start'; -import './root.css'; - -export default function Root() { - return ( - - - - - - - - - - - - - - - - - ); -} -``` - -Start development server - -```bash -pnpm dev -``` - -Open [localhost:3000](http://localhost:3000/). - -## Deployment Adapters - -```bash -pnpm add -D solid-start-netlify -``` - -```toml -# netlify.toml - -[build] - command = "npm run build" - publish = "netlify" -``` - -```jsx -// vite.config.js - -import { defineConfig } from 'vite'; -import solid from 'solid-start/vite'; -import netlify from 'solid-start-netlify'; - -export default defineConfig({ - plugins: [solid({ adapter: netlify({ edge: true }) })] -}); -``` +### Create Store \ No newline at end of file diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md new file mode 100644 index 00000000..c0470466 --- /dev/null +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md @@ -0,0 +1,66 @@ +--- +type: lesson +authors: + - anthony-campolo +cloudinary_convert: false +cover: +locked: locked +published: draft +slug: deployment +title: Deployment +weight: 2 +--- + +## Deployment + +You can deploy the `dist` folder to any static hosting provider. To see what this `dist` folder contains, run the `vite build` command with `pnpm` or `npm`. + +```bash +pnpm build +# npm run build +``` + +### Create GitHub Repository + +Create a GitHub + +```bash +git init +git add . +git commit -m "solid" +gh repo create ajcwebdev-solid \ + --description="An example SolidJS application deployed on Netlify" \ + --public \ + --push \ + --source=. \ + --remote=upstream +``` + +### Configure Netlify Deployment + +```bash +echo > netlify.toml +``` + +```toml +# netlify.toml + +[build] + command = "npm run build" + publish = "dist" +``` + +### Deploy with Netlify CLI + +```bash +pnpm add -D netlify-cli +``` + +Login to your Netlify account with `ntl login` and then initialize the Netlify project with `ntl init`. + +``` +pnpm ntl login +pnpm ntl init +``` + +Open [ajcwebdev-solid.netlify.app](https://ajcwebdev-solid.netlify.app/). \ No newline at end of file diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md index be72da87..c9072e4c 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md @@ -10,10 +10,161 @@ title: Fundamentals weight: 1 --- -## What is Solid? +## Project Structure and Vite Configuration -Solid VSCode Extensions and Settings +Create a blank directory called `intro-to-solid` and initialize a `package.json` file with either `pnpm` or `npm`. -What are the Benefits of Solid? +```bash +mkdir intro-to-solid +cd intro-to-solid +pnpm init +# npm i +``` -What is SolidStart? +Install the following project dependencies: + +- `solid-js` - A reactive JavaScript UI library, updating directly on the DOM for high performance. +- `@solidjs/meta` - Tools for managing metadata within Solid applications, enhancing SEO. +- `@solidjs/router` - A router library for Solid, enabling single-page application creation. +- `vite` - A modern front-end build tool providing fast development experience via features like hot module replacement. +- `vite-plugin-solid` - A Vite plugin that adds Solid support, allowing Vite to compile Solid's syntax and reactivity system. + +```bash +pnpm add -D solid-js @solidjs/meta @solidjs/router vite vite-plugin-solid +# npm i -D solid-js @solidjs/meta @solidjs/router vite vite-plugin-solid +``` + +Add `vite` scripts to `package.json` for `dev`, `build`, and `preview`. + +- `dev` is set to `vite` which starts the Vite development server. It provides features like hot module replacement and fast refresh, allowing you to instantly see changes as you develop your application. +- `build` is set to `vite build` which instructs Vite to build your project for production. It optimizes and minifies your code, resulting in smaller bundle sizes that load faster for your users. It typically outputs the build assets into a `dist` folder in your project directory. +- `serve` is set to `vite preview` which allows you to preview your built application in a local server environment. It serves the files generated by `vite build` from a local server, enabling you to preview the production build of your application before deploying it. + +```json +{ + "name": "An Introduction to SolidJS", + "description": "An example SolidJS application using Solid Router and Vite", + "type": "module", + "keywords": [ "SolidJS" ], + "author": "Anthony Campolo", + "license": "MIT", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview" + }, + "devDependencies": { + "@solidjs/meta": "^0.28.0", + "@solidjs/router": "^0.4.3", + "solid-js": "^1.5.5", + "vite": "^3.1.3", + "vite-plugin-solid": "^2.3.6" + } +} +``` + +Create a `vite.config.js` file. This will allow us to define our Vite Configuration with the Solid Plugin. + +```bash +echo > vite.config.js +``` + +Import `solidPlugin` from `vite-plugin-solid` and add it to the `plugins` array inside Vite's `defineConfig` helper. + +```js +// vite.config.js + +import { defineConfig } from 'vite' +import solidPlugin from 'vite-plugin-solid' + +export default defineConfig({ + plugins: [solidPlugin()] +}) +``` + +### HTML Entry Point + +Create an `index.html` file for our HTML entry point. + +```bash +echo > index.html +``` + +The root Solid component will be imported as an ESM module from `/src/root.jsx` and set to the `src` attribute on `script`. + +```html + + + + + + + + + A First Look at Solid + + + + +
+ + + +``` + +### Render Function + +In a SolidJS application, the root `render` function is responsible for mounting your application to a DOM element. Create a file called `root.jsx` in a directory called `src`. + +```bash +mkdir src +echo > src/root.jsx +``` + +`render` is the root render function imported from `solid-js/web` and is analogous to `ReactDOM.render()` in a React application or `Vue.mount()` in a Vue application. + +The root `render` function takes two arguments: + +1. The component that you want to render +2. The DOM element you want to render it into + +```jsx +// src/root.jsx + +/* @refresh reload */ +import { render } from 'solid-js/web' + +function App() { + return ( +
+
+

A First Look at Solid

+ + Learn Solid + +
+
+ ) +} + +render( + () => , document.getElementById('root') +) +``` + +Here, the `App` component is the top-level component for the application where your main application logic resides. `document.getElementById('root')` is the DOM node that the application will be mounted to. + +This is typically a `div` with an `id` of `root` in your HTML. Once this code runs, SolidJS will create an instance of `App`, mount it to the specified DOM node, and keep it up-to-date with the state of your application. + +### Start Development Server + +Run `pnpm dev` or `npm run dev` to start the development server on localhost. + +```bash +pnpm dev +# npm run dev +``` + +Open [localhost:5173](http://localhost:5173/) to view the running application in your browser. The page will reload if you make edits. + +![Showing SolidJS running on localhost:5173](https://media.codingcat.dev/image/upload/v1684519512/main-codingcatdev-photo/courses/solidjs-intro/01-solid-home-page-on-localhost-5173.png) \ No newline at end of file diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/solidstart/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/solidstart/+page.md new file mode 100644 index 00000000..f61e89ae --- /dev/null +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/solidstart/+page.md @@ -0,0 +1,178 @@ +--- +type: lesson +authors: + - anthony-campolo +cloudinary_convert: false +cover: +locked: locked +published: draft +slug: solidstart +title: SolidStart +weight: 3 +--- + +## Project Setup + +Change your `dev`, `build`, and `start` scripts to use the `solid-start` command. + +```json +{ + "scripts": { + "dev": "solid-start dev", + "build": "solid-start build", + "start": "solid-start start" + } +} +``` + +### Vite Configuration + +In `vite.config.js`, remove the `solidPlugin` from `vite-plugin-solid` and replace it with `solid` from `solid-start/vite`. + +```jsx +// vite.config.js + +import { defineConfig } from 'vite' +import solid from 'solid-start/vite' +// import solidPlugin from "vite-plugin-solid" + +export default defineConfig({ + plugins: [solid()] + // plugins: [solidPlugin()] +}) +``` + +### Client and Server Entry + +SolidStart projects are organized in a similar way to Remix or projects using React Server Components. One file is used as an entry point for the application to start in the client and another file is used as an entry point for the application to start on the server. Create files called `entry-client.jsx` and `entry-server.jsx` for each. + +```bash +echo > src/entry-client.jsx +echo > src/entry-server.jsx +``` + +`entry-client.jsx` is where your app starts in the browser. `` wraps our application root and includes `Context` providers for routing and meta data. `mount` either calls `render` or `hydrate` depending on the configuration. + +```jsx +// src/entry-client.jsx + +import { mount, StartClient } from 'solid-start/entry-client' + +mount( + () => , document +) +``` + +`entry-server.jsx` is where your app starts on the server. `` wraps our application root and also includes `Context` providers for routing and meta data. It accepts an `event` and passes it to the `renderAsync(codeFn, options)` middleware which then calls Solid's `renderToStringAsync` under the hood to asynchronously render the application. This responds when the page has been fully loaded and rendered. + +```jsx +// src/entry-server.jsx + +import { + StartServer, createHandler, renderAsync +} from 'solid-start/entry-server' + +export default createHandler( + renderAsync((event) => ) +) +``` + +All `Suspense` and data loading on initial load happens on the server. `Event` objects that originate from our underlying runtime are passed with a `PageEvent` object containing the following information: + +- `request` - The current request +- `responseHeaders` - The headers being built for the response +- `clientAddress` - The IP address of the remote client +- `locals` - An object for storing local data that lives the life of the request, like user or authentication data +- `setStatusCode(code)` - Sets the status code +- `getStatusCode()` - Returns the current status code +- `fetch(url, init)` - Fetch API that can call API helpers directly on the server + +### Root + +`root.jsx` defines the document rendered by your application. The `Root` component from `root.jsx` is an isomorphic entry into your application, structured like an HTML document but with capitalized components, including core elements like `Suspense` and `ErrorBoundary` for managing loading and error states. + +Notably, it provides a space for defining ``, positioning `` high up for effective error catching, and inserting global Context Providers and universal components, such as top-level navigation, into the ``. + +```jsx +// src/root.jsx + +// @refresh reload +import { Suspense } from 'solid-js' +import { + Body, ErrorBoundary, FileRoutes, Head, Html, Meta, Routes, Scripts +} from 'solid-start' +import './root.css' + +export default function Root() { + return ( + + + + + + + + + + + + + + + + + ) +} +``` + +### Start Development Server + +Run your development server with the `solid-start dev` command. + +```bash +pnpm dev +# npm run dev +``` + +Open [localhost:3000](http://localhost:3000/). + +## Deployment Adapters + +SolidStart includes various adapters for deploying your project to specific hosting providers like Netlify or Vercel. + +### Configure Netlify Adapter + +We'll use the Netlify adapter, so install `solid-start-netlify` with `pnpm` or `npm`. + +```bash +pnpm add -D solid-start-netlify +# npm i -D solid-start-netlify +``` + +Our `build` command will be `pnpm build` and our publish directory will now be called `netlify`. + +```toml +# netlify.toml + +[build] + command = "pnpm build" + publish = "netlify" +``` + +Return to `vite.config.js` and import `netlify` from `solid-start-netlify`. Set it to `adapter` and specify `true` for the `edge` configuration. + +```jsx +// vite.config.js + +import { defineConfig } from 'vite' +import solid from 'solid-start/vite' +import netlify from 'solid-start-netlify' + +export default defineConfig({ + plugins: [solid({ + adapter: netlify({ edge: true }) + })] +}) +``` + +Push your new changes to GitHub and your Netlify website should rebuild and update automatically. \ No newline at end of file From e27856fc18c2038dfbc206dd4e0797f08ada3826 Mon Sep 17 00:00:00 2001 From: Anthony Campolo <12433465+ajcwebdev@users.noreply.github.com> Date: Thu, 13 Jul 2023 02:38:09 -0500 Subject: [PATCH 5/8] create solidstart section --- .../course/intro-to-solid-js/lesson/deployment/+page.md | 2 +- .../course/intro-to-solid-js/lesson/solidstart/+page.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md index c0470466..f022bb4b 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md @@ -8,7 +8,7 @@ locked: locked published: draft slug: deployment title: Deployment -weight: 2 +weight: 3 --- ## Deployment diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/solidstart/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/solidstart/+page.md index f61e89ae..2f88af69 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/solidstart/+page.md +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/solidstart/+page.md @@ -7,8 +7,9 @@ cover: locked: locked published: draft slug: solidstart +section: SolidStart title: SolidStart -weight: 3 +weight: 4 --- ## Project Setup From b25efac675b49ef37a0ed468d782dd715a3b6410 Mon Sep 17 00:00:00 2001 From: Alex Patterson Date: Thu, 13 Jul 2023 14:14:21 -0400 Subject: [PATCH 6/8] add cover images --- .../course/intro-to-solid-js/lesson/deployment/+page.md | 2 +- .../course/intro-to-solid-js/lesson/solidstart/+page.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md index f022bb4b..0f51fb04 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md @@ -3,7 +3,7 @@ type: lesson authors: - anthony-campolo cloudinary_convert: false -cover: +cover: https://media.codingcat.dev/image/upload/v1689262234/main-codingcatdev-photo/courses/solidjs-intro/deployment.png locked: locked published: draft slug: deployment diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/solidstart/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/solidstart/+page.md index 2f88af69..dd885ae6 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/solidstart/+page.md +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/solidstart/+page.md @@ -3,7 +3,7 @@ type: lesson authors: - anthony-campolo cloudinary_convert: false -cover: +cover: https://media.codingcat.dev/image/upload/v1689262234/main-codingcatdev-photo/courses/solidjs-intro/solidstart.png locked: locked published: draft slug: solidstart From 78adb785fee3c9167c08181042b13b6aa1854058 Mon Sep 17 00:00:00 2001 From: Anthony Campolo <12433465+ajcwebdev@users.noreply.github.com> Date: Fri, 13 Oct 2023 09:59:51 -0500 Subject: [PATCH 7/8] complete first draft of entire course --- .../intro-to-solid-js/lesson/basics/+page.md | 63 +++++++------------ .../lesson/deployment/+page.md | 56 +++++++++++------ .../lesson/fundamentals/+page.md | 16 ++--- 3 files changed, 68 insertions(+), 67 deletions(-) diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md index 20a5b573..bcbe2861 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md @@ -54,15 +54,14 @@ While Solid can be used with popular styling libraries or framework like [Tailwi echo > src/root.css ``` -Include the following CSS in that file: +Include the following styling in that file: ```css /* src/root.css */ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; - -webkit-font-smoothing: antialiased; + font-family: system-ui; -moz-osx-font-smoothing: grayscale; } @@ -97,7 +96,8 @@ import App from './routes/index' import './root.css' render( - () => , document.getElementById('root') + () => , + document.getElementById('root') ) ``` @@ -112,13 +112,11 @@ mkdir src/components echo > src/components/Counter.jsx ``` -A Component is a function that accepts a `props` object and returns JSX elements. It is a lightweight factory function that does not hold state itself. +A Component is a function that accepts a `props` object and returns JSX elements. It is a lightweight factory function that does not hold state itself. Adding an `input` tag after `BasicComponent` in the following example lets you change the value being passed as `props`. ```jsx // src/components/Counter.jsx -import { createSignal } from 'solid-js' - const BasicComponent = (props) => { const value = () => props.value || 'default' return
{value}
@@ -128,19 +126,13 @@ export default function Counter() { return (
+ setValue(e.currentTarget.value)} />
) } ``` -Add an `input` tag after `BasicComponent` so you can change the value being passed as `props`. - -```jsx -// src/components/Counter.jsx - - - setValue(e.currentTarget.value)} /> -``` +But where is the value coming from in the first place and where it is being stored and modified when state changes in your application? ### Create Signal @@ -176,9 +168,9 @@ import Counter from '../components/Counter' export default function App() { return (
-
+

A First Look at Solid

- + Learn Solid @@ -188,7 +180,7 @@ export default function App() { } ``` -This modifies the state directly by running `getValue` as a function. Change the `Counter` component so the value will be changed with `setValue`. +This modifies the state directly by running `getValue` as a function. But your component will only display a value of 0 right now and there is no way to change it. To do this, we have to change the `Counter` component so the value will be set with `setValue`. ```jsx // src/components/Counter.jsx @@ -258,7 +250,7 @@ echo > src/components/Users.jsx ```jsx // src/components/Users.jsx -import { createResource, createSignal, For } from 'solid-js' +import { createResource } from 'solid-js' const fetchUser = async () => ( await fetch(`https://jsonplaceholder.typicode.com/users?_limit=5`) @@ -266,19 +258,11 @@ const fetchUser = async () => ( export default function Users() { const [user] = createResource(fetchUser) - const [users, setUsers] = createSignal([]) return (
{user.loading && 'Loading...'} - -
-
{JSON.stringify(user(), null, 2)}
-
- - Loading...

}> - {(user) =>
{user.name}
} -
+
{JSON.stringify(user(), null, 2)}
) } @@ -294,19 +278,18 @@ import Users from '../components/Users' export default function App() { return ( -
-

A First Look at Solid

- - Learn Solid - - - - -
+
+
+

A First Look at Solid

+ + Learn Solid + + + +
+
) } ``` -![Browser window showing a count of 1 with a list of names](https://media.codingcat.dev/image/upload/v1684519512/main-codingcatdev-photo/courses/solidjs-intro/05-onmount-displaying-users.png) - -### Create Store \ No newline at end of file +![Browser window showing a count of 1 with a list of names](https://media.codingcat.dev/image/upload/v1684519512/main-codingcatdev-photo/courses/solidjs-intro/05-onmount-displaying-users.png) \ No newline at end of file diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md index 0f51fb04..4a48f19b 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md @@ -20,22 +20,6 @@ pnpm build # npm run build ``` -### Create GitHub Repository - -Create a GitHub - -```bash -git init -git add . -git commit -m "solid" -gh repo create ajcwebdev-solid \ - --description="An example SolidJS application deployed on Netlify" \ - --public \ - --push \ - --source=. \ - --remote=upstream -``` - ### Configure Netlify Deployment ```bash @@ -50,17 +34,49 @@ echo > netlify.toml publish = "dist" ``` -### Deploy with Netlify CLI +### Create GitHub Repository + +Before initializing a git repo and pushing it to GitHub, create a `.gitignore` file. ```bash -pnpm add -D netlify-cli +echo >> .gitignore ``` -Login to your Netlify account with `ntl login` and then initialize the Netlify project with `ntl init`. +Add the following to `.gitignore`. ``` +.DS_Store +node_modules +dist +``` + +After staging and committing your project you can create a GitHub repository through the website's dashboard, with a desktop GUI, or with the GitHub CLI commands detailed below: + +```bash +git init +git add . +git commit -m "solid" +gh repo create intro-to-solid \ + --description="An example SolidJS application deployed on Netlify" \ + --public \ + --push \ + --source=. \ + --remote=upstream +``` + +### Deploy with Netlify CLI + +Add the `netlify-cli` as a package and login to your Netlify account with `ntl login`. + +```bash +pnpm add -D netlify-cli pnpm ntl login +``` + +Initialize the Netlify project with `ntl init`. + +```bash pnpm ntl init ``` -Open [ajcwebdev-solid.netlify.app](https://ajcwebdev-solid.netlify.app/). \ No newline at end of file +Open [intro-to-solid.netlify.app](https://intro-to-solid.netlify.app/). \ No newline at end of file diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md index c9072e4c..110c978f 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md @@ -40,9 +40,11 @@ Add `vite` scripts to `package.json` for `dev`, `build`, and `preview`. - `build` is set to `vite build` which instructs Vite to build your project for production. It optimizes and minifies your code, resulting in smaller bundle sizes that load faster for your users. It typically outputs the build assets into a `dist` folder in your project directory. - `serve` is set to `vite preview` which allows you to preview your built application in a local server environment. It serves the files generated by `vite build` from a local server, enabling you to preview the production build of your application before deploying it. +Also make sure that `type` is set to `module` in `package.json`. + ```json { - "name": "An Introduction to SolidJS", + "name": "into-to-solid", "description": "An example SolidJS application using Solid Router and Vite", "type": "module", "keywords": [ "SolidJS" ], @@ -63,13 +65,13 @@ Add `vite` scripts to `package.json` for `dev`, `build`, and `preview`. } ``` -Create a `vite.config.js` file. This will allow us to define our Vite Configuration with the Solid Plugin. +Create a `vite.config.js` file. ```bash echo > vite.config.js ``` -Import `solidPlugin` from `vite-plugin-solid` and add it to the `plugins` array inside Vite's `defineConfig` helper. +Vite works with multiple frameworks that use different syntaxes and file types like React, Vue, and Svelte. Vite will know what to expect and how to handle different frameworks through plugins in its configuration file. ```js // vite.config.js @@ -82,9 +84,11 @@ export default defineConfig({ }) ``` +Here we have defined our Vite configuration with the Solid Plugin. It is imported as `solidPlugin` from `vite-plugin-solid` and added to the `plugins` array inside Vite's `defineConfig` helper. + ### HTML Entry Point -Create an `index.html` file for our HTML entry point. +Create an `index.html` file for our HTML entry point. This will be the page shell that our root DOM will render into. ```bash echo > index.html @@ -147,9 +151,7 @@ function App() { ) } -render( - () => , document.getElementById('root') -) +render(() => , document.getElementById('root')) ``` Here, the `App` component is the top-level component for the application where your main application logic resides. `document.getElementById('root')` is the DOM node that the application will be mounted to. From 7754535693578de81b0b7d95d43bbfb0b518bfc8 Mon Sep 17 00:00:00 2001 From: Alex FusionAuth Date: Fri, 13 Oct 2023 15:03:03 -0400 Subject: [PATCH 8/8] fix locked courses --- .../(content-single)/course/+layout.server.ts | 106 +++++---- .../course/intro-to-solid-js/+page.md | 2 +- .../intro-to-solid-js/lesson/basics/+page.md | 208 +++++++++--------- .../lesson/deployment/+page.md | 4 +- .../lesson/fundamentals/+page.md | 98 ++++----- .../lesson/solidstart/+page.md | 98 ++++----- .../HomeProBenefits.svelte | 18 +- .../(home-pro-benefits)/ProSelect.svelte | 26 ++- .../src/routes/(protected)/+layout.server.ts | 23 +- .../src/routes/login/+page.server.ts | 66 +++--- .../src/routes/login/+page.svelte | 2 + 11 files changed, 337 insertions(+), 314 deletions(-) diff --git a/apps/codingcatdev/src/routes/(content-single)/course/+layout.server.ts b/apps/codingcatdev/src/routes/(content-single)/course/+layout.server.ts index 9a36e9c5..606fd464 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/+layout.server.ts +++ b/apps/codingcatdev/src/routes/(content-single)/course/+layout.server.ts @@ -1,49 +1,65 @@ -import { error } from '@sveltejs/kit'; -import { filterContent, getContentTypePath } from '$lib/server/content'; +import { error, redirect } from '@sveltejs/kit'; +import { allowLocal, filterContent, getContentTypePath } from '$lib/server/content'; import { ContentType, type Course, type Author, type Sponsor } from '$lib/types'; export const prerender = false; -export const load = (async (params) => { - try { - const splitPath = params.url.pathname.split('/'); - const courseSlug = splitPath.at(2); - const lessonSlug = splitPath.at(4); - - if (!courseSlug) throw error(404); - const md = await getContentTypePath(ContentType.course, courseSlug); - - if (!md) throw error(404); - const contentItems = await filterContent({ contentItems: [md] }) - const course = contentItems?.at(0); - if (!course) throw error(404); - - // Content is good, fetch surrounding items - const authors: Author[] = []; - if (course?.authors) { - for (const authorSlug of course.authors) { - const author = await getContentTypePath(ContentType.author, authorSlug); - if (author) authors.push(author) - } - } - - const sponsors: Sponsor[] = []; - if (course?.sponsors) { - for (const sponsorSlug of course.sponsors) { - const sponsor = await getContentTypePath(ContentType.sponsor, sponsorSlug); - if (sponsor) sponsors.push(sponsor) - } - } - - return { - content: course.lesson?.find(l => l.slug === lessonSlug), - course, - authors, - sponsors - } - } - catch (e) { - console.error(e) - throw error(404) - } -}) \ No newline at end of file +export const load = async ({ url, parent }) => { + const data = await parent(); + + try { + const splitPath = url.pathname.split('/'); + const courseSlug = splitPath.at(2); + const lessonSlug = splitPath.at(4); + + if (!courseSlug) throw error(404); + const md = await getContentTypePath(ContentType.course, courseSlug); + + if (!md) throw error(404); + const contentItems = await filterContent({ contentItems: [md] }); + const course = contentItems?.at(0); + if (!course) throw error(404); + + // Content is good, fetch surrounding items + const authors: Author[] = []; + if (course?.authors) { + for (const authorSlug of course.authors) { + const author = await getContentTypePath(ContentType.author, authorSlug); + if (author) authors.push(author); + } + } + + const sponsors: Sponsor[] = []; + if (course?.sponsors) { + for (const sponsorSlug of course.sponsors) { + const sponsor = await getContentTypePath(ContentType.sponsor, sponsorSlug); + if (sponsor) sponsors.push(sponsor); + } + } + + const content = course.lesson?.find((l) => l.slug === lessonSlug); + if ( + lessonSlug && + content?.locked && + !allowLocal && + (!data?.user?.uid || !data?.user?.stripeRole) + ) { + throw 'app:redirect'; + } + + return { + content, + course, + authors, + sponsors + }; + } catch (e) { + console.error(e); + + if (e === 'app:redirect') { + throw redirect(307, `/login?redirectTo=${url.pathname}`); + } + + throw error(404); + } +}; diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/+page.md index 249fbf81..b7e3eb7a 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/+page.md +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/+page.md @@ -5,7 +5,7 @@ authors: cloudinary_convert: false cover: https://media.codingcat.dev/image/upload/v1684518966/main-codingcatdev-photo/courses/solidjs-intro/SolidJSCourse.png excerpt: 'In this course, you will learn everything you need to know to build user interfaces with SolidJS.' -published: draft +published: published slug: intro-to-solid-js section: Intro start: May 19, 2023 11:15 AM diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md index bcbe2861..fa2bcbec 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/basics/+page.md @@ -5,7 +5,7 @@ authors: cloudinary_convert: false cover: https://media.codingcat.dev/image/upload/v1684519320/main-codingcatdev-photo/courses/solidjs-intro/basics.png locked: locked -published: draft +published: published section: Basics slug: basics title: Solid Basics @@ -33,16 +33,16 @@ Create and export an `App` component that displays a header and link to the Soli // src/routes/index.jsx export default function App() { - return ( -
-
-

A First Look at Solid

- - Learn Solid - -
-
- ) + return ( +
+
+

A First Look at Solid

+ + Learn Solid + +
+
+ ); } ``` @@ -60,28 +60,28 @@ Include the following styling in that file: /* src/root.css */ body { - margin: 0; - font-family: system-ui; - -moz-osx-font-smoothing: grayscale; + margin: 0; + font-family: system-ui; + -moz-osx-font-smoothing: grayscale; } .App { - text-align: center; + text-align: center; } .header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; } .link { - color: #b318f0; + color: #b318f0; } ``` @@ -91,14 +91,11 @@ Import the `App` component into `root.jsx` file. // src/root.jsx /* @refresh reload */ -import { render } from 'solid-js/web' -import App from './routes/index' -import './root.css' - -render( - () => , - document.getElementById('root') -) +import { render } from 'solid-js/web'; +import App from './routes/index'; +import './root.css'; + +render(() => , document.getElementById('root')); ``` ![A page showing A First Look at Solid text](https://media.codingcat.dev/image/upload/v1684519512/main-codingcatdev-photo/courses/solidjs-intro/02-solid-home-page-with-styling.png) @@ -118,17 +115,17 @@ A Component is a function that accepts a `props` object and returns JSX elements // src/components/Counter.jsx const BasicComponent = (props) => { - const value = () => props.value || 'default' - return
{value}
-} + const value = () => props.value || 'default'; + return
{value}
; +}; export default function Counter() { - return ( -
- - setValue(e.currentTarget.value)} /> -
- ) + return ( +
+ + setValue(e.currentTarget.value)} /> +
+ ); } ``` @@ -145,16 +142,16 @@ The `createSignal` function takes an `initialValue` as its first argument and re ```jsx // src/components/Counter.jsx -import { createSignal } from 'solid-js' +import { createSignal } from 'solid-js'; -const initialValue = 0 +const initialValue = 0; export default function Counter() { - const [getValue, setValue] = createSignal(initialValue) - console.log(getValue()) - // getValue() == 0 + const [getValue, setValue] = createSignal(initialValue); + console.log(getValue()); + // getValue() == 0 - return
Value: {getValue()}
+ return
Value: {getValue()}
; } ``` @@ -163,20 +160,20 @@ Import the `Counter` component to `src/routes/index.jsx` and return ` ```jsx // src/routes/index.jsx -import Counter from '../components/Counter' +import Counter from '../components/Counter'; export default function App() { - return ( -
-
-

A First Look at Solid

- - Learn Solid - - -
-
- ) + return ( +
+
+

A First Look at Solid

+ + Learn Solid + + +
+
+ ); } ``` @@ -185,21 +182,17 @@ This modifies the state directly by running `getValue` as a function. But your c ```jsx // src/components/Counter.jsx -import { createSignal } from 'solid-js' +import { createSignal } from 'solid-js'; -const initialValue = 0 -const newValue = 1 +const initialValue = 0; +const newValue = 1; export default function Counter() { - const [getValue, setValue] = createSignal(initialValue) - setValue(newValue) - console.log(getValue()) // getValue() == 1 + const [getValue, setValue] = createSignal(initialValue); + setValue(newValue); + console.log(getValue()); // getValue() == 1 - return ( - <> - Value: {getValue()} - - ) + return <>Value: {getValue()}; } ``` @@ -212,21 +205,19 @@ An **[Effect](https://www.solidjs.com/tutorial/introduction_effects)** is an exa ```jsx // src/components/Counter.jsx -import { createSignal, createEffect } from 'solid-js' +import { createSignal, createEffect } from 'solid-js'; export default function Counter() { - const [count, setCount] = createSignal(0) - createEffect(() => count()) - - return ( - <> - - -
The count is now: {count()}
- - ) + const [count, setCount] = createSignal(0); + createEffect(() => count()); + + return ( + <> + + +
The count is now: {count()}
+ + ); } ``` @@ -250,21 +241,20 @@ echo > src/components/Users.jsx ```jsx // src/components/Users.jsx -import { createResource } from 'solid-js' +import { createResource } from 'solid-js'; -const fetchUser = async () => ( - await fetch(`https://jsonplaceholder.typicode.com/users?_limit=5`) -).json() +const fetchUser = async () => + (await fetch(`https://jsonplaceholder.typicode.com/users?_limit=5`)).json(); export default function Users() { - const [user] = createResource(fetchUser) - - return ( -
- {user.loading && 'Loading...'} -
{JSON.stringify(user(), null, 2)}
-
- ) + const [user] = createResource(fetchUser); + + return ( +
+ {user.loading && 'Loading...'} +
{JSON.stringify(user(), null, 2)}
+
+ ); } ``` @@ -273,23 +263,21 @@ This demonstrates the first way of using `createResource` since it involves pass ```jsx // src/routes/index.jsx -import Counter from '../components/Counter' -import Users from '../components/Users' +import Counter from '../components/Counter'; +import Users from '../components/Users'; export default function App() { - return ( -
-
-

A First Look at Solid

- - Learn Solid - - - -
-
- ) + return ( +
+
+

A First Look at Solid

+ Learn Solid + + +
+
+ ); } ``` -![Browser window showing a count of 1 with a list of names](https://media.codingcat.dev/image/upload/v1684519512/main-codingcatdev-photo/courses/solidjs-intro/05-onmount-displaying-users.png) \ No newline at end of file +![Browser window showing a count of 1 with a list of names](https://media.codingcat.dev/image/upload/v1684519512/main-codingcatdev-photo/courses/solidjs-intro/05-onmount-displaying-users.png) diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md index 4a48f19b..3136ff01 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/deployment/+page.md @@ -5,7 +5,7 @@ authors: cloudinary_convert: false cover: https://media.codingcat.dev/image/upload/v1689262234/main-codingcatdev-photo/courses/solidjs-intro/deployment.png locked: locked -published: draft +published: published slug: deployment title: Deployment weight: 3 @@ -79,4 +79,4 @@ Initialize the Netlify project with `ntl init`. pnpm ntl init ``` -Open [intro-to-solid.netlify.app](https://intro-to-solid.netlify.app/). \ No newline at end of file +Open [intro-to-solid.netlify.app](https://intro-to-solid.netlify.app/). diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md index 110c978f..46924da1 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/fundamentals/+page.md @@ -4,7 +4,7 @@ authors: - anthony-campolo cloudinary_convert: false cover: https://media.codingcat.dev/image/upload/v1684519320/main-codingcatdev-photo/courses/solidjs-intro/fundamentals.png -published: draft +published: published section: Getting Started title: Fundamentals weight: 1 @@ -44,24 +44,24 @@ Also make sure that `type` is set to `module` in `package.json`. ```json { - "name": "into-to-solid", - "description": "An example SolidJS application using Solid Router and Vite", - "type": "module", - "keywords": [ "SolidJS" ], - "author": "Anthony Campolo", - "license": "MIT", - "scripts": { - "dev": "vite", - "build": "vite build", - "serve": "vite preview" - }, - "devDependencies": { - "@solidjs/meta": "^0.28.0", - "@solidjs/router": "^0.4.3", - "solid-js": "^1.5.5", - "vite": "^3.1.3", - "vite-plugin-solid": "^2.3.6" - } + "name": "into-to-solid", + "description": "An example SolidJS application using Solid Router and Vite", + "type": "module", + "keywords": ["SolidJS"], + "author": "Anthony Campolo", + "license": "MIT", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview" + }, + "devDependencies": { + "@solidjs/meta": "^0.28.0", + "@solidjs/router": "^0.4.3", + "solid-js": "^1.5.5", + "vite": "^3.1.3", + "vite-plugin-solid": "^2.3.6" + } } ``` @@ -71,17 +71,17 @@ Create a `vite.config.js` file. echo > vite.config.js ``` -Vite works with multiple frameworks that use different syntaxes and file types like React, Vue, and Svelte. Vite will know what to expect and how to handle different frameworks through plugins in its configuration file. +Vite works with multiple frameworks that use different syntaxes and file types like React, Vue, and Svelte. Vite will know what to expect and how to handle different frameworks through plugins in its configuration file. ```js // vite.config.js -import { defineConfig } from 'vite' -import solidPlugin from 'vite-plugin-solid' +import { defineConfig } from 'vite'; +import solidPlugin from 'vite-plugin-solid'; export default defineConfig({ - plugins: [solidPlugin()] -}) + plugins: [solidPlugin()] +}); ``` Here we have defined our Vite configuration with the Solid Plugin. It is imported as `solidPlugin` from `vite-plugin-solid` and added to the `plugins` array inside Vite's `defineConfig` helper. @@ -99,20 +99,20 @@ The root Solid component will be imported as an ESM module from `/src/root.jsx` ```html - + - - - - - A First Look at Solid - - - - -
- - + + + + + A First Look at Solid + + + + +
+ + ``` @@ -136,22 +136,20 @@ The root `render` function takes two arguments: // src/root.jsx /* @refresh reload */ -import { render } from 'solid-js/web' +import { render } from 'solid-js/web'; function App() { - return ( -
-
-

A First Look at Solid

- - Learn Solid - -
-
- ) + return ( +
+
+

A First Look at Solid

+ Learn Solid +
+
+ ); } -render(() => , document.getElementById('root')) +render(() => , document.getElementById('root')); ``` Here, the `App` component is the top-level component for the application where your main application logic resides. `document.getElementById('root')` is the DOM node that the application will be mounted to. @@ -169,4 +167,4 @@ pnpm dev Open [localhost:5173](http://localhost:5173/) to view the running application in your browser. The page will reload if you make edits. -![Showing SolidJS running on localhost:5173](https://media.codingcat.dev/image/upload/v1684519512/main-codingcatdev-photo/courses/solidjs-intro/01-solid-home-page-on-localhost-5173.png) \ No newline at end of file +![Showing SolidJS running on localhost:5173](https://media.codingcat.dev/image/upload/v1684519512/main-codingcatdev-photo/courses/solidjs-intro/01-solid-home-page-on-localhost-5173.png) diff --git a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/solidstart/+page.md b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/solidstart/+page.md index dd885ae6..a6a58734 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/solidstart/+page.md +++ b/apps/codingcatdev/src/routes/(content-single)/course/intro-to-solid-js/lesson/solidstart/+page.md @@ -5,7 +5,7 @@ authors: cloudinary_convert: false cover: https://media.codingcat.dev/image/upload/v1689262234/main-codingcatdev-photo/courses/solidjs-intro/solidstart.png locked: locked -published: draft +published: published slug: solidstart section: SolidStart title: SolidStart @@ -18,11 +18,11 @@ Change your `dev`, `build`, and `start` scripts to use the `solid-start` command ```json { - "scripts": { - "dev": "solid-start dev", - "build": "solid-start build", - "start": "solid-start start" - } + "scripts": { + "dev": "solid-start dev", + "build": "solid-start build", + "start": "solid-start start" + } } ``` @@ -33,14 +33,14 @@ In `vite.config.js`, remove the `solidPlugin` from `vite-plugin-solid` and repla ```jsx // vite.config.js -import { defineConfig } from 'vite' -import solid from 'solid-start/vite' +import { defineConfig } from 'vite'; +import solid from 'solid-start/vite'; // import solidPlugin from "vite-plugin-solid" export default defineConfig({ - plugins: [solid()] - // plugins: [solidPlugin()] -}) + plugins: [solid()] + // plugins: [solidPlugin()] +}); ``` ### Client and Server Entry @@ -57,11 +57,9 @@ echo > src/entry-server.jsx ```jsx // src/entry-client.jsx -import { mount, StartClient } from 'solid-start/entry-client' +import { mount, StartClient } from 'solid-start/entry-client'; -mount( - () => , document -) +mount(() => , document); ``` `entry-server.jsx` is where your app starts on the server. `` wraps our application root and also includes `Context` providers for routing and meta data. It accepts an `event` and passes it to the `renderAsync(codeFn, options)` middleware which then calls Solid's `renderToStringAsync` under the hood to asynchronously render the application. This responds when the page has been fully loaded and rendered. @@ -69,13 +67,9 @@ mount( ```jsx // src/entry-server.jsx -import { - StartServer, createHandler, renderAsync -} from 'solid-start/entry-server' +import { StartServer, createHandler, renderAsync } from 'solid-start/entry-server'; -export default createHandler( - renderAsync((event) => ) -) +export default createHandler(renderAsync((event) => )); ``` All `Suspense` and data loading on initial load happens on the server. `Event` objects that originate from our underlying runtime are passed with a `PageEvent` object containing the following information: @@ -98,31 +92,29 @@ Notably, it provides a space for defining ``, positioning ` - - - - - - - - - - - - - - - - ) + return ( + + + + + + + + + + + + + + + + + ); } ``` @@ -165,15 +157,17 @@ Return to `vite.config.js` and import `netlify` from `solid-start-netlify`. Set ```jsx // vite.config.js -import { defineConfig } from 'vite' -import solid from 'solid-start/vite' -import netlify from 'solid-start-netlify' +import { defineConfig } from 'vite'; +import solid from 'solid-start/vite'; +import netlify from 'solid-start-netlify'; export default defineConfig({ - plugins: [solid({ - adapter: netlify({ edge: true }) - })] -}) + plugins: [ + solid({ + adapter: netlify({ edge: true }) + }) + ] +}); ``` -Push your new changes to GitHub and your Netlify website should rebuild and update automatically. \ No newline at end of file +Push your new changes to GitHub and your Netlify website should rebuild and update automatically. diff --git a/apps/codingcatdev/src/routes/(home-partials)/(home-pro-benefits)/HomeProBenefits.svelte b/apps/codingcatdev/src/routes/(home-partials)/(home-pro-benefits)/HomeProBenefits.svelte index d1b0b1cb..ddc155ba 100644 --- a/apps/codingcatdev/src/routes/(home-partials)/(home-pro-benefits)/HomeProBenefits.svelte +++ b/apps/codingcatdev/src/routes/(home-partials)/(home-pro-benefits)/HomeProBenefits.svelte @@ -8,16 +8,20 @@ import { inView } from '$lib/actions/inView'; import { fade } from 'svelte/transition'; let priceVisible = false; + export let login = false; -
+
-
- - - -
+ {#if !login} +
+ + + +
+ {/if} +
@@ -80,7 +84,7 @@ on:enter={() => (priceVisible = true)} on:exit={() => (priceVisible = false)} > - +
diff --git a/apps/codingcatdev/src/routes/(home-partials)/(home-pro-benefits)/ProSelect.svelte b/apps/codingcatdev/src/routes/(home-partials)/(home-pro-benefits)/ProSelect.svelte index e7a73d07..98daac30 100644 --- a/apps/codingcatdev/src/routes/(home-partials)/(home-pro-benefits)/ProSelect.svelte +++ b/apps/codingcatdev/src/routes/(home-partials)/(home-pro-benefits)/ProSelect.svelte @@ -3,6 +3,7 @@ import GitLineGradient from '../(home-campaign)/GitLineGradient.svelte'; let subscription = 1; + export let login = false;
@@ -27,12 +28,21 @@ {/if}
- + {#if login} + + {:else} + + {/if}
diff --git a/apps/codingcatdev/src/routes/(protected)/+layout.server.ts b/apps/codingcatdev/src/routes/(protected)/+layout.server.ts index dab65363..ec92a84d 100644 --- a/apps/codingcatdev/src/routes/(protected)/+layout.server.ts +++ b/apps/codingcatdev/src/routes/(protected)/+layout.server.ts @@ -4,13 +4,16 @@ import { redirect } from '@sveltejs/kit'; export const prerender = false; -export const load = (async ({ url, parent }) => { - const data = await parent(); - if (!allowLocal && !data?.user?.uid) { - throw redirect(307, `/login?redirectTo=${url.pathname}`); - } - return { - products: await getStripeProducts() - }; - -}); \ No newline at end of file +export const load = async ({ url, parent }) => { + const data = await parent(); + if (!allowLocal && !data?.user?.uid) { + throw redirect(307, `/login?redirectTo=${url.pathname}`); + } + console.log(data?.user?.stripeRole); + if (data?.user?.stripeRole && url.searchParams.has('redirectTo')) { + throw redirect(303, url.searchParams.get('redirectTo') || '/'); + } + return { + products: await getStripeProducts() + }; +}; diff --git a/apps/codingcatdev/src/routes/login/+page.server.ts b/apps/codingcatdev/src/routes/login/+page.server.ts index bf51d8bf..825e37cf 100644 --- a/apps/codingcatdev/src/routes/login/+page.server.ts +++ b/apps/codingcatdev/src/routes/login/+page.server.ts @@ -1,41 +1,49 @@ import { ccdCreateSessionCookie } from '$lib/server/firebase'; import type { Actions, PageServerLoad } from './$types'; -import { fail, redirect } from '@sveltejs/kit' +import { fail, redirect } from '@sveltejs/kit'; export const prerender = false; export const actions = { - login: async ({ cookies, url }) => { - const ccdLoginIdToken = cookies.get('__ccdlogin'); + login: async ({ cookies, url }) => { + const ccdLoginIdToken = cookies.get('__ccdlogin'); - if (!ccdLoginIdToken) { - return fail(400, { missing: true }); - } + if (!ccdLoginIdToken) { + return fail(400, { missing: true }); + } - const sessionCookie = await ccdCreateSessionCookie(ccdLoginIdToken); - if (!sessionCookie) { - return fail(400, { incorrect: true }); - } - cookies.set(sessionCookie.name, sessionCookie.sessionCookie, sessionCookie.options); - cookies.set('__ccdlogin', '', { expires: new Date(Date.now() - 3600) }); + const sessionCookie = await ccdCreateSessionCookie(ccdLoginIdToken); + if (!sessionCookie) { + return fail(400, { incorrect: true }); + } + cookies.set(sessionCookie.name, sessionCookie.sessionCookie, sessionCookie.options); + cookies.set('__ccdlogin', '', { expires: new Date(Date.now() - 3600) }); - if (url.searchParams.has('redirectTo')) { - throw redirect(303, url.searchParams.get('redirectTo') || '/'); - } - throw redirect(303, '/'); - }, - logout: async ({ cookies }) => { - console.debug('logging out') - cookies.set('session', '', { expires: new Date(Date.now() - 3600) }); - throw redirect(303, '/'); - } + if (url.searchParams.has('redirectTo')) { + throw redirect(303, url.searchParams.get('redirectTo') || '/'); + } + throw redirect(303, '/'); + }, + logout: async ({ cookies }) => { + console.debug('logging out'); + cookies.set('session', '', { expires: new Date(Date.now() - 3600) }); + throw redirect(303, '/'); + } } satisfies Actions; -export const load = (async ({ parent, url }) => { - const { user } = await parent(); - if (user) throw redirect(303, '/account'); +export const load = async ({ parent, url }) => { + const { user } = await parent(); + if (user) + throw redirect( + 303, + `/account${ + url.searchParams.has('redirectTo') + ? '?redirectTo=' + url.searchParams.get('redirectTo') + : '' + }` + ); - return { - redirectTo: url.searchParams.get('redirectTo') || '' - } -}); \ No newline at end of file + return { + redirectTo: url.searchParams.get('redirectTo') || '' + }; +}; diff --git a/apps/codingcatdev/src/routes/login/+page.svelte b/apps/codingcatdev/src/routes/login/+page.svelte index cb1ae682..e1543ba4 100644 --- a/apps/codingcatdev/src/routes/login/+page.svelte +++ b/apps/codingcatdev/src/routes/login/+page.svelte @@ -9,6 +9,7 @@ import type { PageData } from './$types'; import EmailAuth from './EmailAuth.svelte'; + import HomeProBenefits from '../(home-partials)/(home-pro-benefits)/HomeProBenefits.svelte'; export let data: PageData; $: action = `?/login&redirectTo=${data.redirectTo ? data.redirectTo : '/dashboard'}`; @@ -23,4 +24,5 @@ +