diff --git a/src/SiteGenSPA/components/CardWithOptions/index.js b/src/SiteGenSPA/components/CardWithOptions/index.js
new file mode 100644
index 000000000..9f31157a5
--- /dev/null
+++ b/src/SiteGenSPA/components/CardWithOptions/index.js
@@ -0,0 +1,76 @@
+import { addThemeSuffix } from '../../utils/helper';
+import { Icon, chevronRight } from '@wordpress/icons';
+
+const CardWithOptions = ( { title, options, skip, setSelection } ) => {
+ const buildOptions = () => {
+ return options.map( ( data, idx ) => {
+ return (
+
{
+ setSelection( idx );
+ } }
+ onKeyDown={ () => {
+ setSelection( idx );
+ } }
+ >
+
+
+ { data.title }
+
+
+ { data.desc }
+
+
+
+
+ );
+ } );
+ };
+
+ return (
+
+
+ { title }
+
+
+ { buildOptions() }
+
+
{
+ setSelection( -1 );
+ } }
+ onKeyDown={ () => {
+ setSelection( -1 );
+ } }
+ >
+ { skip }
+
+
+ );
+};
+
+export default CardWithOptions;
diff --git a/src/SiteGenSPA/components/CardWithOptions/stylesheet.scss b/src/SiteGenSPA/components/CardWithOptions/stylesheet.scss
new file mode 100644
index 000000000..80a1c4879
--- /dev/null
+++ b/src/SiteGenSPA/components/CardWithOptions/stylesheet.scss
@@ -0,0 +1,77 @@
+.nfd-sg-card {
+
+ margin: 8px;
+ max-width: 90vw;
+ padding: 24px 12px;
+ border-radius: 12px;
+ background-color: #1e2327;
+ width: clamp(18.75rem, 22.6136rem + 5.6818vw, 31.25rem);
+ box-shadow: 3px 3px 5px rgba($color: #000, $alpha: 0.2);
+
+ &__title {
+ color: #fff;
+ margin: 16px;
+ line-height: 2;
+ font-size: 18px;
+ text-align: center;
+ margin-bottom: 30px;
+ letter-spacing: 1.5px;
+ }
+
+ &__data {
+ margin: 12px;
+
+ &__option {
+ display: flex;
+ cursor: pointer;
+ margin: 16px 4px;
+ align-items: center;
+ border-radius: 4px 4px 0 0;
+ padding: 16px 12px 20px 12px;
+ justify-content: space-between;
+ transition: background-color 400ms ease-in-out;
+
+ &:not(:last-child) {
+ border-bottom: 0.5px solid rgba(255, 255, 255, 0.3);
+ }
+
+ &:hover {
+ background-color: #262c30;
+ }
+
+ &__left_top {
+ color: #fff;
+ font-size: 16px;
+ font-weight: 500;
+ padding-bottom: 12px;
+ }
+
+ &__left_bottom {
+ color: #fff;
+ font-size: 14px;
+ font-weight: 300;
+ }
+
+ &__right {
+ fill: #fff;
+ transition: all 200ms ease-in-out;
+
+ &:hover {
+ transform: scale(1.1);
+ }
+ }
+ }
+ }
+
+ &__skip {
+ cursor: pointer;
+ text-align: end;
+ margin: 0 20px 6px 20px;
+ color: rgba(255, 255, 255, 0.6);
+ transition: color 200ms ease-in-out;
+
+ &:hover {
+ color: #fff;
+ }
+ }
+}
diff --git a/src/SiteGenSPA/components/Loader/contents.js b/src/SiteGenSPA/components/Loader/contents.js
new file mode 100644
index 000000000..3ebb1b078
--- /dev/null
+++ b/src/SiteGenSPA/components/Loader/contents.js
@@ -0,0 +1,32 @@
+import { __ } from '@wordpress/i18n';
+
+const getContents = () => {
+ return {
+ title: __( 'Building Website', 'wp-module-onboarding' ),
+ status: [
+ {
+ title: __( 'Generating Website', 'wp-module-onboarding' ),
+ },
+ {
+ title: __( 'Finding Font Pairings', 'wp-module-onboarding' ),
+ },
+ {
+ title: __(
+ 'Building Custom Color Palettes',
+ 'wp-module-onboarding'
+ ),
+ },
+ {
+ title: __( 'Populating Images', 'wp-module-onboarding' ),
+ },
+ {
+ title: __( 'Finalizing Previews', 'wp-module-onboarding' ),
+ },
+ {
+ title: __( 'Packaging Website', 'wp-module-onboarding' ),
+ },
+ ],
+ };
+};
+
+export default getContents;
diff --git a/src/SiteGenSPA/components/Loader/index.js b/src/SiteGenSPA/components/Loader/index.js
new file mode 100644
index 000000000..eea146bb1
--- /dev/null
+++ b/src/SiteGenSPA/components/Loader/index.js
@@ -0,0 +1,59 @@
+import getContents from './contents';
+import { addThemeSuffix } from '../../utils/helper';
+import { useEffect, useState } from '@wordpress/element';
+
+const Loader = () => {
+ let statusIdx = 0;
+ const content = getContents();
+ const [ percentage, setPercentage ] = useState( 0 );
+ const [ status, setStatus ] = useState( content.status[ statusIdx ].title );
+
+ const checkStatus = async () => {
+ // Make fake API Call to get the status.
+ if ( percentage !== 100 ) setPercentage( ( t ) => t + 10 );
+ };
+
+ useEffect( () => {
+ const statusTimer = setInterval( () => {
+ checkStatus();
+ statusIdx += 1;
+ if ( statusIdx === content.status.length ) statusIdx = 0;
+ setStatus( content.status[ statusIdx ].title );
+ }, 3000 );
+ return () => {
+ clearInterval( statusTimer );
+ };
+ }, [] );
+
+ return (
+
+
+ { content.title }
+
+
+
{ `${ status }...` }
+
+ );
+};
+
+export default Loader;
diff --git a/src/SiteGenSPA/components/Loader/stylesheet.scss b/src/SiteGenSPA/components/Loader/stylesheet.scss
new file mode 100644
index 000000000..5b11e2e46
--- /dev/null
+++ b/src/SiteGenSPA/components/Loader/stylesheet.scss
@@ -0,0 +1,93 @@
+.nfd-sg-loader {
+
+ margin: 8px;
+ max-width: 90vw;
+ padding: 16px 12px;
+ border-radius: 12px;
+ background-color: #1e2327;
+ width: clamp(18.75rem, 22.6136rem + 5.6818vw, 31.25rem);
+ box-shadow: 3px 3px 5px rgba($color: #000, $alpha: 0.2);
+
+ &__title {
+ color: #fff;
+ line-height: 2;
+ font-size: 18px;
+ text-align: center;
+ letter-spacing: 1.5px;
+ }
+
+ &__progress {
+ display: flex;
+ margin: 20px 60px;
+ align-items: center;
+ justify-content: center;
+
+ @media (max-width: #{ ($break-small) }) {
+ margin: 20px 30px;
+ }
+
+ &_bars {
+ width: 100%;
+ display: flex;
+ position: relative;
+ align-items: center;
+ justify-content: start;
+
+ &_bg {
+ height: 6px;
+ width: 100%;
+ border-radius: 6px;
+ background-color: #353a40;
+ }
+
+ &_bar {
+ top: 0;
+ height: 6px;
+ max-width: 100%;
+ border-radius: 6px;
+ position: absolute;
+ background-color: #0060f0;
+ transition: width 2s ease-in-out;
+ }
+ }
+ }
+
+ &__status {
+ color: #fff;
+ line-height: 2;
+ font-size: 14px;
+ text-align: center;
+ letter-spacing: 1.3px;
+ animation: anim 3s ease-out infinite;
+ }
+}
+
+@keyframes bar {
+
+ 0% {
+ width: 0%;
+ }
+
+ 100% {
+ width: 100%;
+ }
+}
+
+@keyframes anim {
+
+ 0% {
+ opacity: 0.1;
+ }
+
+ 25% {
+ opacity: 1;
+ }
+
+ 75% {
+ opacity: 1;
+ }
+
+ 100% {
+ opacity: 0.1;
+ }
+}
diff --git a/src/SiteGenSPA/steps/ExperienceLevel/contents.js b/src/SiteGenSPA/steps/ExperienceLevel/contents.js
new file mode 100644
index 000000000..246dbb06e
--- /dev/null
+++ b/src/SiteGenSPA/steps/ExperienceLevel/contents.js
@@ -0,0 +1,36 @@
+import { __ } from '@wordpress/i18n';
+
+const getContents = () => {
+ return {
+ heading: __(
+ 'How familiar are you with using WordPress?',
+ 'wp-module-onboarding'
+ ),
+ options: [
+ {
+ title: __( 'Beginner', 'wp-module-onboarding' ),
+ desc: __(
+ 'First time here, where am I?',
+ 'wp-module-onboarding'
+ ),
+ },
+ {
+ title: __( 'Used it some', 'wp-module-onboarding' ),
+ desc: __(
+ "I'll ask for help when I need it",
+ 'wp-module-onboarding'
+ ),
+ },
+ {
+ title: __( 'Expert', 'wp-module-onboarding' ),
+ desc: __(
+ "Stay out of my way, I know what I'm doing",
+ 'wp-module-onboarding'
+ ),
+ },
+ ],
+ skip: __( 'Skip', 'wp-module-onboarding' ),
+ };
+};
+
+export default getContents;
diff --git a/src/SiteGenSPA/steps/ExperienceLevel/index.js b/src/SiteGenSPA/steps/ExperienceLevel/index.js
new file mode 100644
index 000000000..fc9bc0dfb
--- /dev/null
+++ b/src/SiteGenSPA/steps/ExperienceLevel/index.js
@@ -0,0 +1,33 @@
+import getContents from './contents';
+import Loader from '../../components/Loader';
+import { addThemeSuffix } from '../../utils/helper';
+import CommonLayout from '../../../Shared/Layouts/Common';
+import CardWithOptions from '../../components/CardWithOptions';
+import { useEffect, useState } from '@wordpress/element';
+
+const ExperienceLevel = () => {
+ const content = getContents();
+ // Index of the selection user makes
+ const [ selection, setSelection ] = useState();
+
+ useEffect( () => {
+ // undefined => not selected, 0-2 => Selections, -1 => Skip
+ // console.log( 'Selection changed to', selection );
+ }, [ selection ] );
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+export default ExperienceLevel;
diff --git a/src/SiteGenSPA/steps/ExperienceLevel/stylesheet.scss b/src/SiteGenSPA/steps/ExperienceLevel/stylesheet.scss
new file mode 100644
index 000000000..ee5e0c38f
--- /dev/null
+++ b/src/SiteGenSPA/steps/ExperienceLevel/stylesheet.scss
@@ -0,0 +1,6 @@
+.nfd-sg-experience-level {
+ display: flex;
+ align-items: center;
+ flex-direction: column;
+ justify-content: center;
+}
diff --git a/src/SiteGenSPA/styles/app.scss b/src/SiteGenSPA/styles/app.scss
index e7c26a745..6de94e0f3 100644
--- a/src/SiteGenSPA/styles/app.scss
+++ b/src/SiteGenSPA/styles/app.scss
@@ -12,11 +12,14 @@
@import "../components/Header/stylesheet";
@import "../components/AIHeading/stylesheet";
@import "../components/TextInput/stylesheet";
+@import "../components/CardWithOptions/stylesheet";
@import "../components/Navigation/NextButton/stylesheet";
-@import "../steps/CustomerDetail/stylesheet";
+@import "../components/Loader/stylesheet";
// CSS for Pages
@import "../steps/SiteGenGetStarted/stylesheet";
+@import "../steps/CustomerDetail/stylesheet";
+@import "../steps/ExperienceLevel/stylesheet";
.nfd-onboarding-container {
display: flex;