Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Building out projects structures using AI
Project strcutures are the files and folders that make up your application. The importance of your model knowing your project structure, gives your responses context that ensure prompts from any of the knowledge areas align to the project structure you are working with.
Once you have your language and libraries established, you will want to define your project structure and store it as a prompt store.
In the context of a Next.js application, there are a few common project structures that you can use, depending on your needs. One common structure is to organize your application by feature, with each feature having its own folder. Within each feature folder, you can have sub-folders for components, pages, and utilities. Here's an example:
In this structure, the components
folder contains reusable components that can be used across features. The features
folder contains the main functionality of the application, with each feature having its own folder. Each feature folder has a components
folder for feature-specific components, a pages
folder for feature-specific pages, and a utils
folder for feature-specific utility functions.
The pages
folder contains the top-level pages of the application, such as the homepage and any other static pages. The _app.js
file is used to initialize the application and can be used to set up things like global styles or state providers.
The public
folder contains any static assets that should be served directly by the server, such as images or favicon.ico.
The utils
folder contains utility functions that can be used across features.
The .env.local
file contains environment variables that are specific to the local development environment.
The next.config.js
file is used to configure Next.js, such as setting up webpack or configuring plugins.
Here's an example of how you could structure your markdown prompt store based on this project structure:
This way, when your model receives a prompt that references a component or utility function, it can look for it in the appropriate folder based on the project structure.
Specifying schemas with the help of generative AI
In programming, schemas are structures. These structures help define what is and is not allowed in a given call and response. Let's take a payment input form for example. Each field in the form has "structure" to it. For instance, names cannot have numbers, credit card numbers can not have alphabetical characters, expiration year cannot be in the past and must be a four digit integer.
Documentation and use of schemas in validation (a process that checks whether a given value matches a specified schema), provides a means of communication to users, developers, and systems.
In the case of the payment form, an API schema is used to let the client (a bicycle rental application for example) know what fields are expected for the payment request to go through . Client side validation on the user interface (credit card number input form for example) lets a user know that only 16 digit integers are accepted. Server side validation ensures that just because a user does not the use specified payment form, for the server to only accept requests if they align to a particular schema.
Example: Creating a schema for a credit card form
Prompt
Response
Sure! Here's an example of how you can create a schema for a credit card form to be used on the client side in a Next.js Chakra UI app:
In this schema, we're using the Yup library to define a schema for a credit card form with the following fields: name, cardNumber, expirationMonth, expirationYear, and cvv.
The name
field is a string that is required and must match the regular expression /^[a-zA-Z\s]*$/
to ensure that it only contains letters and spaces.
The cardNumber
field is a string that is required and must match the regular expression /^[0-9]{16}$/
to ensure that it only contains 16 numeric digits.
The expirationMonth
field is a number that is required and must be between 1 and 12.
The expirationYear
field is a number that is required and must be in the future and within the next 10 years.
The cvv
field is a string that is required and must match the regular expression /^[0-9]{3}$/
to ensure that it only contains 3 numeric digits.
You can use this schema to validate the input data on the client side before submitting it to the server. For example, you can use the validate
function from Yup to validate the form data against the schema, like this:
In this example, we're using Chakra UI's FormControl, FormErrorMessage, FormLabel, and Input components to create a form that includes the fields defined in the credit card schema. We're also using the useFormik hook from formik to manage the form state and handle form submission.
We're passing the credit card schema to the validationSchema
prop of the useFormik hook to validate the form data against the schema. The isInvalid
prop of the FormControl component is set to true
if the field has been touched and there is a validation error.
Finally, we're using the getFieldProps
function from formik to bind each form input to the corresponding formik field, and using the handleSubmit
function from formik to handle form submission.
That's it! You can use this credit card form component in any other React component in your Next.js app.
Discussion
In the response from ChatGPT, we can see the code provided uses a library called Yup and Formik to specify the schema and then apply that schema to the form.
Example: Specifying a credit card OpenAPI Spec
OpenAPI spec's are the industry standard for documenting an API service. An API service is a application hosted on a server that accepts requests from the web and returns responses. These specifications help systems and developers understand what data and thieir types are expected to be sent to receive an expected response.
Prompt
Response
In this OpenAPI spec, we're defining a POST
operation for submitting credit card information to the /credit-card
endpoint. The operation expects a JSON object in the request body with the following fields: name
, cardNumber
, expirationMonth
, expirationYear
, and cvv
. We're using the CreditCardInput
schema to define the structure of the request body, which includes the required fields and their data types, minimum and maximum lengths, and minimum and maximum values.
We're also defining two possible responses: a successful 200
response and an error 400
response that includes an array of error messages if the input data is invalid.
Finally, we're defining the OpenAPI spec components, including the CreditCardInput
schema, which can be reused in other endpoints or operations.
Note that this OpenAPI spec is just an example, and you may need to adjust it based on your specific use case and requirements.
Specifying languages to build your apps in AI
There are a number of reasons of to use one programming language over another.
Cost: Some programming languages are free to use, while others require licensing fees or paid support. Depending on the organization's budget, they may choose a language that is more cost-effective for their needs.
Resource expertise: If an organization already has a team of developers who are proficient in a particular programming language, they may choose to use that language for new projects to minimize the need for training and to leverage the team's expertise.
Performance: Some programming languages are better suited for specific tasks or applications than others. For example, C++ is often used for system-level programming and high-performance applications, while Python is popular for data science and machine learning.
Security: Some programming languages have more built-in security features and libraries than others. For example, Rust is designed to prevent memory errors and is often used for systems programming where security is a critical concern.
Compatibility: Some programming languages are more compatible with specific platforms or operating systems than others. For example, Java is known for its cross-platform compatibility, making it a popular choice for developing mobile and web applications.
In our bicycle rental application, we specified the use of Javascript as the primary language, React as the core framework, Next.js as a specific front-end framework on top of React, and Chakra UI as an element library for styling elements like buttons, forms, and sections. This decision was made due to my familiarity with the language, frameworks, and libraries in addition to a large support community.
After considering the above reasons of choosing one application over another and you have made a selection of which language you would like to proceed with, simply add it to the specifier of your prompt.
For example:
"in javascript" is the specifier in the example above.
To specify a language in a LLM, we should remember to specify a version or indicate the latest version
in the prompt and keep in mind that the latest in the model may not be the latest version published.
It is always recommended to read the latest documentation and release notes for a language when leveraging generative AI.
For well-established frameworks, breaking changes are not as frequent as newer frameworks that are going through rapid change. Meaning that even if the model is not running off the latest version, the code may still be the most optimal and syntactically correct implementation.
Let's use the difference between Javascript ES5 and ES6 for example.
Imports are a feature in JavaScript that allow developers to share and use code from other JavaScript files. The syntax and mechanism for imports differ between ES5 and ES6.
In ES5, developers commonly used script loading to include external JavaScript files in a web page. This technique required creating a new <script>
tag in the HTML file and specifying the src
attribute to point to the external JavaScript file. The code in the external file would then be executed in the context of the web page.
In ES6, a new syntax for importing and exporting code was introduced, along with a module system that allows developers to define and import modules that encapsulate code and data. The import
statement is used to import functions or variables from another module. The new module system allows for static analysis of dependencies, which can result in faster and more efficient code execution.
Here's an example of an import in ES5 and ES6:
In ES5:
In ES6:
In the ES6 example, the export
statement is used to export the add
function from the module.js
file. In the main.js
file, the import
statement is used to import the add
function and make it available for use. This syntax is more concise and allows for better management of dependencies between different JavaScript files.
Using generative AI to create specifications to build the foundation for you applications
The Specification knowledge area is crucial when working with generative AI, as it helps define the output of a prompt with greater accuracy and detail. In the "Learn through Creation" section, we illustrated how specifying the language, framework, and UI library could guide the development of a bicycle rental application. In many cases, organizations or users of generative AI might possess expertise in specific frameworks, or face financial, compliance, or technological requirements that necessitate using particular tools. In this article, we will explore various prompts and their roles in the Specification knowledge area.
Language Specification: When using generative AI, it is important to specify the programming language you want the generated code to be written in. This ensures that the output aligns with your project's technical requirements and your team's expertise.
Prompt: "Generate a function in Python that calculates the rental cost for a bicycle rental application."
Framework Specification: Specifying the desired framework can help you get the most out of the generated code, as it will be tailored to work seamlessly within the chosen environment.
Prompt: "Create a REST API endpoint for a bicycle rental application using the Express.js framework."
UI Library Specification: Clearly indicating the UI library to be used can help streamline the development process, as the generated code will be compatible with the specified library's components and design system.
Prompt: "Design a user registration form for a bicycle rental application using the Material-UI library in React."
Compliance and Security Specification: Some projects may require adherence to specific compliance or security standards. Specifying these requirements in the prompt can ensure that the generated output complies with relevant regulations and best practices.
Prompt: "Develop a secure authentication system for a bicycle rental application that is GDPR-compliant."
Platform or Device Specification: For projects targeting specific platforms or devices, it's essential to mention these requirements in the prompt to ensure the generated code is optimized for the desired environment.
Prompt: "Create a responsive navigation menu for a bicycle rental application that works well on both desktop and mobile devices."
In conclusion, the Specification knowledge area plays a vital role in obtaining precise output from generative AI. By specifying the language, framework, UI library, compliance requirements, and target platforms or devices, you can guide the AI to generate code that aligns with your project's needs and constraints. Leveraging the Specification knowledge area effectively can lead to more accurate and relevant results, ultimately streamlining the development process and improving the quality of the final product.
Choosing libraries and packages through generative AI
In the context of JavaScript, a library and a package are both terms used to describe collections of code that can be used to add functionality to a JavaScript application. However, there are some differences between the two.
A library is a collection of code that provides a set of pre-built functions or modules that can be used to perform specific tasks or add functionality to a JavaScript application. Libraries typically provide a set of APIs that can be called from within an application to perform specific tasks, such as manipulating the DOM, making HTTP requests, or performing data validation.
Some popular JavaScript libraries include jQuery, React, and Vue.js. Libraries can be used to speed up development time and improve code quality by providing pre-built functionality that can be easily integrated into an application.
A package, on the other hand, is a collection of code that can include libraries, modules, and other resources needed to run a JavaScript application or module. Packages are typically distributed using a package manager, such as npm or Yarn, and can include metadata about the package, such as version numbers and dependencies.
Packages can be used to manage dependencies and versioning in a JavaScript application, and can make it easier to share code between different applications or modules. Packages can include libraries, modules, and other resources needed to run a JavaScript application, and can be installed using a package manager.
In summary, a library is a collection of code that provides pre-built functionality for a JavaScript application, while a package is a collection of code and resources needed to run a JavaScript application or module, which can include libraries, modules, and other resources.
Let's look at a use case for the bicycle rental application, displaying bicycles on a map so that users can see what bikes are close to them.
First of mind, is to use Google Maps to display bikes that are close to the customer.
Sure, here's an example of a React component in Chakra UI using Next.js to show a bicycle icon using Google Maps:
First, you need to install the required dependencies:
Then, create a file called MapWithBikeIcon.js
in your components directory:
In this component, we're importing GoogleMapReact
and Box
from Chakra UI, and FaBicycle
from react-icons/fa
. We're also defining a functional component AnyReactComponent
that will render the bicycle icon.
MapWithBikeIcon
is the main component that takes two props, center
and zoom
, to determine the initial position and zoom level of the map. In the component's return statement, we're rendering a Box
with a fixed height and width to contain the Google Map. Inside the GoogleMapReact
component, we're passing the required bootstrapURLKeys
, defaultCenter
, and defaultZoom
props, and rendering the AnyReactComponent
with the lat and lng values from center
.
Replace YOUR_API_KEY
with your actual Google Maps API key. Then, you can use this component in any other React component in your Next.js app:
Here, we're importing Box
from Chakra UI, and MapWithBikeIcon
from the component we just created. We're defining the center
and zoom
props, and passing them to MapWithBikeIcon
inside a Box
. You can customize the center
and zoom
values to show the map at any location and zoom level you want.
That's it! You should now see a map with a red bicycle icon in the center of the page when you navigate to the MapPage
route in your Next.js app.
In the above, the instructions and component are largely clear. I think the naming of AnyReactComponent
could be better, and could be improved through a quick replacement prompt of rename the AnyReactComponent to BicyleIcon
.
However, let's assume that in discussing looking at Google Map's features and pricing, you find that Google Maps has more features than you need, and you're simply looking for a simpler more cost effective mapping solution. After some research, you decide to use MapBox.
Let's use a replacement prompt to change to a mapbox implementation:
Sure! Here's an example of how you can modify the React component we previously created to use the Mapbox library instead of Google Maps:
First, you need to install the required dependencies:
Then, create a file called MapWithBikeIcon.js in your components directory:
In this component, we're importing ReactMapGL and Marker from react-map-gl instead of GoogleMapReact. We're also using process.env.NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN to access your Mapbox API access token, which you should add to your .env.local file.
MapWithBikeIcon is the main component that takes a viewport object as a prop, which contains the initial position and zoom level of the map. In the component's return statement, we're rendering a Box with a fixed height and width to contain the Mapbox map. Inside the ReactMapGL component, we're passing the mapboxApiAccessToken and viewport props, and rendering the AnyReactComponent with the latitude and longitude values from the viewport object.
You can use this component in any other React component in your Next.js app:
Here, we're defining the center and zoom values as latitude and longitude in the viewport object, and passing it to MapWithBikeIcon. We're also using the onViewportChange function to update the viewport state.
That's it! You should now see a Mapbox map with a red bicycle icon in the center of the page when you navigate to the MapPage route in your Next.js app.
As expected, ChatGPT successfully replaced the Google-Maps-React library with a MapBox implementation.
The ability to quickly iterate through various libraries makes it efficient to create POCs (proof of concepts) or try different products out during the RFP (request for product) process.
Specifying elements with the assistance of generative AI
An element is a description of what you want to see on the screen. An element is a lightweight representation of a DOM node, and can be thought of as a blueprint for creating components. In regards to Javascript, elements are typically created using JSX, which allows you to write HTML-like syntax directly in your JavaScript code.
There is a considerable amount of overlap between Specifying Elements in the Specification knowledge area and UI elements in the Generation knowledge area. However, they differ in intent. The intent of specification is to define where UI is to generate.
Here is an example of an element in React:
In this example, we create an element that represents a heading with the text "Hello, world!". This element can be rendered to the screen using the ReactDOM.render() method.
Attributes are properties that are applied to elements in React, and can be used to modify the behavior and appearance of components. Attributes are specified as key-value pairs within JSX syntax, and are typically passed down from parent components to child components.
Here is an example of an attribute in React:
In this example, we create an img element with a src attribute that specifies the URL of an image file, and an alt attribute that provides alternative text for the image. These attributes can be used to modify the appearance and behavior of the img element when it is rendered to the screen.
Overall, elements and attributes are fundamental concepts in React that are used to define the structure and behavior of user interfaces. By creating and manipulating elements and attributes, you can build complex and dynamic UI components in a declarative and modular way.
Specifying Elements
Let's look at specifying elements for the subscription component of a bicycle rental application. The subscription component is used to display various monthly plans that users can sign up for to rent bicyles on the platform.
Sure! Here's an example of how you can create a subscription component in Next.js using Chakra UI as buttons inside of cards to show different subscription plans for a bicycle application:
First, you need to install the required dependencies:
Then, create a file called SubscriptionCard.js in your components directory:
In this component, we're using Chakra UI's Box, Button, Flex, Heading, and Text components to create a card that shows the title, price, description, and a button for each subscription plan. The title, price, description, buttonText, and buttonVariant props are passed to customize the subscription card.
Then, create another file called Subscription.js to display the subscription cards:
In this component, we're using Chakra UI's SimpleGrid component to display the subscription cards in a grid layout. We're also passing the subscription data as an array of objects and using the map function to create a SubscriptionCard component for each subscription.
Finally, you can use the Subscription component in any other React component in your Next.js app:
As expected, ChatGPT creates the subscription component with the elements specified. This prompt pattern allows you to quickly specify the elements you want to render. When combined with transformation, replacement, and visualization prompts specification is very useful in quickly iterating through various interfaces and user flows.
How to specify API specifications using generative AI
APIs (application programming interfaces) are applications that orchestrate calls and responses between systems.
Consider an instant message on an application like WhatsApp. When the user sends a message, it is going to an url (endpoint) that might be something like https://apis.whatsapp.com/messenger/thread/{threadId}
. The message is received by this API and then written into a database.
Creating an OpenAPI specification for your bicycle rental application API middleware is a great way to establish clear documentation and generate boilerplate code for your Node.js Express server. In this article, we will walk through the process of creating an OpenAPI specification and then generating a Node.js Express application based on that specification.
Start by designing the OpenAPI specification for your bicycle rental application. The specification should define the API's endpoints, request and response formats, and any necessary authentication or authorization details. Here's a simple example of an OpenAPI specification for a bicycle rental application:
Save the specification in a file named bicycle-rental-api.yaml
.
Below I have imported the spec into the documentation to demonstrate that the created spec compiles successfully.
Note the above is a very simple API specification. You could use prompt patterns from the replacement, transformation, and generation knowledges areas to build out a production grade API spec.
To generate the Node.js Express code based on your OpenAPI specification, you can use tools like OpenAPI Generator or swagger-node-codegen. In this example, we'll use the OpenAPI Generator.
First, install the OpenAPI Generator CLI:
Next, generate the Node.js Express code:
This command will create a new directory named bicycle-rental-api
, containing the generated Node.js Express code based on your OpenAPI specification.
Navigate to the bicycle-rental-api
directory and install the required dependencies:
Now, run the generated Express server:
Your Express server should now be running, and you can access the API endpoints as defined in your OpenAPI specification.
By creating an OpenAPI specification for your bicycle rental application API middleware and using a code generation tool, you can establish clear documentation and kickstart your Node.js Express server development. As you continue to develop your application, you can update the OpenAPI specification to reflect changes or additions to your API and regenerate the server code as needed.
Successfully retrieved the list of bicycles
Successfully retrieved the bicycle details