Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
4205845
feat: Add consult us form
stefanskoricdev Aug 25, 2025
f4a13d3
fix: Image size
stefanskoricdev Sep 2, 2025
10823b9
fix: Section widths
stefanskoricdev Sep 2, 2025
9bb364d
feat: Update hero section on staff augmentation page
stefanskoricdev Sep 2, 2025
f20958b
refactor: Split Staff augmentation into components. Add content to md…
stefanskoricdev Sep 3, 2025
eaf0a5c
fix: Smaller styling issues
stefanskoricdev Sep 3, 2025
d11ace9
refactor: Move components to staff augmentation dir
stefanskoricdev Sep 3, 2025
236eb2a
feat: Add Book a call button
stefanskoricdev Sep 3, 2025
7d90459
fix: improve color contrast on form submit button
stefanskoricdev Sep 3, 2025
c6bd857
fix: Remove button opacity when disabled
stefanskoricdev Sep 3, 2025
bbc94f3
fix: Heading elements in sequentially-descending order
stefanskoricdev Sep 3, 2025
9cadc43
fix: Heading elements in sequentially-descending order
stefanskoricdev Sep 3, 2025
b0c763f
feat: create thank you card, edit existing form to fit design
ivke995 Sep 8, 2025
fa509e6
fix: Staff augmentation background pattern issue on wide screens
stefanskoricdev Sep 9, 2025
e008555
feat: Make main content fact check section dynamic based on URL query…
stefanskoricdev Sep 10, 2025
501a702
feat: Add content for different hero and ideal for section variants
stefanskoricdev Sep 10, 2025
4b6e968
chore: copy updates
vele616 Sep 11, 2025
81ec619
feat: Make page content dynamic and update existing content (#605)
stefanskoricdev Sep 11, 2025
cae9817
feat: 2 separated requests for modal and primary form, created form f…
ivke995 Sep 11, 2025
c4e2700
feat: add source into getPlan endpoint
ivke995 Sep 11, 2025
0fcb0e9
feat: add notification error message and source in api response message
ivke995 Sep 11, 2025
d24dd98
feat: show 2 quarters ahead on the dropdown
ivke995 Sep 11, 2025
62a73c3
fix: Svg background gets blurry on bigger screens
stefanskoricdev Sep 11, 2025
02daa09
fix: Smaller styling issues
stefanskoricdev Sep 11, 2025
33ba7de
fix: edit variant id's, pill width on small screens
ivke995 Sep 12, 2025
8be4351
fix: add opacity for disabled button
ivke995 Sep 12, 2025
4e30ae3
chore: copy updates
vele616 Sep 12, 2025
e01a506
chore: minor copy correction
vele616 Sep 12, 2025
3f3768e
fix: edit line heights and text sizes for headers and description par…
ivke995 Sep 15, 2025
a9e5e4a
fix: change button background
ivke995 Sep 16, 2025
bdf580f
fix: add hover bg and cursor pointer on thank you card button
ivke995 Sep 16, 2025
1223b24
fix: enable all button click but show error message if something wrong
ivke995 Sep 16, 2025
5679c3b
fix: path to notion
ivke995 Sep 16, 2025
7629a26
feat: frontend contact us validation on get your plan form
ivke995 Sep 18, 2025
7e53b37
feat: add frontend validation for base contact form
ivke995 Sep 18, 2025
cbe3f47
fix: import collections with astro:content
ivke995 Sep 18, 2025
ec1198d
fix: astro:content available only on server-side
ivke995 Sep 18, 2025
0dbcce7
fix: allow 1 char for name in contact form API
ivke995 Sep 19, 2025
c46afce
fix: revert direct .md file import for single files
ivke995 Sep 19, 2025
7856fef
Feat ideal for section redesign (#619)
stefanskoricdev Sep 19, 2025
21afed8
fix: add listener on whole form and check input clicked
ivke995 Sep 19, 2025
080f1ce
FEAT: Update specialization page (#622)
stefanskoricdev Sep 19, 2025
0ff1ae6
FEAT: Add Trusted by and Testimonial section (#626)
stefanskoricdev Sep 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions apps/contact/app/api/contact/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import { NextRequest } from "next/server";
import z from "zod";

const bodyValidationSchema = z.object({
name: z
.string()
.min(2, { message: "Name must be at least 2 characters long" }),
name: z.string(),
email: z
.email({ message: "Invalid email adress" })
.min(1, { message: "Required field" }),
Expand Down
142 changes: 142 additions & 0 deletions apps/contact/app/api/get-plan/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import { processContact } from "@/helpers/notion";
import { nanoid } from "nanoid";
import { NextRequest } from "next/server";
import z from "zod";

const { NOTION_GET_PLAN_DATABASE_ID } = process.env;

const bodyValidationSchema = z.object({
name: z.string(),
email: z
.email({ message: "Invalid email adress" })
.min(1, { message: "Required field" }),
companyName: z.string().optional(),
mainChallenge: z.string().optional(),
expectedStartDate: z.string().optional(),
hasConsent: z.boolean().optional(),
});

type RequestBody = z.infer<typeof bodyValidationSchema>;

const allowRequest = async (request: Request & { ip?: string }) => {
return { success: true, limit: 1, reset: Date.now() + 30000, remaining: 1 };
};

export async function OPTIONS() {
return new Response(null, {
status: 200,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "OPTIONS, POST",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
},
});
}

export async function POST(request: NextRequest) {
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": "true",
"Access-Control-Allow-Methods": "POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
};

if (request.headers.get("Content-Type") === "application/json") {
try {
const body = (await request.json()) as RequestBody;
const bodyValidationResult = bodyValidationSchema.safeParse(body);

if (!body || bodyValidationResult.error) {
return new Response(
JSON.stringify({
message: bodyValidationResult.error?.message || "No body was found",
}),
{
status: 400,
headers: {
...corsHeaders,
},
},
);
}

const {
name,
email,
companyName,
mainChallenge,
expectedStartDate,
hasConsent,
} = body;

const message = `
Company name: ${companyName || ""} \n
Main challenge: ${mainChallenge || ""} \n
Expected start date: ${expectedStartDate || ""} \n`;

if (!hasConsent) {
return new Response(JSON.stringify({ message: "No consent by user" }), {
status: 403,
headers: {
...corsHeaders,
},
});
}

const { success, limit, reset, remaining } = await allowRequest(request);

if (!success) {
return new Response(
JSON.stringify({
message: "Too many requests. Please try again in a minute",
}),
{
status: 429,
headers: {
...corsHeaders,
},
},
);
}

await processContact({
id: nanoid(),
email,
name,
message: message || "",
databaseID: NOTION_GET_PLAN_DATABASE_ID || "",
source: request.nextUrl.searchParams.get("source") || "Unknown",
});

return new Response(
JSON.stringify({
message: "Success",
}),
{
status: 200,
headers: {
...corsHeaders,
"X-RateLimit-Limit": limit.toString(),
"X-RateLimit-Remaining": remaining.toString(),
"X-RateLimit-Reset": reset.toString(),
},
},
);
} catch (error) {
console.error("Error - api/get-plan", error);

const statusCode = (error as any).statusCode || 501;
const message =
(error as any)?.body?.message || "Issue while processing request";

return new Response(JSON.stringify({ message }), {

Check warning

Code scanning / CodeQL

Exception text reinterpreted as HTML Medium

Exception text
is reinterpreted as HTML without escaping meta-characters.
status: statusCode,
headers: {
...corsHeaders,
},
});
}
}

return new Response(null, { status: 400, headers: corsHeaders });
}
5 changes: 4 additions & 1 deletion apps/website/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ export default defineConfig({
adapter: vercel({
imageService: true,
imagesConfig: {
sizes: [320, 480, 578, 640, 720, 800, 940, 1200, 1412, 1536, 1800, 1920],
sizes: [
320, 480, 578, 640, 720, 800, 940, 960, 1200, 1280, 1412, 1440, 1536,
1600, 1800, 1920,
],
formats: ["image/avif", "image/webp"],
},
}),
Expand Down
6 changes: 6 additions & 0 deletions apps/website/public/target_large.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions apps/website/src/assets/code_monitor_dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/website/src/assets/croco_in_cloud.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/website/src/assets/crocodile-board_v3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions apps/website/src/assets/performance_increase.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified apps/website/src/assets/pic_phase_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions apps/website/src/assets/staff-hero.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/website/src/assets/staff/gloria.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/website/src/assets/staff/marija.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/website/src/assets/staff/stefan.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/website/src/assets/staff_collaboration.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading