{
const [showVideo, setShowVideo] = React.useState(false);
@@ -213,7 +213,7 @@ const Player = ({
position="relative"
boxShadow={image_thumb?.shadow && "20px 15px 0px 0px rgba(0,0,0,1)"}
//border={image_thumb?.shadow && "3px solid black"}
- style={imgStyles && {...JSON.parse(image_thumb?.style)}}
+ style={imgStyles && { ...JSON.parse(image_thumb?.style) }}
>
{id && (
)}
{thumb && thumb.childImageSharp ? (
@@ -272,13 +272,13 @@ const Player = ({
export default Player;
Player.defaultProps = {
- onPlay: () => { },
- onPause: () => { },
- onEnd: () => { },
- onError: () => { },
- onStateChange: () => { },
- onPlaybackRateChange: () => { },
- onPlaybackQualityChange: () => { },
+ onPlay: () => {},
+ onPause: () => {},
+ onEnd: () => {},
+ onError: () => {},
+ onStateChange: () => {},
+ onPlaybackRateChange: () => {},
+ onPlaybackQualityChange: () => {},
imageSize: "default",
playerVars: {},
noCookies: false,
@@ -320,11 +320,11 @@ Player.propTypes = {
};
const Play = styled.button`
- background: ${(props) => props.background || "rgba(0, 0, 0, 0.7)"} ;
+ background: ${(props) => props.background || "rgba(0, 0, 0, 0.7)"};
border-radius: 3px;
color: ${(props) => props.white};
font-size: 1em;
- height: 36px;
+ height: 36px;
padding: 0;
text-align: center;
text-indent: 0.1em;
@@ -333,9 +333,13 @@ const Play = styled.button`
position: absolute !important;
top: 50%;
left: 50%;
- transform: ${(props) => props.transformPlay || "translateX(-50%) translateY(-50%)"}; {/*translateX(-50%) translateY(-50%);*/}
+ transform: ${(props) =>
+ props.transformPlay || "translateX(-50%) translateY(-50%)"};
+ {
+ /*translateX(-50%) translateY(-50%);*/
+ }
border: none;
- opacity: ${(props) => props.opacity || "0.8"};
+ opacity: ${(props) => props.opacity || "0.8"};
cursor: pointer;
z-index: 9;
&:hover {
diff --git a/src/components/Sections/index.js b/src/components/Sections/index.js
index 0b2a90248..f7e66b7bf 100644
--- a/src/components/Sections/index.js
+++ b/src/components/Sections/index.js
@@ -215,7 +215,7 @@ export const Div = styled.div`
margin: ${(props) => props.margin_xs};
display: ${(props) => props.display_xs};
justify-content: ${(props) =>
- justifyContentOptions[props.justifyContent_xs]};
+ justifyContentOptions[props.justifyContent_xs]};
order: ${(props) => props.order_xs};
border: ${(props) => props.border_xs};
border-top: ${(props) => props.borderTop_xs};
@@ -230,7 +230,7 @@ export const Div = styled.div`
@media ${Devices.sm} {
padding: ${(props) => props.padding_sm};
justify-content: ${(props) =>
- justifyContentOptions[props.justifyContent_sm]};
+ justifyContentOptions[props.justifyContent_sm]};
height: ${(props) => props.height_sm};
position: ${(props) => props.position_sm};
margin: ${(props) => props.margin_sm};
@@ -250,16 +250,16 @@ export const Div = styled.div`
}
@media ${Devices.tablet} {
flex: ${(props) =>
- props.flex_tablet || props.size_tablet
- ? `0 0 ${(props.size_tablet / 12) * 100}%`
- : null};
+ props.flex_tablet || props.size_tablet
+ ? `0 0 ${(props.size_tablet / 12) * 100}%`
+ : null};
flex-flow: ${(props) => props.flexFlow_tablet};
max-width: ${(props) =>
- props.size_tablet ? `${(props.size_tablet / 12) * 100}%` : null};
+ props.size_tablet ? `${(props.size_tablet / 12) * 100}%` : null};
max-width: ${(props) =>
- props.maxWidth_tablet
- ? props.maxWidth_tablet
- : props.size_tablet
+ props.maxWidth_tablet
+ ? props.maxWidth_tablet
+ : props.size_tablet
? `${(props.size_tablet / 12) * 100}%`
: null};
align-self: ${(props) => props.alignSelf_tablet};
@@ -283,7 +283,7 @@ export const Div = styled.div`
height: ${(props) => props.height_tablet};
flex: ${(props) => props.flex_tablet};
flex-shrink: ${(props) =>
- props.flexShrink_tablet ? props.flexShrink_tablet : 1};
+ props.flexShrink_tablet ? props.flexShrink_tablet : 1};
flex-wrap: ${(props) => props.flexWrap_tablet};
border: ${(props) => props.border_tablet};
border-top: ${(props) => props.borderTop_tablet};
@@ -300,7 +300,7 @@ export const Div = styled.div`
grid-row: ${(props) => props.gridRow_tablet};
justify-self: ${(props) => props.justifySelf_tablet};
justify-content: ${(props) =>
- justifyContentOptions[props.justifyContent_tablet]};
+ justifyContentOptions[props.justifyContent_tablet]};
z-index: ${(props) => props.zIndex_tablet};
top: ${(props) => props.top_tablet};
bottom: ${(props) => props.bottom_tablet};
@@ -312,11 +312,11 @@ export const Div = styled.div`
}
@media ${Devices.md} {
flex: ${(props) =>
- props.size_md ? `0 0 ${(props.size_md / 12) * 100}%` : null};
+ props.size_md ? `0 0 ${(props.size_md / 12) * 100}%` : null};
max-width: ${(props) =>
- props.maxWidth_md
- ? props.maxWidth_md
- : props.size_md
+ props.maxWidth_md
+ ? props.maxWidth_md
+ : props.size_md
? `${(props.size_md / 12) * 100}%`
: null};
min-width: ${(props) => props.minWidth_md};
@@ -326,7 +326,7 @@ export const Div = styled.div`
gap: ${(props) => (props) => props.gap_md};
flex-wrap: ${(props) => props.flexWrap_md};
justify-content: ${(props) =>
- justifyContentOptions[props.justifyContent_md]};
+ justifyContentOptions[props.justifyContent_md]};
text-align: ${(props) => props.textAlign_md};
align-items: ${(props) => props.alignItems_md};
margin: ${(props) => props.margin_md};
@@ -345,7 +345,7 @@ export const Div = styled.div`
@media ${Devices.lg} {
display: ${(props) => props.display_lg};
justify-content: ${(props) =>
- justifyContentOptions[props.justifyContent_lg]};
+ justifyContentOptions[props.justifyContent_lg]};
padding: ${(props) => props.padding_lg};
max-width: ${(props) => props.maxWidth_lg};
min-width: ${(props) => props.minWidth_lg};
@@ -387,18 +387,18 @@ export const Grid = styled(Div)`
grid-template-areas: ${(props) => props.gridTemplateAreas};
@media ${Devices.xxs} {
grid-template-columns: ${(props) =>
- props.columns_xxs ? `repeat(${props.columns_xxs}, 1fr)` : null};
+ props.columns_xxs ? `repeat(${props.columns_xxs}, 1fr)` : null};
}
@media ${Devices.xs} {
grid-template-columns: ${(props) =>
- props.columns_xs ? `repeat(${props.columns_xs}, 1fr)` : null};
+ props.columns_xs ? `repeat(${props.columns_xs}, 1fr)` : null};
display: ${(props) => props.display_xs || "grid"};
}
@media ${Devices.sm} {
grid-template-columns: ${(props) =>
- props.gridTemplateColumns_sm
- ? `repeat(${props.gridTemplateColumns_sm}, 1fr)`
- : null};
+ props.gridTemplateColumns_sm
+ ? `repeat(${props.gridTemplateColumns_sm}, 1fr)`
+ : null};
display: ${(props) => props.display_sm || "grid"};
}
@media ${Devices.tablet} {
@@ -407,13 +407,13 @@ export const Grid = styled(Div)`
display: ${(props) => props.display_tablet || "grid"};
width: ${(props) => props.width_tablet};
grid-template-columns: ${(props) =>
- props.gridTemplateColumns_tablet
- ? `${props.gridTemplateColumns_tablet}`
- : "2fr repeat(12, 1fr) 2fr"};
+ props.gridTemplateColumns_tablet
+ ? `${props.gridTemplateColumns_tablet}`
+ : "2fr repeat(12, 1fr) 2fr"};
grid-template-rows: ${(props) =>
- props.gridTemplateRows_tablet
- ? `repeat(${props.gridTemplateRows_tablet})`
- : null};
+ props.gridTemplateRows_tablet
+ ? `repeat(${props.gridTemplateRows_tablet})`
+ : null};
grid-gap: ${(props) => props.gridGap_tablet};
grid-auto-rows: ${(props) => props.gridAutoRows_tablet};
grid-column: ${(props) => props.gridColumn_tablet};
@@ -425,9 +425,9 @@ export const Grid = styled(Div)`
margin: ${(props) => props.margin_md};
grid-template-columns: ${(props) => props.gridTemplateColumns_md};
grid-template-rows: ${(props) =>
- props.gridTemplateRows_md
- ? `repeat(${props.gridTemplateRows_md})`
- : null};
+ props.gridTemplateRows_md
+ ? `repeat(${props.gridTemplateRows_md})`
+ : null};
grid-gap: ${(props) => props.gridGap_md};
grid-column: ${(props) => props.gridColumn_md};
display: ${(props) => props.display_md || "grid"};
@@ -456,28 +456,28 @@ export const Old_Grid = styled.div`
margin: ${(props) => props.margin};
@media ${Devices.xxs} {
grid-template-columns: ${(props) =>
- props.columns_xxs ? `repeat(${props.columns_xxs}, 1fr)` : null};
+ props.columns_xxs ? `repeat(${props.columns_xxs}, 1fr)` : null};
}
@media ${Devices.xs} {
grid-template-columns: ${(props) =>
- props.columns_xs ? `repeat(${props.columns_xs}, 1fr)` : null};
+ props.columns_xs ? `repeat(${props.columns_xs}, 1fr)` : null};
}
@media ${Devices.sm} {
grid-template-columns: ${(props) =>
- props.columns_sm ? `repeat(${props.columns_sm}, 1fr)` : null};
+ props.columns_sm ? `repeat(${props.columns_sm}, 1fr)` : null};
}
@media ${Devices.tablet} {
grid-template-columns: ${(props) =>
- props.columns_tablet ? `repeat(${props.columns_tablet}, 1fr)` : null};
+ props.columns_tablet ? `repeat(${props.columns_tablet}, 1fr)` : null};
grid-template-rows: ${(props) =>
- props.rows_tablet ? `repeat(${props.rows_tablet}, 5vw)` : null};
+ props.rows_tablet ? `repeat(${props.rows_tablet}, 5vw)` : null};
padding: ${(props) => props.padding_tablet};
}
@media ${Devices.md} {
grid-template-columns: ${(props) =>
- props.columns_md ? `repeat(${props.columns_md})` : null};
+ props.columns_md ? `repeat(${props.columns_md})` : null};
grid-template-rows: ${(props) =>
- props.rows_md ? `repeat(${props.rows_md})` : null};
+ props.rows_md ? `repeat(${props.rows_md})` : null};
grid-gap: ${(props) => props.gridGap_md};
height: ${(props) => props.height_md};
padding: ${(props) => props.padding_md};
@@ -486,16 +486,16 @@ export const Old_Grid = styled.div`
}
@media ${Devices.lg} {
grid-template-columns: ${(props) =>
- props.columns_lg ? `repeat(${props.columns_lg}, 1fr)` : null};
+ props.columns_lg ? `repeat(${props.columns_lg}, 1fr)` : null};
padding: ${(props) => props.padding_lg};
}
@media ${Devices.xl} {
grid-template-columns: ${(props) =>
- props.columns_xl ? `repeat(${props.columns_xl}, 1fr)` : null};
+ props.columns_xl ? `repeat(${props.columns_xl}, 1fr)` : null};
}
@media ${Devices.xxl} {
grid-template-columns: ${(props) =>
- props.columns_xxl ? `repeat(${props.columns_xxl}, 1fr)` : null};
+ props.columns_xxl ? `repeat(${props.columns_xxl}, 1fr)` : null};
}
`;
@@ -647,6 +647,9 @@ export const GridContainer = ({
childHeight,
displayChild,
displayChild_tablet,
+ displayChild_xs,
+ displayChild_sm,
+ displayChild_md,
columns_sm,
justifyContentChild,
}) => {
@@ -686,7 +689,10 @@ export const GridContainer = ({
Aprovecha esta alianza y forma parte de la evolución tecnológica a nivel mundial ¡Comienza HOY!
+ button:
+ text: "Únete a la Academia"
+ background: black
+ color: white
+ hover_color: "#white"
+ path: "#top"
badges:
diff --git a/src/data/landing/costa-rica-curso-de-programacion.es.yml b/src/data/landing/costa-rica-curso-de-programacion.es.yml
index 7e8620cb0..44584b998 100644
--- a/src/data/landing/costa-rica-curso-de-programacion.es.yml
+++ b/src/data/landing/costa-rica-curso-de-programacion.es.yml
@@ -91,6 +91,29 @@ follow_bar:
# ⬇ FROM HERE ON YOU CAN COMMENT ANYTHING TO HIDE IT ON THE LANDING ⬇
#
components:
+ - name: some_id
+ position: 3
+ layout: two_column_right
+ background: "lightBlue2"
+ image:
+ style: '{ "border" : "3px solid black" }'
+ shadow: true
+ src: "../../../static/images/testimonials/Mattia-Tozzi-testimonial.jpg"
+ video: "B01-eTfgqqc"
+ heading:
+ text: "El viaje de Mattia Tozzi en 4geeks Academy y como cambió su vida profesional."
+ #xl lg md sm xs
+ font_size: ["40px", "34px", "34px", "25px", "20px"]
+ content:
+ text: "Conoce la historia inspiradora de Mattia Tozzi, quien, buscando un cambio en su carrera, se unió a 4Geeks Academy. Su experiencia demuestra cómo la dedicación y el aprendizaje en este bootcamp lo llevaron a convertirse en un profesional altamente capacitado."
+ font_size: ["16px"]
+ button:
+ text: "Unete a la academia!"
+ path: "#bottom"
+ color: "white"
+ background: "black"
+ hover: "lightBlue"
+
- name: top_coding_bootcamp
position: 1
layout: two_column_left
@@ -128,7 +151,7 @@ rating_reviews:
url: ""
badges:
- position: 3
+ position: 7
heading: "4Geeks Academy cuenta con premios y reconocimientos que validan su excelencia"
program_details:
@@ -148,3 +171,4 @@ who_is_hiring:
heading: "¿Quién contrata a nuestros alumnos?"
sub_heading: "84% de nuestros estudiantes que completaron el proceso de GeekFORCE han conseguido trabajo luego de haberse graduado (incluso dentro de los sigiuientes 100 días)"
+
diff --git a/src/data/landing/madrid-curso-de-programacion.es.yml b/src/data/landing/madrid-curso-de-programacion.es.yml
index 10ff1d07b..8ef34693e 100644
--- a/src/data/landing/madrid-curso-de-programacion.es.yml
+++ b/src/data/landing/madrid-curso-de-programacion.es.yml
@@ -9,7 +9,7 @@ meta_info:
template: "landing_a" # <--- choose your landing template
redirects: # <--- URL redirections to avoid 404 errors
- ["/landing/coding-course"]
+ ["/landing/coding-course", "/es/landing/curso-de-programacion"]
# Set a particular course or location to the landing page
# this UTM fields will be also included in the CRM contact
@@ -127,12 +127,12 @@ geeks_vs_others:
total_rows: 5
why_4geeks:
- position: 5
+ position: 6
heading: "¿Por qué debes estudiar en 4Geeks Academy?"
sub_heading: " "
who_is_hiring:
- position: 6
+ position: 7
limit: 4
heading: "Empresas que contratan a nuestros estudiantes"
sub_heading: "Más de 500 partners y más de 150 vacantes abiertas como Full-Stack Developer"
@@ -143,6 +143,29 @@ who_is_hiring:
# sub_heading: "Take a look at our previous student projects"
components:
+ - name: some_id
+ position: 5
+ layout: two_column_right
+ background: "lightYellow"
+ image:
+ style: '{ "border" : "3px solid black" }'
+ shadow: true
+ src: "../../../static/images/testimonials/Mattia-Tozzi-testimonial.jpg"
+ video: "B01-eTfgqqc"
+ heading:
+ text: "El viaje de Mattia Tozzi en 4geeks Academy y como cambió su vida profesional."
+ #xl lg md sm xs
+ font_size: ["40px", "34px", "34px", "25px", "20px"]
+ content:
+ text: "Descubre la historia de Mattia Tozzi, quien decidió unirse a 4Geeks Academy en busca de un cambio en su carrera profesional. Su experiencia demuestra cómo la dedicación y el aprendizaje en este bootcamp lo llevaron a convertirse en un profesional altamente capacitado en España."
+ font_size: ["16px"]
+ button:
+ text: "Unete a la academia!"
+ path: "#bottom"
+ color: "white"
+ background: "black"
+ hover: "lightBlue"
+
- name: python_y_javascript
position: 1
layout: two_column_right
diff --git a/src/data/landing/mexico-curso-programacion.es.yml b/src/data/landing/mexico-curso-programacion.es.yml
index 7e184cd52..142c0165d 100644
--- a/src/data/landing/mexico-curso-programacion.es.yml
+++ b/src/data/landing/mexico-curso-programacion.es.yml
@@ -92,7 +92,7 @@ follow_bar:
#
rating_reviews:
- position: 2
+ position: 3
heading: "Lee acerca de nosotros"
rating_list:
- alt: "Career Karma"
@@ -139,3 +139,26 @@ who_is_hiring:
heading: "¿Quién contrata a nuestros alumnos?"
sub_heading: "84% de nuestros estudiantes que completaron el proceso de GeekFORCE han conseguido trabajo luego de haberse graduado (incluso dentro de los sigiuientes 100 días)"
+components:
+ - name: some_id
+ position: 2
+ layout: two_column_right
+ background: "lightBlue2"
+ image:
+ style: '{ "border" : "3px solid black" }'
+ # shadow: true
+ src: "../../../static/images/testimonials/samantha-review.png"
+ video: "https://www.youtube.com/watch?v=32a-phct9I0"
+ heading:
+ text: "4Geeks en México La Elección de Samantha para su Bootcamp Ideal"
+ #xl lg md sm xs
+ font_size: ["40px", "34px", "34px", "25px", "20px"]
+ content:
+ text: "La excelencia en el contenido del curso, la dedicada mentoría individual y las sólidas colaboraciones industriales son solo algunos de los aspectos que destacan a 4Geeks. Además, el historial de éxito de los graduados respalda la reputación de la institución."
+ font_size: ["16px"]
+ button:
+ text: "Unete a la academia!"
+ path: "https://4geeksacademy.com/us/coding-campus/coding-bootcamp-mexico"
+ color: "white"
+ background: "black"
+ hover: "lightBlue"
\ No newline at end of file
diff --git a/src/data/landing/no-excuses.us.yml b/src/data/landing/no-excuses.us.yml
index bb727d5c6..972fe8f16 100644
--- a/src/data/landing/no-excuses.us.yml
+++ b/src/data/landing/no-excuses.us.yml
@@ -27,7 +27,7 @@ form:
# always the first_name, email and phone will be mandatory if added.
fields: ["full_name", "phone", "email"]
heading: "Join our award-winning Coding Program"
- motivation: "Fill out the form and get the scholarship towards your tuition at 4Geeks. Only 85 seats remain available."
+ motivation: "Fill out the form and get a Scholarship to reduce your tuition at 4Geeks. A few seats remain available."
button_label: Get more info Now
redirect: null #you can redirect to another url or entirely diffrent website
@@ -39,7 +39,7 @@ apply_schollarship: # form that is displayed at the end of the landing
# jumbotron on the top (cannot be commented out)
header_data:
background: "#FFF1D1"
- tagline: No Excuses. Boost your career. Money is what you’ll make!
+ tagline: No Excuses. The Go-to Coding Bootcamp in Florida.
badge: "../../../static/images/badges/Course-Report-Badge-2023.png"
image_filter: brightness(0.3)
@@ -50,9 +50,9 @@ features:
styles: '{ "fontSize": "20px", "margin": "10px 0px 10px 0px" }'
text: With our expertise and your hard work, you'll be a professional developer in just 18 weeks!
bullets:
- - Scholarships available. Award winning Bootcamp at the Best pricing
- - Unlimited Mentorship and senior support FOREVER
- - 84% placement rate
+ - Money is not excuse. Best pricing (ask for scholarships)
+ - Unlimited Mentorship and lifetime access to career services
+ - Award winning Florida Bootcamp (Miami, Orlando, Boca, and online!)
- Job placement rate of 81%
- "Part-time: it’s immersive but with a flexible schedule"
diff --git a/src/prompt/prompt.awards.js b/src/prompt/prompt.awards.js
new file mode 100644
index 000000000..2f0ff2179
--- /dev/null
+++ b/src/prompt/prompt.awards.js
@@ -0,0 +1,29 @@
+const fs = require("fs");
+const { toYML, loadYML } = require("../test/_utils");
+
+async function generate() {
+ const max_tokens = 400;
+ console.log(`Starting to generate a prompt for all the academy awards`);
+
+ const doc = loadYML(`${__dirname}/../data/page/awards.us.yml`);
+ let awards = doc.yaml.awards_list.map((old) => {
+ let _new = [
+ `Award title: ${old.title}`,
+ `Description of the award: as ${old.paragraph}`,
+ ];
+ // if(old.linkedin_url) _new.push(`LinkedIn profile URL: ${old.linkedin_url}`);
+ return _new.join("\n");
+ });
+
+ fs.writeFileSync(
+ `./prompts/awards.prompt`,
+ [
+ `The following are awards and recognitions 4Geeks Academy has received thru the years:`,
+ awards.join("\n\n---\n\n"),
+ `You can learn more about the awards here: https://4geeksacademy.com/us/${doc.yaml.meta_info.slug}`,
+ ].join("\n\n"),
+ "utf8"
+ );
+ console.log(`Finished generating awards.`);
+}
+generate();
diff --git a/src/prompt/prompt.course.js b/src/prompt/prompt.course.js
new file mode 100644
index 000000000..f6ccc56a2
--- /dev/null
+++ b/src/prompt/prompt.course.js
@@ -0,0 +1,47 @@
+const fs = require("fs");
+const { complete, getCourses } = require("./utils.js");
+const { toYML } = require("../test/_utils");
+
+async function generate() {
+ console.log(
+ `Starting to generate a prompt for all the academy course offerings`
+ );
+ const max_tokens = 400;
+ const courses = await getCourses();
+ const activeCourses = Object.keys(courses).filter(
+ (slug) => courses[slug].meta_info.show_in_apply
+ );
+ for (let courseSlug of activeCourses) {
+ console.log(`Summarizing prompt information for program: ${courseSlug}`);
+ const old = courses[courseSlug];
+ const course = {};
+ course.title = old.meta_info.title;
+ course.description = old.meta_info.description;
+ course.website = `https://4geeksacademy.com/us/coding-bootcamps/${old.meta_info.slug}`;
+ course.highlight = old.header.paragraph;
+ course.instructors = old.course_instructors.instructors;
+ course.about = old.details.about;
+ course.details = old.details.list;
+ course.duration = `${old.weeks} ${old.weeks_label}`;
+ course.modules = old.details_modules;
+ const raw = toYML(course);
+
+ const answer = await complete({
+ max_tokens,
+ system: `You are like a senior prompt engineer with deep coding knowledge, very familiar with the YML, CSV and JSON syntax.`,
+ user: `The following information is part of 4Geeks Academy courses and bootcamps.
+Read and understand the information and write a summary of the courses available.
+Do not include any information about these instructions in your answer.
+Include the word "stop" at the end of your answer.
+Inlcude the website url for more information.
+Be concise, don't add a summary at the end of the article.
+Don't take more than ${max_tokens * 2} characters.
+Here is the YML: ${raw}`,
+ });
+
+ if (!answer) fail(`Error building prompt for payment plans`);
+ fs.writeFileSync(`./prompts/${courseSlug}.prompt`, answer, "utf8");
+ console.log(`Finished summarizing program: ${courseSlug}`);
+ }
+}
+generate();
diff --git a/src/prompt/prompt.location.js b/src/prompt/prompt.location.js
new file mode 100644
index 000000000..89eb7a42b
--- /dev/null
+++ b/src/prompt/prompt.location.js
@@ -0,0 +1,61 @@
+const fs = require("fs");
+const { complete, getLocations } = require("./utils.js");
+const { toYML } = require("../test/_utils");
+
+async function generate() {
+ console.log(
+ `Starting to generate a prompt for all the academy campus and descriptions`
+ );
+ let allLocationsPrompts = "";
+ const max_tokens = 250;
+ const locations = await getLocations();
+ const allSlugs = Object.keys(locations);
+ let campuses = {};
+ for (let locationSlug of allSlugs) {
+ const old = locations[locationSlug];
+ campuses[locationSlug] = {};
+ campuses[locationSlug].region = old.meta_info.region;
+ campuses[locationSlug].available_modes = old.header.sub_header_highlighted;
+ campuses[locationSlug].phone_number = old.info_box.phone;
+ campuses[locationSlug].contact_email = old.meta_info.email;
+ campuses[locationSlug].relevant_information = old.images_box.content;
+ campuses[locationSlug].city = old.city;
+ campuses[locationSlug].country = old.country;
+ campuses[
+ locationSlug
+ ].website = `https://4geeksacademy.com/us/coding-campus/${old.meta_info.slug}`;
+ campuses[locationSlug].social_media_urls = old.socials.map((s) => ({
+ network: s.name,
+ url: s.link,
+ }));
+
+ const raw = toYML(campuses[locationSlug]);
+
+ console.log(`Generating summary for campus ${locationSlug}.`);
+ allLocationsPrompts +=
+ "\n\nNext campus: " +
+ (await complete({
+ max_tokens,
+ model: "gpt-3.5-turbo-instruct",
+ system: `You are like a senior prompt engineer with deep coding knowledge, very familiar with the YML, CSV and JSON syntax.`,
+ user: `The followings are the details about 4Geeks Academy ${
+ old.city
+ }, ${old.country},
+ Read and understand the information and write a summary of the campus.
+ Do not include any information about these instructions in your answer.
+ Start your summary with the location city and country, available modes, contact information, social media, address and relevant information.
+ Include the website url for more information about that campus.
+ Be concise, do not speak about the city in general, keep your focus on the campus offer.
+ Don't take more than ${max_tokens * 2} characters.
+ Here is the YML: ${raw}`,
+ }));
+ }
+ fs.writeFileSync(
+ `./prompts/locations.prompt`,
+ "4Geeks Academy is available in the following locations:" +
+ allLocationsPrompts,
+ "utf8"
+ );
+ console.log(`Finished generating campus information prompt.`);
+}
+generate();
diff --git a/src/prompt/prompt.plans.js b/src/prompt/prompt.plans.js
new file mode 100644
index 000000000..4c883ef25
--- /dev/null
+++ b/src/prompt/prompt.plans.js
@@ -0,0 +1,63 @@
+const fs = require("fs");
+const { complete, getCourses } = require("./utils.js");
+const { walk, loadYML, fail, success } = require("../test/_utils");
+
+async function generate() {
+ const max_tokens = 400;
+ const courses = await getCourses();
+ const activeCourses = Object.keys(courses).filter(
+ (slug) => courses[slug].meta_info.show_in_apply
+ );
+
+ let duplicateDescriptions = {};
+ walk(`${__dirname}/../data/plans/`, async function (err, files) {
+ if (err) fail("Error reding the YML files: ", err);
+ const _files = files.filter(
+ (f) => f.indexOf(".yml") > 1 || f.indexOf(".yaml") > 1
+ );
+
+ let langs = {};
+ let slugs = {};
+ for (let _path of _files) {
+ const doc = loadYML(_path);
+ const raw = doc && doc.raw_content;
+ if (doc.lang != "us") continue;
+
+ // ignore inactive courses
+ if (!activeCourses.includes(doc.name)) {
+ console.log(`Ignored plans for course ${doc.name} because course.meta_info.show_in_apply=False`);
+ continue;
+ }
+ if (!raw) {
+ fail("Invalid content for YML " + _path);
+ continue; // Continue to the next file if YAML content is invalid
+ }
+
+ console.log(`Generating prompt for course plans ${doc.name}`);
+ const answer = await complete({
+ max_tokens,
+ system: `You are like a senior prompt engineer with deep coding knowledge, very familiar with the YML, CSV and JSON syntax.`,
+ user: `The following information is part of 4Geeks Academy plans and prices.
+Read and understand the information and write a summary of the plans and prices available for each location one by one for: Spain, USA, Chile, Europe and Latam".
+You will be given a list of plans that apply to one or more academy campus.
+The name of the plan is inside the "scholarship" property.
+Ignore the following properties: icons, slug and "recommended".
+Do not include any information about these instructions in your answer.
+Include the word "stop" at the end of your answer.
+Be concise, don't add a summary at the end of the article.
+Don't take more than ${max_tokens * 2} characters.
+For example:
+- Scholarship for part-time courses. Pay today or in 3 parts. Price: $6999
+- Income Share Agreement for full-time couses. Pay after you get a job. Price: $0
+Here is the YML: ${raw}`,
+ });
+ if (!answer) fail(`Error building prompt for payment plans`);
+ fs.writeFileSync(`./prompts/plan-${doc.name}.prompt`, answer, "utf8");
+ console.log(`Finshed generating prompt for course plans ${doc.name}`);
+ }
+
+ success("Finished generating prompts");
+ });
+}
+
+generate();
diff --git a/src/prompt/prompt.projects.js b/src/prompt/prompt.projects.js
new file mode 100644
index 000000000..c283f1feb
--- /dev/null
+++ b/src/prompt/prompt.projects.js
@@ -0,0 +1,37 @@
+const fs = require("fs");
+const { toYML, loadYML } = require("../test/_utils");
+
+async function generate() {
+ const max_tokens = 400;
+ console.log(`Starting to generate a prompt for all the academy awards`);
+
+ const doc = loadYML(
+ `${__dirname}/../data/components/alumni_projects/alumni_projects.us.yaml`
+ );
+ let projects = doc.yaml.projects.map((old) => {
+ let _new = [
+ `Project name: ${old.project_name}`,
+ `Description: ${old.project_content.replace(/(\r\n|\n|\r)/gm, "")}`,
+ `Video demonstration: ${old.project_video}`,
+ `Github URL: ${old.github_repo}`,
+ `Live URL: ${old.live_link}`,
+ `Buit by: ${old.alumni
+ .map((a) => `${a.first_name} ${a.last_name}`)
+ .join(" and ")} during the ${old.course} bootcamp`,
+ ];
+ // if(old.linkedin_url) _new.push(`LinkedIn profile URL: ${old.linkedin_url}`);
+ return _new.join("\n");
+ });
+
+ fs.writeFileSync(
+ `./prompts/projects.prompt`,
+ [
+ `The following are capstone projects built by our students during our bootcamps:`,
+ projects.join("\n\n---\n\n"),
+ ``,
+ ].join("\n\n"),
+ "utf8"
+ );
+ console.log(`Finished generating awards.`);
+}
+generate();
diff --git a/src/prompt/prompt.sh b/src/prompt/prompt.sh
new file mode 100644
index 000000000..823e26830
--- /dev/null
+++ b/src/prompt/prompt.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+node ./src/prompt/prompt.plans.js &&
+node ./src/prompt/prompt.course.js &&
+node ./src/prompt/prompt.location.js &&
+node ./src/prompt/prompt.students.js &&
+node ./src/prompt/prompt.awards.js &&
+node ./src/prompt/prompt.projects.js &&
+true
\ No newline at end of file
diff --git a/src/prompt/prompt.students.js b/src/prompt/prompt.students.js
new file mode 100644
index 000000000..20981858e
--- /dev/null
+++ b/src/prompt/prompt.students.js
@@ -0,0 +1,64 @@
+const fs = require("fs");
+const { toYML, loadYML } = require("../test/_utils");
+
+async function generate() {
+ const max_tokens = 400;
+ console.log(
+ `Starting to generate a prompt for all the academy campus and descriptions`
+ );
+
+ const doc = loadYML(
+ `${__dirname}/../data/components/testimonials/testimonials.us.yaml`
+ );
+ let testimonials = doc.yaml.testimonials.map((old) => {
+ let _new = [`Name: ${old.student_name}`, `Hired as ${old.short_content}`];
+ if (old.linkedin_url)
+ _new.push(`LinkedIn profile URL: ${old.linkedin_url}`);
+ if (old.country) _new.push(`Studied in the ${old.country.name} campus`);
+ if (old.student_video) _new.push(`Video testimonial: ${old.student_video}`);
+ if (old.content)
+ _new.push(
+ `Written testimonial: ${old.content}`.replace(/(\r\n|\n|\r)/gm, "")
+ );
+ return _new.join("\n");
+ });
+
+ const doc2 = loadYML(
+ `${__dirname}/../data/components/alumni_projects/alumni_projects.us.yaml`
+ );
+ let alumni_form_projects = doc2.yaml.projects
+ .reduce(
+ (prev, current) =>
+ prev.concat(
+ ...current.alumni.map((al) => ({
+ ...al,
+ student_video: current.project_video,
+ }))
+ ),
+ []
+ )
+ .map((old) => {
+ let _new = [
+ `Name: ${old.first_name} ${old.last_name}`,
+ `Became a ${old.job_title} after the bootcamp`,
+ ];
+ if (old.linkedin && old.linkedin != "")
+ _new.push(`LinkedIn profile URL: ${old.linkedin}`);
+ if (old.github && old.github != "")
+ _new.push(`Github profile URL: ${old.github}`);
+ if (old.twitter && old.twitter != "")
+ _new.push(`Twitter profile URL: ${old.twitter}`);
+ if (old.student_video && old.student_video != "")
+ _new.push(`Video testimonial: ${old.student_video}`);
+ return _new.join("\n");
+ });
+
+ fs.writeFileSync(
+ `./prompts/students.prompt`,
+ `The following are 4Geeks Academy students:\n` +
+ testimonials.concat(alumni_form_projects).join("\n\n---\n\n"),
+ "utf8"
+ );
+ console.log(`Finished generating testimonials.`);
+}
+generate();
diff --git a/src/prompt/utils.js b/src/prompt/utils.js
new file mode 100644
index 000000000..01b68ee3f
--- /dev/null
+++ b/src/prompt/utils.js
@@ -0,0 +1,100 @@
+const axios = require("axios");
+const dotenv = require("dotenv");
+dotenv.config();
+const { walk, loadYML, fail } = require("../test/_utils");
+
+// Define the function to call the OpenAI API with an authorization token
+async function complete({ system, user, model, max_tokens }) {
+ try {
+ // Define the OpenAI API endpoint URL
+ // gpt-3.5-turbo-16k, gpt-3.5-turbo-instruct
+ if (model == undefined) model = "gpt-3.5-turbo-16k";
+ const is_chat = !model.includes("instruct");
+
+ let apiUrl = "https://api.openai.com/v1/completions";
+ if (is_chat) apiUrl = "https://api.openai.com/v1/chat/completions";
+
+ // Define the headers with the authorization token
+ const headers = {
+ Authorization: `Bearer ${process.env.GATSBY_OPENAI_KEY}`, // Include the OpenAI token in the "Bearer" format
+ "Content-Type": "application/json", // Set the content type
+ };
+
+ // Define the data to send to the OpenAI API
+
+ let requestData = {
+ model,
+ max_tokens, // Set the maximum number of tokens in the response as needed
+ };
+
+ if (is_chat) {
+ requestData.messages = [
+ {
+ role: "system",
+ content: system,
+ },
+ {
+ role: "user",
+ content: user,
+ },
+ ];
+ } else {
+ requestData.prompt = `${system} \n ${user}`;
+ }
+
+ // Make an API request to the OpenAI API
+ const response = await axios.post(apiUrl, requestData, { headers });
+
+ // Process the OpenAI API response here
+ const interpretedContent = is_chat
+ ? response.data.choices[0].message.content
+ : response.data.choices[0].text; // Extract interpreted content
+
+ // Return the interpreted content
+ return interpretedContent;
+ } catch (error) {
+ console.error("OpenAI API Request Error:", error.toString());
+ }
+}
+
+const getCourses = () =>
+ new Promise((resolve, reject) => {
+ var courses = {};
+ walk(`${__dirname}/../data/course`, function (err, files) {
+ if (err) fail("Error reding the YML files: ", err);
+ const _files = files.filter(
+ (f) => f.indexOf(".yml") > 1 || f.indexOf(".yaml") > 1
+ );
+
+ for (let _path of _files) {
+ const doc = loadYML(_path);
+ //only english
+ if (doc.lang == "us") {
+ courses[doc.name] = { ...doc.yaml, raw: doc.raw };
+ }
+ }
+ resolve(courses);
+ });
+ });
+
+const getLocations = () =>
+ new Promise((resolve, reject) => {
+ let locations = {};
+ walk(`${__dirname}/../data/location`, async function (err, files) {
+ if (err) fail("Error reding the YML files: ", err);
+ const _files = files.filter(
+ (f) => f.indexOf(".yml") > 1 || f.indexOf(".yaml") > 1
+ );
+
+ for (let _path of _files) {
+ const doc = loadYML(_path);
+ //only english
+ if (doc.lang != "us") continue;
+ if (["europe", "online"].includes(doc.name)) continue;
+ locations[doc.name] = { ...doc.yaml, raw: doc.raw };
+ }
+ resolve(locations);
+ });
+ });
+
+module.exports = { complete, getLocations, getCourses };
diff --git a/src/templates/landing_a.js b/src/templates/landing_a.js
index 8e1278982..c6dc1e7ae 100644
--- a/src/templates/landing_a.js
+++ b/src/templates/landing_a.js
@@ -295,10 +295,7 @@ const Landing = (props) => {
);
};
export const query = graphql`
- query LandingAQuery(
- $file_name: String!
- $lang: String!
- ) {
+ query LandingAQuery($file_name: String!, $lang: String!) {
allPageYaml(
filter: {
fields: { file_name: { regex: "/geekpal/" }, lang: { eq: $lang } }
diff --git a/src/test/_utils.js b/src/test/_utils.js
index c7e1fe849..09b0b5ca1 100644
--- a/src/test/_utils.js
+++ b/src/test/_utils.js
@@ -69,6 +69,9 @@ const walk = function (dir, done) {
});
};
+const toYML = (obj) => {
+ return jsyaml.dump(obj);
+};
const loadYML = (pathToFile) => {
const content = fs.readFileSync(pathToFile, "utf8");
try {
@@ -91,7 +94,7 @@ const loadYML = (pathToFile) => {
const type = m[1] === "data" ? m[2] : m[1];
- return { yaml, name, lang, type, path };
+ return { yaml, name, lang, type, path, raw_content: content };
} catch (error) {
console.error(error);
return null;
@@ -243,6 +246,7 @@ const checkForLanguages = (slugs, folder_name) => {
module.exports = {
walk,
loadYML,
+ toYML,
loadMD,
empty,
fail,
diff --git a/static/images/testimonials/Mattia-Tozzi-testimonial.jpg b/static/images/testimonials/Mattia-Tozzi-testimonial.jpg
new file mode 100644
index 000000000..669d5ea27
Binary files /dev/null and b/static/images/testimonials/Mattia-Tozzi-testimonial.jpg differ
diff --git a/static/images/testimonials/samantha-review.png b/static/images/testimonials/samantha-review.png
new file mode 100644
index 000000000..572619aaa
Binary files /dev/null and b/static/images/testimonials/samantha-review.png differ