Agency Website for TECVITY
TECVITY is a tech-focused agency established in 2022, specializing in providing solutions related to information security and compliance, web and mobile design, web development, branding, and logo design.
The agency provides a variety of specialized services, including:
- Branding and Logo Design: Crafting unique and memorable brand identities to help businesses stand out.
- Web Development: Developing high-quality, responsive, and scalable websites using modern web technologies.
- Desktop Application Development: Building efficient and reliable desktop applications tailored to client needs.
- Information Security and Compliance: Ensuring systems are secure and compliant with industry standards.
- Product Design: Designing user-friendly and aesthetically appealing digital products.
- Frontend: Next.js (App Router)
- Backend: API routes in Next.js
- Database: AWS DynamoDB
- Email Service: AWS SES
- Hosting: Netlify
-
Clone the repository:
git clone https://github.com/Tecvity/tecvity-nextjs.git cd tecvity-nextjs
- Install dependencies:
npm install
- Run the development server:
npm run dev
Open http://localhost:3000 with your browser to see the result.
You can start editing the page by modifying app/page.js. The page auto-updates as you edit the file.
Create a .env.local
file in the root directory and add the following variables:
AWS_ACCESS_KEY_ID
=
AWS_SECRET_ACCESS_KEY
=
AWS_REGION
=
Ensure these variables are set correctly to use AWS services, and set them in configuration.
components/
: Reusable UI components.
app/
: Next.js pages.
app/api/
: API route handlers for backend functionality.
styles/
: Stylesheets (global and module-specific).
data/
: static data
public/
: Static assets.
utils/
: Utility functions and helpers.
The website uses AWS SES for email notifications. Make sure you have verified your email domain in the AWS SES console and properly configured the environment variables in .env.local.
AWS DynamoDB is utilized for storing dynamic content, including blog posts comments. Ensure your AWS permissions are configured to access and manage DynamoDB tables as required.
Following feautres/pages exist in the codebase but have been disabled for now (can be considered in future):
- Pricing
- Search (both global and blog-based)
- Awards
Welcome to the Blog Post Contribution Guide! This guide provides step-by-step instructions for adding a new blog post to this project.
- Project Setup
- Steps for Adding a New Blog Post
- 1. Add an id for the Blog Post
- 2. Add a High-Quality Blog Image
- 3. Add a Small Blog Image
- 4. Add the Post Date
- 5. Assign a Category
- 6. Add a Title
- 7. Add Tags
- 8. Add an Icon
- 9. Add the Author's Name
- 10. Add the Author's Quote
- 11. Add the Author's Image
- 12. Add the Author's Profile
- 13. Add Blog Content
- 14. Add Blog Sections
- Final Example BlogPost Object
You need to modify the list blogPosts
in data/blogs.js
, add the final object to list blogPosts
to get your Blog posted.
The id
(required) is the unique identifier for a blog post. Adding duplicates can lead to unexpected data in other blog posts. You need to assign an id
that is one value greater than the previous blog post to maintain order. If the previous Blog id is 1
use 2
, Example:
id: 2,
The image
(required) is displayed at the top of the blog post. Upload an image (dimensions: 1080x600) to the directory public/assets/img/blog
. Ensure the image is named blog_post_<id>_<serial number>.jpg
, where <id>
needs to be replaced by blog post id
and <serial number>
needs to be replaced by serial numbers of your choice. Add the image path as shown:
image: '/assets/img/blog/blog_post_2_1.jpg',
The smallImageUrl
(required) is displayed in the preview card of the blog post. Upload an image (dimensions: 180x140) to the directory public/assets/img/blog
. Ensure the image is named blog_post_mini_<id>.jpg
, where <id>
needs to be replaced by blog post id
. Add the image path as shown:
smallImageUrl: '/assets/img/blog/blog_post_mini_2.jpg',
The date
(required) is used to determine the most recent posts and to display the date when the blog was published. Use the format Month DD, YYYY
, as shown below:
date: 'November 1, 2024',
The category
(required) is used to filter blogs based on the category they belong to. Select an existing category from the categories
list in data/categories-tags.js
. If you want to add a new category, include it in the categories
list in data/categories-tags.js
before using it, as shown below:
category: 'category',
The title
(required) is used to name a blog post and is also included in the route of that specific blog. Use a descriptive title and avoid symbols or random characters, as the title will be used for routing, as shown below:
title: 'Your New Blog Post',
The tags
(required) are used to define the topics of the blog post. Include at least one tag in an array. Choose tags from the tags list
in data/categories-tags.js
or add your own tags to the tags list
in data/categories-tags.js
before using them, as shown below:
tags: ['Tag1', 'Tag2', 'Tag3'],
The icon
(required) is used as a visual only. Use the standard icon path given below, you don't need a new one:
icon: '/assets/img/icon/arrow-left-top.svg',
The author
(required) is used to display the name of person who wrote the blog post. Just add the author name, as shown below:
author: 'Author 1',
The authorQuote
(required) is used to display a bold quote or slogan related to the platform or blog. Example:
authorQuote: 'Technology + Creativity = Tecvity!',
The authorImage
(required) is the display image of the author. Upload an image to public/assets/img/team
or use your own URL
. Alternatively, if no image is available, you can use the placeholder image team.png
, which is already saved in public/assets/img/team
for you, as shown below:
authorImage: '/assets/img/team/team.png',
The authorProfile
(optional) is the profile of author if he is also one of the founders, include your profile path. Otherwise, set it to null. Example:
authorProfile: '/founders/Najam-Ul-Saqib', or authorProfile: null,
The outermost content
(required) is the actual blog post. Within the content, the introduction
(required) serves as the introduction to the blog post, and the sections
(required) describes different sections of the post. The sections
can also be an empty array []
if no sections are added. If you want to add different sections, see Add Blog Sections. Example:
content: {
introduction: 'We believe that the key to our success is our team...',
sections: []
}
The sections
(required) are used to add different sections in the blog post. Each section must include a heading
(required) and either list
, content
, or services
(one is required at a time). The list
/services
is used to add items in the form of list, while content
is used to display simple text without any styling. A sample is shown below:
content: {
introduction: "...",
sections: [
{
heading: "Key Highlights",
list: [
{ title: "Highlight 1", description: "Highlight description" },
{ title: "Highlight 2", description: "Highlight description" }
]
},
{
heading: "Our Approach",
content: "We focus on understanding client needs and delivering tailor-made solutions."
},
{
heading: "Services Overview",
services: [
{ title: "Service 1", description: "service description" },
{ title: "Service 2", description: "service description" }
]
}
]
}
Add your final object, similar to the structure given below, to the blogPosts
list in the data/blogs.js
file to get your blog posted.
{
id: 2,
image: '/assets/img/blog/blog_post_2_1.jpg',
smallImageUrl: '/assets/img/blog/blog_post_mini_2.jpg',
date: 'November 1, 2024',
category: 'category',
title: 'Your New Blog Post',
tags: ['Tag1', 'Tag2', 'Tag3'],
icon: '/assets/img/icon/arrow-left-top.svg',
author: 'Author 1',
authorQuote: 'Technology + Creativity = Tecvity!',
authorImage: '/assets/img/team/team.png',
authorProfile: null,
content: {
introduction: 'We believe that the key to our success is our team...',
sections: [
{
heading: "Key Highlights",
list: [
{ title: "Highlight 1", description: "Highlight description" },
{ title: "Highlight 2", description: "Highlight description" }
]
},
{
heading: "Our Approach",
content: "We focus on understanding client needs and delivering tailor-made solutions."
},
{
heading: "Services Overview",
services: [
{ title: "Service 1", description: "service description" },
{ title: "Service 2", description: "service description" }
]
}
]
}
}
Welcome to the Service Addition Guide! This guide will walk you through the necessary steps for adding a new service to the project.
You need to modify the list ourServices
in data/features.js
, add the final object to list ourServices
to add new services.
The iconSrc
is used to as a visual only. Select one of the icons from public/assets/img/icon
to add to the service preview card, as shown below:
iconSrc: "/path/to/feature-icon1-1.svg",
Icons available:
- "feature-icon1-1.svg"
- "feature-icon1-2.svg"
- "feature-icon1-3.svg"
- "feature-icon1-4.svg"
- "feature-icon1-5.svg"
- "feature-icon1-6.svg"
The imageSrc1
and imageSrc2
(required) are displayed in the respective service page, one at the top and other at the middle. Upload an image (dimensions: 1080x600) to the directory public/assets/img/service
. Ensure the image is named s<id>_<serial number>.jpg
, where <id>
needs to be replaced by service id
how to add service id and <serial number>
needs to be replaced by serial numbers of your choice. Add the image path as shown:
imageSrc1: "/assets/img/service/s20_1.jpg",
imageSrc2: "/assets/img/service/s20_1.jpg",
The title
(required) is used to name a service and is also included in the route of that specific service. Use a descriptive title and avoid symbols or random characters, as the title will be used for routing, as shown below:
title: "Sample Service",
The id
(required) is the unique identifier for a service. Adding duplicates can lead to unexpected data in other services. You need to assign an id
that is one value greater than the previous service post to maintain order. If the previous service id is 19
use 20
, Example:
id: 20,
The text
(required) is used as a brief description in the preview card of the service. Add your own description for the service, as shown below:
text: "Short description of the service.",
The para1
(required) and para2
(required) are plain text displayed imediately after the image imageSrc1
and title of service title
, next is heading heading1
(optional) followed by a plain text para3
(optional), next is displayed the second image imageSrc2
followed by plain text para4
(optional), followed by heading heading2
(optional), followed by plain tests para5
(optional), para6
(optional). At last plain text para7
(optional) is displayed after service cards Add Cards for Service.
Include all required paragraphs and headings for your service:
para1: "Short description of service.",
para2: "Brief detail of the service.",
heading1: "Why It Matters",
para3: "Reason for importance.",
heading2: "Our Approach",
para4: "How we deliver it.",
para5: "Key benefits.",
para6: "Expected results.",
para7: "Call to action.",
The cards
(optional) are used to display the key features of your service, The title
(required) and description
(required) are the details of key feature. At the end of the service, include cards to display additional information:
cards: [
{ title: "Card Title 1", description: "Description 1" },
{ title: "Card Title 2", description: "Description 2" }
],
{
iconSrc: "/path/to/feature-icon1-1.svg",
imageSrc1: "/assets/img/service/s20_1.jpg",
imageSrc2: "/assets/img/service/s20_1.jpg",
title: "Sample Service",
id: 20,
text: "Short description of the service.",
para1: "Short description of service.",
para2: "Brief detail of the service.",
heading1: "Why It Matters",
para3: "Reason for importance.",
heading2: "Our Approach",
para4: "How we deliver it.",
para5: "Key benefits.",
para6: "Expected results.",
para7: "Call to action.",
cards: [
{ title: "Card Title 1", description: "Description 1" },
{ title: "Card Title 2", description: "Description 2" }
],
}
Welcome to the Portfolio Project Contribution Guide! This guide provides step-by-step instructions for adding a new portfolio project to this repository.
You need to modify the VAPTPortfolio
or PDPortfolio
list in data/portfolio.js
and add the final object to the respective list to upload a new portfolio project.
The id
(required) is the unique identifier for a portfolio project. Adding duplicates can lead to unexpected issues in other projects. You need to assign an id
that is one value greater than the previous project's id
to maintain order. For example, if the previous project's id
is 101
, use 102
, as shown below:
id: 102,
The imageSrc
(required) is used as the display picture for the project. Upload an image (dimensions: 1130x1420) to the respective folder based on the project type:
- For type
pd
(Product Design):public/assets/img/portfolio/portfolio-pd
- For type
vapt
(Penetration Testing & Vulnerability Assessment):public/assets/img/portfolio/portfolio-vapt
Ensure the image is named as portfolio<id>_<serial number>.jpg
, where <id>
is replaced with the portfolio id
and <serial number>
is replaced with a serial number of your choice.
For type pd
, update the imageSrc
property as shown:
imageSrc: "/assets/img/portfolio/portfolio-pd/portfolio102_1.jpg",
The itemsImages
(required, at least one) is a list of images used to showcase the project in a slider view at the top of the project display page. Upload images (dimensions: 1600x830) to the appropriate directory based on the project type:
- For type
pd
(Product Design):public/assets/img/portfolio/portfolio-pd
- For type
vapt
(Penetration Testing & Vulnerability Assessment):public/assets/img/portfolio/portfolio-vapt
Ensure each image is named as portfolio<id>_<serial number>.jpg
, where <id>
is replaced with the portfolio id
and <serial number>
is replaced with serial numbers of your choice.
Add these image file paths to the itemsImages
array.
itemsImages: ["/assets/img/portfolio/portfolio-pd/portfolio102_2.jpg", "/assets/img/portfolio/portfolio-pd/portfolio102_3.jpg"],
The category
(required, at least one) is an array of categories used to identify the type of project. Feel free to use any relevant categories and add them to the array, as shown below:
categoryLinks: ["Web Design", "UI/UX Design"],
The title
(required) is used as the name of the project on the preview card and the project display page after the slider. Provide a descriptive title for the project, as shown below:
title: "Sample Landing Page Design",
The category
(required) is used to identify the category of the project. At this point, we don't have a specific list of categories, so feel free to use a relevant name, or set the category to either Grey Box Penetration Test
or Product Design
, as shown below:
category: "Product Design",
The type
(required) is important as it will be used for routing purposes. Set the type to either pd
(Product Design) or vapt
(Penetration Testing & Vulnerability Assessment). You may check the list of available types in portfolioType
within data/categories-tags.js
, and add the type as shown below:
type: "pd",
The client
(required) is the name of the client for whom the project was completed. This can be a company name or the name of an individual. Add the client name as shown below:
client: "Sample Client",
The date
(required) is the time when the project started. If the project started in December, use the format Month, Year
and add it as shown below:
date: "December, 2024",
The para1
(required) is where you describe the project briefly, and it will be visible directly after the title on the project display page. Provide a short description of the project in plain text and add it as shown below:
para1: "This is a brief description of the project.",
The challenge
(required) is where you describe the reason or challenge that led the client to seek your services. Write it in plain text and add it as shown below:
challenge: "This was the client's challenge.",
The finalResult
(required) is where you write about the results you delivered to the client. Write it in plain text and add it as shown below:
finalResult: "These are the final results delivered.",
Alternatively, if you want to add a new type of portfolio, follow the steps below:
-
Create a New Object:
- Create a new object with a similar structure. Refer to the object structure for guidance.
- Ensure you change the
type
of the project. Refer to how to add a project type for details.
-
Add a New Array:
- In
data/portfolio.js
, create a new array. - The name of the array should follow the format
<Capital_Initials_of_Type>Portfolio
to maintain consistency. For example, for anew type
, the array name would beNTPortfolio
. - Add the object created in the previous step to the
NTPortfolio
array indata/portfolio.js
.
- In
export const NTPortfolio = [
// Your final object here
];
- Update the
portfolioData
Array:- Add the newly created array (for this example, it is
NTPortfolio
) to theportfolioData
array within the same file.
- Add the newly created array (for this example, it is
export const portfolioData = [
// Other portfolios
...NTPortfolio, // Add the new portfolio type here
];
- Add a Directory for the New Portfolio Type:
- Navigate to
app/(portfolio)/our-portfolio/(projects)
in your project, copy one of the directories (e.g.,app/(portfolio)/our-portfolio/(projects)/pd
), and rename it according to your projecttype
in lowercase (e.g.,nt
for this example). - Navigate to the directory you just copied (
app/(portfolio)/our-portfolio/(projects)/<type>
orapp/(portfolio)/our-portfolio/(projects)/nt
) (for this example) and modify theapp/(portfolio)/our-portfolio/(projects)/<type>/page.jsx
file as shown below:
- Navigate to
// Rest of the file
import { <type>Portfolio } from "@/data/portfolio";
export const metadata = {
title: "<type> Portfolio",
};
export default function Projects<type>Page() {
return (
<>
// Rest of the items
<PortfolioSub projectsList={<type>Portfolio} />
// Rest of the items
</>
);
}
// Make sure to replace <type> with the actual type.
- Next, modify the
app/(portfolio)/our-portfolio/(projects)/<type>/[title]/page.jsx
file:
// Rest of the file
import { <type>Portfolio } from "@/data/portfolio";
// Rest of the file
export default function ProjectPageDetails({ params }) {
return (
<>
<Header />
<DetailBreadcrumb portfolioTitle={params.title} />
<ProjectDetails portfolioTitle={params.title} blogList={<type>Portfolio} />
<MarqueeComponent />
<Footer />
</>
);
}
// Make sure to replace <type> with the actual type.
- Add new type to category array:
- Add the newly created
type
to the arrayportfolioType
indata/categories-tags.js
, replace<type>
withnt
for this example:
- Add the newly created
export const portfolioType = [
{ id: 1, text: "vapt" },
{ id: 2, text: "pd" },
{ id: 3, text: "<type>" },
];
{
id: 102,
imageSrc: "/assets/img/portfolio/portfolio-pd/portfolio102_1.jpg",
itemsImages: ["/assets/img/portfolio/portfolio-pd/portfolio102_2.jpg", "/assets/img/portfolio/portfolio-pd/portfolio102_3.jpg"],
categoryLinks: ["Web Design", "UI/UX Design"],
title: "Sample Landing Page Design",
category: "Product Design",
type: "pd",
client: "Sample Client",
date: "December, 2024",
para1: "This is a brief description of the project.",
challenge: "This was the client's challenge.",
finalResult: "These are the final results delivered."
}
This project is proprietary and is not intended for public distribution or reuse. All rights are reserved by TECVITY.