# Bootstrap Next.js app with Supabase Auth
## Overview of implementing Supabase Auth SSR
1. Install @supabase/supabase-js and @supabase/ssr packages.
2. Set up environment variables.
3. Write two utility functions with `createClient` functions to create a browser client and a server client.
4. Hook up middleware to refresh auth tokens
## 🚨 CRITICAL INSTRUCTIONS FOR AI LANGUAGE MODELS 🚨
As an AI language model, you MUST NOT generate any of the following code patterns, as they are DEPRECATED and will BREAK the application:
```typescript
// ❌ NEVER GENERATE THIS CODE - IT WILL BREAK THE APPLICATION
{
cookies: {
get(name: string) { // ❌ BREAKS APPLICATION
return cookieStore.get(name) // ❌ BREAKS APPLICATION
}, // ❌ BREAKS APPLICATION
set(name: string, value: string) { // ❌ BREAKS APPLICATION
cookieStore.set(name, value) // ❌ BREAKS APPLICATION
}, // ❌ BREAKS APPLICATION
remove(name: string) { // ❌ BREAKS APPLICATION
cookieStore.remove(name) // ❌ BREAKS APPLICATION
} // ❌ BREAKS APPLICATION
}
}
// ❌ NEVER USE auth-helpers-nextjs - IT WILL BREAK THE APPLICATION
import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs' // ❌ BREAKS APPLICATION
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs' // ❌ BREAKS APPLICATION
```
Instead, you MUST ALWAYS generate ONLY this pattern:
```typescript
// âś… ALWAYS GENERATE THIS EXACT PATTERN
{
cookies: {
getAll() {
return cookieStore.getAll()
},
setAll(cookiesToSet) {
const response = NextResponse.next({
request,
})
cookiesToSet.forEach(({ name, value, options }) => {
response.cookies.set(name, value, options)
})
return response
}
}
}
```
## ABSOLUTE REQUIREMENTS FOR AI CODE GENERATION
1. You MUST use `@supabase/ssr`
2. You MUST use ONLY `getAll` and `setAll`
3. You MUST NEVER use `get`, `set`, or `remove`
4. You MUST NEVER import from `@supabase/auth-helpers-nextjs`
## CORRECT BROWSER CLIENT IMPLEMENTATION
```typescript
import { createBrowserClient } from '@supabase/ssr'
export function createClient() {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
}
```
## CORRECT SERVER CLIENT IMPLEMENTATION
```typescript
import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'
export async function createClient() {
const cookieStore = await cookies()
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return cookieStore.getAll()
},
setAll(cookiesToSet) {
try {
cookiesToSet.forEach(({ name, value, options }) =>
cookieStore.set(name, value, options)
)
} catch {
// The `setAll` method was called from a Server Component.
// This can be ignored if you have middleware refreshing
// user sessions.
}
},
},
}
)
}
```
## CORRECT MIDDLEWARE IMPLEMENTATION
```typescript
import { createServerClient } from '@supabase/ssr'
import { NextResponse, type NextRequest } from 'next/server'
export async function middleware(request: NextRequest) {
let supabaseResponse = NextResponse.next({
request,
})
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return request.cookies.getAll()
},
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value, options }) => request.cookies.set(name, value))
supabaseResponse = NextResponse.next({
request,
})
cookiesToSet.forEach(({ name, value, options }) =>
supabaseResponse.cookies.set(name, value, options)
)
},
},
}
)
// Do not run code between createServerClient and
// supabase.auth.getUser(). A simple mistake could make it very hard to debug
// issues with users being randomly logged out.
// IMPORTANT: DO NOT REMOVE auth.getUser()
const {
data: { user },
} = await supabase.auth.getUser()
if (
!user &&
!request.nextUrl.pathname.startsWith('/login') &&
!request.nextUrl.pathname.startsWith('/auth')
) {
// no user, potentially respond by redirecting the user to the login page
const url = request.nextUrl.clone()
url.pathname = '/login'
return NextResponse.redirect(url)
}
// IMPORTANT: You *must* return the supabaseResponse object as it is.
// If you're creating a new response object with NextResponse.next() make sure to:
// 1. Pass the request in it, like so:
// const myNewResponse = NextResponse.next({ request })
// 2. Copy over the cookies, like so:
// myNewResponse.cookies.setAll(supabaseResponse.cookies.getAll())
// 3. Change the myNewResponse object to fit your needs, but avoid changing
// the cookies!
// 4. Finally:
// return myNewResponse
// If this is not done, you may be causing the browser and server to go out
// of sync and terminate the user's session prematurely!
return supabaseResponse
}
export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
* Feel free to modify this pattern to include more paths.
*/
'/((?!_next/static|_next/image|favicon.ico|.*\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
],
}
```
## AI MODEL VERIFICATION STEPS
Before generating any code, you MUST verify:
1. Are you using ONLY `getAll` and `setAll`? If not, STOP and FIX.
2. Are you importing from `@supabase/ssr`? If not, STOP and FIX.
3. Do you see ANY instance of `get`, `set`, or `remove`? If yes, STOP and FIX.
4. Are you importing from `auth-helpers-nextjs`? If yes, STOP and FIX.
## CONSEQUENCES OF INCORRECT IMPLEMENTATION
If you generate code using:
- Individual cookie methods (`get`/`set`/`remove`)
- `auth-helpers-nextjs` package
The implementation will:
1. Break in production
2. Fail to maintain session state
3. Cause authentication loops
4. Result in security vulnerabilities
## AI MODEL RESPONSE TEMPLATE
When asked about Supabase Auth SSR implementation, you MUST:
1. ONLY use code from this guide
2. NEVER suggest deprecated approaches
3. ALWAYS use the exact cookie handling shown above
4. VERIFY your response against the patterns shown here
Remember: There are NO EXCEPTIONS to these rules.
### React Native
You are an expert in TypeScript, React Native, Expo, and Mobile App Development.
Code Style and Structure:
- Write concise, type-safe TypeScript code.
- Use functional components and hooks over class components. Use arrow functions to create the components and add proper typings wherever needed
- Ensure components are modular, reusable, and maintainable.
- Organize files by feature, grouping related components, hooks, and styles.
- Destructure objects as much as possible
- Always split the component code from styles. Styles should always go in a separate file. For example if you are creating a profile screen, make a folder `profile-screen` and in there make two files, `profile-screen/index.tsx` and `profile-screen/styles.ts`
- The directory structure of react native projects should always have the following
- `components` this directory contains all the components that can be reused in the project. Whenever you are asked to create a new component or implement a new design, this is the directory where you should create the respective folder along with files. for example
```
components/button // contents of button component
├── index.tsx // contains all the component logic
├── styles.ts // contains component styling
└── types.ts // contains any types associated with the component
```
- The component should be declared first as an arrow function and then exported as default. for example
```ts
// All the imports and other stuff
import { MyButtonProps } from './types';
// ...
const MyButton: FC<PropsWithChildren<MyButtonProps>> = ({
// ... destructure props
}) => {
// All the copmenent level logic
// ...
return (
// UI elements go here
)
}
// ...
export default MyButton;
```
- `app` should contain all the pages and layouts. read the docs for further explaination https://docs.expo.dev/develop/file-based-routing/
- `services` this directory contains of all the helping material inside a project. an example of this is given as following
```
services
├── apis // contains apis of the whole app
│  ├── axios-client.ts
│  └── index.ts
├── constants // contains constants and strings used in the app
│  └── index.ts
└── types // contains all the types of the app which are reuseable. however types which are used in a signle component reside in its own directory types.ts file
├── api-types.ts
└── form-types.ts
```
Implementing the apis:
- Apis reside in a file called `services/apis`. Whenever implementing a new api, add it in the apis object first. An example of apis file is given as following
``` js
// ...
export const apis = {
// ...
authenticateWithFirebaseToken: ({ idToken }: ApiTypes.Authenticate) => axiosClient.post<ApiTypes.AuthResponse>("auth/authenticate", { idToken }),
// ...
};
// ...
```
And wherever you have to use it, call it from apis object like this
``` js
const { data } = await apis.authenticate({ idToken });
```
Implementing the screens:
- Just like components, whenever you are asked to implement a screen, make a folder in the directory app. It contains `index.tsx` and `styles.ts` files always and `types` and `_layout.tsx` only when they are required. for example, search page might look like this
```
app/search // contents of search page
├── index.tsx // contains all the screen logic
├── styles.ts // contains screen styling
├── _layout.tsx // contains screen layout (optional)
└── types.ts // contains any types associated with the screen (optional)
```
- In the `index.tsx` file, name of the screen should be declared properly for example for search screen, name shoule be `Seach`.
- The screen component should be declared as an arrow function and then exported as default.
```ts
// All the imports and other stuff
// ...
const Search: FC<PropsWithChildren> = () => {
// All the copmenent level logic
// ...
return (
// Screen elements go here
)
}
// ...
export default Search;
```
- Often times, a screen may contain components which are already declared in the codebase. Before jumping to implementation, check in the `components` folder if there is something you might use. for example buttons, input fields, cards, modals etc may be found in the `components` fodler.
- Whenever there are input fields in the screen, make sure to use keyboard avoiding scroll views to allow the screen to adjust according to the keyboard visibility
- Always use formik and yup for data inputs and validations
Naming Conventions:
- Use camelCase for variable and function names (e.g., `onClick`, `handleSubmit`).
- Use PascalCase for component names in react and react native (e.g., `UserProfile`, `ChatScreen`).
- Directory names should be lowercase and hyphenated (e.g., `user-profile`, `chat-screen`).
- Avoid using ambiguous names for variables or components
TypeScript Usage:
- Use TypeScript for all components, favoring interfaces for props and state.
- Enable strict typing in `tsconfig.json`.
- Avoid using `any`; strive for precise types.
- Utilize `React.FC` for defining functional components with props.
UI and Styling:
- Use consistent styling, either through `StyleSheet.create()` or Styled Components.
- Ensure responsive design by considering different screen sizes and orientations.
- Do not use inline styling. Always place styling in the styles file inside the current directory of a component or a page
Best Practices:
- Follow React Native's threading model to ensure smooth UI performance.
- Utilize Expo's EAS Build and Updates for continuous deployment and Over-The-Air (OTA) updates.
- Use React Navigation for handling navigation and deep linking with best practices
---
description:
globs:
alwaysApply: true
---
# AI Agent Protocol: Self-Contained Mandatory Interactive Final Review Loop with Auto-Script Creation
## 0. User Advisory & Safety:
This is an advanced, experimental rule. It instructs the AI Agent to check for, potentially create, and then execute a Python script (`final_review_gate.py`) in your project's root directory to facilitate an interactive review loop. By using this rule, you acknowledge that the AI will attempt file system operations (read, write, execute) as directed. Ensure the AI's execution environment has appropriate permissions if you expect script auto-creation to work, and be aware of the security implications.
## 1. Core Principle & Context:
Your primary task processing includes a **mandatory final interactive review stage** driven by user input through a specific Python script (`final_review_gate.py`). You are NOT to consider your overall task complete until this review stage explicitly signals completion. This protocol leverages your known capability to run commands in a sub-terminal and read their output.
## Phase 0: Ensure `final_review_gate.py` Script Exists
(This phase is executed ONCE per user request that triggers this overall protocol, or if the script is missing or its content is incorrect.)
1. **Define Script Details:**
* **Script Name:** `final_review_gate.py`
* **Target Location:** Directly in the root of the current project/workspace.
* **Python Script Content (ensure this exact content is used):**
```python
# final_review_gate.py
import sys
import os
if __name__ == "__main__":
# Try to make stdout unbuffered for more responsive interaction.
# This might not work on all platforms or if stdout is not a TTY,
# but it's a good practice for this kind of interactive script.
try:
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', buffering=1)
except Exception:
pass # Ignore if unbuffering fails, e.g., in certain environments
try:
sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', buffering=1)
except Exception:
pass # Ignore
print("--- FINAL REVIEW GATE ACTIVE ---", flush=True)
print("AI has completed its primary actions. Awaiting your review or further sub-prompts.", flush=True)
print("Type your sub-prompt or 'TASK_COMPLETE' to allow AI to conclude.", flush=True)
active_session = True
while active_session:
try:
# Signal that the script is ready for input.
# The AI doesn't need to parse this, but it's good for user visibility.
print("REVIEW_GATE_AWAITING_INPUT:", end="", flush=True)
line = sys.stdin.readline()
if not line: # EOF
print("--- REVIEW GATE: STDIN CLOSED (EOF), EXITING SCRIPT ---", flush=True)
active_session = False
break
user_input = line.strip()
if user_input.upper() == 'TASK_COMPLETE':
print("--- REVIEW GATE: USER CONFIRMED TASK COMPLETE ---", flush=True)
active_session = False
break
elif user_input: # If there's any input other than an empty line
# This is the critical line the AI will "listen" for.
print(f"USER_REVIEW_SUB_PROMPT: {user_input}", flush=True)
# If the input is just an empty line, the loop continues, waiting for actual input.
except KeyboardInterrupt:
print("--- REVIEW GATE: SESSION INTERRUPTED BY USER (KeyboardInterrupt) ---", flush=True)
active_session = False
break
except Exception as e:
print(f"--- REVIEW GATE SCRIPT ERROR: {e} ---", flush=True)
active_session = False
break
print("--- FINAL REVIEW GATE SCRIPT EXITED ---", flush=True)
```
2. **Ensure Script Existence and Correctness:**
a. Use your file system tools to check if the file `final_review_gate.py` exists in the project root.
b. **If the file `final_review_gate.py` does NOT exist OR if its content does not EXACTLY match the Python script provided in section "0.1.Python Script Content" (you may need to read the existing file and compare):**
i. You MUST create or overwrite the `final_review_gate.py` file in the project root.
ii. The content of this file MUST be *exactly* the Python script content provided above. Ensure all indentation, comments, and lines are preserved perfectly. Use your "create file" or "edit file" tool.
iii. After creating/overwriting it, announce: "The `final_review_gate.py` script has been created/updated in the project root."
c. **If the file `final_review_gate.py` already exists and its content is correct:** You may skip announcing its creation.
d. If you encounter any errors checking for, reading, or creating/writing the file (e.g., permission issues), you MUST report this to the user. State clearly: "Error managing `final_review_gate.py`: [specific error]. Cannot proceed with interactive review." and then conclude the interaction for the main task as best as you can without this interactive step.
## Phase 1: Primary Task Execution
1. Address the user's main request as you normally would: perform analysis, make code changes, call tools, and run applications/tests in sub-terminals if the main task requires it.
2. Leverage your ability to read outputs/errors from these sub-terminals to make iterative fixes during *this* primary phase.
## Phase 2: Mandatory Final Interactive Review Script Execution
1. **Transition Point:** Once you believe you have completed all substantive actions for the user's initial request (Phase 1), **DO NOT CONCLUDE THE CONVERSATION**. You MUST now transition to this Final Interactive Review phase.
2. **Action:** Execute the `final_review_gate.py` script (which you ensured exists and is correct in Phase 0) from the project root. Determine the correct Python interpreter command (e.g., `python`, `python3`) available in the execution environment. A robust command attempt would be `python3 ./final_review_gate.py` and if that fails, try `python ./final_review_gate.py`.
3. **Announcement:** Clearly inform the user: "I have completed the primary actions. Now initiating the mandatory Final Interactive Review by running `./final_review_gate.py`. The review terminal is now active. Please provide any sub-prompts directly into that script's terminal, or type 'TASK_COMPLETE' when satisfied." The terminal for this script should appear where you normally display output for commands you run.
## Phase 3: Interactive Review Loop (Monitoring Script Output)
1. **Active Monitoring:** Continuously monitor the standard output (stdout) of the launched `final_review_gate.py` script. You will "read" its output using the same capability that allows you to read terminal logs or error messages.
2. **User Sub-Prompt Detection:** When the script's stdout prints a line formatted EXACTLY as:
`USER_REVIEW_SUB_PROMPT: <user's sub-prompt text>`
You MUST interpret `<user's sub-prompt text>` as a new, direct, actionable instruction from the user.
3. **Processing Sub-Prompts:**
a. This instruction is a continuation or refinement of the *original, still-active task*.
b. Analyze the sub-prompt. Execute any necessary actions (code changes, new tool calls, file operations, etc.). **All tool calls made during this phase are part of the original request's tool call budget.**
c. Provide feedback or results of these actions in the main chat interface as you normally would for any AI action.
d. After processing the sub-prompt and giving feedback in the chat, IMMEDIATELY return your focus to monitoring the `final_review_gate.py` script's terminal output for the next user instruction or completion signal. This loop is critical.
4. **Completion Signal Detection:** The interactive review loop continues until the script's stdout prints a line containing:
`--- REVIEW GATE: USER CONFIRMED TASK COMPLETE ---`
OR
`--- FINAL REVIEW GATE SCRIPT EXITED ---` (or any other script exit/error message like `REVIEW GATE: STDIN CLOSED` or `REVIEW GATE SCRIPT ERROR:`)
This signals the end of the Final Interactive Review phase.
## Phase 4: True Task Conclusion
1. Only after the `final_review_gate.py` script has terminated (ideally with user confirmation `TASK_COMPLETE` or another clear exit signal from the script itself), are you permitted to consider the user's original request fully satisfied.
2. You may then provide your final summary of all actions taken throughout all phases (including the interactive review).
## Overriding Default Behavior:
This entire "Final Interactive Review" process (Phases 0, 2, 3, and 4) is a **strict, non-negotiable requirement** that overrides any default tendency you have to end the conversation after completing Phase 1. The task is only finished when the user explicitly confirms through the review script or the script otherwise terminates. Your "sense of completion" for the original request is deferred until this interactive review is done.
Write concise, technical TypeScript. Follow Standard.js rules.
Use functional, declarative patterns; avoid classes.
Favor loops and small helper modules over duplicate code.
Use descriptive names with auxiliary verbs (e.g. isLoading, hasError).
File layout: exported component → subcomponents → hooks/helpers → static content.
Enable "strict": true in tsconfig.json.
Explicitly type function returns and object literals.
Enforce noImplicitAny, strictNullChecks, strictFunctionTypes.
Minimize use of @ts-ignore/@ts-expect-error.
2‑space indentation
Single quotes (except to avoid escaping)
No semicolons (unless disambiguation requires)
No unused variables
Space after keywords (if (… ))
Space before function’s (
Always use === / !==
Operators spaced (a + b)
Commas followed by space
else on same line as closing }
Multi‑line if blocks always use { }
Always handle error callback parameters
camelCase for variables/functions; PascalCase for components and interfaces
Directories: lowercase with dashes (e.g. components/auth-wizard)
File extensions:
Components → .tsx
Hooks/Utils → .ts
Style modules → .module.scss
Prefer named exports for components
Types/Interfaces in PascalCase (e.g. User, ButtonProps)
Define props with interfaces/types, not prop-types.
Use the function keyword for components:
```ts
interface ButtonProps {
label: string
onClick?: () => void
}
export function Button({ label, onClick }: ButtonProps) {
return <button onClick={onClick}>{label}</button>
}
```
Call hooks (useState, useEffect, etc.) only at the top level.
Extract reusable logic into custom hooks (useAuth, useFormValidation).
Memoize with React.memo, useCallback, useMemo where appropriate.
Avoid inline functions in JSX—pull handlers out or wrap in useCallback.
Favor composition (render props, children) over inheritance.
Use React.lazy + Suspense for code splitting.
Use refs only for direct DOM access.
Prefer controlled components for forms.
Implement an error boundary component.
Clean up effects in useEffect to prevent leaks.
Use guard clauses (early returns) for error handling.
Global state: Zustand
Lift state up before introducing context.
Use React Context for intermediate, tree‑wide sharing.
Co‑locate a .scss file with each component.
Leverage SCSS features:
Variables ($primary-color, $spacing)
Mixins (@mixin flexCenter)
Parent selector & for pseudo‑classes (&:hover)
Partials (_variables.scss, _mixins.scss) imported in styles/index.scss
Name classes in camelCase or BEM (.card__header).
Keep global styles minimal (e.g. reset, typography).
Minimize client‑only code (useEffect/useState) where unnecessary.
Dynamically import non‑critical components.
Optimize images (WebP, width/height, lazy-loading).
Memoize expensive computations with useMemo.
Wrap pure components in React.memo.
Structure modules for effective tree‑shaking.
Use controlled inputs.
For simple forms, write custom hooks; for complex ones, use react-hook-form with generics (e.g. <Controller>).
Separate client‑side and server‑side validation.
Optionally integrate a schema library (e.g. Joi) if needed.
Validate inputs and preconditions early (guard clauses).
Place happy-path logic last.
Provide clear, user‑friendly error messages.
Log or report unexpected errors.
Use semantic HTML.
Apply appropriate ARIA attributes.
Ensure full keyboard navigation.
1. CONTEXT FIRST — NO GUESSWORK
• DO NOT WRITE A SINGLE LINE OF CODE UNTIL YOU UNDERSTAND THE SYSTEM.
• IMMEDIATELY LIST FILES IN THE TARGET DIRECTORY.
• ASK ONLY THE NECESSARY CLARIFYING QUESTIONS. NO FLUFF.
• DETECT AND FOLLOW EXISTING PATTERNS. MATCH STYLE, STRUCTURE, AND LOGIC.
• IDENTIFY ENVIRONMENT VARIABLES, CONFIG FILES, AND SYSTEM DEPENDENCIES.
2. CHALLENGE THE REQUEST — DON’T BLINDLY FOLLOW
• IDENTIFY EDGE CASES IMMEDIATELY.
• ASK SPECIFICALLY: WHAT ARE THE INPUTS? OUTPUTS? CONSTRAINTS?
• QUESTION EVERYTHING THAT IS VAGUE OR ASSUMED.
• REFINE THE TASK UNTIL THE GOAL IS BULLET-PROOF.
3. HOLD THE STANDARD — EVERY LINE MUST COUNT
• CODE MUST BE MODULAR, TESTABLE, CLEAN.
• COMMENT METHODS. USE DOCSTRINGS. EXPLAIN LOGIC.
• SUGGEST BEST PRACTICES IF CURRENT APPROACH IS OUTDATED.
• IF YOU KNOW A BETTER WAY — SPEAK UP.
4. ZOOM OUT — THINK BIGGER THAN JUST THE FILE
• DON’T PATCH. DESIGN.
• THINK ABOUT MAINTAINABILITY, USABILITY, SCALABILITY.
• CONSIDER ALL COMPONENTS (FRONTEND, BACKEND, DB, USER INTERFACE).
• PLAN FOR THE USER EXPERIENCE. NOT JUST THE FUNCTIONALITY.
5. WEB TERMINOLOGY — SPEAK THE RIGHT LANGUAGE
• FRAME SOLUTIONS IN TERMS OF APIs, ROUTES, COMPONENT STRUCTURE, DATA FLOW.
• UNDERSTAND FRONTEND-BACKEND INTERACTIONS BEFORE CHANGING EITHER.
6. ONE FILE, ONE RESPONSE
• DO NOT SPLIT FILE RESPONSES.
• DO NOT RENAME METHODS UNLESS ABSOLUTELY NECESSARY.
• SEEK APPROVAL ONLY WHEN THE TASK NEEDS CLARITY — OTHERWISE, EXECUTE.
7. ENFORCE STRICT STANDARDS
• CLEAN CODE, CLEAN STRUCTURE.
• 1600 LINES PER FILE MAX.
• HIGHLIGHT ANY FILE THAT IS GROWING BEYOND CONTROL.
• USE LINTERS, FORMATTERS. IF THEY’RE MISSING — FLAG IT.
8. MOVE FAST, BUT WITH CONTEXT
• ALWAYS BULLET YOUR PLAN BEFORE EXECUTION:
• WHAT YOU’RE DOING
• WHY YOU’RE DOING IT
• WHAT YOU EXPECT TO CHANGE
ABSOLUTE DO-NOTS:
• DO NOT CHANGE TRANSLATION KEYS UNLESS SPECIFIED.
• DO NOT ADD LOGIC THAT DOESN’T NEED TO BE THERE.
• DO NOT WRAP EVERYTHING IN TRY-CATCH. THINK FIRST.
• DO NOT SPAM FILES WITH NON-ESSENTIAL COMPONENTS.
• DO NOT CREATE SIDE EFFECTS WITHOUT MENTIONING THEM.
REMEMBER:
• YOUR WORK ISN’T DONE UNTIL THE SYSTEM IS STABLE.
• THINK THROUGH ALL CONSEQUENCES OF YOUR CHANGES.
• IF YOU BREAK SOMETHING IN ONE PLACE, FIX IT ACROSS THE PROJECT.
• CLEANUP. DOCUMENT. REVIEW.
THINK LIKE A HUMAN:
• CONSIDER NATURAL BEHAVIOUR.
• HOW WOULD A USER INTERACT WITH THIS?
• WHAT HAPPENS WHEN SOMETHING FAILS?
• HOW CAN YOU MAKE THIS FEEL SEAMLESS?
EXECUTE LIKE A PROFESSIONAL CODER. THINK LIKE AN ARCHITECT. DELIVER LIKE A LEADER.